Repository: bitcoin-core/secp256k1
Pull request #408 (2016-07-28 16:12:20)

Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate`
I have an application which uses summed secret keys as a keysplitting mechanism. To use this with BIP32, I would like to negate the public parent key, which would give the following result:
- one of the key shards is the negative parent key, the other the child key
- the "summed key" is then the BIP32 tweak

In my case I can change my application to use a difference of keys rather than sum of keys, but this adds another way for the user to get things wrong, especially when used with a more "symmetric" key split where it's unclear which of the two shards ought to be negated.


sipa: Concept ACK if you also add a `secp256k1_ec_privkey_negate`. Also, what about using the `secp256k1_ec_*_tweak_negate` name, for consistency with `_tweak_add` and `_tweak_mul` ?
apoelstra: Sure, I can add a privkey negate.

As for the `tweak_` names, I had thought that the "tweak" was the extra parameter, not the original element -- you are multiplying by a tweak, or adding a tweak.
apoelstra: Added negate_privkey.

That test failure is a randomness test failure, I think it's just a fluke.
instagibbs: change PR title to match new functionality?
instagibbs: This is failing a test.
apoelstra: kicked travis
gmaxwell: No strong view, but these are multiplicative tweaks with a fixed tweak value of -1.

Concept ACK, will ACK with nits fixed.
apoelstra: Fixed nits.
gmaxwell: @apoelstra ping see above: "for consistency, memset(pubkey, 0, sizeof(*pubkey)); after the load, unless you've got an argument that its bad to clear it completely (in which case we should change it everywhere)"

Patch:
diff --git a/.gitignore b/.gitignore
index 87fea16..efb277d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,6 @@ bench_schnorr_verify
 bench_recover
 bench_internal
 tests
-exhaustive_tests
 gen_context
 *.exe
 *.so
diff --git a/.travis.yml b/.travis.yml
index 2439529..2c5c63a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ cache:
   - src/java/guava/
 env:
   global:
-    - FIELD=auto  BIGNUM=auto  SCALAR=auto  ENDOMORPHISM=no  STATICPRECOMPUTATION=yes  ASM=no  BUILD=check  EXTRAFLAGS=  HOST=  ECDH=no  RECOVERY=no  EXPERIMENTAL=no
+    - FIELD=auto  BIGNUM=auto  SCALAR=auto  ENDOMORPHISM=no  STATICPRECOMPUTATION=yes  ASM=no  BUILD=check  EXTRAFLAGS=  HOST=  ECDH=no  schnorr=no  RECOVERY=no  EXPERIMENTAL=no
     - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar
   matrix:
     - SCALAR=32bit    RECOVERY=yes
@@ -22,14 +22,15 @@ env:
     - FIELD=64bit     ENDOMORPHISM=yes  ECDH=yes EXPERIMENTAL=yes
     - FIELD=64bit                       ASM=x86_64
     - FIELD=64bit     ENDOMORPHISM=yes  ASM=x86_64
+    - FIELD=32bit     SCHNORR=yes EXPERIMENTAL=yes
     - FIELD=32bit     ENDOMORPHISM=yes
     - BIGNUM=no
-    - BIGNUM=no       ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes
+    - BIGNUM=no       ENDOMORPHISM=yes SCHNORR=yes  RECOVERY=yes EXPERIMENTAL=yes
     - BIGNUM=no       STATICPRECOMPUTATION=no
     - BUILD=distcheck
     - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC
     - EXTRAFLAGS=CFLAGS=-O0
-    - BUILD=check-java ECDH=yes EXPERIMENTAL=yes
+    - BUILD=check-java ECDH=yes SCHNORR=yes EXPERIMENTAL=yes
 matrix:
   fast_finish: true
   include:
@@ -65,5 +66,5 @@ before_script: ./autogen.sh
 script:
  - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi
  - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi
- - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD
+ - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD
 os: linux
diff --git a/Makefile.am b/Makefile.am
index e5657f7..3d130bd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,11 +12,9 @@ noinst_HEADERS =
 noinst_HEADERS += src/scalar.h
 noinst_HEADERS += src/scalar_4x64.h
 noinst_HEADERS += src/scalar_8x32.h
-noinst_HEADERS += src/scalar_low.h
 noinst_HEADERS += src/scalar_impl.h
 noinst_HEADERS += src/scalar_4x64_impl.h
 noinst_HEADERS += src/scalar_8x32_impl.h
-noinst_HEADERS += src/scalar_low_impl.h
 noinst_HEADERS += src/group.h
 noinst_HEADERS += src/group_impl.h
 noinst_HEADERS += src/num_gmp.h
@@ -89,23 +87,13 @@ bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES)
 endif
 
-TESTS =
 if USE_TESTS
 noinst_PROGRAMS += tests
 tests_SOURCES = src/tests.c
 tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES)
 tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
 tests_LDFLAGS = -static
-TESTS += tests
-endif
-
-if USE_EXHAUSTIVE_TESTS
-noinst_PROGRAMS += exhaustive_tests
-exhaustive_tests_SOURCES = src/tests_exhaustive.c
-exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src $(SECP_INCLUDES)
-exhaustive_tests_LDADD = $(SECP_LIBS)
-exhaustive_tests_LDFLAGS = -static
-TESTS += exhaustive_tests
+TESTS = tests
 endif
 
 JAVAROOT=src/java
@@ -166,6 +154,10 @@ if ENABLE_MODULE_ECDH
 include src/modules/ecdh/Makefile.am.include
 endif
 
+if ENABLE_MODULE_SCHNORR
+include src/modules/schnorr/Makefile.am.include
+endif
+
 if ENABLE_MODULE_RECOVERY
 include src/modules/recovery/Makefile.am.include
 endif
diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4
index b74acb8..b25d8ad 100644
--- a/build-aux/m4/bitcoin_secp.m4
+++ b/build-aux/m4/bitcoin_secp.m4
@@ -46,10 +46,6 @@ if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then
     ECDSA_sign(0, NULL, 0, NULL, NULL, eckey);
     ECDSA_verify(0, NULL, 0, NULL, 0, eckey);
     EC_KEY_free(eckey);
-    ECDSA_SIG *sig_openssl;
-    sig_openssl = ECDSA_SIG_new();
-    (void)sig_openssl->r;
-    ECDSA_SIG_free(sig_openssl);
   ]])],[has_openssl_ec=yes],[has_openssl_ec=no])
   AC_MSG_RESULT([$has_openssl_ec])
 fi
diff --git a/configure.ac b/configure.ac
index ec50ffe..0743c36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -104,11 +104,6 @@ AC_ARG_ENABLE(experimental,
     [use_experimental=$enableval],
     [use_experimental=no])
 
-AC_ARG_ENABLE(exhaustive_tests,
-    AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]),
-    [use_exhaustive_tests=$enableval],
-    [use_exhaustive_tests=yes])
-
 AC_ARG_ENABLE(endomorphism,
     AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]),
     [use_endomorphism=$enableval],
@@ -124,6 +119,11 @@ AC_ARG_ENABLE(module_ecdh,
     [enable_module_ecdh=$enableval],
     [enable_module_ecdh=no])
 
+AC_ARG_ENABLE(module_schnorr,
+    AS_HELP_STRING([--enable-module-schnorr],[enable Schnorr signature module (experimental)]),
+    [enable_module_schnorr=$enableval],
+    [enable_module_schnorr=no])
+
 AC_ARG_ENABLE(module_recovery,
     AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]),
     [enable_module_recovery=$enableval],
@@ -381,6 +381,9 @@ fi
 if test x"$use_jni" != x"no"; then
   AX_JNI_INCLUDE_DIR
   have_jni_dependencies=yes
+  if test x"$enable_module_schnorr" = x"no"; then
+    have_jni_dependencies=no
+  fi
   if test x"$enable_module_ecdh" = x"no"; then
     have_jni_dependencies=no
   fi
@@ -389,7 +392,7 @@ if test x"$use_jni" != x"no"; then
   fi
   if test "x$have_jni_dependencies" = "xno"; then
     if test x"$use_jni" = x"yes"; then
-      AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.])
+      AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and Schnorr and try again.])
     fi
     AC_MSG_WARN([jni headers/dependencies not found. jni support disabled])
     use_jni=no
@@ -410,7 +413,7 @@ if test x"$use_endomorphism" = x"yes"; then
   AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization])
 fi
 
-if test x"$set_precomp" = x"yes"; then
+if test x"$use_ecmult_static_precomputation" = x"yes"; then
   AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table])
 fi
 
@@ -418,6 +421,10 @@ if test x"$enable_module_ecdh" = x"yes"; then
   AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module])
 fi
 
+if test x"$enable_module_schnorr" = x"yes"; then
+  AC_DEFINE(ENABLE_MODULE_SCHNORR, 1, [Define this symbol to enable the Schnorr signature module])
+fi
+
 if test x"$enable_module_recovery" = x"yes"; then
   AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module])
 fi
@@ -435,6 +442,7 @@ AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
 AC_MSG_NOTICE([Using scalar implementation: $set_scalar])
 AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism])
 AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
+AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr])
 AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery])
 AC_MSG_NOTICE([Using jni: $use_jni])
 
@@ -443,8 +451,12 @@ if test x"$enable_experimental" = x"yes"; then
   AC_MSG_NOTICE([WARNING: experimental build])
   AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.])
   AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
+  AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr])
   AC_MSG_NOTICE([******])
 else
+  if test x"$enable_module_schnorr" = x"yes"; then
+    AC_MSG_ERROR([Schnorr signature module is experimental. Use --enable-experimental to allow.])
+  fi
   if test x"$enable_module_ecdh" = x"yes"; then
     AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.])
   fi
@@ -461,10 +473,10 @@ AC_SUBST(SECP_LIBS)
 AC_SUBST(SECP_TEST_LIBS)
 AC_SUBST(SECP_TEST_INCLUDES)
 AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
-AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"])
 AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
-AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"])
+AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_precomputation" = x"yes"])
 AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])
+AM_CONDITIONAL([ENABLE_MODULE_SCHNORR], [test x"$enable_module_schnorr" = x"yes"])
 AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"])
 AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"])
 AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"])
diff --git a/include/secp256k1.h b/include/secp256k1.h
index f268e30..18a7254 100644
--- a/include/secp256k1.h
+++ b/include/secp256k1.h
@@ -47,8 +47,11 @@ typedef struct secp256k1_context_struct secp256k1_context;
  *  The exact representation of data inside is implementation defined and not
  *  guaranteed to be portable between different platforms or versions. It is
  *  however guaranteed to be 64 bytes in size, and can be safely copied/moved.
- *  If you need to convert to a format suitable for storage, transmission, or
- *  comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse.
+ *  If you need to convert to a format suitable for storage or transmission, use
+ *  secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse.
+ *
+ *  Furthermore, it is guaranteed that identical public keys (ignoring
+ *  compression) will have identical representation, so they can be memcmp'ed.
  */
 typedef struct {
     unsigned char data[64];
@@ -59,9 +62,12 @@ typedef struct {
  *  The exact representation of data inside is implementation defined and not
  *  guaranteed to be portable between different platforms or versions. It is
  *  however guaranteed to be 64 bytes in size, and can be safely copied/moved.
- *  If you need to convert to a format suitable for storage, transmission, or
- *  comparison, use the secp256k1_ecdsa_signature_serialize_* and
+ *  If you need to convert to a format suitable for storage or transmission, use
+ *  the secp256k1_ecdsa_signature_serialize_* and
  *  secp256k1_ecdsa_signature_serialize_* functions.
+ *
+ *  Furthermore, it is guaranteed to identical signatures will have identical
+ *  representation, so they can be memcmp'ed.
  */
 typedef struct {
     unsigned char data[64];
@@ -485,6 +491,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
     const unsigned char *seckey
 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
 
+/** Negates a private key in place.
+ *
+ *  Returns: 1 always
+ *  Args:   ctx:        pointer to a context object
+ *  In/Out: pubkey:     pointer to the public key to be negated (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
+    const secp256k1_context* ctx,
+    unsigned char *seckey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
+
+/** Negates a public key in place.
+ *
+ *  Returns: 1 always
+ *  Args:   ctx:        pointer to a context object
+ *  In/Out: pubkey:     pointer to the public key to be negated (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
+    const secp256k1_context* ctx,
+    secp256k1_pubkey *pubkey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
+
 /** Tweak a private key by adding tweak to it.
  * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
  *          uniformly random 32-byte arrays, or if the resulting private key
diff --git a/include/secp256k1_schnorr.h b/include/secp256k1_schnorr.h
new file mode 100644
index 0000000..dc32fec
--- /dev/null
+++ b/include/secp256k1_schnorr.h
@@ -0,0 +1,173 @@
+#ifndef _SECP256K1_SCHNORR_
+# define _SECP256K1_SCHNORR_
+
+# include "secp256k1.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/** Create a signature using a custom EC-Schnorr-SHA256 construction. It
+ *  produces non-malleable 64-byte signatures which support public key recovery
+ *  batch validation, and multiparty signing.
+ *  Returns: 1: signature created
+ *           0: the nonce generation function failed, or the private key was
+ *              invalid.
+ *  Args:    ctx:    pointer to a context object, initialized for signing
+ *                   (cannot be NULL)
+ *  Out:     sig64:  pointer to a 64-byte array where the signature will be
+ *                   placed (cannot be NULL)
+ *  In:      msg32:  the 32-byte message hash being signed (cannot be NULL)
+ *           seckey: pointer to a 32-byte secret key (cannot be NULL)
+ *           noncefp:pointer to a nonce generation function. If NULL,
+ *                   secp256k1_nonce_function_default is used
+ *           ndata:  pointer to arbitrary data used by the nonce generation
+ *                   function (can be NULL)
+ */
+SECP256K1_API int secp256k1_schnorr_sign(
+  const secp256k1_context* ctx,
+  unsigned char *sig64,
+  const unsigned char *msg32,
+  const unsigned char *seckey,
+  secp256k1_nonce_function noncefp,
+  const void *ndata
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+
+/** Verify a signature created by secp256k1_schnorr_sign.
+ *  Returns: 1: correct signature
+ *           0: incorrect signature
+ *  Args:    ctx:       a secp256k1 context object, initialized for verification.
+ *  In:      sig64:     the 64-byte signature being verified (cannot be NULL)
+ *           msg32:     the 32-byte message hash being verified (cannot be NULL)
+ *           pubkey:    the public key to verify with (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify(
+  const secp256k1_context* ctx,
+  const unsigned char *sig64,
+  const unsigned char *msg32,
+  const secp256k1_pubkey *pubkey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+
+/** Recover an EC public key from a Schnorr signature created using
+ *  secp256k1_schnorr_sign.
+ *  Returns: 1: public key successfully recovered (which guarantees a correct
+ *           signature).
+ *           0: otherwise.
+ *  Args:    ctx:        pointer to a context object, initialized for
+ *                       verification (cannot be NULL)
+ *  Out:     pubkey:     pointer to a pubkey to set to the recovered public key
+ *                       (cannot be NULL).
+ *  In:      sig64:      signature as 64 byte array (cannot be NULL)
+ *           msg32:      the 32-byte message hash assumed to be signed (cannot
+ *                       be NULL)
+ */
+SECP256K1_API int secp256k1_schnorr_recover(
+  const secp256k1_context* ctx,
+  secp256k1_pubkey *pubkey,
+  const unsigned char *sig64,
+  const unsigned char *msg32
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+
+/** Generate a nonce pair deterministically for use with
+ *  secp256k1_schnorr_partial_sign.
+ *  Returns: 1: valid nonce pair was generated.
+ *           0: otherwise (nonce generation function failed)
+ *  Args:    ctx:         pointer to a context object, initialized for signing
+ *                        (cannot be NULL)
+ *  Out:     pubnonce:    public side of the nonce (cannot be NULL)
+ *           privnonce32: private side of the nonce (32 byte) (cannot be NULL)
+ *  In:      msg32:       the 32-byte message hash assumed to be signed (cannot
+ *                        be NULL)
+ *           sec32:       the 32-byte private key (cannot be NULL)
+ *           noncefp:     pointer to a nonce generation function. If NULL,
+ *                        secp256k1_nonce_function_default is used
+ *           noncedata:   pointer to arbitrary data used by the nonce generation
+ *                        function (can be NULL)
+ *
+ *  Do not use the output as a private/public key pair for signing/validation.
+ */
+SECP256K1_API int secp256k1_schnorr_generate_nonce_pair(
+  const secp256k1_context* ctx,
+  secp256k1_pubkey *pubnonce,
+  unsigned char *privnonce32,
+  const unsigned char *msg32,
+  const unsigned char *sec32,
+  secp256k1_nonce_function noncefp,
+  const void* noncedata
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+/** Produce a partial Schnorr signature, which can be combined using
+ *  secp256k1_schnorr_partial_combine, to end up with a full signature that is
+ *  verifiable using secp256k1_schnorr_verify.
+ *  Returns: 1: signature created successfully.
+ *           0: no valid signature exists with this combination of keys, nonces
+ *              and message (chance around 1 in 2^128)
+ *          -1: invalid private key, nonce, or public nonces.
+ *  Args: ctx:             pointer to context object, initialized for signing (cannot
+ *                         be NULL)
+ *  Out:  sig64:           pointer to 64-byte array to put partial signature in
+ *  In:   msg32:           pointer to 32-byte message to sign
+ *        sec32:           pointer to 32-byte private key
+ *        pubnonce_others: pointer to pubkey containing the sum of the other's
+ *                         nonces (see secp256k1_ec_pubkey_combine)
+ *        secnonce32:      pointer to 32-byte array containing our nonce
+ *
+ * The intended procedure for creating a multiparty signature is:
+ * - Each signer S[i] with private key x[i] and public key Q[i] runs
+ *   secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of
+ *   private/public nonces.
+ * - All signers communicate their public nonces to each other (revealing your
+ *   private nonce can lead to discovery of your private key, so it should be
+ *   considered secret).
+ * - All signers combine all the public nonces they received (excluding their
+ *   own) using secp256k1_ec_pubkey_combine to obtain an
+ *   Rall[i] = sum(R[0..i-1,i+1..n]).
+ * - All signers produce a partial signature using
+ *   secp256k1_schnorr_partial_sign, passing in their own private key x[i],
+ *   their own private nonce k[i], and the sum of the others' public nonces
+ *   Rall[i].
+ * - All signers communicate their partial signatures to each other.
+ * - Someone combines all partial signatures using
+ *   secp256k1_schnorr_partial_combine, to obtain a full signature.
+ * - The resulting signature is validatable using secp256k1_schnorr_verify, with
+ *   public key equal to the result of secp256k1_ec_pubkey_combine of the
+ *   signers' public keys (sum(Q[0..n])).
+ *
+ *  Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine
+ *  function take their arguments in any order, and it is possible to
+ *  pre-combine several inputs already with one call, and add more inputs later
+ *  by calling the function again (they are commutative and associative).
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_sign(
+  const secp256k1_context* ctx,
+  unsigned char *sig64,
+  const unsigned char *msg32,
+  const unsigned char *sec32,
+  const secp256k1_pubkey *pubnonce_others,
+  const unsigned char *secnonce32
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
+
+/** Combine multiple Schnorr partial signatures.
+ * Returns: 1: the passed signatures were successfully combined.
+ *          0: the resulting signature is not valid (chance of 1 in 2^256)
+ *         -1: some inputs were invalid, or the signatures were not created
+ *             using the same set of nonces
+ * Args:   ctx:      pointer to a context object
+ * Out:    sig64:    pointer to a 64-byte array to place the combined signature
+ *                   (cannot be NULL)
+ * In:     sig64sin: pointer to an array of n pointers to 64-byte input
+ *                   signatures
+ *         n:        the number of signatures to combine (at least 1)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_combine(
+  const secp256k1_context* ctx,
+  unsigned char *sig64,
+  const unsigned char * const * sig64sin,
+  size_t n
+) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h
index 9a42e51..d110b4b 100644
--- a/src/ecdsa_impl.h
+++ b/src/ecdsa_impl.h
@@ -203,9 +203,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
 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) {
     unsigned char c[32];
     secp256k1_scalar sn, u1, u2;
-#if !defined(EXHAUSTIVE_TEST_ORDER)
     secp256k1_fe xr;
-#endif
     secp256k1_gej pubkeyj;
     secp256k1_gej pr;
 
@@ -221,21 +219,6 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
     if (secp256k1_gej_is_infinity(&pr)) {
         return 0;
     }
-
-#if defined(EXHAUSTIVE_TEST_ORDER)
-{
-    secp256k1_scalar computed_r;
-    int overflow = 0;
-    secp256k1_ge pr_ge;
-    secp256k1_ge_set_gej(&pr_ge, &pr);
-    secp256k1_fe_normalize(&pr_ge.x);
-
-    secp256k1_fe_get_b32(c, &pr_ge.x);
-    secp256k1_scalar_set_b32(&computed_r, c, &overflow);
-    /* we fully expect overflow */
-    return secp256k1_scalar_eq(sigr, &computed_r);
-}
-#else
     secp256k1_scalar_get_b32(c, sigr);
     secp256k1_fe_set_b32(&xr, c);
 
@@ -269,7 +252,6 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const
         return 1;
     }
     return 0;
-#endif
 }
 
 static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) {
diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h
index 0db314c..7a6a253 100644
--- a/src/ecmult_const_impl.h
+++ b/src/ecmult_const_impl.h
@@ -78,7 +78,7 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) {
     /* Negative numbers will be negated to keep their bit representation below the maximum width */
     flip = secp256k1_scalar_is_high(&s);
     /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
-    bit = flip ^ !secp256k1_scalar_is_even(&s);
+    bit = flip ^ (s.d[0] & 1);
     /* We check for negative one, since adding 2 to it will cause an overflow */
     secp256k1_scalar_negate(&neg_s, &s);
     not_neg_one = !secp256k1_scalar_is_one(&neg_s);
diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h
index 35f2546..b63c4d8 100644
--- a/src/ecmult_gen_impl.h
+++ b/src/ecmult_gen_impl.h
@@ -77,7 +77,7 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx
                 secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL);
             }
         }
-        secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb);
+        secp256k1_ge_set_all_gej_var(1024, prec, precj, cb);
     }
     for (j = 0; j < 64; j++) {
         for (i = 0; i < 16; i++) {
diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h
index 4e40104..e6e5f47 100644
--- a/src/ecmult_impl.h
+++ b/src/ecmult_impl.h
@@ -7,29 +7,13 @@
 #ifndef _SECP256K1_ECMULT_IMPL_H_
 #define _SECP256K1_ECMULT_IMPL_H_
 
-#include <string.h>
-
 #include "group.h"
 #include "scalar.h"
 #include "ecmult.h"
 
-#if defined(EXHAUSTIVE_TEST_ORDER)
-/* We need to lower these values for exhaustive tests because
- * the tables cannot have infinities in them (this breaks the
- * affine-isomorphism stuff which tracks z-ratios) */
-#  if EXHAUSTIVE_TEST_ORDER > 128
-#    define WINDOW_A 5
-#    define WINDOW_G 8
-#  elif EXHAUSTIVE_TEST_ORDER > 8
-#    define WINDOW_A 4
-#    define WINDOW_G 4
-#  else
-#    define WINDOW_A 2
-#    define WINDOW_G 2
-#  endif
-#else
 /* optimal for 128-bit and 256-bit exponents. */
 #define WINDOW_A 5
+
 /** larger numbers may result in slightly better performance, at the cost of
     exponentially larger precomputed tables. */
 #ifdef USE_ENDOMORPHISM
@@ -39,7 +23,6 @@
 /** One table for window size 16: 1.375 MiB. */
 #define WINDOW_G 16
 #endif
-#endif
 
 /** The number of entries a table with precomputed multiples needs to have. */
 #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
@@ -118,7 +101,7 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge
     /* Compute the odd multiples in Jacobian form. */
     secp256k1_ecmult_odd_multiples_table(n, prej, zr, a);
     /* Convert them in batch to affine coordinates. */
-    secp256k1_ge_set_table_gej_var(prea, prej, zr, n);
+    secp256k1_ge_set_table_gej_var(n, prea, prej, zr);
     /* Convert them to compact storage form. */
     for (i = 0; i < n; i++) {
         secp256k1_ge_to_storage(&pre[i], &prea[i]);
diff --git a/src/field.h b/src/field.h
index bbb1ee8..c5ba074 100644
--- a/src/field.h
+++ b/src/field.h
@@ -30,8 +30,6 @@
 #error "Please select field implementation"
 #endif
 
-#include "util.h"
-
 /** Normalize a field element. */
 static void secp256k1_fe_normalize(secp256k1_fe *r);
 
@@ -52,9 +50,6 @@ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r);
 /** Set a field element equal to a small integer. Resulting field element is normalized. */
 static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
 
-/** Sets a field element equal to zero, initializing all fields. */
-static void secp256k1_fe_clear(secp256k1_fe *a);
-
 /** Verify whether a field element is zero. Requires the input to be normalized. */
 static int secp256k1_fe_is_zero(const secp256k1_fe *a);
 
@@ -115,7 +110,7 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
 /** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be
  *  at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and
  *  outputs must not overlap in memory. */
-static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len);
+static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe *r, const secp256k1_fe *a);
 
 /** Convert a field element to the storage type. */
 static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
diff --git a/src/field_impl.h b/src/field_impl.h
index 5127b27..52cd902 100644
--- a/src/field_impl.h
+++ b/src/field_impl.h
@@ -260,7 +260,7 @@ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) {
 #endif
 }
 
-static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) {
+static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe *r, const secp256k1_fe *a) {
     secp256k1_fe u;
     size_t i;
     if (len < 1) {
diff --git a/src/group.h b/src/group.h
index 4957b24..d515716 100644
--- a/src/group.h
+++ b/src/group.h
@@ -65,12 +65,12 @@ static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a);
 static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a);
 
 /** Set a batch of group elements equal to the inputs given in jacobian coordinates */
-static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb);
+static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_callback *cb);
 
 /** Set a batch of group elements equal to the inputs given in jacobian
  *  coordinates (with known z-ratios). zr must contain the known z-ratios such
  *  that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */
-static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len);
+static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr);
 
 /** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to
  *  the same global z "denominator". zr must contain the known z-ratios such
diff --git a/src/group_impl.h b/src/group_impl.h
index 2e192b6..3e9c4c4 100644
--- a/src/group_impl.h
+++ b/src/group_impl.h
@@ -11,53 +11,6 @@
 #include "field.h"
 #include "group.h"
 
-/* These points can be generated in sage as follows:
- *
- * 0. Setup a worksheet with the following parameters.
- *   b = 4  # whatever CURVE_B will be set to
- *   F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
- *   C = EllipticCurve ([F (0), F (b)])
- *
- * 1. Determine all the small orders available to you. (If there are
- *    no satisfactory ones, go back and change b.)
- *   print C.order().factor(limit=1000)
- *
- * 2. Choose an order as one of the prime factors listed in the above step.
- *    (You can also multiply some to get a composite order, though the
- *    tests will crash trying to invert scalars during signing.) We take a
- *    random point and scale it to drop its order to the desired value.
- *    There is some probability this won't work; just try again.
- *   order = 199
- *   P = C.random_point()
- *   P = (int(P.order()) / int(order)) * P
- *   assert(P.order() == order)
- *
- * 3. Print the values. You'll need to use a vim macro or something to
- *    split the hex output into 4-byte chunks.
- *   print "%x %x" % P.xy()
- */
-#if defined(EXHAUSTIVE_TEST_ORDER)
-#  if EXHAUSTIVE_TEST_ORDER == 199
-const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
-    0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069,
-    0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18,
-    0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868,
-    0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED
-);
-
-const int CURVE_B = 4;
-#  elif EXHAUSTIVE_TEST_ORDER == 13
-const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
-    0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0,
-    0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15,
-    0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e,
-    0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac
-);
-const int CURVE_B = 2;
-#  else
-#    error No known generator for the specified exhaustive test group order.
-#  endif
-#else
 /** Generator for secp256k1, value 'g' defined in
  *  "Standards for Efficient Cryptography" (SEC2) 2.7.1.
  */
@@ -68,11 +21,8 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
     0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
 );
 
-const int CURVE_B = 7;
-#endif
-
 static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
-    secp256k1_fe zi2;
+    secp256k1_fe zi2; 
     secp256k1_fe zi3;
     secp256k1_fe_sqr(&zi2, zi);
     secp256k1_fe_mul(&zi3, &zi2, zi);
@@ -126,7 +76,7 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
     r->y = a->y;
 }
 
-static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) {
+static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_callback *cb) {
     secp256k1_fe *az;
     secp256k1_fe *azi;
     size_t i;
@@ -139,7 +89,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
     }
 
     azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count);
-    secp256k1_fe_inv_all_var(azi, az, count);
+    secp256k1_fe_inv_all_var(count, azi, az);
     free(az);
 
     count = 0;
@@ -152,7 +102,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
     free(azi);
 }
 
-static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) {
+static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr) {
     size_t i = len - 1;
     secp256k1_fe zi;
 
@@ -195,15 +145,9 @@ static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp
 
 static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
     r->infinity = 1;
-    secp256k1_fe_clear(&r->x);
-    secp256k1_fe_clear(&r->y);
-    secp256k1_fe_clear(&r->z);
-}
-
-static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
-    r->infinity = 1;
-    secp256k1_fe_clear(&r->x);
-    secp256k1_fe_clear(&r->y);
+    secp256k1_fe_set_int(&r->x, 0);
+    secp256k1_fe_set_int(&r->y, 0);
+    secp256k1_fe_set_int(&r->z, 0);
 }
 
 static void secp256k1_gej_clear(secp256k1_gej *r) {
@@ -225,7 +169,7 @@ static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
     secp256k1_fe_sqr(&x2, x);
     secp256k1_fe_mul(&x3, x, &x2);
     r->infinity = 0;
-    secp256k1_fe_set_int(&c, CURVE_B);
+    secp256k1_fe_set_int(&c, 7);
     secp256k1_fe_add(&c, &x3);
     return secp256k1_fe_sqrt(&r->y, &c);
 }
@@ -284,7 +228,7 @@ static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) {
     secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
     secp256k1_fe_sqr(&z2, &a->z);
     secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
-    secp256k1_fe_mul_int(&z6, CURVE_B);
+    secp256k1_fe_mul_int(&z6, 7);
     secp256k1_fe_add(&x3, &z6);
     secp256k1_fe_normalize_weak(&x3);
     return secp256k1_fe_equal_var(&y2, &x3);
@@ -298,7 +242,7 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
     /* y^2 = x^3 + 7 */
     secp256k1_fe_sqr(&y2, &a->y);
     secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
-    secp256k1_fe_set_int(&c, CURVE_B);
+    secp256k1_fe_set_int(&c, 7);
     secp256k1_fe_add(&x3, &c);
     secp256k1_fe_normalize_weak(&x3);
     return secp256k1_fe_equal_var(&y2, &x3);
@@ -316,7 +260,7 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
     /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity,
      *  Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have
      *  y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p.
-     *
+     *  
      *  Having said this, if this function receives a point on a sextic twist, e.g. by
      *  a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6,
      *  since -6 does have a cube root mod p. For this point, this function will not set
diff --git a/src/java/org/bitcoin/NativeSecp256k1.java b/src/java/org/bitcoin/NativeSecp256k1.java
index 1c67802..be67048 100644
--- a/src/java/org/bitcoin/NativeSecp256k1.java
+++ b/src/java/org/bitcoin/NativeSecp256k1.java
@@ -32,7 +32,7 @@ import static org.bitcoin.NativeSecp256k1Util.*;
  * <p>You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1</p>
  *
  * <p>To build secp256k1 for use with bitcoinj, run
- * `./configure --enable-jni --enable-experimental --enable-module-ecdh`
+ * `./configure --enable-jni --enable-experimental --enable-module-schnorr --enable-module-ecdh`
  * and `make` then copy `.libs/libsecp256k1.so` to your system library path
  * or point the JVM to the folder containing it with -Djava.library.path
  * </p>
@@ -417,6 +417,36 @@ public class NativeSecp256k1 {
         }
     }
 
+    public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailException {
+        Preconditions.checkArgument(data.length == 32 && sec.length <= 32);
+
+        ByteBuffer byteBuff = nativeECDSABuffer.get();
+        if (byteBuff == null) {
+            byteBuff = ByteBuffer.allocateDirect(32 + 32);
+            byteBuff.order(ByteOrder.nativeOrder());
+            nativeECDSABuffer.set(byteBuff);
+        }
+        byteBuff.rewind();
+        byteBuff.put(data);
+        byteBuff.put(sec);
+
+        byte[][] retByteArray;
+
+        r.lock();
+        try {
+          retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext());
+        } finally {
+          r.unlock();
+        }
+
+        byte[] sigArr = retByteArray[0];
+        int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
+
+        assertEquals(sigArr.length, 64, "Got bad signature length.");
+
+        return retVal == 0 ? new byte[0] : sigArr;
+    }
+
     private static native long secp256k1_ctx_clone(long context);
 
     private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context);
@@ -441,6 +471,8 @@ public class NativeSecp256k1 {
 
     private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen);
 
+    private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context);
+
     private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
 
 }
diff --git a/src/java/org_bitcoin_NativeSecp256k1.c b/src/java/org_bitcoin_NativeSecp256k1.c
index bcef7b3..dba9524 100644
--- a/src/java/org_bitcoin_NativeSecp256k1.c
+++ b/src/java/org_bitcoin_NativeSecp256k1.c
@@ -5,6 +5,7 @@
 #include "include/secp256k1.h"
 #include "include/secp256k1_ecdh.h"
 #include "include/secp256k1_recovery.h"
+#include "include/secp256k1_schnorr.h"
 
 
 SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone
@@ -332,6 +333,39 @@ SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1p
   return 0;
 }
 
+SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign
+  (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l)
+{
+  secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
+  unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
+  unsigned char* secKey = (unsigned char*) (data + 32);
+
+  jobjectArray retArray;
+  jbyteArray sigArray, intsByteArray;
+  unsigned char intsarray[1];
+  unsigned char sig[64];
+
+  int ret = secp256k1_schnorr_sign(ctx, sig, data, secKey, NULL, NULL);
+
+  intsarray[0] = ret;
+
+  retArray = (*env)->NewObjectArray(env, 2,
+    (*env)->FindClass(env, "[B"),
+    (*env)->NewByteArray(env, 1));
+
+  sigArray = (*env)->NewByteArray(env, 64);
+  (*env)->SetByteArrayRegion(env, sigArray, 0, 64, (jbyte*)sig);
+  (*env)->SetObjectArrayElement(env, retArray, 0, sigArray);
+
+  intsByteArray = (*env)->NewByteArray(env, 1);
+  (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray);
+  (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
+
+  (void)classObject;
+
+  return retArray;
+}
+
 SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh
   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen)
 {
diff --git a/src/java/org_bitcoin_NativeSecp256k1.h b/src/java/org_bitcoin_NativeSecp256k1.h
index fe613c9..4125a1f 100644
--- a/src/java/org_bitcoin_NativeSecp256k1.h
+++ b/src/java/org_bitcoin_NativeSecp256k1.h
@@ -104,6 +104,14 @@ SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1e
 SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse
   (JNIEnv *, jclass, jobject, jlong, jint);
 
+/*
+ * Class:     org_bitcoin_NativeSecp256k1
+ * Method:    secp256k1_schnorr_sign
+ * Signature: (Ljava/nio/ByteBuffer;JI)[[B
+ */
+SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign
+  (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l);
+
 /*
  * Class:     org_bitcoin_NativeSecp256k1
  * Method:    secp256k1_ecdh
diff --git a/src/modules/recovery/main_impl.h b/src/modules/recovery/main_impl.h
old mode 100755
new mode 100644
index 86f2f0c..ec42f4b
--- a/src/modules/recovery/main_impl.h
+++ b/src/modules/recovery/main_impl.h
@@ -138,15 +138,16 @@ int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecd
     secp256k1_scalar_set_b32(&sec, seckey, &overflow);
     /* Fail if the secret key is invalid. */
     if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
-        unsigned char nonce32[32];
         unsigned int count = 0;
         secp256k1_scalar_set_b32(&msg, msg32, NULL);
         while (1) {
+            unsigned char nonce32[32];
             ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
             if (!ret) {
                 break;
             }
             secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+            memset(nonce32, 0, 32);
             if (!secp256k1_scalar_is_zero(&non) && !overflow) {
                 if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) {
                     break;
@@ -154,7 +155,6 @@ int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecd
             }
             count++;
         }
-        memset(nonce32, 0, 32);
         secp256k1_scalar_clear(&msg);
         secp256k1_scalar_clear(&non);
         secp256k1_scalar_clear(&sec);
diff --git a/src/modules/schnorr/Makefile.am.include b/src/modules/schnorr/Makefile.am.include
new file mode 100644
index 0000000..f1af8e8
--- /dev/null
+++ b/src/modules/schnorr/Makefile.am.include
@@ -0,0 +1,10 @@
+include_HEADERS += include/secp256k1_schnorr.h
+noinst_HEADERS += src/modules/schnorr/main_impl.h
+noinst_HEADERS += src/modules/schnorr/schnorr.h
+noinst_HEADERS += src/modules/schnorr/schnorr_impl.h
+noinst_HEADERS += src/modules/schnorr/tests_impl.h
+if USE_BENCHMARK
+noinst_PROGRAMS += bench_schnorr_verify
+bench_schnorr_verify_SOURCES = src/bench_schnorr_verify.c
+bench_schnorr_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
+endif
diff --git a/src/modules/schnorr/main_impl.h b/src/modules/schnorr/main_impl.h
new file mode 100644
index 0000000..fa176a1
--- /dev/null
+++ b/src/modules/schnorr/main_impl.h
@@ -0,0 +1,164 @@
+/**********************************************************************
+ * Copyright (c) 2014-2015 Pieter Wuille                              *
+ * Distributed under the MIT software license, see the accompanying   *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef SECP256K1_MODULE_SCHNORR_MAIN
+#define SECP256K1_MODULE_SCHNORR_MAIN
+
+#include "include/secp256k1_schnorr.h"
+#include "modules/schnorr/schnorr_impl.h"
+
+static void secp256k1_schnorr_msghash_sha256(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) {
+    secp256k1_sha256_t sha;
+    secp256k1_sha256_initialize(&sha);
+    secp256k1_sha256_write(&sha, r32, 32);
+    secp256k1_sha256_write(&sha, msg32, 32);
+    secp256k1_sha256_finalize(&sha, h32);
+}
+
+static const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256  ";
+
+int secp256k1_schnorr_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) {
+    secp256k1_scalar sec, non;
+    int ret = 0;
+    int overflow = 0;
+    unsigned int count = 0;
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+    ARG_CHECK(msg32 != NULL);
+    ARG_CHECK(sig64 != NULL);
+    ARG_CHECK(seckey != NULL);
+    if (noncefp == NULL) {
+        noncefp = secp256k1_nonce_function_default;
+    }
+
+    secp256k1_scalar_set_b32(&sec, seckey, NULL);
+    while (1) {
+        unsigned char nonce32[32];
+        ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)noncedata, count);
+        if (!ret) {
+            break;
+        }
+        secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+        memset(nonce32, 0, 32);
+        if (!secp256k1_scalar_is_zero(&non) && !overflow) {
+            if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, NULL, secp256k1_schnorr_msghash_sha256, msg32)) {
+                break;
+            }
+        }
+        count++;
+    }
+    if (!ret) {
+        memset(sig64, 0, 64);
+    }
+    secp256k1_scalar_clear(&non);
+    secp256k1_scalar_clear(&sec);
+    return ret;
+}
+
+int secp256k1_schnorr_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_pubkey *pubkey) {
+    secp256k1_ge q;
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+    ARG_CHECK(msg32 != NULL);
+    ARG_CHECK(sig64 != NULL);
+    ARG_CHECK(pubkey != NULL);
+
+    secp256k1_pubkey_load(ctx, &q, pubkey);
+    return secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32);
+}
+
+int secp256k1_schnorr_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *sig64, const unsigned char *msg32) {
+    secp256k1_ge q;
+
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+    ARG_CHECK(msg32 != NULL);
+    ARG_CHECK(sig64 != NULL);
+    ARG_CHECK(pubkey != NULL);
+
+    if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32)) {
+        secp256k1_pubkey_save(pubkey, &q);
+        return 1;
+    } else {
+        memset(pubkey, 0, sizeof(*pubkey));
+        return 0;
+    }
+}
+
+int secp256k1_schnorr_generate_nonce_pair(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, unsigned char *privnonce32, const unsigned char *sec32, const unsigned char *msg32, secp256k1_nonce_function noncefp, const void* noncedata) {
+    int count = 0;
+    int ret = 1;
+    secp256k1_gej Qj;
+    secp256k1_ge Q;
+    secp256k1_scalar sec;
+
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+    ARG_CHECK(msg32 != NULL);
+    ARG_CHECK(sec32 != NULL);
+    ARG_CHECK(pubnonce != NULL);
+    ARG_CHECK(privnonce32 != NULL);
+
+    if (noncefp == NULL) {
+        noncefp = secp256k1_nonce_function_default;
+    }
+
+    do {
+        int overflow;
+        ret = noncefp(privnonce32, sec32, msg32, secp256k1_schnorr_algo16, (void*)noncedata, count++);
+        if (!ret) {
+            break;
+        }
+        secp256k1_scalar_set_b32(&sec, privnonce32, &overflow);
+        if (overflow || secp256k1_scalar_is_zero(&sec)) {
+            continue;
+        }
+        secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sec);
+        secp256k1_ge_set_gej(&Q, &Qj);
+
+        secp256k1_pubkey_save(pubnonce, &Q);
+        break;
+    } while(1);
+
+    secp256k1_scalar_clear(&sec);
+    if (!ret) {
+        memset(pubnonce, 0, sizeof(*pubnonce));
+    }
+    return ret;
+}
+
+int secp256k1_schnorr_partial_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *sec32, const secp256k1_pubkey *pubnonce_others, const unsigned char *secnonce32) {
+    int overflow = 0;
+    secp256k1_scalar sec, non;
+    secp256k1_ge pubnon;
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+    ARG_CHECK(msg32 != NULL);
+    ARG_CHECK(sig64 != NULL);
+    ARG_CHECK(sec32 != NULL);
+    ARG_CHECK(secnonce32 != NULL);
+    ARG_CHECK(pubnonce_others != NULL);
+
+    secp256k1_scalar_set_b32(&sec, sec32, &overflow);
+    if (overflow || secp256k1_scalar_is_zero(&sec)) {
+        return -1;
+    }
+    secp256k1_scalar_set_b32(&non, secnonce32, &overflow);
+    if (overflow || secp256k1_scalar_is_zero(&non)) {
+        return -1;
+    }
+    secp256k1_pubkey_load(ctx, &pubnon, pubnonce_others);
+    return secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, &pubnon, secp256k1_schnorr_msghash_sha256, msg32);
+}
+
+int secp256k1_schnorr_partial_combine(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char * const *sig64sin, size_t n) {
+    ARG_CHECK(sig64 != NULL);
+    ARG_CHECK(n >= 1);
+    ARG_CHECK(sig64sin != NULL);
+    return secp256k1_schnorr_sig_combine(sig64, n, sig64sin);
+}
+
+#endif
diff --git a/src/modules/schnorr/schnorr.h b/src/modules/schnorr/schnorr.h
new file mode 100644
index 0000000..de18147
--- /dev/null
+++ b/src/modules/schnorr/schnorr.h
@@ -0,0 +1,20 @@
+/***********************************************************************
+ * Copyright (c) 2014-2015 Pieter Wuille                               *
+ * Distributed under the MIT software license, see the accompanying    *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php. *
+ ***********************************************************************/
+
+#ifndef _SECP256K1_MODULE_SCHNORR_H_
+#define _SECP256K1_MODULE_SCHNORR_H_
+
+#include "scalar.h"
+#include "group.h"
+
+typedef void (*secp256k1_schnorr_msghash)(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32);
+
+static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32);
+static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32);
+static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32);
+static int secp256k1_schnorr_sig_combine(unsigned char *sig64, size_t n, const unsigned char * const *sig64ins);
+
+#endif
diff --git a/src/modules/schnorr/schnorr_impl.h b/src/modules/schnorr/schnorr_impl.h
new file mode 100644
index 0000000..e13ab6d
--- /dev/null
+++ b/src/modules/schnorr/schnorr_impl.h
@@ -0,0 +1,207 @@
+/***********************************************************************
+ * Copyright (c) 2014-2015 Pieter Wuille                               *
+ * Distributed under the MIT software license, see the accompanying    *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php. *
+ ***********************************************************************/
+
+#ifndef _SECP256K1_SCHNORR_IMPL_H_
+#define _SECP256K1_SCHNORR_IMPL_H_
+
+#include <string.h>
+
+#include "schnorr.h"
+#include "num.h"
+#include "field.h"
+#include "group.h"
+#include "ecmult.h"
+#include "ecmult_gen.h"
+
+/**
+ * Custom Schnorr-based signature scheme. They support multiparty signing, public key
+ * recovery and batch validation.
+ *
+ * Rationale for verifying R's y coordinate:
+ * In order to support batch validation and public key recovery, the full R point must
+ * be known to verifiers, rather than just its x coordinate. In order to not risk
+ * being more strict in batch validation than normal validation, validators must be
+ * required to reject signatures with incorrect y coordinate. This is only possible
+ * by including a (relatively slow) field inverse, or a field square root. However,
+ * batch validation offers potentially much higher benefits than this cost.
+ *
+ * Rationale for having an implicit y coordinate oddness:
+ * If we commit to having the full R point known to verifiers, there are two mechanism.
+ * Either include its oddness in the signature, or give it an implicit fixed value.
+ * As the R y coordinate can be flipped by a simple negation of the nonce, we choose the
+ * latter, as it comes with nearly zero impact on signing or validation performance, and
+ * saves a byte in the signature.
+ *
+ * Signing:
+ *   Inputs: 32-byte message m, 32-byte scalar key x (!=0), 32-byte scalar nonce k (!=0)
+ *
+ *   Compute point R = k * G. Reject nonce if R's y coordinate is odd (or negate nonce).
+ *   Compute 32-byte r, the serialization of R's x coordinate.
+ *   Compute scalar h = Hash(r || m). Reject nonce if h == 0 or h >= order.
+ *   Compute scalar s = k - h * x.
+ *   The signature is (r, s).
+ *
+ *
+ * Verification:
+ *   Inputs: 32-byte message m, public key point Q, signature: (32-byte r, scalar s)
+ *
+ *   Signature is invalid if s >= order.
+ *   Signature is invalid if r >= p.
+ *   Compute scalar h = Hash(r || m). Signature is invalid if h == 0 or h >= order.
+ *   Option 1 (faster for single verification):
+ *     Compute point R = h * Q + s * G. Signature is invalid if R is infinity or R's y coordinate is odd.
+ *     Signature is valid if the serialization of R's x coordinate equals r.
+ *   Option 2 (allows batch validation and pubkey recovery):
+ *     Decompress x coordinate r into point R, with odd y coordinate. Fail if R is not on the curve.
+ *     Signature is valid if R + h * Q + s * G == 0.
+ */
+
+static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32) {
+    secp256k1_gej Rj;
+    secp256k1_ge Ra;
+    unsigned char h32[32];
+    secp256k1_scalar h, s;
+    int overflow;
+    secp256k1_scalar n;
+
+    if (secp256k1_scalar_is_zero(key) || secp256k1_scalar_is_zero(nonce)) {
+        return 0;
+    }
+    n = *nonce;
+
+    secp256k1_ecmult_gen(ctx, &Rj, &n);
+    if (pubnonce != NULL) {
+        secp256k1_gej_add_ge(&Rj, &Rj, pubnonce);
+    }
+    secp256k1_ge_set_gej(&Ra, &Rj);
+    secp256k1_fe_normalize(&Ra.y);
+    if (secp256k1_fe_is_odd(&Ra.y)) {
+        /* R's y coordinate is odd, which is not allowed (see rationale above).
+           Force it to be even by negating the nonce. Note that this even works
+           for multiparty signing, as the R point is known to all participants,
+           which can all decide to flip the sign in unison, resulting in the
+           overall R point to be negated too. */
+        secp256k1_scalar_negate(&n, &n);
+    }
+    secp256k1_fe_normalize(&Ra.x);
+    secp256k1_fe_get_b32(sig64, &Ra.x);
+    hash(h32, sig64, msg32);
+    overflow = 0;
+    secp256k1_scalar_set_b32(&h, h32, &overflow);
+    if (overflow || secp256k1_scalar_is_zero(&h)) {
+        secp256k1_scalar_clear(&n);
+        return 0;
+    }
+    secp256k1_scalar_mul(&s, &h, key);
+    secp256k1_scalar_negate(&s, &s);
+    secp256k1_scalar_add(&s, &s, &n);
+    secp256k1_scalar_clear(&n);
+    secp256k1_scalar_get_b32(sig64 + 32, &s);
+    return 1;
+}
+
+static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) {
+    secp256k1_gej Qj, Rj;
+    secp256k1_ge Ra;
+    secp256k1_fe Rx;
+    secp256k1_scalar h, s;
+    unsigned char hh[32];
+    int overflow;
+
+    if (secp256k1_ge_is_infinity(pubkey)) {
+        return 0;
+    }
+    hash(hh, sig64, msg32);
+    overflow = 0;
+    secp256k1_scalar_set_b32(&h, hh, &overflow);
+    if (overflow || secp256k1_scalar_is_zero(&h)) {
+        return 0;
+    }
+    overflow = 0;
+    secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow);
+    if (overflow) {
+        return 0;
+    }
+    if (!secp256k1_fe_set_b32(&Rx, sig64)) {
+        return 0;
+    }
+    secp256k1_gej_set_ge(&Qj, pubkey);
+    secp256k1_ecmult(ctx, &Rj, &Qj, &h, &s);
+    if (secp256k1_gej_is_infinity(&Rj)) {
+        return 0;
+    }
+    secp256k1_ge_set_gej_var(&Ra, &Rj);
+    secp256k1_fe_normalize_var(&Ra.y);
+    if (secp256k1_fe_is_odd(&Ra.y)) {
+        return 0;
+    }
+    return secp256k1_fe_equal_var(&Rx, &Ra.x);
+}
+
+static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) {
+    secp256k1_gej Qj, Rj;
+    secp256k1_ge Ra;
+    secp256k1_fe Rx;
+    secp256k1_scalar h, s;
+    unsigned char hh[32];
+    int overflow;
+
+    hash(hh, sig64, msg32);
+    overflow = 0;
+    secp256k1_scalar_set_b32(&h, hh, &overflow);
+    if (overflow || secp256k1_scalar_is_zero(&h)) {
+        return 0;
+    }
+    overflow = 0;
+    secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow);
+    if (overflow) {
+        return 0;
+    }
+    if (!secp256k1_fe_set_b32(&Rx, sig64)) {
+        return 0;
+    }
+    if (!secp256k1_ge_set_xo_var(&Ra, &Rx, 0)) {
+        return 0;
+    }
+    secp256k1_gej_set_ge(&Rj, &Ra);
+    secp256k1_scalar_inverse_var(&h, &h);
+    secp256k1_scalar_negate(&s, &s);
+    secp256k1_scalar_mul(&s, &s, &h);
+    secp256k1_ecmult(ctx, &Qj, &Rj, &h, &s);
+    if (secp256k1_gej_is_infinity(&Qj)) {
+        return 0;
+    }
+    secp256k1_ge_set_gej(pubkey, &Qj);
+    return 1;
+}
+
+static int secp256k1_schnorr_sig_combine(unsigned char *sig64, size_t n, const unsigned char * const *sig64ins) {
+    secp256k1_scalar s = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
+    size_t i;
+    for (i = 0; i < n; i++) {
+        secp256k1_scalar si;
+        int overflow;
+        secp256k1_scalar_set_b32(&si, sig64ins[i] + 32, &overflow);
+        if (overflow) {
+            return -1;
+        }
+        if (i) {
+            if (memcmp(sig64ins[i - 1], sig64ins[i], 32) != 0) {
+                return -1;
+            }
+        }
+        secp256k1_scalar_add(&s, &s, &si);
+    }
+    if (secp256k1_scalar_is_zero(&s)) {
+        return 0;
+    }
+    memcpy(sig64, sig64ins[0], 32);
+    secp256k1_scalar_get_b32(sig64 + 32, &s);
+    secp256k1_scalar_clear(&s);
+    return 1;
+}
+
+#endif
diff --git a/src/scalar.h b/src/scalar.h
index 27e9d83..b590ccd 100644
--- a/src/scalar.h
+++ b/src/scalar.h
@@ -13,9 +13,7 @@
 #include "libsecp256k1-config.h"
 #endif
 
-#if defined(EXHAUSTIVE_TEST_ORDER)
-#include "scalar_low.h"
-#elif defined(USE_SCALAR_4X64)
+#if defined(USE_SCALAR_4X64)
 #include "scalar_4x64.h"
 #elif defined(USE_SCALAR_8X32)
 #include "scalar_8x32.h"
diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h
index 56e7bd8..aa2703d 100644
--- a/src/scalar_4x64_impl.h
+++ b/src/scalar_4x64_impl.h
@@ -282,8 +282,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "movq 56(%%rsi), %%r14\n"
     /* Initialize r8,r9,r10 */
     "movq 0(%%rsi), %%r8\n"
-    "xorq %%r9, %%r9\n"
-    "xorq %%r10, %%r10\n"
+    "movq $0, %%r9\n"
+    "movq $0, %%r10\n"
     /* (r8,r9) += n0 * c0 */
     "movq %8, %%rax\n"
     "mulq %%r11\n"
@@ -291,7 +291,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq %%rdx, %%r9\n"
     /* extract m0 */
     "movq %%r8, %q0\n"
-    "xorq %%r8, %%r8\n"
+    "movq $0, %%r8\n"
     /* (r9,r10) += l1 */
     "addq 8(%%rsi), %%r9\n"
     "adcq $0, %%r10\n"
@@ -309,7 +309,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq $0, %%r8\n"
     /* extract m1 */
     "movq %%r9, %q1\n"
-    "xorq %%r9, %%r9\n"
+    "movq $0, %%r9\n"
     /* (r10,r8,r9) += l2 */
     "addq 16(%%rsi), %%r10\n"
     "adcq $0, %%r8\n"
@@ -332,7 +332,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq $0, %%r9\n"
     /* extract m2 */
     "movq %%r10, %q2\n"
-    "xorq %%r10, %%r10\n"
+    "movq $0, %%r10\n"
     /* (r8,r9,r10) += l3 */
     "addq 24(%%rsi), %%r8\n"
     "adcq $0, %%r9\n"
@@ -355,7 +355,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq $0, %%r10\n"
     /* extract m3 */
     "movq %%r8, %q3\n"
-    "xorq %%r8, %%r8\n"
+    "movq $0, %%r8\n"
     /* (r9,r10,r8) += n3 * c1 */
     "movq %9, %%rax\n"
     "mulq %%r14\n"
@@ -387,8 +387,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "movq %q11, %%r13\n"
     /* Initialize (r8,r9,r10) */
     "movq %q5, %%r8\n"
-    "xorq %%r9, %%r9\n"
-    "xorq %%r10, %%r10\n"
+    "movq $0, %%r9\n"
+    "movq $0, %%r10\n"
     /* (r8,r9) += m4 * c0 */
     "movq %12, %%rax\n"
     "mulq %%r11\n"
@@ -396,7 +396,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq %%rdx, %%r9\n"
     /* extract p0 */
     "movq %%r8, %q0\n"
-    "xorq %%r8, %%r8\n"
+    "movq $0, %%r8\n"
     /* (r9,r10) += m1 */
     "addq %q6, %%r9\n"
     "adcq $0, %%r10\n"
@@ -414,7 +414,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq $0, %%r8\n"
     /* extract p1 */
     "movq %%r9, %q1\n"
-    "xorq %%r9, %%r9\n"
+    "movq $0, %%r9\n"
     /* (r10,r8,r9) += m2 */
     "addq %q7, %%r10\n"
     "adcq $0, %%r8\n"
@@ -472,7 +472,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "movq %%rax, 0(%q6)\n"
     /* Move to (r8,r9) */
     "movq %%rdx, %%r8\n"
-    "xorq %%r9, %%r9\n"
+    "movq $0, %%r9\n"
     /* (r8,r9) += p1 */
     "addq %q2, %%r8\n"
     "adcq $0, %%r9\n"
@@ -483,7 +483,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq %%rdx, %%r9\n"
     /* Extract r1 */
     "movq %%r8, 8(%q6)\n"
-    "xorq %%r8, %%r8\n"
+    "movq $0, %%r8\n"
     /* (r9,r8) += p4 */
     "addq %%r10, %%r9\n"
     "adcq $0, %%r8\n"
@@ -492,7 +492,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
     "adcq $0, %%r8\n"
     /* Extract r2 */
     "movq %%r9, 16(%q6)\n"
-    "xorq %%r9, %%r9\n"
+    "movq $0, %%r9\n"
     /* (r8,r9) += p3 */
     "addq %q4, %%r8\n"
     "adcq $0, %%r9\n"
diff --git a/src/scalar_impl.h b/src/scalar_impl.h
index f5b2376..c5baf4d 100644
--- a/src/scalar_impl.h
+++ b/src/scalar_impl.h
@@ -14,9 +14,7 @@
 #include "libsecp256k1-config.h"
 #endif
 
-#if defined(EXHAUSTIVE_TEST_ORDER)
-#include "scalar_low_impl.h"
-#elif defined(USE_SCALAR_4X64)
+#if defined(USE_SCALAR_4X64)
 #include "scalar_4x64_impl.h"
 #elif defined(USE_SCALAR_8X32)
 #include "scalar_8x32_impl.h"
@@ -33,37 +31,17 @@ static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a
 
 /** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */
 static void secp256k1_scalar_order_get_num(secp256k1_num *r) {
-#if defined(EXHAUSTIVE_TEST_ORDER)
-    static const unsigned char order[32] = {
-        0,0,0,0,0,0,0,0,
-        0,0,0,0,0,0,0,0,
-        0,0,0,0,0,0,0,0,
-        0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER
-    };
-#else
     static const unsigned char order[32] = {
         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
         0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
         0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41
     };
-#endif
     secp256k1_num_set_bin(r, order, 32);
 }
 #endif
 
 static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) {
-#if defined(EXHAUSTIVE_TEST_ORDER)
-    int i;
-    *r = 0;
-    for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++)
-        if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1)
-            *r = i;
-    /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus
-     * have a composite group order; fix it in exhaustive_tests.c). */
-    VERIFY_CHECK(*r != 0);
-}
-#else
     secp256k1_scalar *t;
     int i;
     /* First compute x ^ (2^N - 1) for some values of N. */
@@ -255,9 +233,9 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
 }
 
 SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) {
+    /* d[0] is present and is the lowest word for all representations */
     return !(a->d[0] & 1);
 }
-#endif
 
 static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) {
 #if defined(USE_SCALAR_INV_BUILTIN)
@@ -281,18 +259,6 @@ static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_sc
 }
 
 #ifdef USE_ENDOMORPHISM
-#if defined(EXHAUSTIVE_TEST_ORDER)
-/**
- * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the
- * full case we don't bother making k1 and k2 be small, we just want them to be
- * nontrivial to get full test coverage for the exhaustive tests. We therefore
- * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda.
- */
-static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
-    *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER;
-    *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER;
-}
-#else
 /**
  * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where
  * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
@@ -365,6 +331,5 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
     secp256k1_scalar_add(r1, r1, a);
 }
 #endif
-#endif
 
 #endif
diff --git a/src/scalar_low.h b/src/scalar_low.h
deleted file mode 100644
index 5574c44..0000000
--- a/src/scalar_low.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2015 Andrew Poelstra                                 *
- * Distributed under the MIT software license, see the accompanying   *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-
-#ifndef _SECP256K1_SCALAR_REPR_
-#define _SECP256K1_SCALAR_REPR_
-
-#include <stdint.h>
-
-/** A scalar modulo the group order of the secp256k1 curve. */
-typedef uint32_t secp256k1_scalar;
-
-#endif
diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h
deleted file mode 100644
index 4f94441..0000000
--- a/src/scalar_low_impl.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2015 Andrew Poelstra                                 *
- * Distributed under the MIT software license, see the accompanying   *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-
-#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_
-#define _SECP256K1_SCALAR_REPR_IMPL_H_
-
-#include "scalar.h"
-
-#include <string.h>
-
-SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) {
-    return !(*a & 1);
-}
-
-SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; }
-SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; }
-
-SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
-    if (offset < 32)
-        return ((*a >> offset) & ((((uint32_t)1) << count) - 1));
-    else
-        return 0;
-}
-
-SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
-    return secp256k1_scalar_get_bits(a, offset, count);
-}
-
-SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; }
-
-static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
-    *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER;
-    return *r < *b;
-}
-
-static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
-    if (flag && bit < 32)
-        *r += (1 << bit);
-#ifdef VERIFY
-    VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
-#endif
-}
-
-static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) {
-    const int base = 0x100 % EXHAUSTIVE_TEST_ORDER;
-    int i;
-    *r = 0;
-    for (i = 0; i < 32; i++) {
-       *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER;
-    }
-    /* just deny overflow, it basically always happens */
-    if (overflow) *overflow = 0;
-}
-
-static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) {
-    memset(bin, 0, 32);
-    bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a;
-}
-
-SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) {
-    return *a == 0;
-}
-
-static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) {
-    if (*a == 0) {
-        *r = 0;
-    } else {
-        *r = EXHAUSTIVE_TEST_ORDER - *a;
-    }
-}
-
-SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
-    return *a == 1;
-}
-
-static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
-    return *a > EXHAUSTIVE_TEST_ORDER / 2;
-}
-
-static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
-    if (flag) secp256k1_scalar_negate(r, r);
-    return flag ? -1 : 1;
-}
-
-static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
-    *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER;
-}
-
-static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) {
-    int ret;
-    VERIFY_CHECK(n > 0);
-    VERIFY_CHECK(n < 16);
-    ret = *r & ((1 << n) - 1);
-    *r >>= n;
-    return ret;
-}
-
-static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) {
-    *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER;
-}
-
-static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) {
-    *r1 = *a;
-    *r2 = 0;
-}
-
-SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) {
-    return *a == *b;
-}
-
-#endif
diff --git a/src/secp256k1.c b/src/secp256k1.c
old mode 100755
new mode 100644
index fb8b882..8ca258f
--- a/src/secp256k1.c
+++ b/src/secp256k1.c
@@ -359,15 +359,16 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
     secp256k1_scalar_set_b32(&sec, seckey, &overflow);
     /* Fail if the secret key is invalid. */
     if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
-        unsigned char nonce32[32];
         unsigned int count = 0;
         secp256k1_scalar_set_b32(&msg, msg32, NULL);
         while (1) {
+            unsigned char nonce32[32];
             ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count);
             if (!ret) {
                 break;
             }
             secp256k1_scalar_set_b32(&non, nonce32, &overflow);
+            memset(nonce32, 0, 32);
             if (!overflow && !secp256k1_scalar_is_zero(&non)) {
                 if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) {
                     break;
@@ -375,7 +376,6 @@ int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature
             }
             count++;
         }
-        memset(nonce32, 0, 32);
         secp256k1_scalar_clear(&msg);
         secp256k1_scalar_clear(&non);
         secp256k1_scalar_clear(&sec);
@@ -424,6 +424,33 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
     return ret;
 }
 
+int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) {
+    secp256k1_scalar sec;
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(seckey != NULL);
+
+    secp256k1_scalar_set_b32(&sec, seckey, NULL);
+    secp256k1_scalar_negate(&sec, &sec);
+    secp256k1_scalar_get_b32(seckey, &sec);
+
+    return 1;
+}
+
+int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) {
+    int ret = 0;
+    secp256k1_ge p;
+    VERIFY_CHECK(ctx != NULL);
+    ARG_CHECK(pubkey != NULL);
+
+    ret = secp256k1_pubkey_load(ctx, &p, pubkey);
+    memset(pubkey, 0, sizeof(*pubkey));
+    if (ret) {
+        secp256k1_ge_neg(&p, &p);
+        secp256k1_pubkey_save(pubkey, &p);
+    }
+    return ret;
+}
+
 int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
     secp256k1_scalar term;
     secp256k1_scalar sec;


Test patch:
diff --git a/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/java/org/bitcoin/NativeSecp256k1Test.java
index c00d088..f18ce95 100644
--- a/src/java/org/bitcoin/NativeSecp256k1Test.java
+++ b/src/java/org/bitcoin/NativeSecp256k1Test.java
@@ -167,6 +167,22 @@ public class NativeSecp256k1Test {
         assertEquals( result, true, "testRandomize");
     }
 
+    /**
+      * This tests signSchnorr() for a valid secretkey
+      */
+    public static void testSchnorrSign() throws AssertFailException{
+
+        byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing"
+        byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
+
+        byte[] resultArr = NativeSecp256k1.schnorrSign(data, sec);
+        String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
+        assertEquals( sigString, "C5E929AA058B982048760422D3B563749B7D0E50C5EBD8CD2FFC23214BD6A2F1B072C13880997EBA847CF20F2F90FCE07C1CA33A890A4127095A351127F8D95F" , "testSchnorrSign");
+    }
+
+    /**
+      * This tests signSchnorr() for a valid secretkey
+      */
     public static void testCreateECDHSecret() throws AssertFailException{
 
         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
@@ -200,6 +216,11 @@ public class NativeSecp256k1Test {
         testSignPos();
         testSignNeg();
 
+        //Test Schnorr (partial support) //TODO
+        testSchnorrSign();
+        //testSchnorrVerify
+        //testSchnorrRecovery
+
         //Test privKeyTweakAdd() 1
         testPrivKeyTweakAdd_1();
 
diff --git a/src/modules/schnorr/tests_impl.h b/src/modules/schnorr/tests_impl.h
new file mode 100644
index 0000000..5bd14a0
--- /dev/null
+++ b/src/modules/schnorr/tests_impl.h
@@ -0,0 +1,175 @@
+/**********************************************************************
+ * Copyright (c) 2014-2015 Pieter Wuille                              *
+ * Distributed under the MIT software license, see the accompanying   *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef SECP256K1_MODULE_SCHNORR_TESTS
+#define SECP256K1_MODULE_SCHNORR_TESTS
+
+#include "include/secp256k1_schnorr.h"
+
+void test_schnorr_end_to_end(void) {
+    unsigned char privkey[32];
+    unsigned char message[32];
+    unsigned char schnorr_signature[64];
+    secp256k1_pubkey pubkey, recpubkey;
+
+    /* Generate a random key and message. */
+    {
+        secp256k1_scalar key;
+        random_scalar_order_test(&key);
+        secp256k1_scalar_get_b32(privkey, &key);
+        secp256k1_rand256_test(message);
+    }
+
+    /* Construct and verify corresponding public key. */
+    CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1);
+    CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1);
+
+    /* Schnorr sign. */
+    CHECK(secp256k1_schnorr_sign(ctx, schnorr_signature, message, privkey, NULL, NULL) == 1);
+    CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 1);
+    CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) == 1);
+    CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
+    /* Destroy signature and verify again. */
+    schnorr_signature[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255);
+    CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 0);
+    CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) != 1 ||
+          memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0);
+}
+
+/** Horribly broken hash function. Do not use for anything but tests. */
+void test_schnorr_hash(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) {
+    int i;
+    for (i = 0; i < 32; i++) {
+        h32[i] = r32[i] ^ msg32[i];
+    }
+}
+
+void test_schnorr_sign_verify(void) {
+    unsigned char msg32[32];
+    unsigned char sig64[3][64];
+    secp256k1_gej pubkeyj[3];
+    secp256k1_ge pubkey[3];
+    secp256k1_scalar nonce[3], key[3];
+    int i = 0;
+    int k;
+
+    secp256k1_rand256_test(msg32);
+
+    for (k = 0; k < 3; k++) {
+        random_scalar_order_test(&key[k]);
+
+        do {
+            random_scalar_order_test(&nonce[k]);
+            if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64[k], &key[k], &nonce[k], NULL, &test_schnorr_hash, msg32)) {
+                break;
+            }
+        } while(1);
+
+        secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj[k], &key[k]);
+        secp256k1_ge_set_gej_var(&pubkey[k], &pubkeyj[k]);
+        CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32));
+
+        for (i = 0; i < 4; i++) {
+            int pos = secp256k1_rand_bits(6);
+            int mod = 1 + secp256k1_rand_int(255);
+            sig64[k][pos] ^= mod;
+            CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32) == 0);
+            sig64[k][pos] ^= mod;
+        }
+    }
+}
+
+void test_schnorr_threshold(void) {
+    unsigned char msg[32];
+    unsigned char sec[5][32];
+    secp256k1_pubkey pub[5];
+    unsigned char nonce[5][32];
+    secp256k1_pubkey pubnonce[5];
+    unsigned char sig[5][64];
+    const unsigned char* sigs[5];
+    unsigned char allsig[64];
+    const secp256k1_pubkey* pubs[5];
+    secp256k1_pubkey allpub;
+    int n, i;
+    int damage;
+    int ret = 0;
+
+    damage = secp256k1_rand_bits(1) ? (1 + secp256k1_rand_int(4)) : 0;
+    secp256k1_rand256_test(msg);
+    n = 2 + secp256k1_rand_int(4);
+    for (i = 0; i < n; i++) {
+        do {
+            secp256k1_rand256_test(sec[i]);
+        } while (!secp256k1_ec_seckey_verify(ctx, sec[i]));
+        CHECK(secp256k1_ec_pubkey_create(ctx, &pub[i], sec[i]));
+        CHECK(secp256k1_schnorr_generate_nonce_pair(ctx, &pubnonce[i], nonce[i], msg, sec[i], NULL, NULL));
+        pubs[i] = &pub[i];
+    }
+    if (damage == 1) {
+        nonce[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
+    } else if (damage == 2) {
+        sec[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
+    }
+    for (i = 0; i < n; i++) {
+        secp256k1_pubkey allpubnonce;
+        const secp256k1_pubkey *pubnonces[4];
+        int j;
+        for (j = 0; j < i; j++) {
+            pubnonces[j] = &pubnonce[j];
+        }
+        for (j = i + 1; j < n; j++) {
+            pubnonces[j - 1] = &pubnonce[j];
+        }
+        CHECK(secp256k1_ec_pubkey_combine(ctx, &allpubnonce, pubnonces, n - 1));
+        ret |= (secp256k1_schnorr_partial_sign(ctx, sig[i], msg, sec[i], &allpubnonce, nonce[i]) != 1) * 1;
+        sigs[i] = sig[i];
+    }
+    if (damage == 3) {
+        sig[secp256k1_rand_int(n)][secp256k1_rand_bits(6)] ^= 1 + secp256k1_rand_int(255);
+    }
+    ret |= (secp256k1_ec_pubkey_combine(ctx, &allpub, pubs, n) != 1) * 2;
+    if ((ret & 1) == 0) {
+        ret |= (secp256k1_schnorr_partial_combine(ctx, allsig, sigs, n) != 1) * 4;
+    }
+    if (damage == 4) {
+        allsig[secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255);
+    }
+    if ((ret & 7) == 0) {
+        ret |= (secp256k1_schnorr_verify(ctx, allsig, msg, &allpub) != 1) * 8;
+    }
+    CHECK((ret == 0) == (damage == 0));
+}
+
+void test_schnorr_recovery(void) {
+    unsigned char msg32[32];
+    unsigned char sig64[64];
+    secp256k1_ge Q;
+
+    secp256k1_rand256_test(msg32);
+    secp256k1_rand256_test(sig64);
+    secp256k1_rand256_test(sig64 + 32);
+    if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &Q, &test_schnorr_hash, msg32) == 1) {
+        CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &Q, &test_schnorr_hash, msg32) == 1);
+    }
+}
+
+void run_schnorr_tests(void) {
+    int i;
+    for (i = 0; i < 32*count; i++) {
+        test_schnorr_end_to_end();
+    }
+    for (i = 0; i < 32 * count; i++) {
+         test_schnorr_sign_verify();
+    }
+    for (i = 0; i < 16 * count; i++) {
+         test_schnorr_recovery();
+    }
+    for (i = 0; i < 10 * count; i++) {
+         test_schnorr_threshold();
+    }
+}
+
+#endif
diff --git a/src/tests.c b/src/tests.c
index 9ae7d30..21ce055 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -10,6 +10,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <time.h>
 
@@ -135,6 +136,7 @@ void random_scalar_order(secp256k1_scalar *num) {
 
 void run_context_tests(void) {
     secp256k1_pubkey pubkey;
+    secp256k1_pubkey zero_pubkey;
     secp256k1_ecdsa_signature sig;
     unsigned char ctmp[32];
     int32_t ecount;
@@ -149,6 +151,8 @@ void run_context_tests(void) {
     secp256k1_scalar msg, key, nonce;
     secp256k1_scalar sigr, sigs;
 
+    memset(&zero_pubkey, 0, sizeof(zero_pubkey));
+
     ecount = 0;
     ecount2 = 10;
     secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
@@ -201,12 +205,20 @@ void run_context_tests(void) {
     CHECK(ecount == 2);
     CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
     CHECK(ecount2 == 13);
-    CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
+    CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
     CHECK(ecount == 2);
-    CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
+    CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
+    CHECK(ecount == 2);
+    CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
+    CHECK(ecount2 == 14);
+    CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
+    CHECK(ecount == 3);
+    CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
     CHECK(ecount == 3);
+    CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
+    CHECK(ecount == 4);
     CHECK(secp256k1_context_randomize(sign, NULL) == 1);
-    CHECK(ecount2 == 13);
+    CHECK(ecount2 == 14);
     secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
     secp256k1_context_set_illegal_callback(sign, NULL, NULL);
 
@@ -520,7 +532,7 @@ void test_num_mod(void) {
     secp256k1_num order, n;
 
     /* check that 0 mod anything is 0 */
-    random_scalar_order_test(&s);
+    random_scalar_order_test(&s); 
     secp256k1_scalar_get_num(&order, &s);
     secp256k1_scalar_set_int(&s, 0);
     secp256k1_scalar_get_num(&n, &s);
@@ -535,7 +547,7 @@ void test_num_mod(void) {
     CHECK(secp256k1_num_is_zero(&n));
 
     /* check that increasing the number past 2^256 does not break this */
-    random_scalar_order_test(&s);
+    random_scalar_order_test(&s); 
     secp256k1_scalar_get_num(&n, &s);
     /* multiply by 2^8, which'll test this case with high probability */
     for (i = 0; i < 8; ++i) {
@@ -568,7 +580,7 @@ void test_num_jacobi(void) {
     /* we first need a scalar which is not a multiple of 5 */
     do {
         secp256k1_num fiven;
-        random_scalar_order_test(&sqr);
+        random_scalar_order_test(&sqr); 
         secp256k1_scalar_get_num(&fiven, &five);
         secp256k1_scalar_get_num(&n, &sqr);
         secp256k1_num_mod(&n, &fiven);
@@ -587,7 +599,7 @@ void test_num_jacobi(void) {
 
     /** test with secp group order as order */
     secp256k1_scalar_order_get_num(&order);
-    random_scalar_order_test(&sqr);
+    random_scalar_order_test(&sqr); 
     secp256k1_scalar_sqr(&sqr, &sqr);
     /* test residue */
     secp256k1_scalar_get_num(&n, &sqr);
@@ -1733,18 +1745,18 @@ void run_field_inv_all_var(void) {
     secp256k1_fe x[16], xi[16], xii[16];
     int i;
     /* Check it's safe to call for 0 elements */
-    secp256k1_fe_inv_all_var(xi, x, 0);
+    secp256k1_fe_inv_all_var(0, xi, x);
     for (i = 0; i < count; i++) {
         size_t j;
         size_t len = secp256k1_rand_int(15) + 1;
         for (j = 0; j < len; j++) {
             random_fe_non_zero(&x[j]);
         }
-        secp256k1_fe_inv_all_var(xi, x, len);
+        secp256k1_fe_inv_all_var(len, xi, x);
         for (j = 0; j < len; j++) {
             CHECK(check_fe_inverse(&x[j], &xi[j]));
         }
-        secp256k1_fe_inv_all_var(xii, xi, len);
+        secp256k1_fe_inv_all_var(len, xii, xi);
         for (j = 0; j < len; j++) {
             CHECK(check_fe_equal(&x[j], &xii[j]));
         }
@@ -1930,7 +1942,7 @@ void test_ge(void) {
                 zs[i] = gej[i].z;
             }
         }
-        secp256k1_fe_inv_all_var(zinv, zs, 4 * runs + 1);
+        secp256k1_fe_inv_all_var(4 * runs + 1, zinv, zs);
         free(zs);
     }
 
@@ -2050,8 +2062,8 @@ void test_ge(void) {
                 secp256k1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z);
             }
         }
-        secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1);
-        secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback);
+        secp256k1_ge_set_table_gej_var(4 * runs + 1, ge_set_table, gej, zr);
+        secp256k1_ge_set_all_gej_var(4 * runs + 1, ge_set_all, gej, &ctx->error_callback);
         for (i = 0; i < 4 * runs + 1; i++) {
             secp256k1_fe s;
             random_fe_non_zero(&s);
@@ -3436,6 +3448,7 @@ void test_ecdsa_end_to_end(void) {
     unsigned char pubkeyc[65];
     size_t pubkeyclen = 65;
     secp256k1_pubkey pubkey;
+    secp256k1_pubkey pubkey_tmp;
     unsigned char seckey[300];
     size_t seckeylen = 300;
 
@@ -3457,6 +3470,13 @@ void test_ecdsa_end_to_end(void) {
     memset(&pubkey, 0, sizeof(pubkey));
     CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);
 
+    /* Verify negation changes the key and changes it back */
+    memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey));
+    CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
+    CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0);
+    CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
+    CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0);
+
     /* Verify private key import and export. */
     CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1));
     CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c
deleted file mode 100644
index bda6ee4..0000000
--- a/src/tests_exhaustive.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/***********************************************************************
- * Copyright (c) 2016 Andrew Poelstra                                 *
- * Distributed under the MIT software license, see the accompanying   *
- * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
- **********************************************************************/
-
-#if defined HAVE_CONFIG_H
-#include "libsecp256k1-config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <time.h>
-
-#undef USE_ECMULT_STATIC_PRECOMPUTATION
-
-#ifndef EXHAUSTIVE_TEST_ORDER
-/* see group_impl.h for allowable values */
-#define EXHAUSTIVE_TEST_ORDER 13
-#define EXHAUSTIVE_TEST_LAMBDA 9   /* cube root of 1 mod 13 */
-#endif
-
-#include "include/secp256k1.h"
-#include "group.h"
-#include "secp256k1.c"
-#include "testrand_impl.h"
-
-/** stolen from tests.c */
-void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) {
-    CHECK(a->infinity == b->infinity);
-    if (a->infinity) {
-        return;
-    }
-    CHECK(secp256k1_fe_equal_var(&a->x, &b->x));
-    CHECK(secp256k1_fe_equal_var(&a->y, &b->y));
-}
-
-void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) {
-    secp256k1_fe z2s;
-    secp256k1_fe u1, u2, s1, s2;
-    CHECK(a->infinity == b->infinity);
-    if (a->infinity) {
-        return;
-    }
-    /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */
-    secp256k1_fe_sqr(&z2s, &b->z);
-    secp256k1_fe_mul(&u1, &a->x, &z2s);
-    u2 = b->x; secp256k1_fe_normalize_weak(&u2);
-    secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z);
-    s2 = b->y; secp256k1_fe_normalize_weak(&s2);
-    CHECK(secp256k1_fe_equal_var(&u1, &u2));
-    CHECK(secp256k1_fe_equal_var(&s1, &s2));
-}
-
-void random_fe(secp256k1_fe *x) {
-    unsigned char bin[32];
-    do {
-        secp256k1_rand256(bin);
-        if (secp256k1_fe_set_b32(x, bin)) {
-            return;
-        }
-    } while(1);
-}
-/** END stolen from tests.c */
-
-int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32,
-                                      const unsigned char *key32, const unsigned char *algo16,
-                                      void *data, unsigned int attempt) {
-    secp256k1_scalar s;
-    int *idata = data;
-    (void)msg32;
-    (void)key32;
-    (void)algo16;
-    /* Some nonces cannot be used because they'd cause s and/or r to be zero.
-     * The signing function has retry logic here that just re-calls the nonce
-     * function with an increased `attempt`. So if attempt > 0 this means we
-     * need to change the nonce to avoid an infinite loop. */
-    if (attempt > 0) {
-        (*idata)++;
-    }
-    secp256k1_scalar_set_int(&s, *idata);
-    secp256k1_scalar_get_b32(nonce32, &s);
-    return 1;
-}
-
-#ifdef USE_ENDOMORPHISM
-void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) {
-    int i;
-    for (i = 0; i < order; i++) {
-        secp256k1_ge res;
-        secp256k1_ge_mul_lambda(&res, &group[i]);
-        ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res);
-    }
-}
-#endif
-
-void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) {
-    int i, j;
-
-    /* Sanity-check (and check infinity functions) */
-    CHECK(secp256k1_ge_is_infinity(&group[0]));
-    CHECK(secp256k1_gej_is_infinity(&groupj[0]));
-    for (i = 1; i < order; i++) {
-        CHECK(!secp256k1_ge_is_infinity(&group[i]));
-        CHECK(!secp256k1_gej_is_infinity(&groupj[i]));
-    }
-
-    /* Check all addition formulae */
-    for (j = 0; j < order; j++) {
-        secp256k1_fe fe_inv;
-        secp256k1_fe_inv(&fe_inv, &groupj[j].z);
-        for (i = 0; i < order; i++) {
-            secp256k1_ge zless_gej;
-            secp256k1_gej tmp;
-            /* add_var */
-            secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL);
-            ge_equals_gej(&group[(i + j) % order], &tmp);
-            /* add_ge */
-            if (j > 0) {
-                secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]);
-                ge_equals_gej(&group[(i + j) % order], &tmp);
-            }
-            /* add_ge_var */
-            secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL);
-            ge_equals_gej(&group[(i + j) % order], &tmp);
-            /* add_zinv_var */
-            zless_gej.infinity = groupj[j].infinity;
-            zless_gej.x = groupj[j].x;
-            zless_gej.y = groupj[j].y;
-            secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv);
-            ge_equals_gej(&group[(i + j) % order], &tmp);
-        }
-    }
-
-    /* Check doubling */
-    for (i = 0; i < order; i++) {
-        secp256k1_gej tmp;
-        if (i > 0) {
-            secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL);
-            ge_equals_gej(&group[(2 * i) % order], &tmp);
-        }
-        secp256k1_gej_double_var(&tmp, &groupj[i], NULL);
-        ge_equals_gej(&group[(2 * i) % order], &tmp);
-    }
-
-    /* Check negation */
-    for (i = 1; i < order; i++) {
-        secp256k1_ge tmp;
-        secp256k1_gej tmpj;
-        secp256k1_ge_neg(&tmp, &group[i]);
-        ge_equals_ge(&group[order - i], &tmp);
-        secp256k1_gej_neg(&tmpj, &groupj[i]);
-        ge_equals_gej(&group[order - i], &tmpj);
-    }
-}
-
-void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) {
-    int i, j, r_log;
-    for (r_log = 1; r_log < order; r_log++) {
-        for (j = 0; j < order; j++) {
-            for (i = 0; i < order; i++) {
-                secp256k1_gej tmp;
-                secp256k1_scalar na, ng;
-                secp256k1_scalar_set_int(&na, i);
-                secp256k1_scalar_set_int(&ng, j);
-
-                secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng);
-                ge_equals_gej(&group[(i * r_log + j) % order], &tmp);
-
-                if (i > 0) {
-                    secp256k1_ecmult_const(&tmp, &group[i], &ng);
-                    ge_equals_gej(&group[(i * j) % order], &tmp);
-                }
-            }
-        }
-    }
-}
-
-void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) {
-    secp256k1_fe x;
-    unsigned char x_bin[32];
-    k %= EXHAUSTIVE_TEST_ORDER;
-    x = group[k].x;
-    secp256k1_fe_normalize(&x);
-    secp256k1_fe_get_b32(x_bin, &x);
-    secp256k1_scalar_set_b32(r, x_bin, NULL);
-}
-
-void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
-    int s, r, msg, key;
-    for (s = 1; s < order; s++) {
-        for (r = 1; r < order; r++) {
-            for (msg = 1; msg < order; msg++) {
-                for (key = 1; key < order; key++) {
-                    secp256k1_ge nonconst_ge;
-                    secp256k1_ecdsa_signature sig;
-                    secp256k1_pubkey pk;
-                    secp256k1_scalar sk_s, msg_s, r_s, s_s;
-                    secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s;
-                    int k, should_verify;
-                    unsigned char msg32[32];
-
-                    secp256k1_scalar_set_int(&s_s, s);
-                    secp256k1_scalar_set_int(&r_s, r);
-                    secp256k1_scalar_set_int(&msg_s, msg);
-                    secp256k1_scalar_set_int(&sk_s, key);
-
-                    /* Verify by hand */
-                    /* Run through every k value that gives us this r and check that *one* works.
-                     * Note there could be none, there could be multiple, ECDSA is weird. */
-                    should_verify = 0;
-                    for (k = 0; k < order; k++) {
-                        secp256k1_scalar check_x_s;
-                        r_from_k(&check_x_s, group, k);
-                        if (r_s == check_x_s) {
-                            secp256k1_scalar_set_int(&s_times_k_s, k);
-                            secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s);
-                            secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s);
-                            secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s);
-                            should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s);
-                        }
-                    }
-                    /* nb we have a "high s" rule */
-                    should_verify &= !secp256k1_scalar_is_high(&s_s);
-
-                    /* Verify by calling verify */
-                    secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s);
-                    memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge));
-                    secp256k1_pubkey_save(&pk, &nonconst_ge);
-                    secp256k1_scalar_get_b32(msg32, &msg_s);
-                    CHECK(should_verify ==
-                          secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk));
-                }
-            }
-        }
-    }
-}
-
-void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
-    int i, j, k;
-
-    /* Loop */
-    for (i = 1; i < order; i++) {  /* message */
-        for (j = 1; j < order; j++) {  /* key */
-            for (k = 1; k < order; k++) {  /* nonce */
-                secp256k1_ecdsa_signature sig;
-                secp256k1_scalar sk, msg, r, s, expected_r;
-                unsigned char sk32[32], msg32[32];
-                secp256k1_scalar_set_int(&msg, i);
-                secp256k1_scalar_set_int(&sk, j);
-                secp256k1_scalar_get_b32(sk32, &sk);
-                secp256k1_scalar_get_b32(msg32, &msg);
-
-                secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k);
-
-                secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig);
-                /* Note that we compute expected_r *after* signing -- this is important
-                 * because our nonce-computing function function might change k during
-                 * signing. */
-                r_from_k(&expected_r, group, k);
-                CHECK(r == expected_r);
-                CHECK((k * s) % order == (i + r * j) % order ||
-                      (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order);
-            }
-        }
-    }
-
-    /* We would like to verify zero-knowledge here by counting how often every
-     * possible (s, r) tuple appears, but because the group order is larger
-     * than the field order, when coercing the x-values to scalar values, some
-     * appear more often than others, so we are actually not zero-knowledge.
-     * (This effect also appears in the real code, but the difference is on the
-     * order of 1/2^128th the field order, so the deviation is not useful to a
-     * computationally bounded attacker.)
-     */
-}
-
-int main(void) {
-    int i;
-    secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER];
-    secp256k1_ge group[EXHAUSTIVE_TEST_ORDER];
-
-    /* Build context */
-    secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
-
-    /* TODO set z = 1, then do num_tests runs with random z values */
-
-    /* Generate the entire group */
-    secp256k1_gej_set_infinity(&groupj[0]);
-    secp256k1_ge_set_gej(&group[0], &groupj[0]);
-    for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
-        /* Set a different random z-value for each Jacobian point */
-        secp256k1_fe z;
-        random_fe(&z);
-
-        secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g);
-        secp256k1_ge_set_gej(&group[i], &groupj[i]);
-        secp256k1_gej_rescale(&groupj[i], &z);
-
-        /* Verify against ecmult_gen */
-        {
-            secp256k1_scalar scalar_i;
-            secp256k1_gej generatedj;
-            secp256k1_ge generated;
-
-            secp256k1_scalar_set_int(&scalar_i, i);
-            secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i);
-            secp256k1_ge_set_gej(&generated, &generatedj);
-
-            CHECK(group[i].infinity == 0);
-            CHECK(generated.infinity == 0);
-            CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x));
-            CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y));
-        }
-    }
-
-    /* Run the tests */
-#ifdef USE_ENDOMORPHISM
-    test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER);
-#endif
-    test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER);
-    test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER);
-    test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
-    test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER);
-
-    return 0;
-}
-