diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 82c73e1d6..c05072260 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -15,10 +15,10 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, windows-2019, macos-11] + os: [ubuntu-22.04, windows-2019, macos-14] env: CIBW_BEFORE_ALL_LINUX: yum install -y swig || apk add swig - CIBW_BEFORE_ALL_MACOS: brew install gnu-sed swig automake + CIBW_BEFORE_ALL_MACOS: brew install gnu-sed swig automake libtool CIBW_BEFORE_ALL_WINDOWS: choco install swig --version=3.0.12 --no-progress --allow-downgrade -y CIBW_BEFORE_BUILD_WINDOWS: .\tools\msvc\swig.bat CIBW_REPAIR_WHEEL_COMMAND_LINUX: auditwheel repair --only-plat -w {dest_dir} {wheel} @@ -42,9 +42,9 @@ jobs: platforms: arm64 - name: Build Wheels - uses: pypa/cibuildwheel@v2.14 + uses: pypa/cibuildwheel@v2.16.5 env: - CIBW_SKIP: "cp3{5..7}-* cp3{6..11}-win32* cp3{6..11}-musllinux_aarch64* pp*" + CIBW_SKIP: "cp3{5..7}-* cp3{6..12}-win32* cp3{6..12}-musllinux_aarch64* pp*" CIBW_ARCHS_LINUX: "x86_64 aarch64" CIBW_ARCHS_MACOS: "x86_64 arm64 universal2" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 164a3ce86..714514ddd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -80,3 +80,32 @@ run_scan_build_clang: - ./tools/cleanup.sh && ./tools/autogen.sh - CC=clang CFLAGS="-O0" scan-build-11 ./configure --enable-export-all --enable-swig-python --enable-swig-java --disable-clear-tests --disable-asm - scan-build-11 --keep-cc --exclude src/secp256k1/ make -j $(($(grep ^processor /proc/cpuinfo | wc -l) / 2)) + +cmake-test: + image: greenaddress/wallycore@sha256:f159b338f3d25e13958d79fbd709238e3864de5468b9d743625466a0a681e52b + tags: + - ga + script: + - mv _cmake cmake + - mv _CMakeLists.txt CMakeLists.txt + - mv src/_CMakeLists.txt src/CMakeLists.txt + - mv src/ctest/_CMakeLists.txt src/ctest/CMakeLists.txt + - cmake -B build-cmake -S . + -DBUILD_SHARED_LIBS:BOOL=FALSE + -DCMAKE_BUILD_TYPE:STRING=Debug + -DWALLYCORE_ENABLE_TESTS:BOOL=TRUE + -DWALLYCORE_ENABLE_COVERAGE:BOOL=TRUE + - cmake --build build-cmake + #- ctest --test-dir build-cmake --output-junit report.xml --output-on-failure -E "test_(clear|elements_tx)" + - cd build-cmake + - ctest --output-on-failure -E "test_(clear|elements_tx)" + - cd - + - pip install gcovr + - gcovr --xml-pretty --exclude-unreachable-branches --print-summary -o coverage.xml --root ${CI_PROJECT_DIR} + coverage: /^\s*lines:\s*\d+.\d+\%/ + artifacts: + reports: + # junit: build-cmake/report.xml # junit report generation not available in cmake 3.18 + coverage_report: + coverage_format: cobertura + path: coverage.xml diff --git a/CHANGES.md b/CHANGES.md index cbe7dfd22..59e71a576 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,15 +1,29 @@ # Changes -## Unreleased +## Version 1.2.0 ### Added +- Python: Add Python 3.12 wheels to the binary releases/PyPI. +- tx: expose `wally_tx_input_clone`/`wally_tx_input_clone` for input cloning. +- Build: Add new static analysis CI runs. + ### Changed - Javascript: The npm build now uses nodejs 20, as nodejs 16 is end-of-life. +- Android: Update android NDK to version 26b. +- libsecp256k1-zkp: The library has been updated to include the latest + changes to its cmake infrastructure. +- cmake: Now takes advantage of the new libsecp256k1-zkp cmake files to build + experimental modules and export the project in cmake style. cmake now also + builds test and collects coverage data. ### Fixed +- Build: Don't use `which` on Debian as it is now deprecated. +- Various bug fixes from static analysis. +- Various build and documentation fixes. + ## Version 1.1.0 diff --git a/README.md b/README.md index b90455748..003f573a8 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ installed. For non-development use, you can install wally from PyPI with `pip` as follows: ``` -pip install wallycore==1.1.0 +pip install wallycore==1.2.0 ``` For development, you can build and install wally using: diff --git a/_CMakeLists.txt b/_CMakeLists.txt index 24a558e86..295bbca67 100644 --- a/_CMakeLists.txt +++ b/_CMakeLists.txt @@ -1,61 +1,50 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.18) project( libwallycore - VERSION 1.1.0 + VERSION 1.2.0 DESCRIPTION "A collection of useful primitives for cryptocurrency wallets" LANGUAGES C ) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) option(BUILD_SHARED_LIBS "Build as shared library" OFF) - +option(WALLYCORE_ENABLE_TESTS "Build tests" OFF) +option(WALLYCORE_INSTALL "Enable install" OFF) +option(WALLYCORE_COVERAGE "Enable coverage" OFF) +option(WALLYCORE_BUILD_ELEMENTS "Build elements" ON) include(cmake/utils.cmake) generate_config_file() configure_file(src/ccan_config.h ccan_config.h COPYONLY) -include(cmake/libsecp256k1.cmake) - -add_subdirectory(src) - - -### install directives -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -set(LIB_CMAKE_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/wallycore) - -configure_package_config_file( - ${CMAKE_SOURCE_DIR}/cmake/wallycore-config.cmake.in - "${CMAKE_CURRENT_BINARY_DIR}/wallycore-config.cmake" - INSTALL_DESTINATION ${LIB_CMAKE_INSTALL_DIR} - PATH_VARS LIB_CMAKE_INSTALL_DIR -) -write_basic_package_version_file( - wallycore-config-version.cmake - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion -) - -install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/wallycore-config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/wallycore-config-version.cmake" - DESTINATION - ${LIB_CMAKE_INSTALL_DIR} -) -install( - TARGETS wallycore - EXPORT "wallycore-target" - COMPONENT wallycore - RUNTIME EXCLUDE_FROM_ALL - OBJECTS EXCLUDE_FROM_ALL - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} -) -install(EXPORT "wallycore-target" - DESTINATION ${LIB_CMAKE_INSTALL_DIR} - NAMESPACE wallycore:: - FILE "wallycore-targets.cmake" -) - +# libsec256k1-zkp +set(SECP256K1_ENABLE_MODULE_ECDH ON) +set(SECP256K1_ENABLE_MODULE_RECOVERY ON) +set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON) +set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) +set(SECP256K1_ENABLE_MODULE_ELLSWIFT OFF) +set(SECP256K1_ENABLE_MODULE_GENERATOR ON) +set(SECP256K1_ENABLE_MODULE_RANGEPROOF ON) +set(SECP256K1_ENABLE_MODULE_SURJECTIONPROOF ON) +set(SECP256K1_ENABLE_MODULE_WHITELIST ON) +set(SECP256K1_ENABLE_MODULE_MUSIG OFF) +set(SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR OFF) +set(SECP256K1_ENABLE_MODULE_ECDSA_S2C ON) +set(SECP256K1_ENABLE_MODULE_BPPP OFF) +set(SECP256K1_BUILD_BENCHMARK OFF) +set(SECP256K1_BUILD_TESTS OFF) +set(SECP256K1_BUILD_EXHAUSTIVE_TESTS OFF) +set(SECP256K1_BUILD_CTIME_TESTS OFF) +set(SECP256K1_BUILD_EXAMPLES OFF) +set(SECP256K1_INSTALL ${WALLYCORE_INSTALL}) +add_subdirectory(./src/secp256k1/) + +add_subdirectory(./src) + +if(NOT WALLYCORE_ENABLE_TESTS) + return() +endif() + +enable_testing() +add_subdirectory(src/ctest) diff --git a/_cmake/libsecp256k1-pkgconfig.cmake b/_cmake/libsecp256k1-pkgconfig.cmake deleted file mode 100644 index a9f8185ab..000000000 --- a/_cmake/libsecp256k1-pkgconfig.cmake +++ /dev/null @@ -1,21 +0,0 @@ -### Update libsecp256k1.pc to fix its installation prefix - -cmake_path(ABSOLUTE_PATH CMAKE_INSTALL_PREFIX OUTPUT_VARIABLE _absolute_prefix ) -find_file(_secp_pkg_cfg libsecp256k1.pc - PATHS ${_absolute_prefix} - PATH_SUFFIXES lib/pkgconfig -) -if(NOT _secp_pkg_cfg) - message(FATAL_ERROR "pkg-config file for libsecp256k1 not found, please check your cmake build system") -endif() - -file(STRINGS ${_secp_pkg_cfg} _libsecpLines) -file(WRITE ${_secp_pkg_cfg} "") -foreach(line ${_libsecpLines}) - string(REGEX MATCH "^prefix=.*" out ${line}) - if (out) - file(APPEND ${_secp_pkg_cfg} "prefix=${_absolute_prefix}\n") - else() - file(APPEND ${_secp_pkg_cfg} "${line}\n") - endif() -endforeach() diff --git a/_cmake/libsecp256k1.cmake b/_cmake/libsecp256k1.cmake deleted file mode 100644 index 9a8a5efe3..000000000 --- a/_cmake/libsecp256k1.cmake +++ /dev/null @@ -1,116 +0,0 @@ - -include(ExternalProject) -include(GNUInstallDirs) - -find_program(MAKE_EXE NAMES gmake nmake make) - -set(_secp_enable_tests --disable-tests) -if(ENABLE_TESTS) - set(_secp_enable_tests --enable-tests) -endif() -set(_secp_with_asm --with-asm=no) -if(ENABLE_ASM AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - set(_secp_with_asm --with-asm=yes) -endif() - -set(_secp_lib_type STATIC) -set(_secp_lib_type_option --disable-shared) -if(BUILD_SHARED_LIBS) - set(_secp_lib_type SHARED) - set(_secp_lib_type_option --enable-shared) -endif() - -set(_secp_host_build_config "") -if(CMAKE_CROSSCOMPILING) - if(NOT CONFIGURE_AC_HOST) - message(FATAL_ERROR "when cross-building, please define CONFIGURE_AC_HOST to be passed to libsecp256k1 as --host=") - endif() - if(NOT CONFIGURE_AC_BUILD) - message(FATAL_ERROR "when cross-building, please define CONFIGURE_AC_BUILD to be passed to libsecp256k1 as --build=") - endif() - set(_secp_host_build_config "--host=${CONFIGURE_AC_HOST} --build=${CONFIGURE_AC_BUILD}") -endif() - -if(CMAKE_BUILD_TYPE) - string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE_UC) -endif() - - -ExternalProject_Add(libsecp256k1-build - DOWNLOAD_COMMAND "" - SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/secp256k1 - CONFIGURE_COMMAND /configure - "CC=${CMAKE_C_COMPILER}" - "AR=${CMAKE_AR}" - "RANLIB=${CMAKE_C_COMPILER_RANLIB}" - "CFLAGS=${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BUILD_TYPE_UC}}" - "LDFLAGS=${CMAKE_${_secp_lib_type}_LINKER_FLAGS} ${CMAKE_${_secp_lib_type}_LINKER_FLAGS_${BUILD_TYPE_UC}}" - --prefix - ${_secp_lib_type_option} - --with-pic - --with-bignum=no - --enable-experimental - --enable-module-ecdh - --enable-module-recovery - --enable-module-ecdsa-s2c - --enable-module-rangeproof - --enable-module-surjectionproof - --enable-module-whitelist - --enable-module-generator - --enable-module-extrakeys - --enable-module-schnorrsig - --enable-openssl-tests=no - --enable-exhaustive-tests=no - --enable-benchmark=no - --disable-dependency-tracking - ${_secp_enable_tests} - ${_secp_with_asm} - ${_secp_host_build_config} - - BUILD_COMMAND ${MAKE_EXE} - - INSTALL_COMMAND ${MAKE_EXE} install -) - - -ExternalProject_Get_Property(libsecp256k1-build INSTALL_DIR) - -add_library(libsecp256k1 STATIC IMPORTED) -set(_secp_public_headers - ${INSTALL_DIR}/include/secp256k1_ecdh.h - ${INSTALL_DIR}/include/secp256k1_ecdsa_s2c.h - ${INSTALL_DIR}/include/secp256k1_extrakeys.h - ${INSTALL_DIR}/include/secp256k1_generator.h - ${INSTALL_DIR}/include/secp256k1.h - ${INSTALL_DIR}/include/secp256k1_preallocated.h - ${INSTALL_DIR}/include/secp256k1_rangeproof.h - ${INSTALL_DIR}/include/secp256k1_recovery.h - ${INSTALL_DIR}/include/secp256k1_schnorrsig.h - ${INSTALL_DIR}/include/secp256k1_surjectionproof.h - ${INSTALL_DIR}/include/secp256k1_whitelist.h -) -set_target_properties(libsecp256k1 PROPERTIES - IMPORTED_LOCATION ${INSTALL_DIR}/lib/libsecp256k1.a - PUBLIC_HEADER "${_secp_public_headers}" -) -add_dependencies(libsecp256k1 libsecp256k1-build) - - -install( - FILES $ - DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT libsecp256k1 -) -install( - FILES $ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT libsecp256k1 -) -install( - FILES ${INSTALL_DIR}/lib/pkgconfig/libsecp256k1.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig - COMPONENT libsecp256k1 -) -install(SCRIPT ${CMAKE_SOURCE_DIR}/cmake/libsecp256k1-pkgconfig.cmake - COMPONENT libsecp256k1 -) diff --git a/_cmake/wallycore-config.cmake.in b/_cmake/wallycore-config.cmake.in index 43698f02f..a6bd7b3c5 100644 --- a/_cmake/wallycore-config.cmake.in +++ b/_cmake/wallycore-config.cmake.in @@ -11,14 +11,11 @@ if("libsecp256k1" IN_LIST wallycore_FIND_COMPONENTS) if(TARGET wallycore::libsecp256k1) message(FATAL_ERROR "wallycore::libsecp256k1 already defined") endif() - include(FindPkgConfig REQUIRED) - set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON) - pkg_check_modules(libsecp256k1 REQUIRED IMPORTED_TARGET libsecp256k1) - add_library(wallycore::libsecp256k1 ALIAS PkgConfig::libsecp256k1) + find_package(libsecp256k1 CONFIG REQUIRED) + add_library(wallycore::libsecp256k1 ALIAS libsecp256k1::libsecp256k1) set(wallycore_libsecp256k1_FOUND TRUE) endif() set(wallycore_COMPONENT_FOUND TRUE) - check_required_components(wallycore) diff --git a/configure.ac b/configure.ac index 5f7329916..bef74f204 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.60]) -AC_INIT([libwallycore],[1.1.0]) +AC_INIT([libwallycore],[1.2.0]) AC_CONFIG_AUX_DIR([tools/build-aux]) AC_CONFIG_MACRO_DIR([tools/build-aux/m4]) AC_CONFIG_SRCDIR([src/mnemonic.h]) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4ce906f71..e54f4830e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -167,7 +167,7 @@ def extract_docs(infile, outfile): # built documents. # # The short X.Y version. -version = u'1.1.0' +version = u'1.2.0' # The full version, including alpha/beta/rc tags. release = version diff --git a/include/wally.hpp b/include/wally.hpp index 370f904e3..a5e6d4d4a 100644 --- a/include/wally.hpp +++ b/include/wally.hpp @@ -1872,6 +1872,18 @@ inline int tx_init_alloc(uint32_t version, uint32_t locktime, size_t inputs_allo return detail::check_ret(__FUNCTION__, ret); } +template +inline int tx_input_clone(const TX_INPUT_IN& tx_input_in, struct wally_tx_input* input) { + int ret = ::wally_tx_input_clone(detail::get_p(tx_input_in), input); + return detail::check_ret(__FUNCTION__, ret); +} + +template +inline int tx_input_clone_alloc(const TX_INPUT_IN& tx_input_in, struct wally_tx_input** input) { + int ret = ::wally_tx_input_clone_alloc(detail::get_p(tx_input_in), input); + return detail::check_ret(__FUNCTION__, ret); +} + inline int tx_input_free(struct wally_tx_input* input) { int ret = ::wally_tx_input_free(input); return detail::check_ret(__FUNCTION__, ret); diff --git a/include/wally_core.h b/include/wally_core.h index f7eda739d..90b67af6b 100644 --- a/include/wally_core.h +++ b/include/wally_core.h @@ -30,9 +30,9 @@ extern "C" { /** Library version */ #define WALLY_MAJOR_VER 1 -#define WALLY_MINOR_VER 1 +#define WALLY_MINOR_VER 2 #define WALLY_PATCH_VER 0 -#define WALLY_BUILD_VER 0x10100 +#define WALLY_BUILD_VER 0x10200 /** * Initialize wally. diff --git a/include/wally_transaction.h b/include/wally_transaction.h index e912364d5..347c4fdfa 100644 --- a/include/wally_transaction.h +++ b/include/wally_transaction.h @@ -294,6 +294,28 @@ WALLY_CORE_API int wally_tx_input_init_alloc( const struct wally_tx_witness_stack *witness, struct wally_tx_input **output); +/** + * Create a new copy of a transaction input. + * + * :param tx_input_in: The transaction input to clone. + * :param input: Destination for the resulting transaction input copy. + */ +WALLY_CORE_API int wally_tx_input_clone_alloc( + const struct wally_tx_input *tx_input_in, + struct wally_tx_input **input); + +/** + * Create a new copy of a transaction input in place. + * + * :param tx_input_in: The transaction input to clone. + * :param input: Destination for the resulting transaction input copy. + * + * .. note:: ``input`` is overwritten in place, and not cleared first. + */ +WALLY_CORE_API int wally_tx_input_clone( + const struct wally_tx_input *tx_input_in, + struct wally_tx_input *input); + /** * Free a transaction input allocated by `wally_tx_input_init_alloc`. * diff --git a/setup.py b/setup.py index 54ebeff81..36e4d9b1c 100644 --- a/setup.py +++ b/setup.py @@ -170,7 +170,7 @@ def _call(args, cwd=ABS_PATH): kwargs = { 'name': 'wallycore', - 'version': '1.1.0', + 'version': '1.2.0', 'description': 'libwally Bitcoin library', 'long_description': 'Python bindings for the libwally Bitcoin library', 'url': 'https://github.com/ElementsProject/libwally-core', diff --git a/src/Makefile.am b/src/Makefile.am index 35f0a5656..b29761b00 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -198,11 +198,11 @@ libwallycore_la_INCLUDES = \ if SHARED_BUILD_ENABLED # Increment at every ABI change (whether breaking or non-breaking) -LT_VER_CURRENT = 2 +LT_VER_CURRENT = 3 # Increment at every release, but reset to 0 at every ABI change LT_VER_REVISION = 0 # Increment at every ABI change, but reset to 0 if breaking -LT_VER_AGE = 1 +LT_VER_AGE = 2 # The library filename will be "libwallycore.so.$((current-age)).$((age)).$((revision))", # and the soname will be "libwallycore.so.$((current-age))". # Do NOT try to make the library version-info follow the project release version number! diff --git a/src/_CMakeLists.txt b/src/_CMakeLists.txt index f85db2b36..2abebb6a8 100644 --- a/src/_CMakeLists.txt +++ b/src/_CMakeLists.txt @@ -1,7 +1,6 @@ - -# libwallycore -add_library(wallycore) -file(GLOB ccan_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} +file( + GLOB ccan_srcs + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "ccan/ccan/base64/*.[ch]" "ccan/ccan/build_assert/*.h" "ccan/ccan/compiler/*.h" @@ -12,18 +11,72 @@ file(GLOB ccan_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "ccan/ccan/str/hex/*.[ch]" "ccan/ccan/tap/*.[ch]" ) -file(GLOB wallycore_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.[ch]") -file(GLOB wallycore_public_headers RELATIVE ${CMAKE_SOURCE_DIR} "${CMAKE_SOURCE_DIR}/include/*.h") +file( + GLOB wallycore_srcs + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + "*.[ch]" +) +file( + GLOB wallycore_public_headers + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + "${CMAKE_SOURCE_DIR}/include/*.h" +) +# wallycore +add_library(wallycore) target_sources(wallycore PRIVATE ${ccan_srcs} ${wallycore_srcs}) set_target_properties(wallycore PROPERTIES PUBLIC_HEADER "${wallycore_public_headers}") target_include_directories( wallycore - PUBLIC - $ - $ - PRIVATE - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/ccan + PUBLIC $ $ $ + PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/ccan +) +target_link_libraries(wallycore PUBLIC secp256k1) +if(WALLYCORE_ENABLE_COVERAGE AND CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_options(wallycore PRIVATE --coverage) + target_link_options(wallycore PUBLIC --coverage) +endif() + +if (WALLYCORE_BUILD_ELEMENTS) + target_compile_definitions(wallycore PRIVATE BUILD_ELEMENTS) +endif() + +if(NOT WALLYCORE_INSTALL) + return() +endif() + +# install directives +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +set(LIB_CMAKE_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/wallycore) + +configure_package_config_file( + ${CMAKE_SOURCE_DIR}/cmake/wallycore-config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/wallycore-config.cmake" + INSTALL_DESTINATION ${LIB_CMAKE_INSTALL_DIR} + PATH_VARS LIB_CMAKE_INSTALL_DIR +) +write_basic_package_version_file( + wallycore-config-version.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/wallycore-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/wallycore-config-version.cmake" DESTINATION ${LIB_CMAKE_INSTALL_DIR} +) +install( + TARGETS wallycore + EXPORT "wallycore-target" + COMPONENT wallycore + RUNTIME EXCLUDE_FROM_ALL + OBJECTS EXCLUDE_FROM_ALL + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) +install( + EXPORT "wallycore-target" + DESTINATION ${LIB_CMAKE_INSTALL_DIR} + NAMESPACE wallycore:: + FILE "wallycore-targets.cmake" ) diff --git a/src/ctest/_CMakeLists.txt b/src/ctest/_CMakeLists.txt new file mode 100644 index 000000000..785081d84 --- /dev/null +++ b/src/ctest/_CMakeLists.txt @@ -0,0 +1,36 @@ + + +add_executable(test_bech32 test_bech32.c) +target_include_directories(test_bech32 PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_bech32 PRIVATE wallycore) +add_test(test_bech32 test_bech32) + +add_executable(test_clear test_clear.c) +target_include_directories(test_clear PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_clear PRIVATE wallycore pthread) +add_test(test_clear test_clear) + +add_executable(test_coinselection test_coinselection.c) +target_include_directories(test_coinselection PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_coinselection PRIVATE wallycore) +add_test(test_coinselection test_coinselection) + +add_executable(test_descriptor test_descriptor.c) +target_include_directories(test_descriptor PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_descriptor PRIVATE wallycore) +add_test(test_descriptor test_descriptor) + +add_executable(test_elements_tx test_elements_tx.c) +target_include_directories(test_elements_tx PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_elements_tx PRIVATE wallycore) +add_test(test_elements_tx test_elements_tx) + +add_executable(test_psbt test_psbt.c) +target_include_directories(test_psbt PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_psbt PRIVATE wallycore) +add_test(test_psbt test_psbt) + +add_executable(test_psbt_limits test_psbt_limits.c) +target_include_directories(test_psbt_limits PRIVATE ${CMAKE_BINARY_DIR}) +target_link_libraries(test_psbt_limits PRIVATE wallycore) +add_test(test_psbt_limits test_psbt_limits) diff --git a/src/secp256k1 b/src/secp256k1 index 2192e9d05..1e04d3244 160000 --- a/src/secp256k1 +++ b/src/secp256k1 @@ -1 +1 @@ -Subproject commit 2192e9d051186754100fd270955fa6e7df26d457 +Subproject commit 1e04d324476f991de0b503343d8de73c505f7276 diff --git a/src/swig_java/swig.i b/src/swig_java/swig.i index 269fe049f..8669155b5 100644 --- a/src/swig_java/swig.i +++ b/src/swig_java/swig.i @@ -342,6 +342,7 @@ static jobjectArray create_jstringArray(JNIEnv *jenv, char **p, size_t len) { %ignore wally_map_init; %ignore wally_psbt_blind; %ignore wally_tx_elements_output_init; +%ignore wally_tx_input_clone; %ignore wally_tx_output_clone; %ignore wally_tx_output_init; /* END AUTOGENERATED */ @@ -1051,6 +1052,8 @@ static jobjectArray create_jstringArray(JNIEnv *jenv, char **p, size_t len) { %rename("tx_init") wally_tx_init_alloc; %returns_struct(wally_tx_clone_alloc, wally_tx); %rename("tx_clone") wally_tx_clone_alloc; +%returns_struct(wally_tx_input_clone_alloc, wally_tx_input_clone); +%rename("tx_input_clone") wally_tx_input_clone_alloc; %returns_void__(wally_tx_input_free); %returns_array_(wally_tx_input_get_blinding_nonce, 2, 3, SHA256_LEN); %returns_array_(wally_tx_input_get_entropy, 2, 3, SHA256_LEN); diff --git a/src/swig_python/python_extra.py_in b/src/swig_python/python_extra.py_in index f9ec2d5f2..1c68f6920 100644 --- a/src/swig_python/python_extra.py_in +++ b/src/swig_python/python_extra.py_in @@ -235,6 +235,7 @@ tx_get_output_script = _wrap_bin(tx_get_output_script, tx_get_output_script_len) tx_get_signature_hash = _wrap_bin(tx_get_signature_hash, SHA256_LEN) tx_get_txid = _wrap_bin(tx_get_txid, WALLY_TXHASH_LEN) tx_init = tx_init_alloc +tx_input_clone = tx_input_clone_alloc tx_input_get_script = _wrap_bin(tx_input_get_script, tx_input_get_script_len) tx_input_get_txhash = _wrap_bin(tx_input_get_txhash, WALLY_TXHASH_LEN) tx_input_get_witness = _wrap_bin(tx_input_get_witness, tx_input_get_witness_len) diff --git a/src/swig_python/swig.i b/src/swig_python/swig.i index f60847965..185ff46ac 100644 --- a/src/swig_python/swig.i +++ b/src/swig_python/swig.i @@ -416,6 +416,7 @@ static void destroy_words(PyObject *obj) { (void)obj; } %ignore wally_psbt_blind; %ignore wally_psbt_get_input_best_utxo; %ignore wally_tx_elements_output_init; +%ignore wally_tx_input_clone; %ignore wally_tx_output_clone; %ignore wally_tx_output_init; /* END AUTOGENERATED */ diff --git a/src/test/util.py b/src/test/util.py index 7d215398f..cca2e8686 100755 --- a/src/test/util.py +++ b/src/test/util.py @@ -684,6 +684,8 @@ class wally_psbt(Structure): ('wally_tx_get_weight', c_int, [POINTER(wally_tx), c_size_t_p]), ('wally_tx_get_witness_count', c_int, [POINTER(wally_tx), c_size_t_p]), ('wally_tx_init_alloc', c_int, [c_uint32, c_uint32, c_size_t, c_size_t, POINTER(POINTER(wally_tx))]), + ('wally_tx_input_clone', c_int, [POINTER(wally_tx_input), POINTER(wally_tx_input)]), + ('wally_tx_input_clone_alloc', c_int, [POINTER(wally_tx_input), POINTER(POINTER(wally_tx_input))]), ('wally_tx_input_free', c_int, [POINTER(wally_tx_input)]), ('wally_tx_input_init_alloc', c_int, [c_void_p, c_size_t, c_uint32, c_uint32, c_void_p, c_size_t, POINTER(wally_tx_witness_stack), POINTER(POINTER(wally_tx_input))]), ('wally_tx_is_coinbase', c_int, [POINTER(wally_tx), c_size_t_p]), diff --git a/src/transaction.c b/src/transaction.c index 6629256b2..23e81cdfd 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -357,9 +357,8 @@ int wally_tx_witness_stack_set_dummy(struct wally_tx_witness_stack *stack, return wally_tx_witness_stack_set(stack, index, p, len); } -static bool clone_input_to( - struct wally_tx_input *dst, - const struct wally_tx_input *src) +int wally_tx_input_clone(const struct wally_tx_input *src, + struct wally_tx_input *output) { unsigned char *new_script = NULL; #ifdef BUILD_ELEMENTS @@ -369,6 +368,9 @@ static bool clone_input_to( #endif struct wally_tx_witness_stack *new_witness = NULL; + if (!src || !output) + return WALLY_EINVAL; + if (src->witness) wally_tx_witness_stack_clone_alloc(src->witness, &new_witness); @@ -394,20 +396,36 @@ static bool clone_input_to( wally_tx_witness_stack_free(new_pegin_witness); #endif wally_tx_witness_stack_free(new_witness); - return false; + return WALLY_ENOMEM; } - memcpy(dst, src, sizeof(*src)); - dst->script = new_script; + memcpy(output, src, sizeof(*src)); + output->script = new_script; #ifdef BUILD_ELEMENTS - dst->issuance_amount = new_issuance_amount; - dst->inflation_keys = new_inflation_keys; - dst->issuance_amount_rangeproof = new_issuance_amount_rangeproof; - dst->inflation_keys_rangeproof = new_inflation_keys_rangeproof; - dst->pegin_witness = new_pegin_witness; + output->issuance_amount = new_issuance_amount; + output->inflation_keys = new_inflation_keys; + output->issuance_amount_rangeproof = new_issuance_amount_rangeproof; + output->inflation_keys_rangeproof = new_inflation_keys_rangeproof; + output->pegin_witness = new_pegin_witness; #endif - dst->witness = new_witness; - return true; + output->witness = new_witness; + return WALLY_OK; +} + +int wally_tx_input_clone_alloc(const struct wally_tx_input *src, + struct wally_tx_input **output) +{ + int ret; + + OUTPUT_CHECK; + OUTPUT_ALLOC(struct wally_tx_input); + + ret = wally_tx_input_clone(src, *output); + if (ret != WALLY_OK) { + wally_free(*output); + *output = NULL; + } + return ret; } static int tx_elements_input_issuance_proof_init( @@ -1214,6 +1232,8 @@ int wally_tx_free(struct wally_tx *tx) int wally_tx_add_input_at(struct wally_tx *tx, uint32_t index, const struct wally_tx_input *input) { + int ret; + if (!is_valid_tx(tx) || index > tx->num_inputs || !is_valid_tx_input(input)) return WALLY_EINVAL; @@ -1233,10 +1253,10 @@ int wally_tx_add_input_at(struct wally_tx *tx, uint32_t index, memmove(tx->inputs + index + 1, tx->inputs + index, (tx->num_inputs - index) * sizeof(*input)); - if (!clone_input_to(tx->inputs + index, input)) { + if ((ret = wally_tx_input_clone(input, tx->inputs + index)) != WALLY_OK) { memmove(tx->inputs + index, tx->inputs + index + 1, (tx->num_inputs - index) * sizeof(*input)); /* Undo */ - return WALLY_ENOMEM; + return ret; } tx->num_inputs += 1; diff --git a/src/wasm_package/package-lock.json b/src/wasm_package/package-lock.json index 9525ac364..e062f841d 100644 --- a/src/wasm_package/package-lock.json +++ b/src/wasm_package/package-lock.json @@ -1,12 +1,12 @@ { "name": "wallycore", - "version": "1.1.0", + "version": "1.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wallycore", - "version": "1.1.0", + "version": "1.2.0", "license": "(MIT or BSD)", "devDependencies": { "buffer": "^6.0.3", diff --git a/src/wasm_package/package.json b/src/wasm_package/package.json index d2c42b9ae..c745385fa 100644 --- a/src/wasm_package/package.json +++ b/src/wasm_package/package.json @@ -1,6 +1,6 @@ { "name": "wallycore", - "version": "1.1.0", + "version": "1.2.0", "description": "JavaScript bindings for libwally", "main": "src/index.js", "type": "module", diff --git a/src/wasm_package/src/const.js b/src/wasm_package/src/const.js index 1a6680cf8..c99c3647c 100755 --- a/src/wasm_package/src/const.js +++ b/src/wasm_package/src/const.js @@ -109,7 +109,7 @@ export const WALLY_ADDRESS_VERSION_WIF_TESTNET = 0xEF; /** Wallet Import Format export const WALLY_BIP32_CHAIN_CODE_LEN = 32; export const WALLY_BIP32_TWEAK_SUM_LEN = 32; export const WALLY_BTC_MAX = 21000000; -export const WALLY_BUILD_VER = 0x10100; +export const WALLY_BUILD_VER = 0x10200; export const WALLY_CA_PREFIX_LIQUID = 0x0c; /** Liquid v1 confidential address prefix */ export const WALLY_CA_PREFIX_LIQUID_REGTEST = 0x04; /** Liquid v1 confidential address prefix for regtest */ export const WALLY_CA_PREFIX_LIQUID_TESTNET = 0x17; /** Liquid v1 confidential address prefix for testnet */ @@ -127,7 +127,7 @@ export const WALLY_MINISCRIPT_POLICY_TEMPLATE = 0x08; /** Only allow policy temp export const WALLY_MINISCRIPT_REQUIRE_CHECKSUM = 0x04; /** Require a checksum to be present */ export const WALLY_MINISCRIPT_TAPSCRIPT = 0x01; /** Tapscript, use x-only pubkeys */ export const WALLY_MINISCRIPT_UNIQUE_KEYPATHS = 0x10; /** For policy templates, ensure BIP32 derivation paths differ for identical keys */ -export const WALLY_MINOR_VER = 1; +export const WALLY_MINOR_VER = 2; export const WALLY_MS_CANONICAL_NO_CHECKSUM = 0x01; /** Do not include a checksum */ export const WALLY_MS_IS_DESCRIPTOR = 0x20; /** Contains only descriptor expressions (no miniscript) */ export const WALLY_MS_IS_MULTIPATH = 0x02; /** Allows multiple paths via ```` */ diff --git a/src/wasm_package/src/functions.js b/src/wasm_package/src/functions.js index 211ed6aa8..4448d67e1 100644 --- a/src/wasm_package/src/functions.js +++ b/src/wasm_package/src/functions.js @@ -677,6 +677,8 @@ export const tx_get_vsize = wrap('wally_tx_get_vsize', [T.OpaqueRef, T.DestPtr(T export const tx_get_weight = wrap('wally_tx_get_weight', [T.OpaqueRef, T.DestPtr(T.Int32)]); export const tx_get_witness_count = wrap('wally_tx_get_witness_count', [T.OpaqueRef, T.DestPtr(T.Int32)]); export const tx_init = wrap('wally_tx_init_alloc', [T.Int32, T.Int32, T.Int32, T.Int32, T.DestPtrPtr(T.OpaqueRef)]); +export const tx_input_clone = wrap('wally_tx_input_clone_alloc', [T.OpaqueRef, T.DestPtrPtr(T.OpaqueRef)]); +export const tx_input_clone_noalloc = wrap('wally_tx_input_clone', [T.OpaqueRef, T.OpaqueRef]); export const tx_input_free = wrap('wally_tx_input_free', [T.OpaqueRef]); export const tx_input_get_blinding_nonce = wrap('wally_tx_input_get_blinding_nonce', [T.OpaqueRef, T.DestPtrSized(T.Bytes, C.SHA256_LEN)]); export const tx_input_get_entropy = wrap('wally_tx_input_get_entropy', [T.OpaqueRef, T.DestPtrSized(T.Bytes, C.SHA256_LEN)]); diff --git a/src/wasm_package/src/index.d.ts b/src/wasm_package/src/index.d.ts index f44d718d8..47599e3f3 100644 --- a/src/wasm_package/src/index.d.ts +++ b/src/wasm_package/src/index.d.ts @@ -637,6 +637,8 @@ export function tx_get_vsize(tx: Ref_wally_tx): number; export function tx_get_weight(tx: Ref_wally_tx): number; export function tx_get_witness_count(tx: Ref_wally_tx): number; export function tx_init(version: number, locktime: number, inputs_allocation_len: number, outputs_allocation_len: number): Ref_wally_tx; +export function tx_input_clone(tx_input_in: Ref_wally_tx_input): Ref_wally_tx_input; +export function tx_input_clone_noalloc(tx_input_in: Ref_wally_tx_input, input: Ref_wally_tx_input): void; export function tx_input_free(input: Ref_wally_tx_input): void; export function tx_input_get_blinding_nonce(tx_input_in: Ref_wally_tx_input): Buffer; export function tx_input_get_entropy(tx_input_in: Ref_wally_tx_input): Buffer; diff --git a/tools/build_android_libraries.sh b/tools/build_android_libraries.sh index 82f413e1e..825822250 100755 --- a/tools/build_android_libraries.sh +++ b/tools/build_android_libraries.sh @@ -11,7 +11,7 @@ if [ ! -f "src/secp256k1/Makefile.am" ]; then fi if [ -z "$ANDROID_NDK" ]; then - export ANDROID_NDK=$(dirname `which ndk-build 2>/dev/null`) + export ANDROID_NDK=$(dirname `command -v ndk-build 2>/dev/null`) fi echo ${ANDROID_NDK:?} if [ -z "$JAVA_HOME" ]; then diff --git a/tools/wasm_exports.sh b/tools/wasm_exports.sh index dda170db2..2b1f865ea 100644 --- a/tools/wasm_exports.sh +++ b/tools/wasm_exports.sh @@ -410,6 +410,8 @@ EXPORTED_FUNCTIONS="['_malloc','_free','_bip32_key_free' \ ,'_wally_tx_get_weight' \ ,'_wally_tx_get_witness_count' \ ,'_wally_tx_init_alloc' \ +,'_wally_tx_input_clone' \ +,'_wally_tx_input_clone_alloc' \ ,'_wally_tx_input_free' \ ,'_wally_tx_input_get_index' \ ,'_wally_tx_input_get_script' \