diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 194b9f5a5..449843ccd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ concurrency: cancel-in-progress: true env: - COINCURVE_UPSTREAM_REF: acf5c55ae6a94e5ca847e07def40427547876101 + COINCURVE_UPSTREAM_REF: 1ad5185cd42c0636104129fcc9f6a4bf9c67cc40 COINCURVE_IGNORE_SYSTEM_LIB: '1' CIBW_BEFORE_ALL_MACOS: ./.github/scripts/install-macos-build-deps.sh CIBW_ENVIRONMENT_PASS_LINUX: > @@ -38,7 +38,7 @@ jobs: runs-on: ubuntu-latest env: - PYTHON_VERSION: '3.10' + PYTHON_VERSION: '3.12' steps: - uses: actions/checkout@v3 @@ -75,7 +75,7 @@ jobs: name: Build Linux wheels needs: - test - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 @@ -99,7 +99,7 @@ jobs: - uses: actions/checkout@v3 - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.16.2 env: CIBW_ARCHS_MACOS: x86_64 @@ -119,7 +119,7 @@ jobs: - uses: actions/checkout@v3 - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.16.2 env: CIBW_ARCHS_MACOS: arm64 COINCURVE_CROSS_HOST: aarch64-apple-darwin @@ -174,7 +174,7 @@ jobs: platforms: arm64 - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.16.2 env: CIBW_ARCHS_LINUX: aarch64 diff --git a/MANIFEST.in b/MANIFEST.in index 06dc9ba47..6059c9358 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ include coincurve/py.typed include setup_support.py recursive-include _cffi_build *.py *.h +prune /* graft libsecp256k1 diff --git a/_cffi_build/build.py b/_cffi_build/build.py index f942d5d8f..f478fb58a 100644 --- a/_cffi_build/build.py +++ b/_cffi_build/build.py @@ -29,6 +29,8 @@ def _mk_ffi(sources, name='_libsecp256k1', **kwargs): Source('secp256k1_extrakeys.h', '#include '), Source('secp256k1_recovery.h', '#include '), Source('secp256k1_schnorrsig.h', '#include '), + Source('secp256k1_ellswift.h', '#include '), + Source('secp256k1_preallocated.h', '#include '), ] ffi = _mk_ffi(modules, libraries=['secp256k1']) diff --git a/_cffi_build/build_shared.py b/_cffi_build/build_shared.py new file mode 100644 index 000000000..4ad89d38e --- /dev/null +++ b/_cffi_build/build_shared.py @@ -0,0 +1,84 @@ +import argparse +import logging +import os +from collections import namedtuple +from typing import List + +from cffi import FFI + +logging.basicConfig(level=logging.INFO) + +here = os.path.dirname(os.path.abspath(__file__)) + +Source = namedtuple('Source', ('h', 'include')) + + +def gather_sources_from_directory(directory: str) -> List[Source]: + """ + Gather source files from a given directory. + + :param directory: The directory where source files are located. + :return: A list of Source namedtuples. + """ + sources = [] + for filename in os.listdir(directory): + if filename.endswith('.h'): + include_line = f'#include <{filename}>' + sources.append(Source(filename, include_line)) + return sorted(sources) + + +define_static_lib = """ +#if defined(_WIN32) +# define SECP256K1_STATIC 1 +# define SECP256K1_API extern __declspec(dllexport) +#endif +""" + +define_shared_lib = """ +#if defined(_WIN32) +# define SECP256K1_API extern __declspec(dllimport) +#endif +""" + + +def mk_ffi(sources: List[Source], + static_lib: str = '0', + name: str = '_libsecp256k1') -> FFI: + """ + Create an FFI object. + + :param sources: A list of Source namedtuples. + :param libraries: A list of libraries to link against. + :param static_lib: Whether to generate a static lib in Windows. + :param name: The name of the FFI object. + :return: An FFI object. + """ + _ffi = FFI() + code = [define_static_lib] if static_lib == '1' else [define_shared_lib] + + for source in sources: + with open(os.path.join(here, source.h)) as h: + logging.info(f' Including {source.h}...') + c_header = h.read().replace('SECP256K1_API', '') + _ffi.cdef(c_header) + + code.append(source.include) + + code.append('#define PY_USE_BUNDLED') + _ffi.set_source(name, '\n'.join(code)) + + return _ffi + + +if __name__ == '__main__': + logging.info('Starting CFFI build process...') + parser = argparse.ArgumentParser(description='Generate C code using CFFI.') + parser.add_argument('c_file', help='Generated C code filename.') + parser.add_argument('static_lib', help='Generate static lib in Windows.', default=False) + args = parser.parse_args() + + modules = gather_sources_from_directory(here) + ffi = mk_ffi(modules, args.static_lib) + ffi.emit_c_code(args.c_file) + logging.info(f' Generated C code: {args.c_file}') diff --git a/_cffi_build/secp256k1.h b/_cffi_build/secp256k1.h index d71c3e508..5c5f1b8f1 100644 --- a/_cffi_build/secp256k1.h +++ b/_cffi_build/secp256k1.h @@ -1,14 +1,11 @@ typedef struct secp256k1_context_struct secp256k1_context; typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; - typedef struct { unsigned char data[64]; } secp256k1_pubkey; - typedef struct { unsigned char data[64]; } secp256k1_ecdsa_signature; - typedef int (*secp256k1_nonce_function)( unsigned char *nonce32, const unsigned char *msg32, @@ -17,7 +14,6 @@ typedef int (*secp256k1_nonce_function)( void *data, unsigned int attempt ); - #define SECP256K1_FLAGS_TYPE_MASK ... #define SECP256K1_FLAGS_TYPE_CONTEXT ... #define SECP256K1_FLAGS_TYPE_COMPRESSION ... @@ -25,164 +21,157 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_FLAGS_BIT_CONTEXT_SIGN ... #define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY ... #define SECP256K1_FLAGS_BIT_COMPRESSION ... - #define SECP256K1_CONTEXT_NONE ... - #define SECP256K1_CONTEXT_VERIFY ... #define SECP256K1_CONTEXT_SIGN ... - #define SECP256K1_CONTEXT_DECLASSIFY ... - #define SECP256K1_EC_COMPRESSED ... #define SECP256K1_EC_UNCOMPRESSED ... - #define SECP256K1_TAG_PUBKEY_EVEN ... #define SECP256K1_TAG_PUBKEY_ODD ... #define SECP256K1_TAG_PUBKEY_UNCOMPRESSED ... -#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN ... -#define SECP256K1_TAG_PUBKEY_HYBRID_ODD ... - -void secp256k1_selftest(void); - -secp256k1_context* secp256k1_context_create( +extern const secp256k1_context *secp256k1_context_static; +extern void secp256k1_selftest(void); +extern secp256k1_context *secp256k1_context_create( unsigned int flags ); - -secp256k1_context* secp256k1_context_clone( - const secp256k1_context* ctx -); - -void secp256k1_context_destroy( - secp256k1_context* ctx -); - -void secp256k1_context_set_illegal_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -); - -void secp256k1_context_set_error_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -); - -secp256k1_scratch_space* secp256k1_scratch_space_create( - const secp256k1_context* ctx, +extern secp256k1_context *secp256k1_context_clone( + const secp256k1_context *ctx +); +extern void secp256k1_context_destroy( + secp256k1_context *ctx +); +extern void secp256k1_context_set_illegal_callback( + secp256k1_context *ctx, + void (*fun)(const char *message, void *data), + const void *data +); +extern void secp256k1_context_set_error_callback( + secp256k1_context *ctx, + void (*fun)(const char *message, void *data), + const void *data +); +extern secp256k1_scratch_space *secp256k1_scratch_space_create( + const secp256k1_context *ctx, size_t size ); - -int secp256k1_ec_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_pubkey* pubkey, +extern void secp256k1_scratch_space_destroy( + const secp256k1_context *ctx, + secp256k1_scratch_space *scratch +); +extern int secp256k1_ec_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen ); - -int secp256k1_ec_pubkey_serialize( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_serialize( + const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, - const secp256k1_pubkey* pubkey, + const secp256k1_pubkey *pubkey, unsigned int flags ); - -int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, +extern int secp256k1_ec_pubkey_cmp( + const secp256k1_context *ctx, + const secp256k1_pubkey *pubkey1, + const secp256k1_pubkey *pubkey2 +); +extern int secp256k1_ecdsa_signature_parse_compact( + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, const unsigned char *input64 ); - -int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, +extern int secp256k1_ecdsa_signature_parse_der( + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, const unsigned char *input, size_t inputlen ); - -int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_signature_serialize_der( + const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, - const secp256k1_ecdsa_signature* sig + const secp256k1_ecdsa_signature *sig ); - -int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_signature_serialize_compact( + const secp256k1_context *ctx, unsigned char *output64, - const secp256k1_ecdsa_signature* sig + const secp256k1_ecdsa_signature *sig ); - -int secp256k1_ecdsa_verify( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_verify( + const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const secp256k1_pubkey *pubkey ); - -int secp256k1_ecdsa_signature_normalize( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_signature_normalize( + const secp256k1_context *ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin ); - extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; - extern const secp256k1_nonce_function secp256k1_nonce_function_default; - -int secp256k1_ecdsa_sign( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_sign( + const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ); - -int secp256k1_ec_seckey_verify( - const secp256k1_context* ctx, +extern int secp256k1_ec_seckey_verify( + const secp256k1_context *ctx, const unsigned char *seckey ); - -int secp256k1_ec_pubkey_create( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_create( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey ); - -int secp256k1_ec_privkey_tweak_add( - const secp256k1_context* ctx, +extern int secp256k1_ec_seckey_negate( + const secp256k1_context *ctx, + unsigned char *seckey +); +extern int secp256k1_ec_pubkey_negate( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey +); +extern int secp256k1_ec_seckey_tweak_add( + const secp256k1_context *ctx, unsigned char *seckey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_tweak_add( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context* ctx, +extern int secp256k1_ec_seckey_tweak_mul( + const secp256k1_context *ctx, unsigned char *seckey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_tweak_mul( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_context_randomize( - secp256k1_context* ctx, +extern int secp256k1_context_randomize( + secp256k1_context *ctx, const unsigned char *seed32 ); - -int secp256k1_ec_pubkey_combine( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_combine( + const secp256k1_context *ctx, secp256k1_pubkey *out, - const secp256k1_pubkey * const * ins, + const secp256k1_pubkey * const *ins, size_t n ); +extern int secp256k1_tagged_sha256( + const secp256k1_context *ctx, + unsigned char *hash32, + const unsigned char *tag, + size_t taglen, + const unsigned char *msg, + size_t msglen +); diff --git a/_cffi_build/secp256k1_ecdh.h b/_cffi_build/secp256k1_ecdh.h index 1a61c7307..f9a074818 100644 --- a/_cffi_build/secp256k1_ecdh.h +++ b/_cffi_build/secp256k1_ecdh.h @@ -1,8 +1,16 @@ -int secp256k1_ecdh( - const secp256k1_context* ctx, - unsigned char *result, - const secp256k1_pubkey *pubkey, - const unsigned char *privkey, - void *hashfp, +typedef int (*secp256k1_ecdh_hash_function)( + unsigned char *output, + const unsigned char *x32, + const unsigned char *y32, void *data ); +extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; +extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; +extern int secp256k1_ecdh( + const secp256k1_context *ctx, + unsigned char *output, + const secp256k1_pubkey *pubkey, + const unsigned char *seckey, + secp256k1_ecdh_hash_function hashfp, + void *data +) ; diff --git a/_cffi_build/secp256k1_ellswift.h b/_cffi_build/secp256k1_ellswift.h new file mode 100644 index 000000000..25542c69f --- /dev/null +++ b/_cffi_build/secp256k1_ellswift.h @@ -0,0 +1,36 @@ +typedef int (*secp256k1_ellswift_xdh_hash_function)( + unsigned char *output, + const unsigned char *x32, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + void *data +); +extern const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix; +extern const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324; +extern int secp256k1_ellswift_encode( + const secp256k1_context *ctx, + unsigned char *ell64, + const secp256k1_pubkey *pubkey, + const unsigned char *rnd32 +) ; +extern int secp256k1_ellswift_decode( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, + const unsigned char *ell64 +) ; +extern int secp256k1_ellswift_create( + const secp256k1_context *ctx, + unsigned char *ell64, + const unsigned char *seckey32, + const unsigned char *auxrnd32 +) ; +extern int secp256k1_ellswift_xdh( + const secp256k1_context *ctx, + unsigned char *output, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + const unsigned char *seckey32, + int party, + secp256k1_ellswift_xdh_hash_function hashfp, + void *data +) ; diff --git a/_cffi_build/secp256k1_extrakeys.h b/_cffi_build/secp256k1_extrakeys.h index 36d4c5784..02dd798d8 100644 --- a/_cffi_build/secp256k1_extrakeys.h +++ b/_cffi_build/secp256k1_extrakeys.h @@ -1,78 +1,66 @@ typedef struct { unsigned char data[64]; } secp256k1_xonly_pubkey; - typedef struct { unsigned char data[96]; } secp256k1_keypair; - -int secp256k1_xonly_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_xonly_pubkey* pubkey, +extern int secp256k1_xonly_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *pubkey, const unsigned char *input32 -); - -int secp256k1_xonly_pubkey_serialize( - const secp256k1_context* ctx, +) ; +extern int secp256k1_xonly_pubkey_serialize( + const secp256k1_context *ctx, unsigned char *output32, - const secp256k1_xonly_pubkey* pubkey -); - -int secp256k1_xonly_pubkey_cmp( - const secp256k1_context* ctx, - const secp256k1_xonly_pubkey* pk1, - const secp256k1_xonly_pubkey* pk2 -); - -int secp256k1_xonly_pubkey_from_pubkey( - const secp256k1_context* ctx, + const secp256k1_xonly_pubkey *pubkey +) ; +extern int secp256k1_xonly_pubkey_cmp( + const secp256k1_context *ctx, + const secp256k1_xonly_pubkey *pk1, + const secp256k1_xonly_pubkey *pk2 +) ; +extern int secp256k1_xonly_pubkey_from_pubkey( + const secp256k1_context *ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey -); - -int secp256k1_xonly_pubkey_tweak_add( - const secp256k1_context* ctx, +) ; +extern int secp256k1_xonly_pubkey_tweak_add( + const secp256k1_context *ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32 -); - -int secp256k1_xonly_pubkey_tweak_add_check( - const secp256k1_context* ctx, +) ; +extern int secp256k1_xonly_pubkey_tweak_add_check( + const secp256k1_context *ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32 -); - -int secp256k1_keypair_create( - const secp256k1_context* ctx, +) ; +extern int secp256k1_keypair_create( + const secp256k1_context *ctx, secp256k1_keypair *keypair, const unsigned char *seckey -); - -int secp256k1_keypair_sec( - const secp256k1_context* ctx, +) ; +extern int secp256k1_keypair_sec( + const secp256k1_context *ctx, unsigned char *seckey, const secp256k1_keypair *keypair -); - -int secp256k1_keypair_pub( - const secp256k1_context* ctx, +) ; +extern int secp256k1_keypair_pub( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair -); - -int secp256k1_keypair_xonly_pub( - const secp256k1_context* ctx, +) ; +extern int secp256k1_keypair_xonly_pub( + const secp256k1_context *ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair -); - -int secp256k1_keypair_xonly_tweak_add( - const secp256k1_context* ctx, +) ; +extern int secp256k1_keypair_xonly_tweak_add( + const secp256k1_context *ctx, secp256k1_keypair *keypair, const unsigned char *tweak32 -); +) ; diff --git a/_cffi_build/secp256k1_preallocated.h b/_cffi_build/secp256k1_preallocated.h new file mode 100644 index 000000000..a4a39bbe0 --- /dev/null +++ b/_cffi_build/secp256k1_preallocated.h @@ -0,0 +1,17 @@ +extern size_t secp256k1_context_preallocated_size( + unsigned int flags +) ; +extern secp256k1_context *secp256k1_context_preallocated_create( + void *prealloc, + unsigned int flags +) ; +extern size_t secp256k1_context_preallocated_clone_size( + const secp256k1_context *ctx +) ; +extern secp256k1_context *secp256k1_context_preallocated_clone( + const secp256k1_context *ctx, + void *prealloc +) ; +extern void secp256k1_context_preallocated_destroy( + secp256k1_context *ctx +) ; diff --git a/_cffi_build/secp256k1_recovery.h b/_cffi_build/secp256k1_recovery.h index 5319cb7a8..f650e6047 100644 --- a/_cffi_build/secp256k1_recovery.h +++ b/_cffi_build/secp256k1_recovery.h @@ -1,39 +1,34 @@ typedef struct { unsigned char data[65]; } secp256k1_ecdsa_recoverable_signature; - -int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature* sig, +extern int secp256k1_ecdsa_recoverable_signature_parse_compact( + const secp256k1_context *ctx, + secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid -); - -int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const secp256k1_ecdsa_recoverable_signature* sigin -); - -int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context* ctx, +) ; +extern int secp256k1_ecdsa_recoverable_signature_convert( + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, + const secp256k1_ecdsa_recoverable_signature *sigin +) ; +extern int secp256k1_ecdsa_recoverable_signature_serialize_compact( + const secp256k1_context *ctx, unsigned char *output64, int *recid, - const secp256k1_ecdsa_recoverable_signature* sig -); - -int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context* ctx, + const secp256k1_ecdsa_recoverable_signature *sig +) ; +extern int secp256k1_ecdsa_sign_recoverable( + const secp256k1_context *ctx, secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata -); - -int secp256k1_ecdsa_recover( - const secp256k1_context* ctx, +) ; +extern int secp256k1_ecdsa_recover( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32 -); + const unsigned char *msghash32 +) ; diff --git a/_cffi_build/secp256k1_schnorrsig.h b/_cffi_build/secp256k1_schnorrsig.h index 137022f96..9762e8824 100644 --- a/_cffi_build/secp256k1_schnorrsig.h +++ b/_cffi_build/secp256k1_schnorrsig.h @@ -8,44 +8,31 @@ typedef int (*secp256k1_nonce_function_hardened)( size_t algolen, void *data ); - extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; - typedef struct { unsigned char magic[4]; secp256k1_nonce_function_hardened noncefp; - void* ndata; + void *ndata; } secp256k1_schnorrsig_extraparams; - -int secp256k1_schnorrsig_sign( - const secp256k1_context* ctx, +extern int secp256k1_schnorrsig_sign32( + const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32 -); - -int secp256k1_schnorrsig_sign32( - const secp256k1_context* ctx, - unsigned char *sig64, - const unsigned char *msg32, - const secp256k1_keypair *keypair, - const unsigned char *aux_rand32 -); - -int secp256k1_schnorrsig_sign_custom( - const secp256k1_context* ctx, +) ; +extern int secp256k1_schnorrsig_sign_custom( + const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams -); - -int secp256k1_schnorrsig_verify( - const secp256k1_context* ctx, +) ; +extern int secp256k1_schnorrsig_verify( + const secp256k1_context *ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_xonly_pubkey *pubkey -); +) ; diff --git a/coincurve/_windows_libsecp256k1.py b/coincurve/_windows_libsecp256k1.py index a99a02721..07b07961f 100644 --- a/coincurve/_windows_libsecp256k1.py +++ b/coincurve/_windows_libsecp256k1.py @@ -44,90 +44,83 @@ #define SECP256K1_TAG_PUBKEY_EVEN ... #define SECP256K1_TAG_PUBKEY_ODD ... #define SECP256K1_TAG_PUBKEY_UNCOMPRESSED ... -#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN ... -#define SECP256K1_TAG_PUBKEY_HYBRID_ODD ... - -void secp256k1_selftest(void); - -secp256k1_context* secp256k1_context_create( +extern const secp256k1_context *secp256k1_context_static; +extern void secp256k1_selftest(void); +extern secp256k1_context *secp256k1_context_create( unsigned int flags ); - -secp256k1_context* secp256k1_context_clone( - const secp256k1_context* ctx +extern secp256k1_context *secp256k1_context_clone( + const secp256k1_context *ctx ); - -void secp256k1_context_destroy( - secp256k1_context* ctx +extern void secp256k1_context_destroy( + secp256k1_context *ctx ); - -void secp256k1_context_set_illegal_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data +extern void secp256k1_context_set_illegal_callback( + secp256k1_context *ctx, + void (*fun)(const char *message, void *data), + const void *data ); - -void secp256k1_context_set_error_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data +extern void secp256k1_context_set_error_callback( + secp256k1_context *ctx, + void (*fun)(const char *message, void *data), + const void *data ); - -secp256k1_scratch_space* secp256k1_scratch_space_create( - const secp256k1_context* ctx, +extern secp256k1_scratch_space *secp256k1_scratch_space_create( + const secp256k1_context *ctx, size_t size ); - -int secp256k1_ec_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_pubkey* pubkey, +extern void secp256k1_scratch_space_destroy( + const secp256k1_context *ctx, + secp256k1_scratch_space *scratch +); +extern int secp256k1_ec_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen ); - -int secp256k1_ec_pubkey_serialize( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_serialize( + const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, - const secp256k1_pubkey* pubkey, + const secp256k1_pubkey *pubkey, unsigned int flags ); - -int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, +extern int secp256k1_ec_pubkey_cmp( + const secp256k1_context *ctx, + const secp256k1_pubkey *pubkey1, + const secp256k1_pubkey *pubkey2 +); +extern int secp256k1_ecdsa_signature_parse_compact( + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, const unsigned char *input64 ); - -int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, +extern int secp256k1_ecdsa_signature_parse_der( + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, const unsigned char *input, size_t inputlen ); - -int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_signature_serialize_der( + const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, - const secp256k1_ecdsa_signature* sig + const secp256k1_ecdsa_signature *sig ); - -int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_signature_serialize_compact( + const secp256k1_context *ctx, unsigned char *output64, - const secp256k1_ecdsa_signature* sig + const secp256k1_ecdsa_signature *sig ); - -int secp256k1_ecdsa_verify( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_verify( + const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const secp256k1_pubkey *pubkey ); - -int secp256k1_ecdsa_signature_normalize( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_signature_normalize( + const secp256k1_context *ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin ); @@ -136,139 +129,135 @@ extern const secp256k1_nonce_function secp256k1_nonce_function_default; -int secp256k1_ecdsa_sign( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_sign( + const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ); - -int secp256k1_ec_seckey_verify( - const secp256k1_context* ctx, +extern int secp256k1_ec_seckey_verify( + const secp256k1_context *ctx, const unsigned char *seckey ); - -int secp256k1_ec_pubkey_create( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_create( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey ); - -int secp256k1_ec_privkey_tweak_add( - const secp256k1_context* ctx, +extern int secp256k1_ec_seckey_negate( + const secp256k1_context *ctx, + unsigned char *seckey +); +extern int secp256k1_ec_pubkey_negate( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey +); +extern int secp256k1_ec_seckey_tweak_add( + const secp256k1_context *ctx, unsigned char *seckey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_tweak_add( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context* ctx, +extern int secp256k1_ec_seckey_tweak_mul( + const secp256k1_context *ctx, unsigned char *seckey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_tweak_mul( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, - const unsigned char *tweak + const unsigned char *tweak32 ); - -int secp256k1_context_randomize( - secp256k1_context* ctx, +extern int secp256k1_context_randomize( + secp256k1_context *ctx, const unsigned char *seed32 ); - -int secp256k1_ec_pubkey_combine( - const secp256k1_context* ctx, +extern int secp256k1_ec_pubkey_combine( + const secp256k1_context *ctx, secp256k1_pubkey *out, - const secp256k1_pubkey * const * ins, + const secp256k1_pubkey * const *ins, size_t n ); +extern int secp256k1_tagged_sha256( + const secp256k1_context *ctx, + unsigned char *hash32, + const unsigned char *tag, + size_t taglen, + const unsigned char *msg, + size_t msglen +); """ EXTRAKEYS_DEFINITIONS = """ typedef struct { unsigned char data[64]; } secp256k1_xonly_pubkey; - typedef struct { unsigned char data[96]; } secp256k1_keypair; - -int secp256k1_xonly_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_xonly_pubkey* pubkey, +extern int secp256k1_xonly_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *pubkey, const unsigned char *input32 ); - -int secp256k1_xonly_pubkey_serialize( - const secp256k1_context* ctx, +extern int secp256k1_xonly_pubkey_serialize( + const secp256k1_context *ctx, unsigned char *output32, - const secp256k1_xonly_pubkey* pubkey + const secp256k1_xonly_pubkey *pubkey ); - -int secp256k1_xonly_pubkey_cmp( - const secp256k1_context* ctx, - const secp256k1_xonly_pubkey* pk1, - const secp256k1_xonly_pubkey* pk2 +extern int secp256k1_xonly_pubkey_cmp( + const secp256k1_context *ctx, + const secp256k1_xonly_pubkey *pk1, + const secp256k1_xonly_pubkey *pk2 ); - -int secp256k1_xonly_pubkey_from_pubkey( - const secp256k1_context* ctx, +extern int secp256k1_xonly_pubkey_from_pubkey( + const secp256k1_context *ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey ); - -int secp256k1_xonly_pubkey_tweak_add( - const secp256k1_context* ctx, +extern int secp256k1_xonly_pubkey_tweak_add( + const secp256k1_context *ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32 ); - -int secp256k1_xonly_pubkey_tweak_add_check( - const secp256k1_context* ctx, +extern int secp256k1_xonly_pubkey_tweak_add_check( + const secp256k1_context *ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32 ); - -int secp256k1_keypair_create( - const secp256k1_context* ctx, +extern int secp256k1_keypair_create( + const secp256k1_context *ctx, secp256k1_keypair *keypair, const unsigned char *seckey ); - -int secp256k1_keypair_sec( - const secp256k1_context* ctx, +extern int secp256k1_keypair_sec( + const secp256k1_context *ctx, unsigned char *seckey, const secp256k1_keypair *keypair ); - -int secp256k1_keypair_pub( - const secp256k1_context* ctx, +extern int secp256k1_keypair_pub( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair ); - -int secp256k1_keypair_xonly_pub( - const secp256k1_context* ctx, +extern int secp256k1_keypair_xonly_pub( + const secp256k1_context *ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair ); - -int secp256k1_keypair_xonly_tweak_add( - const secp256k1_context* ctx, +extern int secp256k1_keypair_xonly_tweak_add( + const secp256k1_context *ctx, secp256k1_keypair *keypair, const unsigned char *tweak32 ); @@ -278,41 +267,36 @@ typedef struct { unsigned char data[65]; } secp256k1_ecdsa_recoverable_signature; - -int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature* sig, +extern int secp256k1_ecdsa_recoverable_signature_parse_compact( + const secp256k1_context *ctx, + secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid ); - -int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const secp256k1_ecdsa_recoverable_signature* sigin +extern int secp256k1_ecdsa_recoverable_signature_convert( + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, + const secp256k1_ecdsa_recoverable_signature *sigin ); - -int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_recoverable_signature_serialize_compact( + const secp256k1_context *ctx, unsigned char *output64, int *recid, - const secp256k1_ecdsa_recoverable_signature* sig + const secp256k1_ecdsa_recoverable_signature *sig ); - -int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_sign_recoverable( + const secp256k1_context *ctx, secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ); - -int secp256k1_ecdsa_recover( - const secp256k1_context* ctx, +extern int secp256k1_ecdsa_recover( + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32 + const unsigned char *msghash32 ); """ @@ -327,42 +311,29 @@ size_t algolen, void *data ); - extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; - typedef struct { unsigned char magic[4]; secp256k1_nonce_function_hardened noncefp; - void* ndata; + void *ndata; } secp256k1_schnorrsig_extraparams; - -int secp256k1_schnorrsig_sign( - const secp256k1_context* ctx, - unsigned char *sig64, - const unsigned char *msg32, - const secp256k1_keypair *keypair, - const unsigned char *aux_rand32 -); - -int secp256k1_schnorrsig_sign32( - const secp256k1_context* ctx, +extern int secp256k1_schnorrsig_sign32( + const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32 ); - -int secp256k1_schnorrsig_sign_custom( - const secp256k1_context* ctx, +extern int secp256k1_schnorrsig_sign_custom( + const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams ); - -int secp256k1_schnorrsig_verify( - const secp256k1_context* ctx, +extern int secp256k1_schnorrsig_verify( + const secp256k1_context *ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, @@ -371,16 +342,83 @@ """ ECDH_DEFINITIONS = """ -int secp256k1_ecdh( - const secp256k1_context* ctx, - unsigned char *result, +typedef int (*secp256k1_ecdh_hash_function)( + unsigned char *output, + const unsigned char *x32, + const unsigned char *y32, + void *data +); +extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; +extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; +extern int secp256k1_ecdh( + const secp256k1_context *ctx, + unsigned char *output, const secp256k1_pubkey *pubkey, - const unsigned char *privkey, - void *hashfp, + const unsigned char *seckey, + secp256k1_ecdh_hash_function hashfp, void *data ); """ +ELLSWIFT_DEFINITIONS = """ +typedef int (*secp256k1_ellswift_xdh_hash_function)( + unsigned char *output, + const unsigned char *x32, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + void *data +); +extern const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix; +extern const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324; +extern int secp256k1_ellswift_encode( + const secp256k1_context *ctx, + unsigned char *ell64, + const secp256k1_pubkey *pubkey, + const unsigned char *rnd32 +); +extern int secp256k1_ellswift_decode( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, + const unsigned char *ell64 +); +extern int secp256k1_ellswift_create( + const secp256k1_context *ctx, + unsigned char *ell64, + const unsigned char *seckey32, + const unsigned char *auxrnd32 +); +extern int secp256k1_ellswift_xdh( + const secp256k1_context *ctx, + unsigned char *output, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + const unsigned char *seckey32, + int party, + secp256k1_ellswift_xdh_hash_function hashfp, + void *data +); +""" + +PREALLOCATED_DEFINITIONS = """ +extern size_t secp256k1_context_preallocated_size( + unsigned int flags +); +extern secp256k1_context *secp256k1_context_preallocated_create( + void *prealloc, + unsigned int flags +); +extern size_t secp256k1_context_preallocated_clone_size( + const secp256k1_context *ctx +); +extern secp256k1_context *secp256k1_context_preallocated_clone( + const secp256k1_context *ctx, + void *prealloc +); +extern void secp256k1_context_preallocated_destroy( + secp256k1_context *ctx +); +""" + ffi = FFI() ffi.cdef(BASE_DEFINITIONS) @@ -391,3 +429,4 @@ here = os.path.dirname(os.path.abspath(__file__)) lib = ffi.dlopen(os.path.join(here, 'libsecp256k1.dll')) + diff --git a/coincurve/keys.py b/coincurve/keys.py index 1f260d15e..3285bd25e 100644 --- a/coincurve/keys.py +++ b/coincurve/keys.py @@ -159,7 +159,7 @@ def add(self, scalar: bytes, update: bool = False): secret = ffi.new('unsigned char [32]', self.secret) - success = lib.secp256k1_ec_privkey_tweak_add(self.context.ctx, secret, scalar) + success = lib.secp256k1_ec_seckey_tweak_add(self.context.ctx, secret, scalar) if not success: raise ValueError('The tweak was out of range, or the resulting private key is invalid.') @@ -186,7 +186,7 @@ def multiply(self, scalar: bytes, update: bool = False): secret = ffi.new('unsigned char [32]', self.secret) - lib.secp256k1_ec_privkey_tweak_mul(self.context.ctx, secret, scalar) + lib.secp256k1_ec_seckey_tweak_mul(self.context.ctx, secret, scalar) secret = bytes(ffi.buffer(secret, 32)) diff --git a/coincurve/utils.py b/coincurve/utils.py index 1e0bf8f4e..731a1df8f 100644 --- a/coincurve/utils.py +++ b/coincurve/utils.py @@ -38,7 +38,7 @@ def __call__(self, bytestr: bytes) -> bytes: def __repr__(self): return 'sha256' - DEFAULT_NONCE = __Nonce((ffi.NULL, ffi.NULL)) # type: ignore + DEFAULT_NONCE = __Nonce((ffi.NULL, ffi.NULL)) sha256 = __HasherSHA256() diff --git a/pyproject.toml b/pyproject.toml index 2ad8f2721..38aadbea8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,53 @@ +[build-system] +requires = ["setuptools>=61", "cffi>=1.3.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "coincurve" +version = "19.0.0" +authors = [ + { name="Ofek Lev", email="oss@ofek.dev" }, +] +description = "Cross-platform Python CFFI bindings for libsecp256k1" +license = { file="LICENSE-MIT" } +keywords = ["secp256k1", "crypto", "elliptic curves", "bitcoin", "ethereum", "cryptocurrency"] +readme = "README.md" +requires-python = ">=3.7" +dependencies = [ + "asn1crypto", + "cffi>=1.3.0" +] +classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'License :: OSI Approved :: Apache Software License', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + 'Topic :: Software Development :: Libraries', + 'Topic :: Security :: Cryptography', +] + +[project.urls] +"Homepage" = "https://github.com/ofek/coincurve" +"Bug Tracker" = "https://github.com/ofek/coincurve/issues" +"Documentation" = "https://ofek.dev/coincurve/" +"Issues" = "https://github.com/ofek/coincurve/issues" +"Source" = "https://github.com/ofek/coincurve" + +[tool.pytest.ini_options] +addopts = [ + "--import-mode=importlib", +] [tool.black] target-version = ["py37"] line-length = 120 @@ -40,6 +90,9 @@ unfixable = [ # Don't touch unused imports "F401", ] +extend-exclude = [ + "_cffi_build/compose_cffi_files.py", +] [tool.ruff.isort] known-first-party = ["coincurve"] diff --git a/setup.py b/setup.py index 12df421c0..5d095f693 100644 --- a/setup.py +++ b/setup.py @@ -5,15 +5,17 @@ import shutil import subprocess import tarfile -from distutils import log -from distutils.command.build_clib import build_clib as _build_clib -from distutils.command.build_ext import build_ext as _build_ext -from distutils.errors import DistutilsError from io import BytesIO import sys from setuptools import Distribution as _Distribution, setup, find_packages, __version__ as setuptools_version +from setuptools._distutils import log +from setuptools._distutils.errors import DistutilsError +from setuptools.command.build_clib import build_clib as _build_clib +from setuptools.command.build_ext import build_ext as _build_ext +from setuptools.extension import Extension from setuptools.command.develop import develop as _develop +from setuptools.command.dist_info import dist_info as _dist_info from setuptools.command.egg_info import egg_info as _egg_info from setuptools.command.sdist import sdist as _sdist @@ -21,13 +23,10 @@ from wheel.bdist_wheel import bdist_wheel as _bdist_wheel except ImportError: _bdist_wheel = None - pass - sys.path.append(os.path.abspath(os.path.dirname(__file__))) from setup_support import absolute, build_flags, detect_dll, has_system_lib # noqa: E402 - BUILDING_FOR_WINDOWS = detect_dll() MAKE = 'gmake' if platform.system() in ['FreeBSD', 'OpenBSD'] else 'make' @@ -35,15 +34,15 @@ # IMPORTANT: keep in sync with .github/workflows/build.yml # # Version of libsecp256k1 to download if none exists in the `libsecp256k1` directory -UPSTREAM_REF = os.getenv('COINCURVE_UPSTREAM_TAG') or 'acf5c55ae6a94e5ca847e07def40427547876101' +UPSTREAM_REF = os.getenv('COINCURVE_UPSTREAM_TAG') or '1ad5185cd42c0636104129fcc9f6a4bf9c67cc40' LIB_TARBALL_URL = f'https://github.com/bitcoin-core/secp256k1/archive/{UPSTREAM_REF}.tar.gz' # We require setuptools >= 3.3 if [int(i) for i in setuptools_version.split('.', 2)[:2]] < [3, 3]: raise SystemExit( - 'Your setuptools version ({}) is too old to correctly install this ' - 'package. Please upgrade to a newer version (>= 3.3).'.format(setuptools_version) + f'Your setuptools version ({setuptools_version}) is too old to correctly install this package. Please upgrade ' + f'to a newer version (>= 3.3).' ) @@ -75,17 +74,29 @@ def download_library(command): except ImportError as e: raise SystemExit('Unable to download secp256k1 library: %s', str(e)) + class egg_info(_egg_info): def run(self): # Ensure library has been downloaded (sdist might have been skipped) - download_library(self) + if not has_system_lib(): + download_library(self) _egg_info.run(self) +class dist_info(_dist_info): + def run(self): + # Ensure library has been downloaded (sdist might have been skipped) + if not has_system_lib(): + download_library(self) + + _dist_info.run(self) + + class sdist(_sdist): def run(self): - download_library(self) + if not has_system_lib(): + download_library(self) _sdist.run(self) @@ -93,7 +104,8 @@ def run(self): class bdist_wheel(_bdist_wheel): def run(self): - download_library(self) + if not has_system_lib(): + download_library(self) _bdist_wheel.run(self) @@ -113,7 +125,8 @@ def finalize_options(self): def get_source_files(self): # Ensure library has been downloaded (sdist might have been skipped) - download_library(self) + if not has_system_lib(): + download_library(self) return [ absolute(os.path.join(root, filename)) @@ -232,27 +245,53 @@ def run(self): package_data = {'coincurve': ['py.typed']} -if BUILDING_FOR_WINDOWS: - class Distribution(_Distribution): - def is_pure(self): - return False +class BuildCFFIForSharedLib(_build_ext): + def build_extensions(self): + build_script = os.path.join('_cffi_build', 'build_shared.py') + c_file = self.extensions[0].sources[0] + subprocess.run([sys.executable, build_script, c_file, '0'], shell=False, check=True) # noqa S603 + super().build_extensions() - package_data['coincurve'].append('libsecp256k1.dll') - setup_kwargs = dict() -else: + +if has_system_lib(): class Distribution(_Distribution): def has_c_libraries(self): return not has_system_lib() + # --- SECP256K1 package definitions --- + secp256k1_package = 'libsecp256k1' + + extension = Extension( + name='coincurve._libsecp256k1', + sources=[os.path.join('coincurve', '_libsecp256k1.c')], + # ABI?: py_limited_api=True, + ) + + extension.extra_compile_args = [ + subprocess.check_output(['pkg-config', '--cflags-only-I', 'libsecp256k1']).strip().decode('utf-8') # noqa S603 + ] + extension.extra_link_args = [ + subprocess.check_output(['pkg-config', '--libs-only-L', 'libsecp256k1']).strip().decode('utf-8'), # noqa S603 + subprocess.check_output(['pkg-config', '--libs-only-l', 'libsecp256k1']).strip().decode('utf-8'), # noqa S603 + ] + + if os.name == 'nt' or sys.platform == 'win32': + # Apparently, the linker on Windows interprets -lxxx as xxx.lib, not libxxx.lib + for i, v in enumerate(extension.__dict__.get('extra_link_args')): + extension.__dict__['extra_link_args'][i] = v.replace('-L', '/LIBPATH:') + + if v.startswith('-l'): + v = v.replace('-l', 'lib') + extension.__dict__['extra_link_args'][i] = f'{v}.lib' + setup_kwargs = dict( setup_requires=['cffi>=1.3.0', 'requests'], - ext_package='coincurve', - cffi_modules=['_cffi_build/build.py:ffi'], + ext_modules=[extension], cmdclass={ 'build_clib': build_clib, - 'build_ext': build_ext, + 'build_ext': BuildCFFIForSharedLib, 'develop': develop, 'egg_info': egg_info, 'sdist': sdist, @@ -260,56 +299,46 @@ def has_c_libraries(self): }, ) +else: + if BUILDING_FOR_WINDOWS: -setup( - name='coincurve', - version='18.0.0', + class Distribution(_Distribution): + def is_pure(self): + return False + + + package_data['coincurve'].append('libsecp256k1.dll') + setup_kwargs = {} + + else: + + class Distribution(_Distribution): + def has_c_libraries(self): + return not has_system_lib() - description='Cross-platform Python CFFI bindings for libsecp256k1', - long_description=open('README.md', 'r').read(), - long_description_content_type='text/markdown', - author_email='Ofek Lev ', - license='MIT OR Apache-2.0', - python_requires='>=3.7', - install_requires=['asn1crypto', 'cffi>=1.3.0'], + setup_kwargs = dict( + setup_requires=['cffi>=1.3.0', 'requests'], + ext_package='coincurve', + cffi_modules=['_cffi_build/build.py:ffi'], + cmdclass={ + 'build_clib': build_clib, + 'build_ext': build_ext, + 'develop': develop, + 'egg_info': egg_info, + 'sdist': sdist, + 'bdist_wheel': bdist_wheel, + }, + ) + +setup( + name='coincurve', + version='19.0.0', packages=find_packages(exclude=('_cffi_build', '_cffi_build.*', 'libsecp256k1', 'tests')), package_data=package_data, distclass=Distribution, zip_safe=False, - - project_urls={ - 'Documentation': 'https://ofek.dev/coincurve/', - 'Issues': 'https://github.com/ofek/coincurve/issues', - 'Source': 'https://github.com/ofek/coincurve', - }, - keywords=[ - 'secp256k1', - 'crypto', - 'elliptic curves', - 'bitcoin', - 'ethereum', - 'cryptocurrency', - ], - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'License :: OSI Approved :: Apache Software License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: Implementation :: CPython', - 'Programming Language :: Python :: Implementation :: PyPy', - 'Topic :: Software Development :: Libraries', - 'Topic :: Security :: Cryptography', - ], **setup_kwargs ) diff --git a/setup_support.py b/setup_support.py index 035c459a0..6e1c09ad0 100644 --- a/setup_support.py +++ b/setup_support.py @@ -61,17 +61,21 @@ def _find_lib(): from cffi import FFI - ffi = FFI() try: - ffi.dlopen('secp256k1') - return os.path.exists('/usr/include/secp256k1_ecdh.h') - except OSError: + subprocess.check_output(['pkg-config', '--exists', 'libsecp256k1']) # noqa S603 + + includes = subprocess.check_output(['pkg-config', '--cflags-only-I', 'libsecp256k1']) # noqa S603 + includes = includes.strip().decode('utf-8') + + return os.path.exists(os.path.join(includes[2:], 'secp256k1_ecdh.h')) + + except (OSError, subprocess.CalledProcessError): if 'LIB_DIR' in os.environ: for path in glob.glob(os.path.join(os.environ['LIB_DIR'], '*secp256k1*')): with suppress(OSError): FFI().dlopen(path) return True - # We couldn't locate libsecp256k1 so we'll use the bundled one + # We couldn't locate libsecp256k1, so we'll use the bundled one return False diff --git a/tox.ini b/tox.ini index 6348ec33a..b164433ff 100644 --- a/tox.ini +++ b/tox.ini @@ -6,6 +6,7 @@ envlist = 3.9 3.10 3.11 + 3.12 pypy3 bench lint @@ -54,7 +55,7 @@ commands = [testenv:typing] skip_install = true deps = - mypy==0.790 + mypy>=0.790 commands = mypy coincurve @@ -66,6 +67,7 @@ setenv = ; Use a set timestamp for reproducible builds. ; See https://reproducible-builds.org/specs/source-date-epoch/ SOURCE_DATE_EPOCH=1580601600 + PYTHONWARNINGS=ignore::UserWarning:mkdocstrings.handlers.python deps = mkdocs~=1.3.1 ; theme @@ -73,7 +75,7 @@ deps = ; plugins mkdocs-minify-plugin~=0.5.0 mkdocs-git-revision-date-localized-plugin~=1.1.0 - mkdocstrings~=0.18.1 + mkdocstrings[python-legacy]~=0.18.1 ; Extensions pymdown-extensions~=9.5.0 mkdocs-material-extensions~=1.0.3