Merge commits 'd7ec49a6 9a5a87e0 aa5d34a8 2a3a97c6 ' into temp-merge-976

Also remove remaining uses of ecmult context in secp-zkp and update API tests
accordingly.
This commit is contained in:
Jonas Nick 2021-09-15 22:03:06 +00:00
commit 938725c1c9
48 changed files with 17370 additions and 816 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
src/ecmult_static_pre_g.h linguist-generated

1
.gitignore vendored
View File

@ -11,6 +11,7 @@ bench_internal
tests tests
exhaustive_tests exhaustive_tests
gen_context gen_context
gen_ecmult_static_pre_g
valgrind_ctime_test valgrind_ctime_test
*.exe *.exe
*.so *.so

View File

@ -129,12 +129,19 @@ exhaustive_tests_LDFLAGS = -static
TESTS += exhaustive_tests TESTS += exhaustive_tests
endif endif
EXTRA_PROGRAMS = gen_ecmult_static_pre_g
gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
# See Automake manual, Section "Errors with distclean"
src/ecmult_static_pre_g.h:
$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_static_pre_g$(EXEEXT)
./gen_ecmult_static_pre_g$(EXEEXT)
if USE_ECMULT_STATIC_PRECOMPUTATION if USE_ECMULT_STATIC_PRECOMPUTATION
CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src
gen_context_OBJECTS = gen_context.o gen_context_OBJECTS = gen_context.o
gen_context_BIN = gen_context$(BUILD_EXEEXT) gen_context_BIN = gen_context$(BUILD_EXEEXT)
gen_%.o: src/gen_%.c src/libsecp256k1-config.h $(gen_context_OBJECTS): src/gen_context.c src/libsecp256k1-config.h
$(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ $(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@
$(gen_context_BIN): $(gen_context_OBJECTS) $(gen_context_BIN): $(gen_context_OBJECTS)
@ -151,7 +158,7 @@ src/ecmult_static_context.h: $(gen_context_BIN)
CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h
endif endif
EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h EXTRA_DIST = autogen.sh src/gen_context.c src/ecmult_static_pre_g.h src/basic-config.h
if ENABLE_MODULE_ECDH if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include include src/modules/ecdh/Makefile.am.include

View File

@ -14,7 +14,7 @@ RUN apt-get install --no-install-recommends --no-upgrade -y \
make automake libtool pkg-config dpkg-dev valgrind qemu-user \ make automake libtool pkg-config dpkg-dev valgrind qemu-user \
gcc clang llvm libc6-dbg \ gcc clang llvm libc6-dbg \
g++ \ g++ \
gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan5:i386 \ gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan6:i386 \
gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \ gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \ gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \
gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \ gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \

View File

@ -217,6 +217,8 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
[window size for ecmult precomputation for verification, specified as integer in range [2..24].] [window size for ecmult precomputation for verification, specified as integer in range [2..24].]
[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] [Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
[The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] [The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.]
[A window size larger than 15 will require you delete the prebuilt ecmult_static_pre_g.h file so that it can be rebuilt.]
[For very large window sizes, use "make -j 1" to reduce memory use during compilation.]
["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]] ["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]]
)], )],
[req_ecmult_window=$withval], [req_ecmult_window=auto]) [req_ecmult_window=$withval], [req_ecmult_window=auto])

View File

@ -226,7 +226,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
* memory allocation entirely, see the functions in secp256k1_preallocated.h. * memory allocation entirely, see the functions in secp256k1_preallocated.h.
* *
* Returns: a newly created context object. * Returns: a newly created context object.
* Args: ctx: an existing context to copy (cannot be NULL) * Args: ctx: an existing context to copy
*/ */
SECP256K1_API secp256k1_context* secp256k1_context_clone( SECP256K1_API secp256k1_context* secp256k1_context_clone(
const secp256k1_context* ctx const secp256k1_context* ctx
@ -247,7 +247,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
*/ */
SECP256K1_API void secp256k1_context_destroy( SECP256K1_API void secp256k1_context_destroy(
secp256k1_context* ctx secp256k1_context* ctx
); ) SECP256K1_ARG_NONNULL(1);
/** Set a callback function to be called when an illegal argument is passed to /** Set a callback function to be called when an illegal argument is passed to
* an API call. It will only trigger for violations that are mentioned * an API call. It will only trigger for violations that are mentioned
@ -278,11 +278,11 @@ SECP256K1_API void secp256k1_context_destroy(
* fails. In this case, the corresponding default handler will be called with * fails. In this case, the corresponding default handler will be called with
* the data pointer argument set to NULL. * the data pointer argument set to NULL.
* *
* Args: ctx: an existing context object (cannot be NULL) * Args: ctx: an existing context object.
* In: fun: a pointer to a function to call when an illegal argument is * In: fun: a pointer to a function to call when an illegal argument is
* passed to the API, taking a message and an opaque pointer. * passed to the API, taking a message and an opaque pointer.
* (NULL restores the default handler.) * (NULL restores the default handler.)
* data: the opaque pointer to pass to fun above. * data: the opaque pointer to pass to fun above, must be NULL for the default handler.
* *
* See also secp256k1_context_set_error_callback. * See also secp256k1_context_set_error_callback.
*/ */
@ -302,12 +302,12 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
* for that). After this callback returns, anything may happen, including * for that). After this callback returns, anything may happen, including
* crashing. * crashing.
* *
* Args: ctx: an existing context object (cannot be NULL) * Args: ctx: an existing context object.
* In: fun: a pointer to a function to call when an internal error occurs, * In: fun: a pointer to a function to call when an internal error occurs,
* taking a message and an opaque pointer (NULL restores the * taking a message and an opaque pointer (NULL restores the
* default handler, see secp256k1_context_set_illegal_callback * default handler, see secp256k1_context_set_illegal_callback
* for details). * for details).
* data: the opaque pointer to pass to fun above. * data: the opaque pointer to pass to fun above, must be NULL for the default handler.
* *
* See also secp256k1_context_set_illegal_callback. * See also secp256k1_context_set_illegal_callback.
*/ */
@ -320,7 +320,7 @@ SECP256K1_API void secp256k1_context_set_error_callback(
/** Create a secp256k1 scratch space object. /** Create a secp256k1 scratch space object.
* *
* Returns: a newly created scratch space. * Returns: a newly created scratch space.
* Args: ctx: an existing context object (cannot be NULL) * Args: ctx: an existing context object.
* In: size: amount of memory to be available as scratch space. Some extra * In: size: amount of memory to be available as scratch space. Some extra
* (<100 bytes) will be allocated for extra accounting. * (<100 bytes) will be allocated for extra accounting.
*/ */
@ -480,8 +480,8 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
* Returns: 1: correct signature * Returns: 1: correct signature
* 0: incorrect or unparseable signature * 0: incorrect or unparseable signature
* Args: ctx: a secp256k1 context object, initialized for verification. * Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig: the signature being verified (cannot be NULL) * In: sig: the signature being verified.
* msghash32: the 32-byte message hash being verified (cannot be NULL). * msghash32: the 32-byte message hash being verified.
* The verifier must make sure to apply a cryptographic * The verifier must make sure to apply a cryptographic
* hash function to the message by itself and not accept an * hash function to the message by itself and not accept an
* msghash32 value directly. Otherwise, it would be easy to * msghash32 value directly. Otherwise, it would be easy to
@ -489,7 +489,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
* secret key. See also * secret key. See also
* https://bitcoin.stackexchange.com/a/81116/35586 for more * https://bitcoin.stackexchange.com/a/81116/35586 for more
* background on this topic. * background on this topic.
* pubkey: pointer to an initialized public key to verify with (cannot be NULL) * pubkey: pointer to an initialized public key to verify with.
* *
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S * To avoid accepting malleable signatures, only ECDSA signatures in lower-S
* form are accepted. * form are accepted.
@ -515,8 +515,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
* or copy if the input was already normalized. (can be NULL if * or copy if the input was already normalized. (can be NULL if
* you're only interested in whether the input was already * you're only interested in whether the input was already
* normalized). * normalized).
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL, * In: sigin: a pointer to a signature to check/normalize (can be identical to sigout)
* can be identical to sigout)
* *
* With ECDSA a third-party can forge a second distinct signature of the same * With ECDSA a third-party can forge a second distinct signature of the same
* message, given a single initial signature, but without knowing the key. This * message, given a single initial signature, but without knowing the key. This
@ -568,12 +567,16 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def
* *
* Returns: 1: signature created * Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid. * 0: the nonce generation function failed, or the secret key was invalid.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Args: ctx: pointer to a context object, initialized for signing.
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL) * Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed (cannot be NULL) * In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key (cannot be NULL) * seckey: pointer to a 32-byte secret key.
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used * noncefp: pointer to a nonce generation function. If NULL,
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * secp256k1_nonce_function_default is used.
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL). If it is non-NULL and
* secp256k1_nonce_function_default is used, then ndata must be a
* pointer to 32-bytes of additional data.
* *
* The created signature is always in lower-S form. See * The created signature is always in lower-S form. See
* secp256k1_ecdsa_signature_normalize for more details. * secp256k1_ecdsa_signature_normalize for more details.
@ -596,8 +599,8 @@ SECP256K1_API int secp256k1_ecdsa_sign(
* *
* Returns: 1: secret key is valid * Returns: 1: secret key is valid
* 0: secret key is invalid * 0: secret key is invalid
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* In: seckey: pointer to a 32-byte secret key (cannot be NULL) * In: seckey: pointer to a 32-byte secret key.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -606,11 +609,11 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
/** Compute the public key for a secret key. /** Compute the public key for a secret key.
* *
* Returns: 1: secret was valid, public key stores * Returns: 1: secret was valid, public key stores.
* 0: secret was invalid, try again * 0: secret was invalid, try again.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Args: ctx: pointer to a context object, initialized for signing.
* Out: pubkey: pointer to the created public key (cannot be NULL) * Out: pubkey: pointer to the created public key.
* In: seckey: pointer to a 32-byte secret key (cannot be NULL) * In: seckey: pointer to a 32-byte secret key.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -626,8 +629,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
* In/Out: seckey: pointer to the 32-byte secret key to be negated. If the * In/Out: seckey: pointer to the 32-byte secret key to be negated. If the
* secret key is invalid according to * secret key is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0 and * secp256k1_ec_seckey_verify, this function returns 0 and
* seckey will be set to some unspecified value. (cannot be * seckey will be set to some unspecified value.
* NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -645,7 +647,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
* *
* Returns: 1 always * Returns: 1 always
* Args: ctx: pointer to a context object * Args: ctx: pointer to a context object
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) * In/Out: pubkey: pointer to the public key to be negated.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -657,15 +659,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
* Returns: 0 if the arguments are invalid or the resulting secret key would be * Returns: 0 if the arguments are invalid or the resulting secret key would be
* invalid (only when the tweak is the negation of the secret key). 1 * invalid (only when the tweak is the negation of the secret key). 1
* otherwise. * otherwise.
* Args: ctx: pointer to a context object (cannot be NULL). * Args: ctx: pointer to a context object.
* In/Out: seckey: pointer to a 32-byte secret key. If the secret key is * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is
* invalid according to secp256k1_ec_seckey_verify, this * invalid according to secp256k1_ec_seckey_verify, this
* function returns 0. seckey will be set to some unspecified * function returns 0. seckey will be set to some unspecified
* value if this function returns 0. (cannot be NULL) * value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For * secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid * uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL). * is negligible (around 1 in 2^128).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -686,14 +688,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
* Returns: 0 if the arguments are invalid or the resulting public key would be * Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding * invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise. * secret key). 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation * Args: ctx: pointer to a context object initialized for validation.
* (cannot be NULL).
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an * In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0 (cannot be NULL). * invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For * secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid * uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL). * is negligible (around 1 in 2^128).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -704,15 +705,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
/** Tweak a secret key by multiplying it by a tweak. /** Tweak a secret key by multiplying it by a tweak.
* *
* Returns: 0 if the arguments are invalid. 1 otherwise. * Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL). * Args: ctx: pointer to a context object.
* In/Out: seckey: pointer to a 32-byte secret key. If the secret key is * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is
* invalid according to secp256k1_ec_seckey_verify, this * invalid according to secp256k1_ec_seckey_verify, this
* function returns 0. seckey will be set to some unspecified * function returns 0. seckey will be set to some unspecified
* value if this function returns 0. (cannot be NULL) * value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For * secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid * uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL). * is negligible (around 1 in 2^128).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -731,14 +732,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
/** Tweak a public key by multiplying it by a tweak value. /** Tweak a public key by multiplying it by a tweak value.
* *
* Returns: 0 if the arguments are invalid. 1 otherwise. * Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation * Args: ctx: pointer to a context object initialized for validation.
* (cannot be NULL).
* In/Out: pubkey: pointer to a public key object. pubkey will be set to an * In/Out: pubkey: pointer to a public key object. pubkey will be set to an
* invalid value if this function returns 0 (cannot be NULL). * invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
* secp256k1_ec_seckey_verify, this function returns 0. For * secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid * uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL). * is negligible (around 1 in 2^128).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -749,7 +749,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
/** Updates the context randomization to protect against side-channel leakage. /** Updates the context randomization to protect against side-channel leakage.
* Returns: 1: randomization successfully updated or nothing to randomize * Returns: 1: randomization successfully updated or nothing to randomize
* 0: error * 0: error
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
* *
* While secp256k1 code is written to be constant-time no matter what secret * While secp256k1 code is written to be constant-time no matter what secret
@ -780,18 +780,17 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
* *
* Returns: 1: the sum of the public keys is valid. * Returns: 1: the sum of the public keys is valid.
* 0: the sum of the public keys is not valid. * 0: the sum of the public keys is not valid.
* Args: ctx: pointer to a context object * Args: ctx: pointer to a context object.
* Out: out: pointer to a public key object for placing the resulting public key * Out: out: pointer to a public key object for placing the resulting public key.
* (cannot be NULL) * In: ins: pointer to array of pointers to public keys.
* In: ins: pointer to array of pointers to public keys (cannot be NULL) * n: the number of public keys to add together (must be at least 1).
* n: the number of public keys to add together (must be at least 1)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
const secp256k1_context* ctx, const secp256k1_context* ctx,
secp256k1_pubkey *out, secp256k1_pubkey *out,
const secp256k1_pubkey * const * ins, const secp256k1_pubkey * const * ins,
size_t n size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Compute a tagged hash as defined in BIP-340. /** Compute a tagged hash as defined in BIP-340.
* *

View File

@ -37,14 +37,15 @@ SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_func
* *
* Returns: 1: exponentiation was successful * Returns: 1: exponentiation was successful
* 0: scalar was invalid (zero or overflow) or hashfp returned 0 * 0: scalar was invalid (zero or overflow) or hashfp returned 0
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* Out: output: pointer to an array to be filled by hashfp * Out: output: pointer to an array to be filled by hashfp.
* In: pubkey: a pointer to a secp256k1_pubkey containing an * In: pubkey: a pointer to a secp256k1_pubkey containing an initialized public key.
* initialized public key * seckey: a 32-byte scalar with which to multiply the point.
* seckey: a 32-byte scalar with which to multiply the point * hashfp: pointer to a hash function. If NULL,
* hashfp: pointer to a hash function. If NULL, secp256k1_ecdh_hash_function_sha256 is used * secp256k1_ecdh_hash_function_sha256 is used
* (in which case, 32 bytes will be written to output) * (in which case, 32 bytes will be written to output).
* data: arbitrary data pointer that is passed through to hashfp * data: arbitrary data pointer that is passed through to hashfp
* (can be NULL for secp256k1_ecdh_hash_function_sha256).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context* ctx, const secp256k1_context* ctx,

View File

@ -39,11 +39,10 @@ typedef struct {
* Returns: 1 if the public key was fully valid. * Returns: 1 if the public key was fully valid.
* 0 if the public key could not be parsed or is invalid. * 0 if the public key could not be parsed or is invalid.
* *
* Args: ctx: a secp256k1 context object (cannot be NULL). * Args: ctx: a secp256k1 context object.
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
* parsed version of input. If not, it's set to an invalid value. * parsed version of input. If not, it's set to an invalid value.
* (cannot be NULL). * In: input32: pointer to a serialized xonly_pubkey.
* In: input32: pointer to a serialized xonly_pubkey (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -55,11 +54,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
* *
* Returns: 1 always. * Returns: 1 always.
* *
* Args: ctx: a secp256k1 context object (cannot be NULL). * Args: ctx: a secp256k1 context object.
* Out: output32: a pointer to a 32-byte array to place the serialized key in * Out: output32: a pointer to a 32-byte array to place the serialized key in.
* (cannot be NULL). * In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an initialized public key.
* In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an
* initialized public key (cannot be NULL).
*/ */
SECP256K1_API int secp256k1_xonly_pubkey_serialize( SECP256K1_API int secp256k1_xonly_pubkey_serialize(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -87,13 +84,12 @@ SECP256K1_API int secp256k1_xonly_pubkey_cmp(
* Returns: 1 if the public key was successfully converted * Returns: 1 if the public key was successfully converted
* 0 otherwise * 0 otherwise
* *
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* Out: xonly_pubkey: pointer to an x-only public key object for placing the * Out: xonly_pubkey: pointer to an x-only public key object for placing the converted public key.
* converted public key (cannot be NULL) * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that
* pk_parity: pointer to an integer that will be set to 1 if the point * will be set to 1 if the point encoded by xonly_pubkey is
* encoded by xonly_pubkey is the negation of the pubkey and * the negation of the pubkey and set to 0 otherwise.
* set to 0 otherwise. (can be NULL) * In: pubkey: pointer to a public key that is converted.
* In: pubkey: pointer to a public key that is converted (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -113,18 +109,14 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
* invalid (only when the tweak is the negation of the corresponding * invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise. * secret key). 1 otherwise.
* *
* Args: ctx: pointer to a context object initialized for verification * Args: ctx: pointer to a context object initialized for verification.
* (cannot be NULL)
* Out: output_pubkey: pointer to a public key to store the result. Will be set * Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0 (cannot * to an invalid value if this function returns 0.
* be NULL)
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to. * In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
* (cannot be NULL).
* tweak32: pointer to a 32-byte tweak. If the tweak is invalid * tweak32: pointer to a 32-byte tweak. If the tweak is invalid
* according to secp256k1_ec_seckey_verify, this function * according to secp256k1_ec_seckey_verify, this function
* returns 0. For uniformly random 32-byte arrays the * returns 0. For uniformly random 32-byte arrays the
* chance of being invalid is negligible (around 1 in * chance of being invalid is negligible (around 1 in 2^128).
* 2^128) (cannot be NULL).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -146,17 +138,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
* *
* Returns: 0 if the arguments are invalid or the tweaked pubkey is not the * Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
* result of tweaking the internal_pubkey with tweak32. 1 otherwise. * result of tweaking the internal_pubkey with tweak32. 1 otherwise.
* Args: ctx: pointer to a context object initialized for verification * Args: ctx: pointer to a context object initialized for verification.
* (cannot be NULL) * In: tweaked_pubkey32: pointer to a serialized xonly_pubkey.
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey (cannot be NULL)
* tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization * tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
* is passed in as tweaked_pubkey32). This must match the * is passed in as tweaked_pubkey32). This must match the
* pk_parity value that is returned when calling * pk_parity value that is returned when calling
* secp256k1_xonly_pubkey with the tweaked pubkey, or * secp256k1_xonly_pubkey with the tweaked pubkey, or
* this function will fail. * this function will fail.
* internal_pubkey: pointer to an x-only public key object to apply the * internal_pubkey: pointer to an x-only public key object to apply the tweak to.
* tweak to (cannot be NULL) * tweak32: pointer to a 32-byte tweak.
* tweak32: pointer to a 32-byte tweak (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -184,9 +174,9 @@ SECP256K1_API int secp256k1_xonly_sort(
* *
* Returns: 1: secret was valid, keypair is ready to use * Returns: 1: secret was valid, keypair is ready to use
* 0: secret was invalid, try again with a different secret * 0: secret was invalid, try again with a different secret
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Args: ctx: pointer to a context object, initialized for signing.
* Out: keypair: pointer to the created keypair (cannot be NULL) * Out: keypair: pointer to the created keypair.
* In: seckey: pointer to a 32-byte secret key (cannot be NULL) * In: seckey: pointer to a 32-byte secret key.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -197,9 +187,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
/** Get the secret key from a keypair. /** Get the secret key from a keypair.
* *
* Returns: 0 if the arguments are invalid. 1 otherwise. * Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* Out: seckey: pointer to a 32-byte buffer for the secret key (cannot be NULL) * Out: seckey: pointer to a 32-byte buffer for the secret key.
* In: keypair: pointer to a keypair (cannot be NULL) * In: keypair: pointer to a keypair.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -210,11 +200,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec(
/** Get the public key from a keypair. /** Get the public key from a keypair.
* *
* Returns: 0 if the arguments are invalid. 1 otherwise. * Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to
* the keypair public key. If not, it's set to an invalid value. * the keypair public key. If not, it's set to an invalid value.
* (cannot be NULL) * In: keypair: pointer to a keypair.
* In: keypair: pointer to a keypair (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -228,14 +217,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
* secp256k1_xonly_pubkey_from_pubkey. * secp256k1_xonly_pubkey_from_pubkey.
* *
* Returns: 0 if the arguments are invalid. 1 otherwise. * Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL) * Args: ctx: pointer to a context object.
* Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set * Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set
* to the keypair public key after converting it to an * to the keypair public key after converting it to an
* xonly_pubkey. If not, it's set to an invalid value (cannot be * xonly_pubkey. If not, it's set to an invalid value.
* NULL). * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the
* pk_parity: pointer to an integer that will be set to the pk_parity * pk_parity argument of secp256k1_xonly_pubkey_from_pubkey.
* argument of secp256k1_xonly_pubkey_from_pubkey (can be NULL). * In: keypair: pointer to a keypair.
* In: keypair: pointer to a keypair (cannot be NULL)
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -255,15 +243,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
* invalid (only when the tweak is the negation of the keypair's * invalid (only when the tweak is the negation of the keypair's
* secret key). 1 otherwise. * secret key). 1 otherwise.
* *
* Args: ctx: pointer to a context object initialized for verification * Args: ctx: pointer to a context object initialized for verification.
* (cannot be NULL)
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to * In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
* an invalid value if this function returns 0 (cannot be * an invalid value if this function returns 0.
* NULL).
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
* to secp256k1_ec_seckey_verify, this function returns 0. For * to secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid * uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL). * is negligible (around 1 in 2^128).
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
const secp256k1_context* ctx, const secp256k1_context* ctx,

View File

@ -55,7 +55,7 @@ SECP256K1_API size_t secp256k1_context_preallocated_size(
* Returns: a newly created context object. * Returns: a newly created context object.
* In: prealloc: a pointer to a rewritable contiguous block of memory of * In: prealloc: a pointer to a rewritable contiguous block of memory of
* size at least secp256k1_context_preallocated_size(flags) * size at least secp256k1_context_preallocated_size(flags)
* bytes, as detailed above (cannot be NULL) * bytes, as detailed above.
* flags: which parts of the context to initialize. * flags: which parts of the context to initialize.
* *
* See also secp256k1_context_randomize (in secp256k1.h) * See also secp256k1_context_randomize (in secp256k1.h)
@ -70,7 +70,7 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create(
* caller-provided memory. * caller-provided memory.
* *
* Returns: the required size of the caller-provided memory block. * Returns: the required size of the caller-provided memory block.
* In: ctx: an existing context to copy (cannot be NULL) * In: ctx: an existing context to copy.
*/ */
SECP256K1_API size_t secp256k1_context_preallocated_clone_size( SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
const secp256k1_context* ctx const secp256k1_context* ctx
@ -87,10 +87,10 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
* secp256k1_context_preallocated_create for details. * secp256k1_context_preallocated_create for details.
* *
* Returns: a newly created context object. * Returns: a newly created context object.
* Args: ctx: an existing context to copy (cannot be NULL) * Args: ctx: an existing context to copy.
* In: prealloc: a pointer to a rewritable contiguous block of memory of * In: prealloc: a pointer to a rewritable contiguous block of memory of
* size at least secp256k1_context_preallocated_size(flags) * size at least secp256k1_context_preallocated_size(flags)
* bytes, as detailed above (cannot be NULL) * bytes, as detailed above.
*/ */
SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone( SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -115,11 +115,11 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
* *
* Args: ctx: an existing context to destroy, constructed using * Args: ctx: an existing context to destroy, constructed using
* secp256k1_context_preallocated_create or * secp256k1_context_preallocated_create or
* secp256k1_context_preallocated_clone (cannot be NULL) * secp256k1_context_preallocated_clone.
*/ */
SECP256K1_API void secp256k1_context_preallocated_destroy( SECP256K1_API void secp256k1_context_preallocated_destroy(
secp256k1_context* ctx secp256k1_context* ctx
); ) SECP256K1_ARG_NONNULL(1);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -43,8 +43,9 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
/** Convert a recoverable signature into a normal signature. /** Convert a recoverable signature into a normal signature.
* *
* Returns: 1 * Returns: 1
* Out: sig: a pointer to a normal signature (cannot be NULL). * Args: ctx: a secp256k1 context object.
* In: sigin: a pointer to a recoverable signature (cannot be NULL). * Out: sig: a pointer to a normal signature.
* In: sigin: a pointer to a recoverable signature.
*/ */
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -55,10 +56,10 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). /** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
* *
* Returns: 1 * Returns: 1
* Args: ctx: a secp256k1 context object * Args: ctx: a secp256k1 context object.
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) * Out: output64: a pointer to a 64-byte array of the compact signature.
* recid: a pointer to an integer to hold the recovery id (can be NULL). * recid: a pointer to an integer to hold the recovery id.
* In: sig: a pointer to an initialized signature object (cannot be NULL) * In: sig: a pointer to an initialized signature object.
*/ */
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -71,12 +72,14 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
* *
* Returns: 1: signature created * Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid. * 0: the nonce generation function failed, or the secret key was invalid.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Args: ctx: pointer to a context object, initialized for signing.
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL) * Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed (cannot be NULL) * In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key (cannot be NULL) * seckey: pointer to a 32-byte secret key.
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used * noncefp: pointer to a nonce generation function. If NULL,
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * secp256k1_nonce_function_default is used.
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL for secp256k1_nonce_function_default).
*/ */
SECP256K1_API int secp256k1_ecdsa_sign_recoverable( SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -91,10 +94,10 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
* *
* Returns: 1: public key successfully recovered (which guarantees a correct signature). * Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise. * 0: otherwise.
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) * Args: ctx: pointer to a context object, initialized for verification.
* Out: pubkey: pointer to the recovered public key (cannot be NULL) * Out: pubkey: pointer to the recovered public key.
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) * In: sig: pointer to initialized signature that supports pubkey recovery.
* msghash32: the 32-byte message hash assumed to be signed (cannot be NULL) * msghash32: the 32-byte message hash assumed to be signed.
*/ */
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
const secp256k1_context* ctx, const secp256k1_context* ctx,

View File

@ -106,10 +106,10 @@ typedef struct {
* signatures from being valid in multiple contexts by accident. * signatures from being valid in multiple contexts by accident.
* *
* Returns 1 on success, 0 on failure. * Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Args: ctx: pointer to a context object, initialized for signing.
* Out: sig64: pointer to a 64-byte array to store the serialized signature (cannot be NULL) * Out: sig64: pointer to a 64-byte array to store the serialized signature.
* In: msg32: the 32-byte message being signed (cannot be NULL) * In: msg32: the 32-byte message being signed.
* keypair: pointer to an initialized keypair (cannot be NULL) * keypair: pointer to an initialized keypair.
* aux_rand32: 32 bytes of fresh randomness. While recommended to provide * aux_rand32: 32 bytes of fresh randomness. While recommended to provide
* this, it is only supplemental to security and can be NULL. See * this, it is only supplemental to security and can be NULL. See
* BIP-340 "Default Signing" for a full explanation of this * BIP-340 "Default Signing" for a full explanation of this
@ -150,7 +150,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom(
* Returns: 1: correct signature * Returns: 1: correct signature
* 0: incorrect signature * 0: incorrect signature
* Args: ctx: a secp256k1 context object, initialized for verification. * Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig64: pointer to the 64-byte signature to verify (cannot be NULL) * In: sig64: pointer to the 64-byte signature to verify.
* msg: the message being verified. Can only be NULL if msglen is 0. * msg: the message being verified. Can only be NULL if msglen is 0.
* msglen: length of the message * msglen: length of the message
* pubkey: pointer to an x-only public key to verify with (cannot be NULL) * pubkey: pointer to an x-only public key to verify with (cannot be NULL)

View File

@ -129,7 +129,7 @@ static void bench_ecmult_1(void* arg, int iters) {
int i; int i;
for (i = 0; i < iters; ++i) { for (i = 0; i < iters; ++i) {
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL); secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL);
} }
} }
@ -145,7 +145,7 @@ static void bench_ecmult_1g(void* arg, int iters) {
secp256k1_scalar_set_int(&zero, 0); secp256k1_scalar_set_int(&zero, 0);
for (i = 0; i < iters; ++i) { for (i = 0; i < iters; ++i) {
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]); secp256k1_ecmult(&data->output[i], NULL, &zero, &data->scalars[(data->offset1+i) % POINTS]);
} }
} }
@ -159,7 +159,7 @@ static void bench_ecmult_2g(void* arg, int iters) {
int i; int i;
for (i = 0; i < iters/2; ++i) { for (i = 0; i < iters/2; ++i) {
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]); secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]);
} }
} }
@ -207,7 +207,7 @@ static void bench_ecmult_multi(void* arg, int iters) {
iters = iters / data->count; iters = iters / data->count;
for (iter = 0; iter < iters; ++iter) { for (iter = 0; iter < iters; ++iter) {
data->ecmult_multi(&data->ctx->error_callback, &data->ctx->ecmult_ctx, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g); data->ecmult_multi(&data->ctx->error_callback, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g);
data->offset1 = (data->offset1 + count) % POINTS; data->offset1 = (data->offset1 + count) % POINTS;
data->offset2 = (data->offset2 + count - 1) % POINTS; data->offset2 = (data->offset2 + count - 1) % POINTS;
} }
@ -266,7 +266,7 @@ static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_
secp256k1_scalar_add(&total, &total, &tmp); secp256k1_scalar_add(&total, &total, &tmp);
} }
secp256k1_scalar_negate(&total, &total); secp256k1_scalar_negate(&total, &total);
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total); secp256k1_ecmult(&data->expected_output[iter], NULL, &zero, &total);
} }
/* Run the benchmark. */ /* Run the benchmark. */

View File

@ -11,7 +11,7 @@
/* from secp256k1.c */ /* from secp256k1.c */
static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak); static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak);
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *pubp, const unsigned char *tweak); static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *pubp, const unsigned char *tweak);
static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33) { static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33) {
if (secp256k1_ge_is_infinity(pubp)) { if (secp256k1_ge_is_infinity(pubp)) {
@ -39,12 +39,12 @@ static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp,
} }
/* Compute an ec commitment as pubp + hash(pubp, data)*G. */ /* Compute an ec commitment as pubp + hash(pubp, data)*G. */
static int secp256k1_ec_commit(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { static int secp256k1_ec_commit(secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) {
unsigned char tweak[32]; unsigned char tweak[32];
*commitp = *pubp; *commitp = *pubp;
return secp256k1_ec_commit_tweak(tweak, commitp, sha, data, data_size) return secp256k1_ec_commit_tweak(tweak, commitp, sha, data, data_size)
&& secp256k1_ec_pubkey_tweak_add_helper(ecmult_ctx, commitp, tweak); && secp256k1_ec_pubkey_tweak_add_helper(commitp, tweak);
} }
/* Compute the seckey of an ec commitment from the original secret key of the pubkey as seckey + /* Compute the seckey of an ec commitment from the original secret key of the pubkey as seckey +
@ -56,11 +56,11 @@ static int secp256k1_ec_commit_seckey(secp256k1_scalar* seckey, secp256k1_ge* pu
} }
/* Verify an ec commitment as pubp + hash(pubp, data)*G ?= commitment. */ /* Verify an ec commitment as pubp + hash(pubp, data)*G ?= commitment. */
static int secp256k1_ec_commit_verify(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { static int secp256k1_ec_commit_verify(const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) {
secp256k1_gej pj; secp256k1_gej pj;
secp256k1_ge p; secp256k1_ge p;
if (!secp256k1_ec_commit(ecmult_ctx, &p, pubp, sha, data, data_size)) { if (!secp256k1_ec_commit(&p, pubp, sha, data, data_size)) {
return 0; return 0;
} }

View File

@ -15,7 +15,7 @@
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
#endif /* SECP256K1_ECDSA_H */ #endif /* SECP256K1_ECDSA_H */

View File

@ -204,7 +204,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
return 1; return 1;
} }
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
unsigned char c[32]; unsigned char c[32];
secp256k1_scalar sn, u1, u2; secp256k1_scalar sn, u1, u2;
#if !defined(EXHAUSTIVE_TEST_ORDER) #if !defined(EXHAUSTIVE_TEST_ORDER)
@ -221,7 +221,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
secp256k1_scalar_mul(&u1, &sn, message); secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_scalar_mul(&u2, &sn, sigr); secp256k1_scalar_mul(&u2, &sn, sigr);
secp256k1_gej_set_ge(&pubkeyj, pubkey); secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (secp256k1_gej_is_infinity(&pr)) { if (secp256k1_gej_is_infinity(&pr)) {
return 0; return 0;
} }

View File

@ -18,8 +18,8 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed);
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak);
#endif /* SECP256K1_ECKEY_H */ #endif /* SECP256K1_ECKEY_H */

View File

@ -57,12 +57,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp25
return !secp256k1_scalar_is_zero(key); return !secp256k1_scalar_is_zero(key);
} }
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak) {
secp256k1_gej pt; secp256k1_gej pt;
secp256k1_scalar one; secp256k1_scalar one;
secp256k1_gej_set_ge(&pt, key); secp256k1_gej_set_ge(&pt, key);
secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_set_int(&one, 1);
secp256k1_ecmult(ctx, &pt, &pt, &one, tweak); secp256k1_ecmult(&pt, &pt, &one, tweak);
if (secp256k1_gej_is_infinity(&pt)) { if (secp256k1_gej_is_infinity(&pt)) {
return 0; return 0;
@ -79,7 +79,7 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp25
return ret; return ret;
} }
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak) {
secp256k1_scalar zero; secp256k1_scalar zero;
secp256k1_gej pt; secp256k1_gej pt;
if (secp256k1_scalar_is_zero(tweak)) { if (secp256k1_scalar_is_zero(tweak)) {
@ -88,7 +88,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx,
secp256k1_scalar_set_int(&zero, 0); secp256k1_scalar_set_int(&zero, 0);
secp256k1_gej_set_ge(&pt, key); secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero); secp256k1_ecmult(&pt, &pt, tweak, &zero);
secp256k1_ge_set_gej(key, &pt); secp256k1_ge_set_gej(key, &pt);
return 1; return 1;
} }

View File

@ -11,20 +11,26 @@
#include "scalar.h" #include "scalar.h"
#include "scratch.h" #include "scratch.h"
typedef struct { /* Noone will ever need more than a window size of 24. The code might
/* For accelerating the computation of a*P + b*G: */ * be correct for larger values of ECMULT_WINDOW_SIZE but this is not
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ * tested.
secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ *
} secp256k1_ecmult_context; * The following limitations are known, and there are probably more:
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
* because the size of the memory object that we allocate (in bytes)
* will not fit in a size_t.
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
* because certain expressions will overflow.
*/
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
#endif
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); /** The number of entries a table with precomputed multiples needs to have. */
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc); #define ECMULT_TABLE_SIZE(w) (1L << ((w)-2))
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src);
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
/** Double multiply: R = na*A + ng*G */ /** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
@ -39,6 +45,6 @@ typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge
* 0 if there is not enough scratch space for a single point or * 0 if there is not enough scratch space for a single point or
* callback returns 0 * callback returns 0
*/ */
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n); static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
#endif /* SECP256K1_ECMULT_H */ #endif /* SECP256K1_ECMULT_H */

View File

@ -14,6 +14,7 @@
#include "group.h" #include "group.h"
#include "scalar.h" #include "scalar.h"
#include "ecmult.h" #include "ecmult.h"
#include "ecmult_static_pre_g.h"
#if defined(EXHAUSTIVE_TEST_ORDER) #if defined(EXHAUSTIVE_TEST_ORDER)
/* We need to lower these values for exhaustive tests because /* We need to lower these values for exhaustive tests because
@ -21,13 +22,10 @@
* affine-isomorphism stuff which tracks z-ratios) */ * affine-isomorphism stuff which tracks z-ratios) */
# if EXHAUSTIVE_TEST_ORDER > 128 # if EXHAUSTIVE_TEST_ORDER > 128
# define WINDOW_A 5 # define WINDOW_A 5
# define WINDOW_G 8
# elif EXHAUSTIVE_TEST_ORDER > 8 # elif EXHAUSTIVE_TEST_ORDER > 8
# define WINDOW_A 4 # define WINDOW_A 4
# define WINDOW_G 4
# else # else
# define WINDOW_A 2 # define WINDOW_A 2
# define WINDOW_G 2
# endif # endif
#else #else
/* optimal for 128-bit and 256-bit exponents. */ /* optimal for 128-bit and 256-bit exponents. */
@ -41,31 +39,12 @@
* Two tables of this size are used (due to the endomorphism * Two tables of this size are used (due to the endomorphism
* optimization). * optimization).
*/ */
# define WINDOW_G ECMULT_WINDOW_SIZE
#endif
/* Noone will ever need more than a window size of 24. The code might
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
* not tested.
*
* The following limitations are known, and there are probably more:
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
* because the size of the memory object that we allocate (in bytes)
* will not fit in a size_t.
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
* because certain expressions will overflow.
*/
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
#endif #endif
#define WNAF_BITS 128 #define WNAF_BITS 128
#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w)) #define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w) #define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
/** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */ /* The number of objects allocated on the scratch space for ecmult_multi algorithms */
#define PIPPENGER_SCRATCH_OBJECTS 6 #define PIPPENGER_SCRATCH_OBJECTS 6
#define STRAUSS_SCRATCH_OBJECTS 6 #define STRAUSS_SCRATCH_OBJECTS 6
@ -119,18 +98,12 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec
/** Fill a table 'pre' with precomputed odd multiples of a. /** Fill a table 'pre' with precomputed odd multiples of a.
* *
* There are two versions of this function: * The resulting point set is brought to a single constant Z denominator, stores the X and Y
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its * coordinates as ge_storage points in pre, and stores the global Z in rz.
* resulting point set to a single constant Z denominator, stores the X and Y * It only operates on tables sized for WINDOW_A wnaf multiples.
* coordinates as ge_storage points in pre, and stores the global Z in rz.
* It only operates on tables sized for WINDOW_A wnaf multiples.
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
* resulting point set to actually affine points, and stores those in pre.
* It operates on tables of any size.
* *
* To compute a*P + b*G, we compute a table for P using the first function, * To compute a*P + b*G, we compute a table for P using this function,
* and for G using the second (which requires an inverse, but it only needs to * and use the precomputed table in <ecmult_static_pre_g.h> for G.
* happen once).
*/ */
static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
@ -142,137 +115,6 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *p
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
} }
static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp256k1_ge_storage *pre, const secp256k1_gej *a) {
secp256k1_gej d;
secp256k1_ge d_ge, p_ge;
secp256k1_gej pj;
secp256k1_fe zi;
secp256k1_fe zr;
secp256k1_fe dx_over_dz_squared;
int i;
VERIFY_CHECK(!a->infinity);
secp256k1_gej_double_var(&d, a, NULL);
/* First, we perform all the additions in an isomorphic curve obtained by multiplying
* all `z` coordinates by 1/`d.z`. In these coordinates `d` is affine so we can use
* `secp256k1_gej_add_ge_var` to perform the additions. For each addition, we store
* the resulting y-coordinate and the z-ratio, since we only have enough memory to
* store two field elements. These are sufficient to efficiently undo the isomorphism
* and recompute all the `x`s.
*/
d_ge.x = d.x;
d_ge.y = d.y;
d_ge.infinity = 0;
secp256k1_ge_set_gej_zinv(&p_ge, a, &d.z);
pj.x = p_ge.x;
pj.y = p_ge.y;
pj.z = a->z;
pj.infinity = 0;
for (i = 0; i < (n - 1); i++) {
secp256k1_fe_normalize_var(&pj.y);
secp256k1_fe_to_storage(&pre[i].y, &pj.y);
secp256k1_gej_add_ge_var(&pj, &pj, &d_ge, &zr);
secp256k1_fe_normalize_var(&zr);
secp256k1_fe_to_storage(&pre[i].x, &zr);
}
/* Invert d.z in the same batch, preserving pj.z so we can extract 1/d.z */
secp256k1_fe_mul(&zi, &pj.z, &d.z);
secp256k1_fe_inv_var(&zi, &zi);
/* Directly set `pre[n - 1]` to `pj`, saving the inverted z-coordinate so
* that we can combine it with the saved z-ratios to compute the other zs
* without any more inversions. */
secp256k1_ge_set_gej_zinv(&p_ge, &pj, &zi);
secp256k1_ge_to_storage(&pre[n - 1], &p_ge);
/* Compute the actual x-coordinate of D, which will be needed below. */
secp256k1_fe_mul(&d.z, &zi, &pj.z); /* d.z = 1/d.z */
secp256k1_fe_sqr(&dx_over_dz_squared, &d.z);
secp256k1_fe_mul(&dx_over_dz_squared, &dx_over_dz_squared, &d.x);
/* Going into the second loop, we have set `pre[n-1]` to its final affine
* form, but still need to set `pre[i]` for `i` in 0 through `n-2`. We
* have `zi = (p.z * d.z)^-1`, where
*
* `p.z` is the z-coordinate of the point on the isomorphic curve
* which was ultimately assigned to `pre[n-1]`.
* `d.z` is the multiplier that must be applied to all z-coordinates
* to move from our isomorphic curve back to secp256k1; so the
* product `p.z * d.z` is the z-coordinate of the secp256k1
* point assigned to `pre[n-1]`.
*
* All subsequent inverse-z-coordinates can be obtained by multiplying this
* factor by successive z-ratios, which is much more efficient than directly
* computing each one.
*
* Importantly, these inverse-zs will be coordinates of points on secp256k1,
* while our other stored values come from computations on the isomorphic
* curve. So in the below loop, we will take care not to actually use `zi`
* or any derived values until we're back on secp256k1.
*/
i = n - 1;
while (i > 0) {
secp256k1_fe zi2, zi3;
const secp256k1_fe *rzr;
i--;
secp256k1_ge_from_storage(&p_ge, &pre[i]);
/* For each remaining point, we extract the z-ratio from the stored
* x-coordinate, compute its z^-1 from that, and compute the full
* point from that. */
rzr = &p_ge.x;
secp256k1_fe_mul(&zi, &zi, rzr);
secp256k1_fe_sqr(&zi2, &zi);
secp256k1_fe_mul(&zi3, &zi2, &zi);
/* To compute the actual x-coordinate, we use the stored z ratio and
* y-coordinate, which we obtained from `secp256k1_gej_add_ge_var`
* in the loop above, as well as the inverse of the square of its
* z-coordinate. We store the latter in the `zi2` variable, which is
* computed iteratively starting from the overall Z inverse then
* multiplying by each z-ratio in turn.
*
* Denoting the z-ratio as `rzr`, we observe that it is equal to `h`
* from the inside of the above `gej_add_ge_var` call. This satisfies
*
* rzr = d_x * z^2 - x * d_z^2
*
* where (`d_x`, `d_z`) are Jacobian coordinates of `D` and `(x, z)`
* are Jacobian coordinates of our desired point -- except both are on
* the isomorphic curve that we were using when we called `gej_add_ge_var`.
* To get back to secp256k1, we must multiply both `z`s by `d_z`, or
* equivalently divide both `x`s by `d_z^2`. Our equation then becomes
*
* rzr = d_x * z^2 / d_z^2 - x
*
* (The left-hand-side, being a ratio of z-coordinates, is unaffected
* by the isomorphism.)
*
* Rearranging to solve for `x`, we have
*
* x = d_x * z^2 / d_z^2 - rzr
*
* But what we actually want is the affine coordinate `X = x/z^2`,
* which will satisfy
*
* X = d_x / d_z^2 - rzr / z^2
* = dx_over_dz_squared - rzr * zi2
*/
secp256k1_fe_mul(&p_ge.x, rzr, &zi2);
secp256k1_fe_negate(&p_ge.x, &p_ge.x, 1);
secp256k1_fe_add(&p_ge.x, &dx_over_dz_squared);
/* y is stored_y/z^3, as we expect */
secp256k1_fe_mul(&p_ge.y, &p_ge.y, &zi3);
/* Store */
secp256k1_ge_to_storage(&pre[i], &p_ge);
}
}
/** The following two macro retrieves a particular odd multiple from a table /** The following two macro retrieves a particular odd multiple from a table
* of precomputed multiples. */ * of precomputed multiples. */
#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ #define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
@ -299,74 +141,6 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25
} \ } \
} while(0) } while(0)
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE =
ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
+ ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
;
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
ctx->pre_g = NULL;
ctx->pre_g_128 = NULL;
}
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) {
secp256k1_gej gj;
void* const base = *prealloc;
size_t const prealloc_size = SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
if (ctx->pre_g != NULL) {
return;
}
/* get the generator */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
{
size_t size = sizeof((*ctx->pre_g)[0]) * ((size_t)ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
}
/* precompute the tables with odd multiples */
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
{
secp256k1_gej g_128j;
int i;
size_t size = sizeof((*ctx->pre_g_128)[0]) * ((size_t) ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g_128)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
/* calculate 2^128*generator */
g_128j = gj;
for (i = 0; i < 128; i++) {
secp256k1_gej_double_var(&g_128j, &g_128j, NULL);
}
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j);
}
}
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) {
if (src->pre_g != NULL) {
/* We cast to void* first to suppress a -Wcast-align warning. */
dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src));
}
if (src->pre_g_128 != NULL) {
dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src));
}
}
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) {
return ctx->pre_g != NULL;
}
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
secp256k1_ecmult_context_init(ctx);
}
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
* with the following guarantees: * with the following guarantees:
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
@ -443,7 +217,7 @@ struct secp256k1_strauss_state {
struct secp256k1_strauss_point_state* ps; struct secp256k1_strauss_point_state* ps;
}; };
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_ge tmpa; secp256k1_ge tmpa;
secp256k1_fe Z; secp256k1_fe Z;
/* Splitted G factors. */ /* Splitted G factors. */
@ -544,11 +318,11 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
} }
} }
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
} }
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g_128, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
} }
} }
@ -558,7 +332,7 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
} }
} }
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
@ -571,7 +345,7 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
state.pre_a = pre_a; state.pre_a = pre_a;
state.pre_a_lam = pre_a_lam; state.pre_a_lam = pre_a_lam;
state.ps = ps; state.ps = ps;
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng); secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng);
} }
static size_t secp256k1_strauss_scratch_size(size_t n_points) { static size_t secp256k1_strauss_scratch_size(size_t n_points) {
@ -579,7 +353,7 @@ static size_t secp256k1_strauss_scratch_size(size_t n_points) {
return n_points*point_size; return n_points*point_size;
} }
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
secp256k1_gej* points; secp256k1_gej* points;
secp256k1_scalar* scalars; secp256k1_scalar* scalars;
struct secp256k1_strauss_state state; struct secp256k1_strauss_state state;
@ -612,14 +386,14 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
} }
secp256k1_gej_set_ge(&points[i], &point); secp256k1_gej_set_ge(&points[i], &point);
} }
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc); secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc);
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
return 1; return 1;
} }
/* Wrapper for secp256k1_ecmult_multi_func interface */ /* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_strauss_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0); return secp256k1_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
} }
static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) { static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) {
@ -866,7 +640,7 @@ static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_windo
return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size; return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size;
} }
static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch); const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
/* Use 2(n+1) with the endomorphism, when calculating batch /* Use 2(n+1) with the endomorphism, when calculating batch
* sizes. The reason for +1 is that we add the G scalar to the list of * sizes. The reason for +1 is that we add the G scalar to the list of
@ -881,7 +655,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
int i, j; int i, j;
int bucket_window; int bucket_window;
(void)ctx;
secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(r);
if (inp_g_sc == NULL && n_points == 0) { if (inp_g_sc == NULL && n_points == 0) {
return 1; return 1;
@ -941,8 +714,8 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
} }
/* Wrapper for secp256k1_ecmult_multi_func interface */ /* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_pippenger_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0); return secp256k1_ecmult_pippenger_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0);
} }
/** /**
@ -986,7 +759,7 @@ static size_t secp256k1_pippenger_max_points(const secp256k1_callback* error_cal
/* Computes ecmult_multi by simply multiplying and adding each point. Does not /* Computes ecmult_multi by simply multiplying and adding each point. Does not
* require a scratch space */ * require a scratch space */
static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) { static int secp256k1_ecmult_multi_simple_var(secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) {
size_t point_idx; size_t point_idx;
secp256k1_scalar szero; secp256k1_scalar szero;
secp256k1_gej tmpj; secp256k1_gej tmpj;
@ -995,7 +768,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(r);
secp256k1_gej_set_infinity(&tmpj); secp256k1_gej_set_infinity(&tmpj);
/* r = inp_g_sc*G */ /* r = inp_g_sc*G */
secp256k1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc); secp256k1_ecmult(r, &tmpj, &szero, inp_g_sc);
for (point_idx = 0; point_idx < n_points; point_idx++) { for (point_idx = 0; point_idx < n_points; point_idx++) {
secp256k1_ge point; secp256k1_ge point;
secp256k1_gej pointj; secp256k1_gej pointj;
@ -1005,7 +778,7 @@ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx
} }
/* r += scalar*point */ /* r += scalar*point */
secp256k1_gej_set_ge(&pointj, &point); secp256k1_gej_set_ge(&pointj, &point);
secp256k1_ecmult(ctx, &tmpj, &pointj, &scalar, NULL); secp256k1_ecmult(&tmpj, &pointj, &scalar, NULL);
secp256k1_gej_add_var(r, r, &tmpj, NULL); secp256k1_gej_add_var(r, r, &tmpj, NULL);
} }
return 1; return 1;
@ -1031,11 +804,11 @@ static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n
return 1; return 1;
} }
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t); typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
size_t i; size_t i;
int (*f)(const secp256k1_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t); int (*f)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
size_t n_batches; size_t n_batches;
size_t n_batch_points; size_t n_batch_points;
@ -1045,11 +818,11 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
} else if (n == 0) { } else if (n == 0) {
secp256k1_scalar szero; secp256k1_scalar szero;
secp256k1_scalar_set_int(&szero, 0); secp256k1_scalar_set_int(&szero, 0);
secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc); secp256k1_ecmult(r, r, &szero, inp_g_sc);
return 1; return 1;
} }
if (scratch == NULL) { if (scratch == NULL) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
} }
/* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than /* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than
@ -1057,13 +830,13 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
* As a first step check if there's enough space for Pippenger's algo (which requires less space * As a first step check if there's enough space for Pippenger's algo (which requires less space
* than Strauss' algo) and if not, use the simple algorithm. */ * than Strauss' algo) and if not, use the simple algorithm. */
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) { if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
} }
if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) {
f = secp256k1_ecmult_pippenger_batch; f = secp256k1_ecmult_pippenger_batch;
} else { } else {
if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) { if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) {
return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n);
} }
f = secp256k1_ecmult_strauss_batch; f = secp256k1_ecmult_strauss_batch;
} }
@ -1071,7 +844,7 @@ static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback,
size_t nbp = n < n_batch_points ? n : n_batch_points; size_t nbp = n < n_batch_points ? n : n_batch_points;
size_t offset = n_batch_points*i; size_t offset = n_batch_points*i;
secp256k1_gej tmp; secp256k1_gej tmp;
if (!f(error_callback, ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) { if (!f(error_callback, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
return 0; return 0;
} }
secp256k1_gej_add_var(r, r, &tmp, NULL); secp256k1_gej_add_var(r, r, &tmp, NULL);

16611
src/ecmult_static_pre_g.h generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
/*****************************************************************************************************
* Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or https://www.opensource.org/licenses/mit-license.php. *
*****************************************************************************************************/
#include <inttypes.h>
#include <stdio.h>
/* Autotools creates libsecp256k1-config.h, of which ECMULT_WINDOW_SIZE is needed.
ifndef guard so downstream users can define their own if they do not use autotools. */
#if !defined(ECMULT_WINDOW_SIZE)
#include "libsecp256k1-config.h"
#endif
/* In principle we could use ASM, but this yields only a minor speedup in
build time and it's very complicated. In particular when cross-compiling, we'd
need to build the ASM for the build and the host machine. */
#undef USE_EXTERNAL_ASM
#undef USE_ASM_X86_64
#include "../include/secp256k1.h"
#include "assumptions.h"
#include "util.h"
#include "field_impl.h"
#include "group_impl.h"
#include "ecmult.h"
void print_table(FILE *fp, const char *name, int window_g, const secp256k1_gej *gen, int with_conditionals) {
static secp256k1_gej gj;
static secp256k1_ge ge, dgen;
static secp256k1_ge_storage ges;
int j;
int i;
gj = *gen;
secp256k1_ge_set_gej_var(&ge, &gj);
secp256k1_ge_to_storage(&ges, &ge);
fprintf(fp, "static const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name);
fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
SECP256K1_GE_STORAGE_CONST_GET(ges));
secp256k1_gej_double_var(&gj, gen, NULL);
secp256k1_ge_set_gej_var(&dgen, &gj);
j = 1;
for(i = 3; i <= window_g; ++i) {
if (with_conditionals) {
fprintf(fp, "#if ECMULT_TABLE_SIZE(WINDOW_G) > %ld\n", ECMULT_TABLE_SIZE(i-1));
}
for(;j < ECMULT_TABLE_SIZE(i); ++j) {
secp256k1_gej_set_ge(&gj, &ge);
secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL);
secp256k1_ge_set_gej_var(&ge, &gj);
secp256k1_ge_to_storage(&ges, &ge);
fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
SECP256K1_GE_STORAGE_CONST_GET(ges));
}
if (with_conditionals) {
fprintf(fp, "#endif\n");
}
}
fprintf(fp, "};\n");
}
void print_two_tables(FILE *fp, int window_g, const secp256k1_ge *g, int with_conditionals) {
secp256k1_gej gj;
int i;
secp256k1_gej_set_ge(&gj, g);
print_table(fp, "secp256k1_pre_g", window_g, &gj, with_conditionals);
for (i = 0; i < 128; ++i) {
secp256k1_gej_double_var(&gj, &gj, NULL);
}
print_table(fp, "secp256k1_pre_g_128", window_g, &gj, with_conditionals);
}
int main(void) {
const secp256k1_ge g = SECP256K1_G;
const secp256k1_ge g_13 = SECP256K1_G_ORDER_13;
const secp256k1_ge g_199 = SECP256K1_G_ORDER_199;
const int window_g_13 = 4;
const int window_g_199 = 8;
FILE* fp;
fp = fopen("src/ecmult_static_pre_g.h","w");
if (fp == NULL) {
fprintf(stderr, "Could not open src/ecmult_static_pre_g.h for writing!\n");
return -1;
}
fprintf(fp, "/* This file was automatically generated by gen_ecmult_static_pre_g. */\n");
fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n");
fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n");
fprintf(fp, " */\n");
fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_PRE_G_H\n");
fprintf(fp, "#define SECP256K1_ECMULT_STATIC_PRE_G_H\n");
fprintf(fp, "#include \"group.h\"\n");
fprintf(fp, "#ifdef S\n");
fprintf(fp, " #error macro identifier S already in use.\n");
fprintf(fp, "#endif\n");
fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
"SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,"
"0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
fprintf(fp, "#if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > %ld\n", ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE));
fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build.\n");
fprintf(fp, "#endif\n");
fprintf(fp, "#if defined(EXHAUSTIVE_TEST_ORDER)\n");
fprintf(fp, "#if EXHAUSTIVE_TEST_ORDER == 13\n");
fprintf(fp, "#define WINDOW_G %d\n", window_g_13);
print_two_tables(fp, window_g_13, &g_13, 0);
fprintf(fp, "#elif EXHAUSTIVE_TEST_ORDER == 199\n");
fprintf(fp, "#define WINDOW_G %d\n", window_g_199);
print_two_tables(fp, window_g_199, &g_199, 0);
fprintf(fp, "#else\n");
fprintf(fp, " #error No known generator for the specified exhaustive test group order.\n");
fprintf(fp, "#endif\n");
fprintf(fp, "#else /* !defined(EXHAUSTIVE_TEST_ORDER) */\n");
fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n");
print_two_tables(fp, ECMULT_WINDOW_SIZE, &g, 1);
fprintf(fp, "#endif\n");
fprintf(fp, "#undef S\n");
fprintf(fp, "#endif\n");
fclose(fp);
return 0;
}

View File

@ -10,6 +10,27 @@
#include "field.h" #include "field.h"
#include "group.h" #include "group.h"
#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,\
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,\
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,\
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24\
)
#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,\
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,\
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,\
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae\
)
/** Generator for secp256k1, value 'g' defined in
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
*/
#define SECP256K1_G SECP256K1_GE_CONST(\
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,\
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,\
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,\
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL\
)
/* These exhaustive group test orders and generators are chosen such that: /* These exhaustive group test orders and generators are chosen such that:
* - The field size is equal to that of secp256k1, so field code is the same. * - The field size is equal to that of secp256k1, so field code is the same.
* - The curve equation is of the form y^2=x^3+B for some constant B. * - The curve equation is of the form y^2=x^3+B for some constant B.
@ -21,23 +42,15 @@
*/ */
#if defined(EXHAUSTIVE_TEST_ORDER) #if defined(EXHAUSTIVE_TEST_ORDER)
# if EXHAUSTIVE_TEST_ORDER == 13 # if EXHAUSTIVE_TEST_ORDER == 13
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13;
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24
);
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST( static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc, 0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc,
0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417 0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417
); );
# elif EXHAUSTIVE_TEST_ORDER == 199 # elif EXHAUSTIVE_TEST_ORDER == 199
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae
);
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST( static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1, 0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1,
0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb 0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb
@ -46,15 +59,7 @@ static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
# error No known generator for the specified exhaustive test group order. # error No known generator for the specified exhaustive test group order.
# endif # endif
#else #else
/** Generator for secp256k1, value 'g' defined in static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
*/
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
);
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7); static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7);
#endif #endif

View File

@ -126,7 +126,7 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *
return ret; return ret;
} }
static int secp256k1_dleq_verify(const secp256k1_ecmult_context *ecmult_ctx, const secp256k1_scalar *s, const secp256k1_scalar *e, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2) { static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scalar *e, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2) {
secp256k1_scalar e_neg; secp256k1_scalar e_neg;
secp256k1_scalar e_expected; secp256k1_scalar e_expected;
secp256k1_gej gen2j; secp256k1_gej gen2j;
@ -140,11 +140,11 @@ static int secp256k1_dleq_verify(const secp256k1_ecmult_context *ecmult_ctx, con
secp256k1_scalar_negate(&e_neg, e); secp256k1_scalar_negate(&e_neg, e);
/* R1 = s*G - e*P1 */ /* R1 = s*G - e*P1 */
secp256k1_ecmult(ecmult_ctx, &r1j, &p1j, &e_neg, s); secp256k1_ecmult(&r1j, &p1j, &e_neg, s);
/* R2 = s*gen2 - e*P2 */ /* R2 = s*gen2 - e*P2 */
secp256k1_ecmult(ecmult_ctx, &tmpj, &p2j, &e_neg, &secp256k1_scalar_zero); secp256k1_ecmult(&tmpj, &p2j, &e_neg, &secp256k1_scalar_zero);
secp256k1_gej_set_ge(&gen2j, gen2); secp256k1_gej_set_ge(&gen2j, gen2);
secp256k1_ecmult(ecmult_ctx, &r2j, &gen2j, s, &secp256k1_scalar_zero); secp256k1_ecmult(&r2j, &gen2j, s, &secp256k1_scalar_zero);
secp256k1_gej_add_var(&r2j, &r2j, &tmpj, NULL); secp256k1_gej_add_var(&r2j, &r2j, &tmpj, NULL);
secp256k1_ge_set_gej(&r1, &r1j); secp256k1_ge_set_gej(&r1, &r1j);

View File

@ -236,7 +236,6 @@ int secp256k1_ecdsa_adaptor_verify(const secp256k1_context* ctx, const unsigned
secp256k1_gej pubkeyj; secp256k1_gej pubkeyj;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(adaptor_sig162 != NULL); ARG_CHECK(adaptor_sig162 != NULL);
ARG_CHECK(pubkey != NULL); ARG_CHECK(pubkey != NULL);
ARG_CHECK(msg32 != NULL); ARG_CHECK(msg32 != NULL);
@ -249,7 +248,7 @@ int secp256k1_ecdsa_adaptor_verify(const secp256k1_context* ctx, const unsigned
return 0; return 0;
} }
/* DLEQ_verify((R', Y, R), dleq_proof) */ /* DLEQ_verify((R', Y, R), dleq_proof) */
if(!secp256k1_dleq_verify(&ctx->ecmult_ctx, &dleq_proof_s, &dleq_proof_e, &rp, &enckey_ge, &r)) { if(!secp256k1_dleq_verify(&dleq_proof_s, &dleq_proof_e, &rp, &enckey_ge, &r)) {
return 0; return 0;
} }
secp256k1_scalar_set_b32(&msg, msg32, NULL); secp256k1_scalar_set_b32(&msg, msg32, NULL);
@ -262,7 +261,7 @@ int secp256k1_ecdsa_adaptor_verify(const secp256k1_context* ctx, const unsigned
secp256k1_scalar_mul(&u1, &sn, &msg); secp256k1_scalar_mul(&u1, &sn, &msg);
secp256k1_scalar_mul(&u2, &sn, &sigr); secp256k1_scalar_mul(&u2, &sn, &sigr);
secp256k1_gej_set_ge(&pubkeyj, &pubkey_ge); secp256k1_gej_set_ge(&pubkeyj, &pubkey_ge);
secp256k1_ecmult(&ctx->ecmult_ctx, &derived_rp, &pubkeyj, &u2, &u1); secp256k1_ecmult(&derived_rp, &pubkeyj, &u2, &u1);
if (secp256k1_gej_is_infinity(&derived_rp)) { if (secp256k1_gej_is_infinity(&derived_rp)) {
return 0; return 0;
} }

View File

@ -43,20 +43,20 @@ void dleq_tests(void) {
rand_scalar(&sk); rand_scalar(&sk);
secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, &p1, &p2, &sk, &gen2); secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, &p1, &p2, &sk, &gen2);
CHECK(secp256k1_dleq_prove(ctx, &s, &e, &sk, &gen2, &p1, &p2, NULL, NULL) == 1); CHECK(secp256k1_dleq_prove(ctx, &s, &e, &sk, &gen2, &p1, &p2, NULL, NULL) == 1);
CHECK(secp256k1_dleq_verify(&ctx->ecmult_ctx, &s, &e, &p1, &gen2, &p2) == 1); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p2) == 1);
{ {
secp256k1_scalar tmp; secp256k1_scalar tmp;
secp256k1_scalar_set_int(&tmp, 1); secp256k1_scalar_set_int(&tmp, 1);
CHECK(secp256k1_dleq_verify(&ctx->ecmult_ctx, &tmp, &e, &p1, &gen2, &p2) == 0); CHECK(secp256k1_dleq_verify(&tmp, &e, &p1, &gen2, &p2) == 0);
CHECK(secp256k1_dleq_verify(&ctx->ecmult_ctx, &s, &tmp, &p1, &gen2, &p2) == 0); CHECK(secp256k1_dleq_verify(&s, &tmp, &p1, &gen2, &p2) == 0);
} }
{ {
secp256k1_ge p_tmp; secp256k1_ge p_tmp;
rand_point(&p_tmp); rand_point(&p_tmp);
CHECK(secp256k1_dleq_verify(&ctx->ecmult_ctx, &s, &e, &p_tmp, &gen2, &p2) == 0); CHECK(secp256k1_dleq_verify(&s, &e, &p_tmp, &gen2, &p2) == 0);
CHECK(secp256k1_dleq_verify(&ctx->ecmult_ctx, &s, &e, &p1, &p_tmp, &p2) == 0); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &p_tmp, &p2) == 0);
CHECK(secp256k1_dleq_verify(&ctx->ecmult_ctx, &s, &e, &p1, &gen2, &p_tmp) == 0); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p_tmp) == 0);
} }
{ {
secp256k1_ge p_inf; secp256k1_ge p_inf;
@ -867,24 +867,22 @@ void test_ecdsa_adaptor_api(void) {
ecount = 0; ecount = 0;
CHECK(secp256k1_ecdsa_adaptor_encrypt(sign, asig, sk, &enckey, msg, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_adaptor_encrypt(sign, asig, sk, &enckey, msg, NULL, NULL) == 1);
CHECK(secp256k1_ecdsa_adaptor_verify(none, asig, &pubkey, msg, &enckey) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(none, asig, &pubkey, msg, &enckey) == 1);
CHECK(ecount == 1); CHECK(secp256k1_ecdsa_adaptor_verify(sign, asig, &pubkey, msg, &enckey) == 1);
CHECK(secp256k1_ecdsa_adaptor_verify(sign, asig, &pubkey, msg, &enckey) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, msg, &enckey) == 1); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, msg, &enckey) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, NULL, &pubkey, msg, &enckey) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, NULL, &pubkey, msg, &enckey) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, NULL, &enckey) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, NULL, &enckey) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, msg, NULL) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, msg, NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, NULL, msg, &enckey) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, NULL, msg, &enckey) == 0);
CHECK(ecount == 6); CHECK(ecount == 4);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &zero_pk, msg, &enckey) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &zero_pk, msg, &enckey) == 0);
CHECK(ecount == 7); CHECK(ecount == 5);
CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, msg, &zero_pk) == 0); CHECK(secp256k1_ecdsa_adaptor_verify(vrfy, asig, &pubkey, msg, &zero_pk) == 0);
CHECK(ecount == 8); CHECK(ecount == 6);
ecount = 0; ecount = 0;
CHECK(secp256k1_ecdsa_adaptor_decrypt(none, &sig, deckey, asig) == 1); CHECK(secp256k1_ecdsa_adaptor_decrypt(none, &sig, deckey, asig) == 1);
@ -1158,11 +1156,11 @@ void multi_hop_lock_tests(void) {
secp256k1_scalar_add(&tp, &t1, &t2); secp256k1_scalar_add(&tp, &t1, &t2);
/* Left lock */ /* Left lock */
secp256k1_pubkey_load(ctx, &l_ge, &pubkey_pop); secp256k1_pubkey_load(ctx, &l_ge, &pubkey_pop);
CHECK(secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &l_ge, &t1)); CHECK(secp256k1_eckey_pubkey_tweak_add(&l_ge, &t1));
secp256k1_pubkey_save(&l, &l_ge); secp256k1_pubkey_save(&l, &l_ge);
/* Right lock */ /* Right lock */
secp256k1_pubkey_load(ctx, &r_ge, &pubkey_pop); secp256k1_pubkey_load(ctx, &r_ge, &pubkey_pop);
CHECK(secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &r_ge, &tp)); CHECK(secp256k1_eckey_pubkey_tweak_add(&r_ge, &tp));
secp256k1_pubkey_save(&r, &r_ge); secp256k1_pubkey_save(&r, &r_ge);
CHECK(secp256k1_ecdsa_adaptor_encrypt(ctx, asig_ab, seckey_a, &l, tx_ab, NULL, NULL)); CHECK(secp256k1_ecdsa_adaptor_encrypt(ctx, asig_ab, seckey_a, &l, tx_ab, NULL, NULL));

View File

@ -103,7 +103,6 @@ int secp256k1_ecdsa_s2c_verify_commit(const secp256k1_context* ctx, const secp25
secp256k1_sha256 s2c_sha; secp256k1_sha256 s2c_sha;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(data32 != NULL); ARG_CHECK(data32 != NULL);
ARG_CHECK(opening != NULL); ARG_CHECK(opening != NULL);
@ -112,7 +111,7 @@ int secp256k1_ecdsa_s2c_verify_commit(const secp256k1_context* ctx, const secp25
return 0; return 0;
} }
secp256k1_s2c_ecdsa_point_sha256_tagged(&s2c_sha); secp256k1_s2c_ecdsa_point_sha256_tagged(&s2c_sha);
if (!secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment_ge, &original_pubnonce_ge, &s2c_sha, data32, 32)) { if (!secp256k1_ec_commit(&commitment_ge, &original_pubnonce_ge, &s2c_sha, data32, 32)) {
return 0; return 0;
} }

View File

@ -137,14 +137,12 @@ static void test_ecdsa_s2c_api(void) {
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_ecdsa_s2c_verify_commit(both, &sig, s2c_data, NULL) == 0); CHECK(secp256k1_ecdsa_s2c_verify_commit(both, &sig, s2c_data, NULL) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_ecdsa_s2c_verify_commit(none, &sig, s2c_data, &s2c_opening) == 0); CHECK(secp256k1_ecdsa_s2c_verify_commit(none, &sig, s2c_data, &s2c_opening) == 1);
CHECK(ecount == 4); CHECK(secp256k1_ecdsa_s2c_verify_commit(sign, &sig, s2c_data, &s2c_opening) == 1);
CHECK(secp256k1_ecdsa_s2c_verify_commit(sign, &sig, s2c_data, &s2c_opening) == 0);
CHECK(ecount == 5);
CHECK(secp256k1_ecdsa_s2c_verify_commit(vrfy, &sig, s2c_data, &s2c_opening) == 1); CHECK(secp256k1_ecdsa_s2c_verify_commit(vrfy, &sig, s2c_data, &s2c_opening) == 1);
CHECK(ecount == 5); CHECK(ecount == 3);
CHECK(secp256k1_ecdsa_s2c_verify_commit(vrfy, &sig, sec, &s2c_opening) == 0); CHECK(secp256k1_ecdsa_s2c_verify_commit(vrfy, &sig, sec, &s2c_opening) == 0);
CHECK(ecount == 5); /* wrong data is not an API error */ CHECK(ecount == 3); /* wrong data is not an API error */
/* Signing with NULL s2c_opening gives the same result */ /* Signing with NULL s2c_opening gives the same result */
CHECK(secp256k1_ecdsa_s2c_sign(sign, &sig, NULL, msg, sec, s2c_data) == 1); CHECK(secp256k1_ecdsa_s2c_sign(sign, &sig, NULL, msg, sec, s2c_data) == 1);
@ -202,12 +200,10 @@ static void test_ecdsa_s2c_api(void) {
CHECK(ecount == 4); CHECK(ecount == 4);
CHECK(secp256k1_anti_exfil_host_verify(both, &sig, msg, &pk, hostrand, NULL) == 0); CHECK(secp256k1_anti_exfil_host_verify(both, &sig, msg, &pk, hostrand, NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 5);
CHECK(secp256k1_anti_exfil_host_verify(none, &sig, msg, &pk, hostrand, &s2c_opening) == 0); CHECK(secp256k1_anti_exfil_host_verify(none, &sig, msg, &pk, hostrand, &s2c_opening) == 1);
CHECK(ecount == 6); CHECK(secp256k1_anti_exfil_host_verify(sign, &sig, msg, &pk, hostrand, &s2c_opening) == 1);
CHECK(secp256k1_anti_exfil_host_verify(sign, &sig, msg, &pk, hostrand, &s2c_opening) == 0);
CHECK(ecount == 7);
CHECK(secp256k1_anti_exfil_host_verify(vrfy, &sig, msg, &pk, hostrand, &s2c_opening) == 1); CHECK(secp256k1_anti_exfil_host_verify(vrfy, &sig, msg, &pk, hostrand, &s2c_opening) == 1);
CHECK(ecount == 7); CHECK(ecount == 5);
secp256k1_context_destroy(both); secp256k1_context_destroy(both);
secp256k1_context_destroy(vrfy); secp256k1_context_destroy(vrfy);

View File

@ -121,12 +121,11 @@ int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pub
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(output_pubkey != NULL); ARG_CHECK(output_pubkey != NULL);
memset(output_pubkey, 0, sizeof(*output_pubkey)); memset(output_pubkey, 0, sizeof(*output_pubkey));
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(internal_pubkey != NULL);
ARG_CHECK(tweak32 != NULL); ARG_CHECK(tweak32 != NULL);
if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
|| !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { || !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
return 0; return 0;
} }
secp256k1_pubkey_save(output_pubkey, &pk); secp256k1_pubkey_save(output_pubkey, &pk);
@ -138,13 +137,12 @@ int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const u
unsigned char pk_expected32[32]; unsigned char pk_expected32[32];
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(internal_pubkey != NULL);
ARG_CHECK(tweaked_pubkey32 != NULL); ARG_CHECK(tweaked_pubkey32 != NULL);
ARG_CHECK(tweak32 != NULL); ARG_CHECK(tweak32 != NULL);
if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
|| !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { || !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) {
return 0; return 0;
} }
secp256k1_fe_normalize_var(&pk.x); secp256k1_fe_normalize_var(&pk.x);
@ -283,7 +281,6 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke
int ret; int ret;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(keypair != NULL); ARG_CHECK(keypair != NULL);
ARG_CHECK(tweak32 != NULL); ARG_CHECK(tweak32 != NULL);
@ -296,7 +293,7 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke
} }
ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32); ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32);
ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32); ret &= secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32);
secp256k1_declassify(ctx, &ret, sizeof(ret)); secp256k1_declassify(ctx, &ret, sizeof(ret));
if (ret) { if (ret) {

View File

@ -197,19 +197,19 @@ void test_xonly_pubkey_tweak(void) {
CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
ecount = 0; ecount = 0;
CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 1); CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
/* NULL internal_xonly_pk zeroes the output_pk */ /* NULL internal_xonly_pk zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
/* NULL tweak zeroes the output_pk */ /* NULL tweak zeroes the output_pk */
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
@ -274,20 +274,20 @@ void test_xonly_pubkey_tweak_check(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 1); CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
/* invalid pk_parity value */ /* invalid pk_parity value */
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
memset(tweak, 1, sizeof(tweak)); memset(tweak, 1, sizeof(tweak));
CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1);
@ -306,7 +306,7 @@ void test_xonly_pubkey_tweak_check(void) {
CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
secp256k1_context_destroy(sign); secp256k1_context_destroy(sign);
@ -479,15 +479,15 @@ void test_keypair_add(void) {
memset(overflows, 0xFF, 32); memset(overflows, 0xFF, 32);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 1);
CHECK(ecount == 1); CHECK(ecount == 0);
CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
/* This does not set the keypair to zeroes */ /* This does not set the keypair to zeroes */
CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);

View File

@ -125,7 +125,6 @@ int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scrat
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(combined_pk != NULL); ARG_CHECK(combined_pk != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(pubkeys != NULL); ARG_CHECK(pubkeys != NULL);
ARG_CHECK(n_pubkeys > 0); ARG_CHECK(n_pubkeys > 0);
@ -147,7 +146,7 @@ int secp256k1_musig_pubkey_combine(const secp256k1_context* ctx, secp256k1_scrat
if (!secp256k1_musig_compute_ell(ctx, ecmult_data.ell, pubkeys, n_pubkeys)) { if (!secp256k1_musig_compute_ell(ctx, ecmult_data.ell, pubkeys, n_pubkeys)) {
return 0; return 0;
} }
if (!secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &pkj, NULL, secp256k1_musig_pubkey_combine_callback, (void *) &ecmult_data, n_pubkeys)) { if (!secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &pkj, NULL, secp256k1_musig_pubkey_combine_callback, (void *) &ecmult_data, n_pubkeys)) {
/* The current implementation of ecmult_multi_var makes this code unreachable with tests. */ /* The current implementation of ecmult_multi_var makes this code unreachable with tests. */
return 0; return 0;
} }
@ -617,7 +616,6 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
int overflow; int overflow;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(session != NULL); ARG_CHECK(session != NULL);
ARG_CHECK(signer != NULL); ARG_CHECK(signer != NULL);
ARG_CHECK(partial_sig != NULL); ARG_CHECK(partial_sig != NULL);
@ -661,7 +659,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2
secp256k1_scalar_negate(&e, &e); secp256k1_scalar_negate(&e, &e);
secp256k1_gej_set_ge(&pkj, &pkp); secp256k1_gej_set_ge(&pkj, &pkp);
secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s); secp256k1_ecmult(&rj, &pkj, &e, &s);
if (!session->combined_nonce_parity) { if (!session->combined_nonce_parity) {
secp256k1_ge_neg(&rp, &rp); secp256k1_ge_neg(&rp, &rp);

View File

@ -159,34 +159,29 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
/* Key combination */ /* Key combination */
ecount = 0; ecount = 0;
CHECK(secp256k1_musig_pubkey_combine(none, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 0); CHECK(secp256k1_musig_pubkey_combine(none, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(ecount == 1); CHECK(secp256k1_musig_pubkey_combine(sign, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(sign, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(ecount == 2);
/* pubkey_combine does not require a scratch space */ /* pubkey_combine does not require a scratch space */
CHECK(secp256k1_musig_pubkey_combine(vrfy, NULL, &combined_pk, &pre_session, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(vrfy, NULL, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(ecount == 2);
/* A small scratch space works too, but will result in using an ineffecient algorithm */ /* A small scratch space works too, but will result in using an ineffecient algorithm */
scratch_small = secp256k1_scratch_space_create(ctx, 1); scratch_small = secp256k1_scratch_space_create(ctx, 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch_small, &combined_pk, &pre_session, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch_small, &combined_pk, &pre_session, pk_ptr, 2) == 1);
secp256k1_scratch_space_destroy(ctx, scratch_small); secp256k1_scratch_space_destroy(ctx, scratch_small);
CHECK(ecount == 2);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, NULL, &pre_session, pk_ptr, 2) == 0); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, NULL, &pre_session, pk_ptr, 2) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, NULL, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, NULL, pk_ptr, 2) == 1);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, NULL, 2) == 0); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, NULL, 2) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, invalid_pk_ptr2, 2) == 0); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, invalid_pk_ptr2, 2) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, invalid_pk_ptr3, 3) == 0); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, invalid_pk_ptr3, 3) == 0);
CHECK(ecount == 6); CHECK(ecount == 4);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 0) == 0); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 0) == 0);
CHECK(ecount == 7); CHECK(ecount == 5);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, NULL, 0) == 0); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, NULL, 0) == 0);
CHECK(ecount == 8); CHECK(ecount == 6);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_combine(vrfy, scratch, &combined_pk, &pre_session, pk_ptr, 2) == 1);
@ -201,31 +196,30 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_musig_pubkey_tweak_add(ctx, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1); CHECK(secp256k1_musig_pubkey_tweak_add(ctx, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1);
/* Reset pre_session */ /* Reset pre_session */
tmp_pre_session = pre_session; tmp_pre_session = pre_session;
CHECK(secp256k1_musig_pubkey_tweak_add(none, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(none, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1);
CHECK(ecount == 1); tmp_pre_session = pre_session;
CHECK(secp256k1_musig_pubkey_tweak_add(sign, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(sign, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1);
CHECK(ecount == 2); tmp_pre_session = pre_session;
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1);
CHECK(ecount == 2);
tmp_pre_session = pre_session; tmp_pre_session = pre_session;
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, NULL, &tmp_output_pk, &tmp_internal_pk, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, NULL, &tmp_output_pk, &tmp_internal_pk, tweak) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
/* Uninitialized pre_session */ /* Uninitialized pre_session */
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &pre_session_uninitialized, &tmp_output_pk, &tmp_internal_pk, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &pre_session_uninitialized, &tmp_output_pk, &tmp_internal_pk, tweak) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
/* Using the same pre_session twice does not work */ /* Using the same pre_session twice does not work */
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 1);
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, tweak) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
tmp_pre_session = pre_session; tmp_pre_session = pre_session;
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, NULL, &tmp_internal_pk, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, NULL, &tmp_internal_pk, tweak) == 0);
CHECK(ecount == 6); CHECK(ecount == 4);
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, NULL, tweak) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, NULL, tweak) == 0);
CHECK(ecount == 7); CHECK(ecount == 5);
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, NULL) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, NULL) == 0);
CHECK(ecount == 8); CHECK(ecount == 6);
CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, ones) == 0); CHECK(secp256k1_musig_pubkey_tweak_add(vrfy, &tmp_pre_session, &tmp_output_pk, &tmp_internal_pk, ones) == 0);
CHECK(ecount == 8); CHECK(ecount == 6);
} }
/** Session creation **/ /** Session creation **/
@ -413,27 +407,23 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
/** Partial signature verification */ /** Partial signature verification */
ecount = 0; ecount = 0;
CHECK(secp256k1_musig_partial_sig_verify(none, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(none, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 1);
CHECK(ecount == 1); CHECK(secp256k1_musig_partial_sig_verify(sign, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 1);
CHECK(secp256k1_musig_partial_sig_verify(sign, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 1); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 1);
CHECK(ecount == 2);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[1], &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[1], &pk[0]) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, NULL, &signer0[0], &partial_sig[0], &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, NULL, &signer0[0], &partial_sig[0], &pk[0]) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
/* Unitialized session */ /* Unitialized session */
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session_uninitialized, &signer0[0], &partial_sig[0], &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session_uninitialized, &signer0[0], &partial_sig[0], &pk[0]) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], NULL, &partial_sig[0], &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], NULL, &partial_sig[0], &pk[0]) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], NULL, &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], NULL, &pk[0]) == 0);
CHECK(ecount == 6); CHECK(ecount == 4);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig_overflow, &pk[0]) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig_overflow, &pk[0]) == 0);
CHECK(ecount == 6); CHECK(ecount == 4);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[0], NULL) == 0); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[0], NULL) == 0);
CHECK(ecount == 7); CHECK(ecount == 5);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 1); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[0], &signer0[0], &partial_sig[0], &pk[0]) == 1);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[1], &signer1[0], &partial_sig[0], &pk[0]) == 1); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[1], &signer1[0], &partial_sig[0], &pk[0]) == 1);
@ -441,7 +431,7 @@ void musig_api_tests(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[1], &signer1[1], &partial_sig[1], &pk[1]) == 1); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &session[1], &signer1[1], &partial_sig[1], &pk[1]) == 1);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &verifier_session, &verifier_signer_data[0], &partial_sig[0], &pk[0]) == 1); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &verifier_session, &verifier_signer_data[0], &partial_sig[0], &pk[0]) == 1);
CHECK(secp256k1_musig_partial_sig_verify(vrfy, &verifier_session, &verifier_signer_data[1], &partial_sig[1], &pk[1]) == 1); CHECK(secp256k1_musig_partial_sig_verify(vrfy, &verifier_session, &verifier_signer_data[1], &partial_sig[1], &pk[1]) == 1);
CHECK(ecount == 7); CHECK(ecount == 5);
/** Adaptor signature verification */ /** Adaptor signature verification */
memcpy(&partial_sig_adapted[1], &partial_sig[1], sizeof(partial_sig_adapted[1])); memcpy(&partial_sig_adapted[1], &partial_sig[1], sizeof(partial_sig_adapted[1]));

View File

@ -14,10 +14,10 @@
#include "ecmult.h" #include "ecmult.h"
#include "ecmult_gen.h" #include "ecmult_gen.h"
int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s,
const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen); const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen);
int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen); const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen);

View File

@ -55,7 +55,7 @@ SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const
* | | r_i = r * | | r_i = r
* | return e_0 ==== H(r_{0..i}||m) * | return e_0 ==== H(r_{0..i}||m)
*/ */
int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0, int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0,
const secp256k1_scalar *s, const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen) { const secp256k1_scalar *s, const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen) {
secp256k1_gej rgej; secp256k1_gej rgej;
secp256k1_ge rge; secp256k1_ge rge;
@ -67,7 +67,6 @@ int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp2
size_t count; size_t count;
size_t size; size_t size;
int overflow; int overflow;
VERIFY_CHECK(ecmult_ctx != NULL);
VERIFY_CHECK(e0 != NULL); VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL); VERIFY_CHECK(s != NULL);
VERIFY_CHECK(pubs != NULL); VERIFY_CHECK(pubs != NULL);
@ -88,7 +87,7 @@ int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp2
/*If requested, save the challenges for proof rewind.*/ /*If requested, save the challenges for proof rewind.*/
evalues[count] = ens; evalues[count] = ens;
} }
secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count], &ens, &s[count]); secp256k1_ecmult(&rgej, &pubs[count], &ens, &s[count]);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej)) {
return 0; return 0;
} }
@ -109,7 +108,7 @@ int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp2
return memcmp(e0, tmp, 32) == 0; return memcmp(e0, tmp, 32) == 0;
} }
int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) { const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) {
secp256k1_gej rgej; secp256k1_gej rgej;
@ -122,7 +121,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const s
size_t count; size_t count;
size_t size; size_t size;
int overflow; int overflow;
VERIFY_CHECK(ecmult_ctx != NULL);
VERIFY_CHECK(ecmult_gen_ctx != NULL); VERIFY_CHECK(ecmult_gen_ctx != NULL);
VERIFY_CHECK(e0 != NULL); VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL); VERIFY_CHECK(s != NULL);
@ -153,7 +151,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const s
* leaks which members are non-forgeries. That the forgeries themselves are variable time may leave * leaks which members are non-forgeries. That the forgeries themselves are variable time may leave
* an additional privacy impacting timing side-channel, but not a key loss one. * an additional privacy impacting timing side-channel, but not a key loss one.
*/ */
secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]); secp256k1_ecmult(&rgej, &pubs[count + j], &ens, &s[count + j]);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej)) {
return 0; return 0;
} }
@ -174,7 +172,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_context* ecmult_ctx, const s
return 0; return 0;
} }
for (j = 0; j < secidx[i]; j++) { for (j = 0; j < secidx[i]; j++) {
secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]); secp256k1_ecmult(&rgej, &pubs[count + j], &ens, &s[count + j]);
if (secp256k1_gej_is_infinity(&rgej)) { if (secp256k1_gej_is_infinity(&rgej)) {
return 0; return 0;
} }

View File

@ -259,11 +259,10 @@ int secp256k1_rangeproof_rewind(const secp256k1_context* ctx,
ARG_CHECK(nonce != NULL); ARG_CHECK(nonce != NULL);
ARG_CHECK(extra_commit != NULL || extra_commit_len == 0); ARG_CHECK(extra_commit != NULL || extra_commit_len == 0);
ARG_CHECK(gen != NULL); ARG_CHECK(gen != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
secp256k1_pedersen_commitment_load(&commitp, commit); secp256k1_pedersen_commitment_load(&commitp, commit);
secp256k1_generator_load(&genp, gen); secp256k1_generator_load(&genp, gen);
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, return secp256k1_rangeproof_verify_impl(&ctx->ecmult_gen_ctx,
blind_out, value_out, message_out, outlen, nonce, min_value, max_value, &commitp, proof, plen, extra_commit, extra_commit_len, &genp); blind_out, value_out, message_out, outlen, nonce, min_value, max_value, &commitp, proof, plen, extra_commit, extra_commit_len, &genp);
} }
@ -278,10 +277,9 @@ int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_valu
ARG_CHECK(max_value != NULL); ARG_CHECK(max_value != NULL);
ARG_CHECK(extra_commit != NULL || extra_commit_len == 0); ARG_CHECK(extra_commit != NULL || extra_commit_len == 0);
ARG_CHECK(gen != NULL); ARG_CHECK(gen != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
secp256k1_pedersen_commitment_load(&commitp, commit); secp256k1_pedersen_commitment_load(&commitp, commit);
secp256k1_generator_load(&genp, gen); secp256k1_generator_load(&genp, gen);
return secp256k1_rangeproof_verify_impl(&ctx->ecmult_ctx, NULL, return secp256k1_rangeproof_verify_impl(NULL,
NULL, NULL, NULL, NULL, NULL, min_value, max_value, &commitp, proof, plen, extra_commit, extra_commit_len, &genp); NULL, NULL, NULL, NULL, NULL, min_value, max_value, &commitp, proof, plen, extra_commit, extra_commit_len, &genp);
} }
@ -299,11 +297,10 @@ int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof
ARG_CHECK(message != NULL || msg_len == 0); ARG_CHECK(message != NULL || msg_len == 0);
ARG_CHECK(extra_commit != NULL || extra_commit_len == 0); ARG_CHECK(extra_commit != NULL || extra_commit_len == 0);
ARG_CHECK(gen != NULL); ARG_CHECK(gen != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
secp256k1_pedersen_commitment_load(&commitp, commit); secp256k1_pedersen_commitment_load(&commitp, commit);
secp256k1_generator_load(&genp, gen); secp256k1_generator_load(&genp, gen);
return secp256k1_rangeproof_sign_impl(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, return secp256k1_rangeproof_sign_impl(&ctx->ecmult_gen_ctx,
proof, plen, min_value, &commitp, blind, nonce, exp, min_bits, value, message, msg_len, extra_commit, extra_commit_len, &genp); proof, plen, min_value, &commitp, blind, nonce, exp, min_bits, value, message, msg_len, extra_commit, extra_commit_len, &genp);
} }

View File

@ -12,8 +12,7 @@
#include "ecmult.h" #include "ecmult.h"
#include "ecmult_gen.h" #include "ecmult_gen.h"
static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx, static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce, unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce,
uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen, uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen,
const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp); const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp);

View File

@ -189,8 +189,7 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, size_t *rin
} }
/* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */ /* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */
SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_context* ecmult_ctx, SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
unsigned char *proof, size_t *plen, uint64_t min_value, unsigned char *proof, size_t *plen, uint64_t min_value,
const secp256k1_ge *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value, const secp256k1_ge *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value,
const unsigned char *message, size_t msg_len, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp){ const unsigned char *message, size_t msg_len, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp){
@ -322,7 +321,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len); secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len);
} }
secp256k1_sha256_finalize(&sha256_m, tmp); secp256k1_sha256_finalize(&sha256_m, tmp);
if (!secp256k1_borromean_sign(ecmult_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) {
return 0; return 0;
} }
len += 32; len += 32;
@ -538,8 +537,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_getheader_impl(size_t *offset,
} }
/* Verifies range proof (len plen) for commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/ /* Verifies range proof (len plen) for commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/
SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_context* ecmult_ctx, SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
const secp256k1_ecmult_gen_context* ecmult_gen_ctx,
unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce, unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce,
uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp) { uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp) {
secp256k1_gej accj; secp256k1_gej accj;
@ -649,7 +647,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm
secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len); secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len);
} }
secp256k1_sha256_finalize(&sha256_m, m); secp256k1_sha256_finalize(&sha256_m, m);
ret = secp256k1_borromean_verify(ecmult_ctx, nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32); ret = secp256k1_borromean_verify(nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32);
if (ret && nonce) { if (ret && nonce) {
/* Given the nonce, try rewinding the witness to recover its initial state. */ /* Given the nonce, try rewinding the witness to recover its initial state. */
secp256k1_scalar blind; secp256k1_scalar blind;

View File

@ -94,35 +94,34 @@ static void test_rangeproof_api(const secp256k1_context *none, const secp256k1_c
CHECK(secp256k1_rangeproof_sign(none, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(none, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 1); CHECK(*ecount == 1);
CHECK(secp256k1_rangeproof_sign(sign, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(sign, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 1);
CHECK(*ecount == 2);
CHECK(secp256k1_rangeproof_sign(vrfy, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(vrfy, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 3); CHECK(*ecount == 2);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 3); CHECK(*ecount == 2);
CHECK(secp256k1_rangeproof_sign(both, NULL, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, NULL, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 4); CHECK(*ecount == 3);
CHECK(secp256k1_rangeproof_sign(both, proof, NULL, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, NULL, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 5); CHECK(*ecount == 4);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, NULL, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, NULL, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 6); CHECK(*ecount == 5);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, NULL, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, NULL, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 7); CHECK(*ecount == 6);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, NULL, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, NULL, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 8); CHECK(*ecount == 7);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, vmin - 1, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, vmin - 1, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 8); CHECK(*ecount == 7);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 9); CHECK(*ecount == 8);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 9); CHECK(*ecount == 8);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, NULL, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, NULL, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 10); CHECK(*ecount == 9);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, NULL, 0, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, NULL, 0, secp256k1_generator_h) != 0);
CHECK(*ecount == 10); CHECK(*ecount == 9);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, NULL, 0, NULL) == 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, NULL, 0, NULL, 0, NULL) == 0);
CHECK(*ecount == 11); CHECK(*ecount == 10);
CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_sign(both, proof, &len, vmin, &commit, blind, commit.data, 0, 0, val, message, mlen, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
{ {
@ -138,44 +137,42 @@ static void test_rangeproof_api(const secp256k1_context *none, const secp256k1_c
CHECK(max_value >= val); CHECK(max_value >= val);
CHECK(secp256k1_rangeproof_info(none, NULL, &mantissa, &min_value, &max_value, proof, len) == 0); CHECK(secp256k1_rangeproof_info(none, NULL, &mantissa, &min_value, &max_value, proof, len) == 0);
CHECK(*ecount == 12); CHECK(*ecount == 11);
CHECK(secp256k1_rangeproof_info(none, &exp, NULL, &min_value, &max_value, proof, len) == 0); CHECK(secp256k1_rangeproof_info(none, &exp, NULL, &min_value, &max_value, proof, len) == 0);
CHECK(*ecount == 13); CHECK(*ecount == 12);
CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, NULL, &max_value, proof, len) == 0); CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, NULL, &max_value, proof, len) == 0);
CHECK(*ecount == 14); CHECK(*ecount == 13);
CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, &min_value, NULL, proof, len) == 0); CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, &min_value, NULL, proof, len) == 0);
CHECK(*ecount == 15); CHECK(*ecount == 14);
CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, &min_value, &max_value, NULL, len) == 0); CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, &min_value, &max_value, NULL, len) == 0);
CHECK(*ecount == 16); CHECK(*ecount == 15);
CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, &min_value, &max_value, proof, 0) == 0); CHECK(secp256k1_rangeproof_info(none, &exp, &mantissa, &min_value, &max_value, proof, 0) == 0);
CHECK(*ecount == 16); CHECK(*ecount == 15);
} }
{ {
uint64_t min_value; uint64_t min_value;
uint64_t max_value; uint64_t max_value;
CHECK(secp256k1_rangeproof_verify(none, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(none, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 1);
CHECK(*ecount == 17); CHECK(secp256k1_rangeproof_verify(sign, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 1);
CHECK(secp256k1_rangeproof_verify(sign, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 18);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 18); CHECK(*ecount == 15);
CHECK(secp256k1_rangeproof_verify(vrfy, NULL, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, NULL, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 19); CHECK(*ecount == 16);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, NULL, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, NULL, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 20); CHECK(*ecount == 17);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, NULL, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, NULL, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 21); CHECK(*ecount == 18);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, NULL, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, NULL, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 22); CHECK(*ecount == 19);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, 0, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, 0, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 22); CHECK(*ecount == 19);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, NULL, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, NULL, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 23); CHECK(*ecount == 20);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, NULL, 0, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, NULL, 0, secp256k1_generator_h) == 0);
CHECK(*ecount == 23); CHECK(*ecount == 20);
CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, NULL, 0, NULL) == 0); CHECK(secp256k1_rangeproof_verify(vrfy, &min_value, &max_value, &commit, proof, len, NULL, 0, NULL) == 0);
CHECK(*ecount == 24); CHECK(*ecount == 21);
} }
{ {
unsigned char blind_out[32]; unsigned char blind_out[32];
@ -186,13 +183,12 @@ static void test_rangeproof_api(const secp256k1_context *none, const secp256k1_c
size_t message_len = sizeof(message_out); size_t message_len = sizeof(message_out);
CHECK(secp256k1_rangeproof_rewind(none, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(none, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 25); CHECK(*ecount == 22);
CHECK(secp256k1_rangeproof_rewind(sign, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(sign, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 1);
CHECK(*ecount == 26);
CHECK(secp256k1_rangeproof_rewind(vrfy, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(vrfy, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 27); CHECK(*ecount == 23);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 27); CHECK(*ecount == 23);
CHECK(min_value == vmin); CHECK(min_value == vmin);
CHECK(max_value >= val); CHECK(max_value >= val);
@ -201,31 +197,31 @@ static void test_rangeproof_api(const secp256k1_context *none, const secp256k1_c
CHECK(memcmp(message, message_out, sizeof(message_out)) == 0); CHECK(memcmp(message, message_out, sizeof(message_out)) == 0);
CHECK(secp256k1_rangeproof_rewind(both, NULL, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_rewind(both, NULL, &value_out, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 27); /* blindout may be NULL */ CHECK(*ecount == 23); /* blindout may be NULL */
CHECK(secp256k1_rangeproof_rewind(both, blind_out, NULL, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, NULL, message_out, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 27); /* valueout may be NULL */ CHECK(*ecount == 23); /* valueout may be NULL */
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, &message_len, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 28); CHECK(*ecount == 24);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) != 0);
CHECK(*ecount == 28); CHECK(*ecount == 24);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, NULL, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, NULL, &min_value, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 29); CHECK(*ecount == 25);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, NULL, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, NULL, &max_value, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 30); CHECK(*ecount == 26);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, NULL, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, NULL, &commit, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 31); CHECK(*ecount == 27);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, NULL, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, NULL, proof, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 32); CHECK(*ecount == 28);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, NULL, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, NULL, len, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 33); CHECK(*ecount == 29);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, 0, ext_commit, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, 0, ext_commit, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 33); CHECK(*ecount == 29);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, NULL, ext_commit_len, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, NULL, ext_commit_len, secp256k1_generator_h) == 0);
CHECK(*ecount == 34); CHECK(*ecount == 30);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, NULL, 0, secp256k1_generator_h) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, NULL, 0, secp256k1_generator_h) == 0);
CHECK(*ecount == 34); CHECK(*ecount == 30);
CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, NULL, 0, NULL) == 0); CHECK(secp256k1_rangeproof_rewind(both, blind_out, &value_out, NULL, 0, commit.data, &min_value, &max_value, &commit, proof, len, NULL, 0, NULL) == 0);
CHECK(*ecount == 35); CHECK(*ecount == 31);
} }
} }
@ -363,11 +359,11 @@ static void test_borromean(void) {
} }
c += rsizes[i]; c += rsizes[i];
} }
CHECK(secp256k1_borromean_sign(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32)); CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32));
CHECK(secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32)); CHECK(secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32));
i = secp256k1_testrand32() % c; i = secp256k1_testrand32() % c;
secp256k1_scalar_negate(&s[i],&s[i]); secp256k1_scalar_negate(&s[i],&s[i]);
CHECK(!secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32)); CHECK(!secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32));
secp256k1_scalar_negate(&s[i],&s[i]); secp256k1_scalar_negate(&s[i],&s[i]);
secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_set_int(&one, 1);
for(j = 0; j < 4; j++) { for(j = 0; j < 4; j++) {
@ -377,7 +373,7 @@ static void test_borromean(void) {
} else { } else {
secp256k1_scalar_add(&s[i],&s[i],&one); secp256k1_scalar_add(&s[i],&s[i],&one);
} }
CHECK(!secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32)); CHECK(!secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32));
} }
} }

View File

@ -40,7 +40,7 @@ int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context*
int ret = 1; int ret = 1;
int overflow = 0; int overflow = 0;
(void)ctx; VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(input64 != NULL); ARG_CHECK(input64 != NULL);
ARG_CHECK(recid >= 0 && recid <= 3); ARG_CHECK(recid >= 0 && recid <= 3);
@ -60,7 +60,7 @@ int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context*
int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) {
secp256k1_scalar r, s; secp256k1_scalar r, s;
(void)ctx; VERIFY_CHECK(ctx != NULL);
ARG_CHECK(output64 != NULL); ARG_CHECK(output64 != NULL);
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(recid != NULL); ARG_CHECK(recid != NULL);
@ -75,7 +75,7 @@ int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx,
secp256k1_scalar r, s; secp256k1_scalar r, s;
int recid; int recid;
(void)ctx; VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(sigin != NULL); ARG_CHECK(sigin != NULL);
@ -84,7 +84,7 @@ int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx,
return 1; return 1;
} }
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { static int secp256k1_ecdsa_sig_recover(const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) {
unsigned char brx[32]; unsigned char brx[32];
secp256k1_fe fx; secp256k1_fe fx;
secp256k1_ge x; secp256k1_ge x;
@ -115,7 +115,7 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, cons
secp256k1_scalar_mul(&u1, &rn, message); secp256k1_scalar_mul(&u1, &rn, message);
secp256k1_scalar_negate(&u1, &u1); secp256k1_scalar_negate(&u1, &u1);
secp256k1_scalar_mul(&u2, &rn, sigs); secp256k1_scalar_mul(&u2, &rn, sigs);
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1); secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj); secp256k1_ge_set_gej_var(pubkey, &qj);
return !secp256k1_gej_is_infinity(&qj); return !secp256k1_gej_is_infinity(&qj);
} }
@ -140,7 +140,6 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
secp256k1_scalar m; secp256k1_scalar m;
int recid; int recid;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(msghash32 != NULL); ARG_CHECK(msghash32 != NULL);
ARG_CHECK(signature != NULL); ARG_CHECK(signature != NULL);
ARG_CHECK(pubkey != NULL); ARG_CHECK(pubkey != NULL);
@ -148,7 +147,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature);
VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */
secp256k1_scalar_set_b32(&m, msghash32, NULL); secp256k1_scalar_set_b32(&m, msghash32, NULL);
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { if (secp256k1_ecdsa_sig_recover(&r, &s, &q, &m, recid)) {
secp256k1_pubkey_save(pubkey, &q); secp256k1_pubkey_save(pubkey, &q);
return 1; return 1;
} else { } else {

View File

@ -92,20 +92,20 @@ void test_ecdsa_recovery_api(void) {
/* Check bad contexts and NULLs for recovery */ /* Check bad contexts and NULLs for recovery */
ecount = 0; ecount = 0;
CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 1); CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
/* Check NULLs for conversion */ /* Check NULLs for conversion */
CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);

View File

@ -122,7 +122,7 @@ static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned c
secp256k1_scalar_set_b32(e, buf, NULL); secp256k1_scalar_set_b32(e, buf, NULL);
} }
int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) { static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
secp256k1_scalar sk; secp256k1_scalar sk;
secp256k1_scalar e; secp256k1_scalar e;
secp256k1_scalar k; secp256k1_scalar k;
@ -216,7 +216,6 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
int overflow; int overflow;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(sig64 != NULL); ARG_CHECK(sig64 != NULL);
ARG_CHECK(msg != NULL || msglen == 0); ARG_CHECK(msg != NULL || msglen == 0);
ARG_CHECK(pubkey != NULL); ARG_CHECK(pubkey != NULL);
@ -241,7 +240,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
/* Compute rj = s*G + (-e)*pkj */ /* Compute rj = s*G + (-e)*pkj */
secp256k1_scalar_negate(&e, &e); secp256k1_scalar_negate(&e, &e);
secp256k1_gej_set_ge(&pkj, &pk); secp256k1_gej_set_ge(&pkj, &pk);
secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s); secp256k1_ecmult(&rj, &pkj, &e, &s);
secp256k1_ge_set_gej_var(&r, &rj); secp256k1_ge_set_gej_var(&r, &rj);
if (secp256k1_ge_is_infinity(&r)) { if (secp256k1_ge_is_infinity(&r)) {

View File

@ -193,22 +193,22 @@ void test_schnorrsig_api(void) {
ecount = 0; ecount = 0;
CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 0); CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 1); CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 0); CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &pk[0]) == 1); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 2); CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0); CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 3); CHECK(ecount == 1);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0);
CHECK(ecount == 4); CHECK(ecount == 2);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0);
CHECK(ecount == 5); CHECK(ecount == 3);
CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &zero_pk) == 0); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), &zero_pk) == 0);
CHECK(ecount == 6); CHECK(ecount == 4);
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
secp256k1_context_destroy(sign); secp256k1_context_destroy(sign);

View File

@ -288,7 +288,6 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
unsigned char msg32[32]; unsigned char msg32[32];
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
ARG_CHECK(proof != NULL); ARG_CHECK(proof != NULL);
ARG_CHECK(ephemeral_input_tags != NULL); ARG_CHECK(ephemeral_input_tags != NULL);
@ -339,7 +338,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
* homage to the rangeproof code which does this very cleverly to encode messages. */ * homage to the rangeproof code which does this very cleverly to encode messages. */
nonce = borromean_s[ring_input_index]; nonce = borromean_s[ring_input_index];
secp256k1_scalar_clear(&borromean_s[ring_input_index]); secp256k1_scalar_clear(&borromean_s[ring_input_index]);
if (secp256k1_borromean_sign(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) { if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
return 0; return 0;
} }
for (i = 0; i < n_used_pubkeys; i++) { for (i = 0; i < n_used_pubkeys; i++) {
@ -361,7 +360,6 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256
unsigned char msg32[32]; unsigned char msg32[32];
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(proof != NULL); ARG_CHECK(proof != NULL);
ARG_CHECK(ephemeral_input_tags != NULL); ARG_CHECK(ephemeral_input_tags != NULL);
ARG_CHECK(ephemeral_output_tag != NULL); ARG_CHECK(ephemeral_output_tag != NULL);
@ -392,7 +390,7 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256
} }
} }
secp256k1_surjection_genmessage(msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag); secp256k1_surjection_genmessage(msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag);
return secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, &proof->data[0], borromean_s, ring_pubkeys, rsizes, 1, msg32, 32); return secp256k1_borromean_verify(NULL, &proof->data[0], borromean_s, ring_pubkeys, rsizes, 1, msg32, 32);
} }
#endif #endif

View File

@ -124,77 +124,74 @@ static void test_surjectionproof_api(void) {
CHECK(secp256k1_surjectionproof_generate(vrfy, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(vrfy, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 9); CHECK(ecount == 9);
CHECK(secp256k1_surjectionproof_generate(sign, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(sign, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 1);
CHECK(ecount == 10);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) != 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) != 0);
CHECK(ecount == 10); CHECK(ecount == 9);
CHECK(secp256k1_surjectionproof_generate(both, NULL, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, NULL, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 11); CHECK(ecount == 10);
CHECK(secp256k1_surjectionproof_generate(both, &proof, NULL, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, NULL, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 12); CHECK(ecount == 11);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs + 1, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs + 1, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 12); CHECK(ecount == 11);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs - 1, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs - 1, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 12); CHECK(ecount == 11);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, 0, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, 0, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 12); CHECK(ecount == 11);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, NULL, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, NULL, 0, input_blinding_key[0], output_blinding_key) == 0);
CHECK(ecount == 13); CHECK(ecount == 12);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 1, input_blinding_key[0], output_blinding_key) != 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 1, input_blinding_key[0], output_blinding_key) != 0);
CHECK(ecount == 13); /* the above line "succeeds" but generates an invalid proof as the input_index is wrong. it is fairly expensive to detect this. should we? */ CHECK(ecount == 12); /* the above line "succeeds" but generates an invalid proof as the input_index is wrong. it is fairly expensive to detect this. should we? */
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, n_inputs + 1, input_blinding_key[0], output_blinding_key) != 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, n_inputs + 1, input_blinding_key[0], output_blinding_key) != 0);
CHECK(ecount == 13); CHECK(ecount == 12);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, NULL, output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, NULL, output_blinding_key) == 0);
CHECK(ecount == 14); CHECK(ecount == 13);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], NULL) == 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], NULL) == 0);
CHECK(ecount == 15); CHECK(ecount == 14);
CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) != 0); CHECK(secp256k1_surjectionproof_generate(both, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) != 0);
/* check verify */ /* check verify */
CHECK(secp256k1_surjectionproof_verify(none, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 0); CHECK(secp256k1_surjectionproof_verify(none, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 1);
CHECK(ecount == 16); CHECK(secp256k1_surjectionproof_verify(sign, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 1);
CHECK(secp256k1_surjectionproof_verify(sign, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 0); CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 1);
CHECK(ecount == 17); CHECK(ecount == 14);
CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) != 0);
CHECK(ecount == 17);
CHECK(secp256k1_surjectionproof_verify(vrfy, NULL, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 0); CHECK(secp256k1_surjectionproof_verify(vrfy, NULL, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 0);
CHECK(ecount == 18); CHECK(ecount == 15);
CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, NULL, n_inputs, &ephemeral_output_tag) == 0); CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, NULL, n_inputs, &ephemeral_output_tag) == 0);
CHECK(ecount == 19); CHECK(ecount == 16);
CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs - 1, &ephemeral_output_tag) == 0); CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs - 1, &ephemeral_output_tag) == 0);
CHECK(ecount == 19); CHECK(ecount == 16);
CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs + 1, &ephemeral_output_tag) == 0); CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs + 1, &ephemeral_output_tag) == 0);
CHECK(ecount == 19); CHECK(ecount == 16);
CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs, NULL) == 0); CHECK(secp256k1_surjectionproof_verify(vrfy, &proof, ephemeral_input_tags, n_inputs, NULL) == 0);
CHECK(ecount == 20); CHECK(ecount == 17);
/* Check serialize */ /* Check serialize */
serialized_len = sizeof(serialized_proof); serialized_len = sizeof(serialized_proof);
CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, &serialized_len, &proof) != 0); CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, &serialized_len, &proof) != 0);
CHECK(ecount == 20); CHECK(ecount == 17);
serialized_len = sizeof(serialized_proof); serialized_len = sizeof(serialized_proof);
CHECK(secp256k1_surjectionproof_serialize(none, NULL, &serialized_len, &proof) == 0); CHECK(secp256k1_surjectionproof_serialize(none, NULL, &serialized_len, &proof) == 0);
CHECK(ecount == 21); CHECK(ecount == 18);
serialized_len = sizeof(serialized_proof); serialized_len = sizeof(serialized_proof);
CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, NULL, &proof) == 0); CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, NULL, &proof) == 0);
CHECK(ecount == 22); CHECK(ecount == 19);
serialized_len = sizeof(serialized_proof); serialized_len = sizeof(serialized_proof);
CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, &serialized_len, NULL) == 0); CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, &serialized_len, NULL) == 0);
CHECK(ecount == 23); CHECK(ecount == 20);
serialized_len = sizeof(serialized_proof); serialized_len = sizeof(serialized_proof);
CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, &serialized_len, &proof) != 0); CHECK(secp256k1_surjectionproof_serialize(none, serialized_proof, &serialized_len, &proof) != 0);
/* Check parse */ /* Check parse */
CHECK(secp256k1_surjectionproof_parse(none, &proof, serialized_proof, serialized_len) != 0); CHECK(secp256k1_surjectionproof_parse(none, &proof, serialized_proof, serialized_len) != 0);
CHECK(ecount == 23); CHECK(ecount == 20);
CHECK(secp256k1_surjectionproof_parse(none, NULL, serialized_proof, serialized_len) == 0); CHECK(secp256k1_surjectionproof_parse(none, NULL, serialized_proof, serialized_len) == 0);
CHECK(ecount == 24); CHECK(ecount == 21);
CHECK(secp256k1_surjectionproof_parse(none, &proof, NULL, serialized_len) == 0); CHECK(secp256k1_surjectionproof_parse(none, &proof, NULL, serialized_len) == 0);
CHECK(ecount == 25); CHECK(ecount == 22);
CHECK(secp256k1_surjectionproof_parse(none, &proof, serialized_proof, 0) == 0); CHECK(secp256k1_surjectionproof_parse(none, &proof, serialized_proof, 0) == 0);
CHECK(ecount == 25); CHECK(ecount == 22);
secp256k1_context_destroy(none); secp256k1_context_destroy(none);
secp256k1_context_destroy(sign); secp256k1_context_destroy(sign);

View File

@ -25,7 +25,6 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
/* Sanity checks */ /* Sanity checks */
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(online_pubkeys != NULL); ARG_CHECK(online_pubkeys != NULL);
@ -90,7 +89,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
/* Actually sign */ /* Actually sign */
if (ret) { if (ret) {
sig->n_keys = n_keys; sig->n_keys = n_keys;
ret = secp256k1_borromean_sign(&ctx->ecmult_ctx, &ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32); ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32);
/* Signing will change s[index], so update in the sig structure */ /* Signing will change s[index], so update in the sig structure */
secp256k1_scalar_get_b32(&sig->data[32 * (index + 1)], &s[index]); secp256k1_scalar_get_b32(&sig->data[32 * (index + 1)], &s[index]);
} }
@ -107,7 +106,6 @@ int secp256k1_whitelist_verify(const secp256k1_context* ctx, const secp256k1_whi
size_t i; size_t i;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(online_pubkeys != NULL); ARG_CHECK(online_pubkeys != NULL);
ARG_CHECK(offline_pubkeys != NULL); ARG_CHECK(offline_pubkeys != NULL);
@ -129,7 +127,7 @@ int secp256k1_whitelist_verify(const secp256k1_context* ctx, const secp256k1_whi
return 0; return 0;
} }
/* Do verification */ /* Do verification */
return secp256k1_borromean_verify(&ctx->ecmult_ctx, NULL, &sig->data[0], s, pubs, &sig->n_keys, 1, msg32, 32); return secp256k1_borromean_verify(NULL, &sig->data[0], s, pubs, &sig->n_keys, 1, msg32, 32);
} }
size_t secp256k1_whitelist_signature_n_keys(const secp256k1_whitelist_signature *sig) { size_t secp256k1_whitelist_signature_n_keys(const secp256k1_whitelist_signature *sig) {

View File

@ -33,7 +33,7 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g
return 1; return 1;
} }
static int secp256k1_whitelist_tweak_pubkey(const secp256k1_context* ctx, secp256k1_gej* pub_tweaked) { static int secp256k1_whitelist_tweak_pubkey(secp256k1_gej* pub_tweaked) {
secp256k1_scalar tweak; secp256k1_scalar tweak;
secp256k1_scalar zero; secp256k1_scalar zero;
int ret; int ret;
@ -42,7 +42,7 @@ static int secp256k1_whitelist_tweak_pubkey(const secp256k1_context* ctx, secp25
ret = secp256k1_whitelist_hash_pubkey(&tweak, pub_tweaked); ret = secp256k1_whitelist_hash_pubkey(&tweak, pub_tweaked);
if (ret) { if (ret) {
secp256k1_ecmult(&ctx->ecmult_ctx, pub_tweaked, pub_tweaked, &tweak, &zero); secp256k1_ecmult(pub_tweaked, pub_tweaked, &tweak, &zero);
} }
return ret; return ret;
} }
@ -118,7 +118,7 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context*
/* compute tweaked keys */ /* compute tweaked keys */
secp256k1_gej_set_ge(&tweaked_gej, &offline_ge); secp256k1_gej_set_ge(&tweaked_gej, &offline_ge);
secp256k1_gej_add_ge_var(&tweaked_gej, &tweaked_gej, &subkey_ge, NULL); secp256k1_gej_add_ge_var(&tweaked_gej, &tweaked_gej, &subkey_ge, NULL);
secp256k1_whitelist_tweak_pubkey(ctx, &tweaked_gej); secp256k1_whitelist_tweak_pubkey(&tweaked_gej);
secp256k1_gej_add_ge_var(&keys[i], &tweaked_gej, &online_ge, NULL); secp256k1_gej_add_ge_var(&keys[i], &tweaked_gej, &online_ge, NULL);
} }
secp256k1_sha256_finalize(&sha, msg32); secp256k1_sha256_finalize(&sha, msg32);

View File

@ -96,7 +96,6 @@ static const secp256k1_callback default_error_callback = {
}; };
struct secp256k1_context_struct { struct secp256k1_context_struct {
secp256k1_ecmult_context ecmult_ctx;
secp256k1_ecmult_gen_context ecmult_gen_ctx; secp256k1_ecmult_gen_context ecmult_gen_ctx;
secp256k1_callback illegal_callback; secp256k1_callback illegal_callback;
secp256k1_callback error_callback; secp256k1_callback error_callback;
@ -104,7 +103,6 @@ struct secp256k1_context_struct {
}; };
static const secp256k1_context secp256k1_context_no_precomp_ = { static const secp256k1_context secp256k1_context_no_precomp_ = {
{ 0 },
{ 0 }, { 0 },
{ secp256k1_default_illegal_callback_fn, 0 }, { secp256k1_default_illegal_callback_fn, 0 },
{ secp256k1_default_error_callback_fn, 0 }, { secp256k1_default_error_callback_fn, 0 },
@ -126,9 +124,6 @@ size_t secp256k1_context_preallocated_size(unsigned int flags) {
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
} }
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
}
return ret; return ret;
} }
@ -138,9 +133,6 @@ size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
} }
if (secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)) {
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
}
return ret; return ret;
} }
@ -162,7 +154,6 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
ret->illegal_callback = default_illegal_callback; ret->illegal_callback = default_illegal_callback;
ret->error_callback = default_error_callback; ret->error_callback = default_error_callback;
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
/* Flags have been checked by secp256k1_context_preallocated_size. */ /* Flags have been checked by secp256k1_context_preallocated_size. */
@ -170,9 +161,6 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc); secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc);
} }
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc);
}
ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY);
return (secp256k1_context*) ret; return (secp256k1_context*) ret;
@ -199,7 +187,6 @@ secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context*
ret = (secp256k1_context*)prealloc; ret = (secp256k1_context*)prealloc;
memcpy(ret, ctx, prealloc_size); memcpy(ret, ctx, prealloc_size);
secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx); secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
secp256k1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx);
return ret; return ret;
} }
@ -217,7 +204,6 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) { void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
if (ctx != NULL) { if (ctx != NULL) {
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
} }
} }
@ -481,7 +467,6 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
secp256k1_scalar r, s; secp256k1_scalar r, s;
secp256k1_scalar m; secp256k1_scalar m;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(msghash32 != NULL); ARG_CHECK(msghash32 != NULL);
ARG_CHECK(sig != NULL); ARG_CHECK(sig != NULL);
ARG_CHECK(pubkey != NULL); ARG_CHECK(pubkey != NULL);
@ -490,7 +475,7 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); secp256k1_ecdsa_signature_load(ctx, &r, &s, sig);
return (!secp256k1_scalar_is_high(&s) && return (!secp256k1_scalar_is_high(&s) &&
secp256k1_pubkey_load(ctx, &q, pubkey) && secp256k1_pubkey_load(ctx, &q, pubkey) &&
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); secp256k1_ecdsa_sig_verify(&r, &s, &q, &m));
} }
static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) {
@ -737,24 +722,23 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32); return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32);
} }
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak32) { static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *p, const unsigned char *tweak32) {
secp256k1_scalar term; secp256k1_scalar term;
int overflow = 0; int overflow = 0;
secp256k1_scalar_set_b32(&term, tweak32, &overflow); secp256k1_scalar_set_b32(&term, tweak32, &overflow);
return !overflow && secp256k1_eckey_pubkey_tweak_add(ecmult_ctx, p, &term); return !overflow && secp256k1_eckey_pubkey_tweak_add(p, &term);
} }
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) { int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) {
secp256k1_ge p; secp256k1_ge p;
int ret = 0; int ret = 0;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(pubkey != NULL); ARG_CHECK(pubkey != NULL);
ARG_CHECK(tweak32 != NULL); ARG_CHECK(tweak32 != NULL);
ret = secp256k1_pubkey_load(ctx, &p, pubkey); ret = secp256k1_pubkey_load(ctx, &p, pubkey);
memset(pubkey, 0, sizeof(*pubkey)); memset(pubkey, 0, sizeof(*pubkey));
ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &p, tweak32); ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&p, tweak32);
if (ret) { if (ret) {
secp256k1_pubkey_save(pubkey, &p); secp256k1_pubkey_save(pubkey, &p);
} }
@ -792,7 +776,6 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
int ret = 0; int ret = 0;
int overflow = 0; int overflow = 0;
VERIFY_CHECK(ctx != NULL); VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(pubkey != NULL); ARG_CHECK(pubkey != NULL);
ARG_CHECK(tweak32 != NULL); ARG_CHECK(tweak32 != NULL);
@ -800,7 +783,7 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
memset(pubkey, 0, sizeof(*pubkey)); memset(pubkey, 0, sizeof(*pubkey));
if (ret) { if (ret) {
if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { if (secp256k1_eckey_pubkey_tweak_mul(&p, &factor)) {
secp256k1_pubkey_save(pubkey, &p); secp256k1_pubkey_save(pubkey, &p);
} else { } else {
ret = 0; ret = 0;
@ -823,6 +806,7 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
secp256k1_gej Qj; secp256k1_gej Qj;
secp256k1_ge Q; secp256k1_ge Q;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(pubnonce != NULL); ARG_CHECK(pubnonce != NULL);
memset(pubnonce, 0, sizeof(*pubnonce)); memset(pubnonce, 0, sizeof(*pubnonce));
ARG_CHECK(n >= 1); ARG_CHECK(n >= 1);
@ -831,6 +815,7 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
secp256k1_gej_set_infinity(&Qj); secp256k1_gej_set_infinity(&Qj);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
ARG_CHECK(pubnonces[i] != NULL);
secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); secp256k1_pubkey_load(ctx, &Q, pubnonces[i]);
secp256k1_gej_add_ge(&Qj, &Qj, &Q); secp256k1_gej_add_ge(&Qj, &Qj, &Q);
} }

View File

@ -319,22 +319,22 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
VG_CHECK(&sig, sizeof(sig)); VG_CHECK(&sig, sizeof(sig));
CHECK(ecount2 == 10); CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 1);
CHECK(ecount2 == 11); CHECK(ecount2 == 10);
CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 1);
CHECK(ecount2 == 12); CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
CHECK(ecount2 == 13); CHECK(ecount2 == 10);
CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1); CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1); CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0); CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
CHECK(ecount2 == 14); CHECK(ecount2 == 11);
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0); CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
@ -344,9 +344,9 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_context_randomize(vrfy, NULL) == 1); CHECK(secp256k1_context_randomize(vrfy, NULL) == 1);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_context_randomize(sign, ctmp) == 1); CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
CHECK(ecount2 == 14); CHECK(ecount2 == 11);
CHECK(secp256k1_context_randomize(sign, NULL) == 1); CHECK(secp256k1_context_randomize(sign, NULL) == 1);
CHECK(ecount2 == 14); CHECK(ecount2 == 11);
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
secp256k1_context_set_illegal_callback(sign, NULL, NULL); secp256k1_context_set_illegal_callback(sign, NULL, NULL);
@ -360,8 +360,8 @@ void run_context_tests(int use_prealloc) {
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
/* try verifying */ /* try verifying */
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
/* cleanup */ /* cleanup */
if (use_prealloc) { if (use_prealloc) {
@ -3542,9 +3542,9 @@ void test_ec_commit(void) {
/* Commit to data and verify */ /* Commit to data and verify */
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 1); CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 32) == 1);
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 1); CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 32) == 1);
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 1); CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 1);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
@ -3552,16 +3552,16 @@ void test_ec_commit(void) {
/* Check that verification fails with different data */ /* Check that verification fails with different data */
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 31) == 0); CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 31) == 0);
/* Check that commmitting fails when the inner pubkey is the point at /* Check that commmitting fails when the inner pubkey is the point at
* infinity */ * infinity */
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
secp256k1_ge_set_infinity(&pubkey); secp256k1_ge_set_infinity(&pubkey);
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 0); CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 32) == 0);
secp256k1_scalar_set_int(&seckey_s, 0); secp256k1_scalar_set_int(&seckey_s, 0);
CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 0); CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 0);
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 0); CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 32) == 0);
} }
void test_ec_commit_api(void) { void test_ec_commit_api(void) {
@ -3582,17 +3582,17 @@ void test_ec_commit_api(void) {
secp256k1_ge_set_gej(&pubkey, &pubkeyj); secp256k1_ge_set_gej(&pubkey, &pubkeyj);
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 1) == 1); CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 1) == 1);
/* The same pubkey can be both input and output of the function */ /* The same pubkey can be both input and output of the function */
{ {
secp256k1_ge pubkey_tmp = pubkey; secp256k1_ge pubkey_tmp = pubkey;
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &pubkey_tmp, &pubkey_tmp, &sha, data, 1) == 1); CHECK(secp256k1_ec_commit(&pubkey_tmp, &pubkey_tmp, &sha, data, 1) == 1);
ge_equals_ge(&commitment, &pubkey_tmp); ge_equals_ge(&commitment, &pubkey_tmp);
} }
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 1) == 1); CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 1) == 1);
} }
void run_ec_commit(void) { void run_ec_commit(void) {
@ -3678,6 +3678,84 @@ void run_group_decompress(void) {
/***** ECMULT TESTS *****/ /***** ECMULT TESTS *****/
void test_pre_g_table(const secp256k1_ge_storage * pre_g, size_t n) {
/* Tests the pre_g / pre_g_128 tables for consistency.
* For independent verification we take a "geometric" approach to verification.
* We check that every entry is on-curve.
* We check that for consecutive entries p and q, that p + gg - q = 0 by checking
* (1) p, gg, and -q are colinear.
* (2) p, gg, and -q are all distinct.
* where gg is twice the generator, where the generator is the first table entry.
*
* Checking the table's generators are correct is done in run_ecmult_pre_g.
*/
secp256k1_gej g2;
secp256k1_ge p, q, gg;
secp256k1_fe dpx, dpy, dqx, dqy;
size_t i;
CHECK(0 < n);
secp256k1_ge_from_storage(&p, &pre_g[0]);
secp256k1_fe_verify(&p.x);
secp256k1_fe_verify(&p.y);
CHECK(secp256k1_ge_is_valid_var(&p));
secp256k1_gej_set_ge(&g2, &p);
secp256k1_gej_double_var(&g2, &g2, NULL);
secp256k1_ge_set_gej_var(&gg, &g2);
for (i = 1; i < n; ++i) {
secp256k1_fe_negate(&dpx, &p.x, 1); secp256k1_fe_add(&dpx, &gg.x); secp256k1_fe_normalize_weak(&dpx);
secp256k1_fe_negate(&dpy, &p.y, 1); secp256k1_fe_add(&dpy, &gg.y); secp256k1_fe_normalize_weak(&dpy);
/* Check that p is not equal to gg */
CHECK(!secp256k1_fe_normalizes_to_zero_var(&dpx) || !secp256k1_fe_normalizes_to_zero_var(&dpy));
secp256k1_ge_from_storage(&q, &pre_g[i]);
secp256k1_fe_verify(&q.x);
secp256k1_fe_verify(&q.y);
CHECK(secp256k1_ge_is_valid_var(&q));
secp256k1_fe_negate(&dqx, &q.x, 1); secp256k1_fe_add(&dqx, &gg.x); secp256k1_fe_normalize_weak(&dqx);
dqy = q.y; secp256k1_fe_add(&dqy, &gg.y); secp256k1_fe_normalize_weak(&dqy);
/* Check that -q is not equal to gg */
CHECK(!secp256k1_fe_normalizes_to_zero_var(&dqx) || !secp256k1_fe_normalizes_to_zero_var(&dqy));
/* Check that -q is not equal to p */
CHECK(!secp256k1_fe_equal_var(&dpx, &dqx) || !secp256k1_fe_equal_var(&dpy, &dqy));
/* Check that p, -q and gg are colinear */
secp256k1_fe_mul(&dpx, &dpx, &dqy);
secp256k1_fe_mul(&dpy, &dpy, &dqx);
CHECK(secp256k1_fe_equal_var(&dpx, &dpy));
p = q;
}
}
void run_ecmult_pre_g(void) {
secp256k1_ge_storage gs;
secp256k1_gej gj;
secp256k1_ge g;
size_t i;
/* Check that the pre_g and pre_g_128 tables are consistent. */
test_pre_g_table(secp256k1_pre_g, ECMULT_TABLE_SIZE(WINDOW_G));
test_pre_g_table(secp256k1_pre_g_128, ECMULT_TABLE_SIZE(WINDOW_G));
/* Check the first entry from the pre_g table. */
secp256k1_ge_to_storage(&gs, &secp256k1_ge_const_g);
CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g[0], sizeof(gs)) == 0);
/* Check the first entry from the pre_g_128 table. */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
for (i = 0; i < 128; ++i) {
secp256k1_gej_double_var(&gj, &gj, NULL);
}
secp256k1_ge_set_gej(&g, &gj);
secp256k1_ge_to_storage(&gs, &g);
CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g_128[0], sizeof(gs)) == 0);
}
void run_ecmult_chain(void) { void run_ecmult_chain(void) {
/* random starting point A (on the curve) */ /* random starting point A (on the curve) */
secp256k1_gej a = SECP256K1_GEJ_CONST( secp256k1_gej a = SECP256K1_GEJ_CONST(
@ -3710,7 +3788,7 @@ void run_ecmult_chain(void) {
x = a; x = a;
for (i = 0; i < 200*count; i++) { for (i = 0; i < 200*count; i++) {
/* in each iteration, compute X = xn*X + gn*G; */ /* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn); secp256k1_ecmult(&x, &x, &xn, &gn);
/* also compute ae and ge: the actual accumulated factors for A and G */ /* also compute ae and ge: the actual accumulated factors for A and G */
/* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */
secp256k1_scalar_mul(&ae, &ae, &xn); secp256k1_scalar_mul(&ae, &ae, &xn);
@ -3736,7 +3814,7 @@ void run_ecmult_chain(void) {
} }
} }
/* redo the computation, but directly with the resulting ae and ge coefficients: */ /* redo the computation, but directly with the resulting ae and ge coefficients: */
secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); secp256k1_ecmult(&x2, &a, &ae, &ge);
secp256k1_gej_neg(&x2, &x2); secp256k1_gej_neg(&x2, &x2);
secp256k1_gej_add_var(&x2, &x2, &x, NULL); secp256k1_gej_add_var(&x2, &x2, &x, NULL);
CHECK(secp256k1_gej_is_infinity(&x2)); CHECK(secp256k1_gej_is_infinity(&x2));
@ -3754,8 +3832,8 @@ void test_point_times_order(const secp256k1_gej *point) {
size_t psize = 65; size_t psize = 65;
random_scalar_order_test(&x); random_scalar_order_test(&x);
secp256k1_scalar_negate(&nx, &x); secp256k1_scalar_negate(&nx, &x);
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_gej_add_var(&res1, &res1, &res2, NULL); secp256k1_gej_add_var(&res1, &res1, &res2, NULL);
CHECK(secp256k1_gej_is_infinity(&res1)); CHECK(secp256k1_gej_is_infinity(&res1));
secp256k1_ge_set_gej(&res3, &res1); secp256k1_ge_set_gej(&res3, &res1);
@ -3765,13 +3843,13 @@ void test_point_times_order(const secp256k1_gej *point) {
psize = 65; psize = 65;
CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0);
/* check zero/one edge cases */ /* check zero/one edge cases */
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); secp256k1_ecmult(&res1, point, &zero, &zero);
secp256k1_ge_set_gej(&res3, &res1); secp256k1_ge_set_gej(&res3, &res1);
CHECK(secp256k1_ge_is_infinity(&res3)); CHECK(secp256k1_ge_is_infinity(&res3));
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); secp256k1_ecmult(&res1, point, &one, &zero);
secp256k1_ge_set_gej(&res3, &res1); secp256k1_ge_set_gej(&res3, &res1);
ge_equals_gej(&res3, point); ge_equals_gej(&res3, point);
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); secp256k1_ecmult(&res1, point, &zero, &one);
secp256k1_ge_set_gej(&res3, &res1); secp256k1_ge_set_gej(&res3, &res1);
ge_equals_ge(&res3, &secp256k1_ge_const_g); ge_equals_ge(&res3, &secp256k1_ge_const_g);
} }
@ -3830,9 +3908,9 @@ void test_ecmult_target(const secp256k1_scalar* target, int mode) {
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p2j, &n2); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p2j, &n2);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &ptj, target); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &ptj, target);
} else if (mode == 1) { } else if (mode == 1) {
secp256k1_ecmult(&ctx->ecmult_ctx, &p1j, &pj, &n1, &zero); secp256k1_ecmult(&p1j, &pj, &n1, &zero);
secp256k1_ecmult(&ctx->ecmult_ctx, &p2j, &pj, &n2, &zero); secp256k1_ecmult(&p2j, &pj, &n2, &zero);
secp256k1_ecmult(&ctx->ecmult_ctx, &ptj, &pj, target, &zero); secp256k1_ecmult(&ptj, &pj, target, &zero);
} else { } else {
secp256k1_ecmult_const(&p1j, &p, &n1, 256); secp256k1_ecmult_const(&p1j, &p, &n1, 256);
secp256k1_ecmult_const(&p2j, &p, &n2, 256); secp256k1_ecmult_const(&p2j, &p, &n2, 256);
@ -4015,7 +4093,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_set_int(&szero, 0); secp256k1_scalar_set_int(&szero, 0);
/* No points to multiply */ /* No points to multiply */
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, NULL, ecmult_multi_callback, &data, 0)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, NULL, ecmult_multi_callback, &data, 0));
/* Check 1- and 2-point multiplies against ecmult */ /* Check 1- and 2-point multiplies against ecmult */
for (ncount = 0; ncount < count; ncount++) { for (ncount = 0; ncount < count; ncount++) {
@ -4030,32 +4108,32 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
pt[1] = secp256k1_ge_const_g; pt[1] = secp256k1_ge_const_g;
/* only G scalar */ /* only G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &szero, &sc[0]); secp256k1_ecmult(&r2, &ptgj, &szero, &sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
secp256k1_gej_neg(&r2, &r2); secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
/* 1-point */ /* 1-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero); secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2); secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
/* Try to multiply 1 point, but callback returns false */ /* Try to multiply 1 point, but callback returns false */
CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1)); CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
/* 2-point */ /* 2-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]); secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&r2, &r2); secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
/* 2-point with G scalar */ /* 2-point with G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]); secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2); secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
@ -4072,7 +4150,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
random_scalar_order(&sc[i]); random_scalar_order(&sc[i]);
secp256k1_ge_set_infinity(&pt[i]); secp256k1_ge_set_infinity(&pt[i]);
} }
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
} }
@ -4082,7 +4160,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
pt[i] = ptg; pt[i] = ptg;
secp256k1_scalar_set_int(&sc[i], 0); secp256k1_scalar_set_int(&sc[i], 0);
} }
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
} }
@ -4095,7 +4173,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
pt[2 * i + 1] = ptg; pt[2 * i + 1] = ptg;
} }
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
random_scalar_order(&sc[0]); random_scalar_order(&sc[0]);
@ -4108,7 +4186,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]); secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]);
} }
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
} }
@ -4123,7 +4201,7 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_negate(&sc[i], &sc[i]); secp256k1_scalar_negate(&sc[i], &sc[i]);
} }
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
} }
@ -4141,8 +4219,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL); secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL);
} }
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero); secp256k1_ecmult(&r2, &r, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2); secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
@ -4164,8 +4242,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
} }
secp256k1_gej_set_ge(&p0j, &pt[0]); secp256k1_gej_set_ge(&p0j, &pt[0]);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero); secp256k1_ecmult(&r2, &p0j, &rs, &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2); secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
@ -4178,13 +4256,13 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
} }
secp256k1_scalar_clear(&sc[0]); secp256k1_scalar_clear(&sc[0]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_scalar_clear(&sc[1]); secp256k1_scalar_clear(&sc[1]);
secp256k1_scalar_clear(&sc[2]); secp256k1_scalar_clear(&sc[2]);
secp256k1_scalar_clear(&sc[3]); secp256k1_scalar_clear(&sc[3]);
secp256k1_scalar_clear(&sc[4]); secp256k1_scalar_clear(&sc[4]);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
/* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */ /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
@ -4208,8 +4286,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_set_int(&t1, (t1i + 1) / 2); secp256k1_scalar_set_int(&t1, (t1i + 1) / 2);
secp256k1_scalar_cond_negate(&t1, t1i & 1); secp256k1_scalar_cond_negate(&t1, t1i & 1);
secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero); secp256k1_ecmult(&t0p, &ptgj, &t0, &szero);
secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero); secp256k1_ecmult(&t1p, &ptgj, &t1, &szero);
for(s0i = 0; s0i < TOP; s0i++) { for(s0i = 0; s0i < TOP; s0i++) {
for(s1i = 0; s1i < TOP; s1i++) { for(s1i = 0; s1i < TOP; s1i++) {
@ -4228,8 +4306,8 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
secp256k1_scalar_mul(&tmp2, &t1, &sc[1]); secp256k1_scalar_mul(&tmp2, &t1, &sc[1]);
secp256k1_scalar_add(&tmp1, &tmp1, &tmp2); secp256k1_scalar_add(&tmp1, &tmp1, &tmp2);
secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero); secp256k1_ecmult(&expected, &ptgj, &tmp1, &szero);
CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2)); CHECK(ecmult_multi(&ctx->error_callback, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&expected, &expected); secp256k1_gej_neg(&expected, &expected);
secp256k1_gej_add_var(&actual, &actual, &expected, NULL); secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
CHECK(secp256k1_gej_is_infinity(&actual)); CHECK(secp256k1_gej_is_infinity(&actual));
@ -4256,7 +4334,7 @@ void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) {
/* Try to multiply 1 point, but scratch space is empty.*/ /* Try to multiply 1 point, but scratch space is empty.*/
scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0); scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0);
CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1)); CHECK(!ecmult_multi(&ctx->error_callback, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_scratch_destroy(&ctx->error_callback, scratch_empty); secp256k1_scratch_destroy(&ctx->error_callback, scratch_empty);
} }
@ -4378,7 +4456,7 @@ void test_ecmult_multi_batching(void) {
/* Get random scalars and group elements and compute result */ /* Get random scalars and group elements and compute result */
random_scalar_order(&scG); random_scalar_order(&scG);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG); secp256k1_ecmult(&r2, &r2, &szero, &scG);
for(i = 0; i < n_points; i++) { for(i = 0; i < n_points; i++) {
secp256k1_ge ptg; secp256k1_ge ptg;
secp256k1_gej ptgj; secp256k1_gej ptgj;
@ -4386,7 +4464,7 @@ void test_ecmult_multi_batching(void) {
secp256k1_gej_set_ge(&ptgj, &ptg); secp256k1_gej_set_ge(&ptgj, &ptg);
pt[i] = ptg; pt[i] = ptg;
random_scalar_order(&sc[i]); random_scalar_order(&sc[i]);
secp256k1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL); secp256k1_ecmult(&ptgj, &ptgj, &sc[i], NULL);
secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL); secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL);
} }
data.sc = sc; data.sc = sc;
@ -4396,7 +4474,7 @@ void test_ecmult_multi_batching(void) {
/* Test with empty scratch space. It should compute the correct result using /* Test with empty scratch space. It should compute the correct result using
* ecmult_mult_simple algorithm which doesn't require a scratch space. */ * ecmult_mult_simple algorithm which doesn't require a scratch space. */
scratch = secp256k1_scratch_create(&ctx->error_callback, 0); scratch = secp256k1_scratch_create(&ctx->error_callback, 0);
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(&ctx->error_callback, scratch); secp256k1_scratch_destroy(&ctx->error_callback, scratch);
@ -4405,7 +4483,7 @@ void test_ecmult_multi_batching(void) {
* ecmult_multi selects strauss which requires more memory. It should * ecmult_multi selects strauss which requires more memory. It should
* therefore select the simple algorithm. */ * therefore select the simple algorithm. */
scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT);
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(&ctx->error_callback, scratch); secp256k1_scratch_destroy(&ctx->error_callback, scratch);
@ -4419,7 +4497,7 @@ void test_ecmult_multi_batching(void) {
size_t scratch_size = secp256k1_strauss_scratch_size(i); size_t scratch_size = secp256k1_strauss_scratch_size(i);
scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT);
} }
CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL); secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r)); CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(&ctx->error_callback, scratch); secp256k1_scratch_destroy(&ctx->error_callback, scratch);
@ -5524,22 +5602,24 @@ void test_ecdsa_sign_verify(void) {
secp256k1_scalar msg, key; secp256k1_scalar msg, key;
secp256k1_scalar sigr, sigs; secp256k1_scalar sigr, sigs;
int getrec; int getrec;
/* Initialize recid to suppress a false positive -Wconditional-uninitialized in clang. int recid;
VG_UNDEF ensures that valgrind will still treat the variable as uninitialized. */
int recid = -1; VG_UNDEF(&recid, sizeof(recid));
random_scalar_order_test(&msg); random_scalar_order_test(&msg);
random_scalar_order_test(&key); random_scalar_order_test(&key);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj); secp256k1_ge_set_gej(&pub, &pubj);
getrec = secp256k1_testrand_bits(1); getrec = secp256k1_testrand_bits(1);
random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); /* The specific way in which this conditional is written sidesteps a potential bug in clang.
See the commit messages of the commit that introduced this comment for details. */
if (getrec) { if (getrec) {
random_sign(&sigr, &sigs, &key, &msg, &recid);
CHECK(recid >= 0 && recid < 4); CHECK(recid >= 0 && recid < 4);
} else {
random_sign(&sigr, &sigs, &key, &msg, NULL);
} }
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg, &msg, &one); secp256k1_scalar_add(&msg, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); CHECK(!secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg));
} }
void run_ecdsa_sign_verify(void) { void run_ecdsa_sign_verify(void) {
@ -6217,7 +6297,7 @@ void test_ecdsa_edge_cases(void) {
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr);
secp256k1_ge_set_gej(&key, &keyj); secp256k1_ge_set_gej(&key, &keyj);
msg = ss; msg = ss;
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
} }
/* Verify signature with r of zero fails. */ /* Verify signature with r of zero fails. */
@ -6236,7 +6316,7 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&msg, 0); secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 0); secp256k1_scalar_set_int(&sr, 0);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0);
} }
/* Verify signature with s of zero fails. */ /* Verify signature with s of zero fails. */
@ -6255,7 +6335,7 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&msg, 0); secp256k1_scalar_set_int(&msg, 0);
secp256k1_scalar_set_int(&sr, 1); secp256k1_scalar_set_int(&sr, 1);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
} }
/* Verify signature with message 0 passes. */ /* Verify signature with message 0 passes. */
@ -6283,14 +6363,14 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_int(&sr, 2); secp256k1_scalar_set_int(&sr, 2);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss); secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_set_int(&ss, 1); secp256k1_scalar_set_int(&ss, 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0);
} }
/* Verify signature with message 1 passes. */ /* Verify signature with message 1 passes. */
@ -6324,15 +6404,15 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_set_b32(&sr, csr, NULL); secp256k1_scalar_set_b32(&sr, csr, NULL);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss); secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1);
secp256k1_scalar_set_int(&ss, 2); secp256k1_scalar_set_int(&ss, 2);
secp256k1_scalar_inverse_var(&ss, &ss); secp256k1_scalar_inverse_var(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0);
} }
/* Verify signature with message -1 passes. */ /* Verify signature with message -1 passes. */
@ -6358,12 +6438,12 @@ void test_ecdsa_edge_cases(void) {
secp256k1_scalar_negate(&msg, &msg); secp256k1_scalar_negate(&msg, &msg);
secp256k1_scalar_set_b32(&sr, csr, NULL); secp256k1_scalar_set_b32(&sr, csr, NULL);
CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
secp256k1_scalar_negate(&ss, &ss); secp256k1_scalar_negate(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1);
secp256k1_scalar_set_int(&ss, 3); secp256k1_scalar_set_int(&ss, 3);
secp256k1_scalar_inverse_var(&ss, &ss); secp256k1_scalar_inverse_var(&ss, &ss);
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0);
} }
/* Signature where s would be zero. */ /* Signature where s would be zero. */
@ -6609,10 +6689,10 @@ void test_ecdsa_openssl(void) {
CHECK(ec_key != NULL); CHECK(ec_key != NULL);
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &q, &msg));
secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg2, &msg, &one); secp256k1_scalar_add(&msg2, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); CHECK(!secp256k1_ecdsa_sig_verify(&sigr, &sigs, &q, &msg2));
random_sign(&sigr, &sigs, &key, &msg, NULL); random_sign(&sigr, &sigs, &key, &msg, NULL);
CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs));
@ -6909,6 +6989,7 @@ int main(int argc, char **argv) {
run_group_decompress(); run_group_decompress();
/* ecmult tests */ /* ecmult tests */
run_ecmult_pre_g();
run_wnaf(); run_wnaf();
run_point_times_order(); run_point_times_order();
run_ecmult_near_split_bound(); run_ecmult_near_split_bound();

View File

@ -163,7 +163,7 @@ void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *gr
} }
} }
void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj) { void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_gej *groupj) {
int i, j, r_log; int i, j, r_log;
uint64_t iter = 0; uint64_t iter = 0;
for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) { for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) {
@ -175,7 +175,7 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
secp256k1_scalar_set_int(&na, i); secp256k1_scalar_set_int(&na, i);
secp256k1_scalar_set_int(&ng, j); secp256k1_scalar_set_int(&ng, j);
secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); secp256k1_ecmult(&tmp, &groupj[r_log], &na, &ng);
ge_equals_gej(&group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER], &tmp); ge_equals_gej(&group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER], &tmp);
if (i > 0) { if (i > 0) {
@ -219,7 +219,7 @@ void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_
data.pt[0] = group[x]; data.pt[0] = group[x];
data.pt[1] = group[y]; data.pt[1] = group[y];
secp256k1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
ge_equals_gej(&group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER], &tmp); ge_equals_gej(&group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER], &tmp);
} }
} }
@ -430,7 +430,7 @@ int main(int argc, char** argv) {
/* Run the tests */ /* Run the tests */
test_exhaustive_endomorphism(group); test_exhaustive_endomorphism(group);
test_exhaustive_addition(group, groupj); test_exhaustive_addition(group, groupj);
test_exhaustive_ecmult(ctx, group, groupj); test_exhaustive_ecmult(group, groupj);
test_exhaustive_ecmult_multi(ctx, group); test_exhaustive_ecmult_multi(ctx, group);
test_exhaustive_sign(ctx, group); test_exhaustive_sign(ctx, group);
test_exhaustive_verify(ctx, group); test_exhaustive_verify(ctx, group);