diff --git a/.circleci/build_lib.sh b/.circleci/build_lib.sh index 3e9c934b12..ab6bc1bf4a 100755 --- a/.circleci/build_lib.sh +++ b/.circleci/build_lib.sh @@ -6,6 +6,7 @@ BUILD_CONFIG="Debug" cmake_params="" # All params passed to cmake to generate build files +export ARCH=$2 ### # Commands of the script. Put them in command line parameters to trigger @@ -20,6 +21,55 @@ function command_Release { add_to_cmake_params -DBUILD_TESTS=OFF } +function command_Debug { + BUILD_CONFIG="Debug" + add_to_cmake_params -DBUILD_TESTS=ON +} + +function command_ios { + export POLLY_IOS_BUNDLE_IDENTIFIER='com.ledger.core' + #Needed for nocodesign toolchains + export XCODE_XCCONFIG_FILE=$POLLY_ROOT/scripts/NoCodeSign.xcconfig + echo "command_ios with architecture : $ARCH" + if [ "$ARCH" == "armv7" ]; then + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3-armv7' + export OSX_SYSROOT=iphoneos + elif [ "$ARCH" == "arm64" ]; then + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3-arm64' + export OSX_SYSROOT=iphoneos + else + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3' + export OSX_SYSROOT=iphonesimulator + export ARCH=x86_64 + #Copy iphone.cmake which is not forcing CMAKE_OSX_SYSROOT to iphoneos in cache + cp `pwd`/../lib-ledger-core/tools/build_ios/iphone.cmake `pwd`/../lib-ledger-core/toolchains/polly/os/ + fi + + cp `pwd`/../lib-ledger-core/tools/build_ios/framework.plist.in `pwd` + cp `pwd`/../lib-ledger-core/tools/build_ios/install_name.sh `pwd` + + + BUILD_CONFIG="Release" + add_to_cmake_params -G "Xcode" -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_TESTS=OFF -DCMAKE_OSX_ARCHITECTURES:STRING=${ARCH} -DCMAKE_MACOSX_BUNDLE:BOOL=ON -DCMAKE_OSX_SYSROOT:STRING=${OSX_SYSROOT} -DCMAKE_TOOLCHAIN_FILE=${POLLY_ROOT}/${TOOLCHAIN_NAME}.cmake +} + +function command_android { + echo "Set Android NDK variable" + export ANDROID_NDK_r16b=/home/circleci/android-ndk-r16b + export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)" || export JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64/" + #Needed for nocodesign toolchains + echo "command_android with architecture : $ARCH" + if [ "$ARCH" == "armeabi-v7a" ]; then + export TOOLCHAIN_NAME='android-ndk-r16b-api-21-armeabi-v7a-clang-libcxx14' + elif [ "$ARCH" == "arm64-v8a" ]; then + export TOOLCHAIN_NAME='android-ndk-r16b-api-24-arm64-v8a-clang-libcxx14' + else + export TOOLCHAIN_NAME='android-ndk-r16b-api-16-x86-clang-libcxx14' + fi + BUILD_CONFIG="Release" + add_to_cmake_params -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_TESTS=OFF -DTARGET_JNI=ON -DCMAKE_TOOLCHAIN_FILE=${POLLY_ROOT}/${TOOLCHAIN_NAME}.cmake +} + ### # Utilities functions ### @@ -32,14 +82,30 @@ function add_to_cmake_params { } function execute_commands { +if [ "$1" == "ios" -o "$1" == "android" ]; then + command_$1 +else local cmd for cmd;do echo $cmd command_$cmd done +fi + } export JAVA_HOME="/usr/lib/jvm/java-8-openjdk" +export POLLY_ROOT=`pwd`/toolchains/polly +### +# Clean +### +if [ "$1" == "ios" -o "$1" == "android" ]; then + echo "=====>Cleaning to prepare clean build" + echo "=====>Cleaning secp256k1" + rm -rf core/lib/secp256k1/include core/lib/secp256k1/src core/lib/secp256k1/tmp core/lib/secp256k1/lib || echo "Failed to clean secp256k1" + echo "=====>Remove build directory" + rm -rf ../lib-ledger-core-build +fi echo "=====>Create build directory" cd .. && (mkdir lib-ledger-core-build || echo "lib-ledger-core-build directory already exists") && cd lib-ledger-core-build @@ -66,4 +132,28 @@ fi echo $cmake_params cmake $cmake_params ../lib-ledger-core echo "======> Build for $unamestr in $BUILD_CONFIG mode" -make -j4 +if [ "$1" == "ios" ]; then + echo " >>> Starting iOS build for architecture ${ARCH} with toolchain ${TOOLCHAIN_NAME} for ${OSX_SYSROOT}" + xcodebuild -project ledger-core.xcodeproj -configuration Release -jobs 4 +else + make -j4 +fi + +if [ "$1" == "ios" ]; then + if [ "$ARCH" == "armv7" -o "$ARCH" == "arm64" ]; then + PATH_TO_LIB=core/src/Release-iphoneos + else + PATH_TO_LIB=core/src/Release-iphonesimulator + #Remove signature + rm -rf $PATH_TO_LIB/ledger-core.framework/_CodeSignature + codesign --remove-signature $PATH_TO_LIB/ledger-core.framework/ledger-core + fi + + #echo "======> Set rpath" + #install_name_tool -id "@rpath/libledger-core.dylib" $PATH_TO_LIB/libledger-core.dylib + #install_name_tool -add_rpath "@executable_path/Frameworks" $PATH_TO_LIB/libledger-core.dylib + + echo "======> Store artifacts to build fat framework" + mkdir -p /Users/distiller/ios/$ARCH && cp -r $PATH_TO_LIB/ledger-core.framework /Users/distiller/ios/$ARCH +fi + diff --git a/.circleci/config.yml b/.circleci/config.yml index 5c706dec39..ebe06ef7f4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,11 +45,40 @@ jobs: command: | . .circleci/build_lib.sh target_jni Release - deploy: - requires: - - hold name: Deploy_jni command: | . .circleci/deploy.sh target_jni + - run: + name: Setup NDK + command: | + apt-get install -y zip unzip + wget --quiet https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip + unzip -q android-ndk-r16b-linux-x86_64.zip -d /home/circleci + ls -la /home/circleci/android-ndk-r16b + - run: + name: Build_Library_android + command: | + . .circleci/build_lib.sh android + - deploy: + name: Deploy_android + command: | + . .circleci/deploy.sh android + - run: + name: Build_Library_android_armeabi-v7a + command: | + . .circleci/build_lib.sh android armeabi-v7a + - deploy: + name: Deploy_android_armeabi-v7a + command: | + . .circleci/deploy.sh android armeabi-v7a + - run: + name: Build_Library_android_arm64-v8a + command: | + . .circleci/build_lib.sh android arm64-v8a + - deploy: + name: Deploy_android_arm64-v8a + command: | + . .circleci/deploy.sh android arm64-v8a build_linux_debug: docker: - image: debian:stretch @@ -119,6 +148,34 @@ jobs: name: Deploy_jni command: | . .circleci/deploy.sh target_jni + - run: + name: Build_Library_ios_x86 + command: | + . .circleci/build_lib.sh ios + - deploy: + name: Deploy_ios_x86 + command: | + . .circleci/deploy.sh ios + - run: + name: Build_Library_ios_armv7 + command: | + . .circleci/build_lib.sh ios armv7 + - deploy: + name: Deploy_ios_armv7 + command: | + . .circleci/deploy.sh ios armv7 + - run: + name: Build_Library_ios_arm64 + command: | + . .circleci/build_lib.sh ios arm64 + - deploy: + name: Deploy_ios_arm64 + command: | + . .circleci/deploy.sh ios arm64 + - run: + name: Build_Fat_Library_ios + command: | + . .circleci/deploy_fat_lib.sh build_macos_debug: macos: xcode: "9.2.0" diff --git a/.circleci/deploy.sh b/.circleci/deploy.sh index 9da0018f2e..84b34afc70 100644 --- a/.circleci/deploy.sh +++ b/.circleci/deploy.sh @@ -2,17 +2,19 @@ unamestr=$(uname) TARGET=$1 -#branchstr=`git rev-parse --abbrev-ref HEAD` +ARCH=$2 branchstr=$(git branch | grep '*' | sed 's/^..//') echo "======> Deploy from $branchstr branch, version : $LIB_VERSION" -if [ "$branchstr" == "develop" -o "$branchstr" == "jni-ci" ]; then +if [ "$branchstr" == "develop" ]; then echo "======> Start deploy for $unamestr" if [ "$unamestr" == "Linux" ]; then if [ "$TARGET" == "target_jni" ]; then mv ../lib-ledger-core-build/core/src/libledger-core.so ../lib-ledger-core-build/core/src/libledger-core_jni.so export BUILD_TYPE=linux/jni + elif [ "$TARGET" == "android" ]; then + export BUILD_TYPE=android/${ARCH} else export BUILD_TYPE=linux fi @@ -25,8 +27,24 @@ if [ "$branchstr" == "develop" -o "$branchstr" == "jni-ci" ]; then fi fi + PATH_TO_LIB=../lib-ledger-core-build/core/src/ + if [ "$TARGET" == "ios" ]; then + if [ "$ARCH" == "armv7" -o "$ARCH" == "arm64" ]; then + export BUILD_TYPE=ios/${ARCH} + PATH_TO_LIB=../lib-ledger-core-build/core/src/Release-iphoneos + else + export BUILD_TYPE=ios/x86_64 + PATH_TO_LIB=../lib-ledger-core-build/core/src/Release-iphonesimulator + fi + elif [ "$TARGET" == "android" ]; then + if [ "$ARCH" == "armeabi-v7a" -o "$ARCH" == "arm64-v8a" ]; then + export BUILD_TYPE=android/${ARCH} + else + export BUILD_TYPE=android/x86 + fi + fi echo "======> Deploy for $unamestr" - aws s3 sync ../lib-ledger-core-build/core/src/ s3://ledger-lib-ledger-core/$LIB_VERSION/$BUILD_TYPE --acl public-read --exclude "CMakeFiles/*" --exclude "Makefile" --exclude "cmake_install.cmake" && \ + aws s3 sync $PATH_TO_LIB s3://ledger-lib-ledger-core/$LIB_VERSION/$BUILD_TYPE --acl public-read --exclude "CMakeFiles/*" --exclude "Makefile" --exclude "cmake_install.cmake" && \ aws s3 ls s3://ledger-lib-ledger-core/$LIB_VERSION/$BUILD_TYPE; else diff --git a/.circleci/deploy_fat_lib.sh b/.circleci/deploy_fat_lib.sh new file mode 100644 index 0000000000..fb8a36007f --- /dev/null +++ b/.circleci/deploy_fat_lib.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +unamestr=$(uname) +branchstr=$(git branch | grep '*' | sed 's/^..//') + +cd /Users/distiller/ios + +echo "======> Build Fat Library" +pwd + +#We don't put x86_64/ledger-core.framework/ledger-core otherwise we have a problem when pushing to AppStore +lipo -create armv7/ledger-core.framework/ledger-core arm64/ledger-core.framework/ledger-core -o ledger-core +mkdir ledger-core.framework +mv ledger-core ledger-core.framework/ +cp arm64/ledger-core.framework/Info.plist ledger-core.framework/ +install_name_tool -add_rpath "@executable_path/Frameworks/universal" ledger-core.framework/ledger-core +lipo -info ledger-core.framework/ledger-core + +echo "======> Deploy from $branchstr branch, version : $LIB_VERSION" + +if [ "$branchstr" == "develop" ]; then + echo "======> Start deploy fat library for $unamestr" + aws s3 sync ./ s3://ledger-lib-ledger-core/$LIB_VERSION/ios/universal --acl public-read --exclude "x86_64/*" --exclude "armv7/*" --exclude "arm64/*" && \ + aws s3 ls s3://ledger-lib-ledger-core/$LIB_VERSION/ios/universal; + +else + echo "======> Deployment only on Develop (temporary) branch" +fi diff --git a/.circleci/init_submodules.sh b/.circleci/init_submodules.sh index 5ee1792993..90884a03f0 100644 --- a/.circleci/init_submodules.sh +++ b/.circleci/init_submodules.sh @@ -13,7 +13,7 @@ git submodule sync echo "========> Update all submodules " #No need for those #git submodule update -- djinni || echo "===========Djinni submodule already updated" -#git submodule update -- toolchains/polly || echo "===========Polly submodule already updated" +git submodule update -- toolchains/polly || echo "===========Polly submodule already updated" #git submodule update -- tools/gyp || echo "===========gyp submodule already updated" git submodule update -- core/lib/spdlog || echo "===========spdlog submodule already updated" git submodule update -- core/lib/leveldb || echo "===========leveldb submodule already updated" diff --git a/CMakeLists.txt b/CMakeLists.txt index 374a478b0a..37beaac197 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ include(UseBackportedModules) # The project version number. set(VERSION_MAJOR 1 CACHE STRING "Project major version number.") set(VERSION_MINOR 1 CACHE STRING "Project minor version number.") -set(VERSION_PATCH 0 CACHE STRING "Project patch version number.") +set(VERSION_PATCH 3 CACHE STRING "Project patch version number.") mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build) diff --git a/api/core/java/BitcoinLikeTransactionBuilder.java b/api/core/java/BitcoinLikeTransactionBuilder.java index 74f103db23..0b5877b0e5 100644 --- a/api/core/java/BitcoinLikeTransactionBuilder.java +++ b/api/core/java/BitcoinLikeTransactionBuilder.java @@ -93,7 +93,11 @@ public abstract class BitcoinLikeTransactionBuilder { /** Reset the current instance to its initial state */ public abstract void reset(); - public static native BitcoinLikeTransaction parseRawUnsignedTransaction(Currency currency, byte[] rawTransaction); + /** + * Parsing unsigned transaction + * parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight) + */ + public static native BitcoinLikeTransaction parseRawUnsignedTransaction(Currency currency, byte[] rawTransaction, Integer currentBlockHeight); private static final class CppProxy extends BitcoinLikeTransactionBuilder { diff --git a/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.cpp b/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.cpp index 4ea9c9ee4f..e35a00cdf8 100644 --- a/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.cpp +++ b/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.cpp @@ -455,9 +455,9 @@ NAN_METHOD(NJSBitcoinLikeTransactionBuilder::reset) { NAN_METHOD(NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction) { //Check if method called with right number of arguments - if(info.Length() != 2) + if(info.Length() != 3) { - return Nan::ThrowError("NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction needs 2 arguments"); + return Nan::ThrowError("NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction needs 3 arguments"); } //Check if parameters have correct types @@ -613,16 +613,23 @@ NAN_METHOD(NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction) { } } + auto arg_2 = std::experimental::optional(); + if(!info[2]->IsNull()) + { + auto opt_arg_2 = Nan::To(info[2]).FromJust(); + arg_2.emplace(opt_arg_2); + } - auto result = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(arg_0,arg_1); + + auto result = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(arg_0,arg_1,arg_2); //Wrap result in node object - auto arg_2_wrap = NJSBitcoinLikeTransaction::wrap(result); - auto arg_2 = Nan::ObjectWrap::Unwrap(arg_2_wrap)->handle(); + auto arg_3_wrap = NJSBitcoinLikeTransaction::wrap(result); + auto arg_3 = Nan::ObjectWrap::Unwrap(arg_3_wrap)->handle(); //Return result - info.GetReturnValue().Set(arg_2); + info.GetReturnValue().Set(arg_3); } NAN_METHOD(NJSBitcoinLikeTransactionBuilder::New) { diff --git a/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.hpp b/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.hpp index 437e5a41c0..4d89aff19c 100644 --- a/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.hpp +++ b/api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.hpp @@ -5,6 +5,7 @@ #define DJINNI_GENERATED_NJSBITCOINLIKETRANSACTIONBUILDER_HPP +#include "../../../core/src/api/../utils/optional.hpp" #include "../../../core/src/api/BitcoinLikeNetworkParameters.hpp" #include "../../../core/src/api/BitcoinLikePickingStrategy.hpp" #include "../../../core/src/api/Currency.hpp" @@ -126,6 +127,10 @@ class NJSBitcoinLikeTransactionBuilder: public Nan::ObjectWrap { /** Reset the current instance to its initial state */ static NAN_METHOD(reset); + /** + * Parsing unsigned transaction + * parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight) + */ static NAN_METHOD(parseRawUnsignedTransaction); static NAN_METHOD(New); diff --git a/api/core/nodejs/ledgerapp_nodejs_doc.js b/api/core/nodejs/ledgerapp_nodejs_doc.js index 6d31e5c2d9..d96b568a23 100644 --- a/api/core/nodejs/ledgerapp_nodejs_doc.js +++ b/api/core/nodejs/ledgerapp_nodejs_doc.js @@ -1707,7 +1707,11 @@ declare class NJSBitcoinLikeTransactionBuilder declare function clone(): NJSBitcoinLikeTransactionBuilder; /** Reset the current instance to its initial state */ declare function reset(); - static declare function parseRawUnsignedTransaction(currency: Currency, rawTransaction: Object): NJSBitcoinLikeTransaction; + /** + * Parsing unsigned transaction + * parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight) + */ + static declare function parseRawUnsignedTransaction(currency: Currency, rawTransaction: Object, currentBlockHeight: ?number): NJSBitcoinLikeTransaction; } /** *Callback triggered by main completed task, diff --git a/appveyor.yml b/appveyor.yml index 0303e5042c..9cb9ce24b1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ branches: image: - Visual Studio 2015 environment: - LIB_VERSION: 1.1.0 #Hardcode the LIB_VERSION : should be retrieved by building libcore node module and run tests/lib_version.js + LIB_VERSION: 1.1.3 #Hardcode the LIB_VERSION : should be retrieved by building libcore node module and run tests/lib_version.js nodejs_version: "9" appveyor_rdp_password: secure: jb1LsDmcxCww7tA38S3xSw== diff --git a/core/idl/wallet/bitcoin/bitcoin_like_wallet.djinni b/core/idl/wallet/bitcoin/bitcoin_like_wallet.djinni index be77124a09..0fee7ed270 100644 --- a/core/idl/wallet/bitcoin/bitcoin_like_wallet.djinni +++ b/core/idl/wallet/bitcoin/bitcoin_like_wallet.djinni @@ -254,7 +254,9 @@ BitcoinLikeTransactionBuilder = interface +c { # Reset the current instance to its initial state reset(); - static parseRawUnsignedTransaction(currency: Currency, rawTransaction: binary): BitcoinLikeTransaction; + # Parsing unsigned transaction + # parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight) + static parseRawUnsignedTransaction(currency: Currency, rawTransaction: binary, currentBlockHeight: optional): BitcoinLikeTransaction; } #Class representing a Bitcoin account diff --git a/core/src/CMakeLists.txt b/core/src/CMakeLists.txt index a386fb13e6..40ca854e78 100644 --- a/core/src/CMakeLists.txt +++ b/core/src/CMakeLists.txt @@ -46,7 +46,7 @@ endif () link_directories(${CMAKE_BINARY_DIR}/lib) -set(LIB_BUILD_TYPE SHARED wallet/common/AbstractAddress.cpp wallet/common/AbstractAddress.h ledger-core.cpp) +set(LIB_BUILD_TYPE SHARED) file(GLOB_RECURSE SRC_FILES *.cpp) file(GLOB_RECURSE HEADERS_FILES *.h *.hpp) @@ -58,6 +58,42 @@ add_library(ledger-core ${LIB_BUILD_TYPE} ${SRC_FILES} ${HEADERS_FILES}) +string(FIND "${CMAKE_OSX_SYSROOT}" "iphone" IS_IOS) +if(IS_IOS GREATER_EQUAL 0) + set(CMAKE_SHARED_LINKER_FLAGS "-Wall") + set(FRAMEWORK_BUNDLE_IDENTIFIER "com.ledger.core") + set(DEPLOYMENT_TARGET 9.0) + set(DEVICE_FAMILY "1") + set(PRODUCT_NAME ledger_core) + set_target_properties(ledger-core PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION A + MACOSX_FRAMEWORK_IDENTIFIER ${FRAMEWORK_BUNDLE_IDENTIFIER} + MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR} + MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" + MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_BINARY_DIR}/framework.plist.in + # "current version" in semantic format in Mach-O binary file + VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + # "compatibility version" in semantic format in Mach-O binary file + SOVERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} + PUBLIC_HEADER "${CMAKE_BINARY_DIR}/include/ledger/core" + XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY ${DEVICE_FAMILY} + XCODE_ATTRIBUTE_SKIP_INSTALL "YES" + ) + add_custom_command( + TARGET ledger-core + POST_BUILD + COMMAND /bin/bash -c "${CMAKE_BINARY_DIR}/install_name.sh \${BUILT_PRODUCTS_DIR}/\${PRODUCT_NAME}.framework/\${PRODUCT_NAME} ${CMAKE_OSX_ARCHITECTURES}" + ) + add_custom_command( + TARGET ledger-core + POST_BUILD + COMMAND install_name_tool -id \"@rpath/\${PRODUCT_NAME}.framework/\${PRODUCT_NAME}\" + \${BUILT_PRODUCTS_DIR}/\${PRODUCT_NAME}.framework/\${PRODUCT_NAME} + ) +endif() + if(UNIX AND NOT APPLE AND NOT ANDROID) target_link_libraries(ledger-core -static-libstdc++) endif() diff --git a/core/src/api/BitcoinLikeTransactionBuilder.hpp b/core/src/api/BitcoinLikeTransactionBuilder.hpp index dc947f36b1..479827d8e8 100644 --- a/core/src/api/BitcoinLikeTransactionBuilder.hpp +++ b/core/src/api/BitcoinLikeTransactionBuilder.hpp @@ -4,6 +4,7 @@ #ifndef DJINNI_GENERATED_BITCOINLIKETRANSACTIONBUILDER_HPP #define DJINNI_GENERATED_BITCOINLIKETRANSACTIONBUILDER_HPP +#include "../utils/optional.hpp" #include #include #include @@ -109,7 +110,11 @@ class BitcoinLikeTransactionBuilder { /** Reset the current instance to its initial state */ virtual void reset() = 0; - static std::shared_ptr parseRawUnsignedTransaction(const Currency & currency, const std::vector & rawTransaction); + /** + * Parsing unsigned transaction + * parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight) + */ + static std::shared_ptr parseRawUnsignedTransaction(const Currency & currency, const std::vector & rawTransaction, std::experimental::optional currentBlockHeight); }; } } } // namespace ledger::core::api diff --git a/core/src/database/DatabaseSessionPool.hpp b/core/src/database/DatabaseSessionPool.hpp index 8bcab2568f..06c0b23778 100644 --- a/core/src/database/DatabaseSessionPool.hpp +++ b/core/src/database/DatabaseSessionPool.hpp @@ -56,7 +56,7 @@ namespace ledger { const std::string& dbName ); - static const int CURRENT_DATABASE_SCHEME_VERSION = 3; + static const int CURRENT_DATABASE_SCHEME_VERSION = 4; private: void performDatabaseMigration(); private: diff --git a/core/src/database/migrations.cpp b/core/src/database/migrations.cpp index a3175938df..2391e68188 100644 --- a/core/src/database/migrations.cpp +++ b/core/src/database/migrations.cpp @@ -198,5 +198,13 @@ namespace ledger { sql << "ALTER TABLE bitcoin_currencies ADD COLUMN additional_BIPs TEXT DEFAULT ''"; } + template <> void migrate<4>(soci::session& sql) { + auto count = 0; + sql << "SELECT COUNT(*) FROM bitcoin_currencies WHERE identifier = 'dgb'", soci::into(count); + if (count > 0) { + sql << "UPDATE bitcoin_currencies SET p2sh_version = '3f' WHERE identifier = 'dgb' "; + } + } + } } \ No newline at end of file diff --git a/core/src/database/migrations.hpp b/core/src/database/migrations.hpp index 62ebceacd4..11764678d7 100644 --- a/core/src/database/migrations.hpp +++ b/core/src/database/migrations.hpp @@ -61,6 +61,7 @@ namespace ledger { template <> void migrate<1>(soci::session& sql); template <> void migrate<2>(soci::session& sql); template <> void migrate<3>(soci::session& sql); + template <> void migrate<4>(soci::session& sql); } } diff --git a/core/src/jni/jni/BitcoinLikeTransactionBuilder.cpp b/core/src/jni/jni/BitcoinLikeTransactionBuilder.cpp index 0a7e2b6b19..abdbb08334 100644 --- a/core/src/jni/jni/BitcoinLikeTransactionBuilder.cpp +++ b/core/src/jni/jni/BitcoinLikeTransactionBuilder.cpp @@ -169,12 +169,13 @@ CJNIEXPORT void JNICALL Java_co_ledger_core_BitcoinLikeTransactionBuilder_00024C } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } -CJNIEXPORT jobject JNICALL Java_co_ledger_core_BitcoinLikeTransactionBuilder_parseRawUnsignedTransaction(JNIEnv* jniEnv, jobject /*this*/, jobject j_currency, jbyteArray j_rawTransaction) +CJNIEXPORT jobject JNICALL Java_co_ledger_core_BitcoinLikeTransactionBuilder_parseRawUnsignedTransaction(JNIEnv* jniEnv, jobject /*this*/, jobject j_currency, jbyteArray j_rawTransaction, jobject j_currentBlockHeight) { try { DJINNI_FUNCTION_PROLOGUE0(jniEnv); auto r = ::ledger::core::api::BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(::djinni_generated::Currency::toCpp(jniEnv, j_currency), - ::djinni::Binary::toCpp(jniEnv, j_rawTransaction)); + ::djinni::Binary::toCpp(jniEnv, j_rawTransaction), + ::djinni::Optional::toCpp(jniEnv, j_currentBlockHeight)); return ::djinni::release(::djinni_generated::BitcoinLikeTransaction::fromCpp(jniEnv, r)); } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) } diff --git a/core/src/wallet/bitcoin/BitcoinLikeAccount.cpp b/core/src/wallet/bitcoin/BitcoinLikeAccount.cpp index f1d2565685..3e8f0e5cf3 100644 --- a/core/src/wallet/bitcoin/BitcoinLikeAccount.cpp +++ b/core/src/wallet/bitcoin/BitcoinLikeAccount.cpp @@ -526,7 +526,7 @@ namespace ledger { //Store newly broadcasted tx in db //First parse it auto txHash = seq.str(); - auto tx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(self->getWallet()->getCurrency(), transaction); + auto tx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(self->getWallet()->getCurrency(), transaction, self->_currentBlockHeight); //Get a BitcoinLikeBlockchainExplorer::Transaction from a BitcoinLikeTransaction BitcoinLikeBlockchainExplorer::Transaction txExplorer; @@ -599,7 +599,7 @@ namespace ledger { getContext(), getWallet()->getCurrency(), logger(), - _picker->getBuildFunction(getUTXO, getTransaction, _explorer, _keychain, logger()) + _picker->getBuildFunction(getUTXO, getTransaction, _explorer, _keychain, _currentBlockHeight,logger()) ); } diff --git a/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp b/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp index 011a9eb57a..5dd0921a35 100644 --- a/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp +++ b/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp @@ -39,11 +39,12 @@ namespace ledger { namespace core { - BitcoinLikeTransactionApi::BitcoinLikeTransactionApi(const api::Currency& currency, bool isSegwit) { - _currency = currency; + BitcoinLikeTransactionApi::BitcoinLikeTransactionApi(const api::Currency& currency, + bool isSegwit, + uint64_t currentBlockHeight) : + _currency(currency), _isSegwit(isSegwit), _currentBlockHeight(currentBlockHeight) { _version = 1; _writable = true; - _isSegwit = isSegwit; } BitcoinLikeTransactionApi::BitcoinLikeTransactionApi(const std::shared_ptr &operation) : BitcoinLikeTransactionApi(operation->getCurrency()) { @@ -229,21 +230,23 @@ namespace ledger { void BitcoinLikeTransactionApi::serializeProlog(BytesWriter &writer) { auto &additionalBIPs = _currency.bitcoinLikeNetworkParameters.value().AdditionalBIPs; - auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), networks::ZIP143); + auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), "ZIP"); + auto zipParameters = _currentBlockHeight > networks::ZIP_SAPLING_PARAMETERS.blockHeight ? + networks::ZIP_SAPLING_PARAMETERS : networks::ZIP143_PARAMETERS; if (it != additionalBIPs.end()) { - setVersion(networks::ZIP143_PARAMETERS.version); + setVersion(zipParameters.version); //New version and overwinter flag - auto header = networks::ZIP143_PARAMETERS.overwinterFlag; + auto header = zipParameters.overwinterFlag; header.push_back(0x00); header.push_back(0x00); - header.push_back(networks::ZIP143_PARAMETERS.version); + header.push_back(zipParameters.version); //Push header (0x80000003 in LE) writer.writeLeByteArray(header); //Version group Id (0x03C48270 in LE) - writer.writeLeByteArray(networks::ZIP143_PARAMETERS.versionGroupId); + writer.writeLeByteArray(zipParameters.versionGroupId); } else { writer.writeLeValue(_version); @@ -311,22 +314,25 @@ namespace ledger { std::shared_ptr api::BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction( - const Currency ¤cy, const std::vector &rawTransaction) { + const Currency ¤cy, const std::vector &rawTransaction, std::experimental::optional currentBlockHeight) { BytesReader reader(rawTransaction); + // Parse version auto version = reader.readNextLeUint(); + //Parse additionalBIPs if there are any auto &additionalBIPs = currency.bitcoinLikeNetworkParameters.value().AdditionalBIPs; - auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), networks::ZIP143); - + auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), "ZIP"); + auto zipParameters = currentBlockHeight.value_or(0) > networks::ZIP_SAPLING_PARAMETERS.blockHeight ? + networks::ZIP_SAPLING_PARAMETERS : networks::ZIP143_PARAMETERS; if (it != additionalBIPs.end()) { //Substract overwinterFlag - auto overwinterFlag = networks::ZIP143_PARAMETERS.overwinterFlag[0]; + auto overwinterFlag = zipParameters.overwinterFlag[0]; version -= (~ (overwinterFlag << 24) + 1); //Read version group Id - reader.read(networks::ZIP143_PARAMETERS.versionGroupId.size()); + reader.read(zipParameters.versionGroupId.size()); } // Parse timestamp @@ -345,7 +351,7 @@ namespace ledger { auto flag = reader.readNextByte(); } - auto tx = std::make_shared(currency, isSegwit); + auto tx = std::make_shared(currency, isSegwit, currentBlockHeight.value_or(0)); tx->setVersion(version); if (usesTimeStamp) { tx->setTimestamp(timeStamp); diff --git a/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h b/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h index db9039c3dc..88148ffc01 100644 --- a/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h +++ b/core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h @@ -46,7 +46,7 @@ namespace ledger { class BytesWriter; class BitcoinLikeTransactionApi : public api::BitcoinLikeTransaction { public: - explicit BitcoinLikeTransactionApi(const api::Currency& currency, bool isSegwit = false); + explicit BitcoinLikeTransactionApi(const api::Currency& currency, bool isSegwit = false, uint64_t currentBlockHeight = 0); explicit BitcoinLikeTransactionApi(const std::shared_ptr& operation); std::vector> getInputs() override; std::vector> getOutputs() override; @@ -98,6 +98,7 @@ namespace ledger { Option _timestamp; bool _writable; bool _isSegwit; + uint64_t _currentBlockHeight; }; } } diff --git a/core/src/wallet/bitcoin/networks.cpp b/core/src/wallet/bitcoin/networks.cpp index 4ba8ca9eeb..6a325ffe61 100644 --- a/core/src/wallet/bitcoin/networks.cpp +++ b/core/src/wallet/bitcoin/networks.cpp @@ -43,18 +43,24 @@ namespace ledger { SIGHASH_ANYONECANPAY = 0x80 }; - const std::string BIP115 = "BIP115"; const BIP115Parameters BIP115_PARAMETERS = { "9ec9845acb02fab24e1c0368b3b517c1a4488fba97f0e3459ac053ea01000000", {0xC0,0x1F,0x02} }; //Zcash overwinter - const std::string ZIP143 = "ZIP143"; - const ZIP143Parameters ZIP143_PARAMETERS = { + const ZIPParameters ZIP143_PARAMETERS = { 3, {0x80}, - {0x03, 0xC4, 0x82, 0x70} + {0x03, 0xC4, 0x82, 0x70}, + 347500 + }; + //Zcash Sapling (starting from block 419200) + const ZIPParameters ZIP_SAPLING_PARAMETERS = { + 4, + {0x80}, + {0x89, 0x2F, 0x20, 0x85}, + 419200 }; const api::BitcoinLikeNetworkParameters getNetworkParameters(const std::string &networkName) { @@ -130,7 +136,7 @@ namespace ledger { false, 0, {sigHashType::SIGHASH_ALL}, - {ZIP143} + {"ZIP"} ); return ZCASH; } else if (networkName == "zencash") { @@ -145,7 +151,7 @@ namespace ledger { false, 0, {sigHashType::SIGHASH_ALL}, - {BIP115} + {"BIP115"} ); return ZENCASH; } else if (networkName == "litecoin") { diff --git a/core/src/wallet/bitcoin/networks.hpp b/core/src/wallet/bitcoin/networks.hpp index 7b91abfb63..4555994590 100644 --- a/core/src/wallet/bitcoin/networks.hpp +++ b/core/src/wallet/bitcoin/networks.hpp @@ -49,22 +49,22 @@ namespace ledger { extern LIBCORE_EXPORT const std::vector ALL; //BIP115 (ex: Zencash) - extern LIBCORE_EXPORT const std::string BIP115; + //extern LIBCORE_EXPORT const std::string BIP115; struct BIP115Parameters { std::string blockHash; std::vector blockHeight; }; extern LIBCORE_EXPORT const BIP115Parameters BIP115_PARAMETERS; - //ZIP143 (ex: Zcash overwinter) - extern LIBCORE_EXPORT const std::string ZIP143; - struct ZIP143Parameters { + //ZIP: Zcash improvements/updates (ex: Zcash overwinter, Sapling ...) + struct ZIPParameters { uint32_t version; std::vector overwinterFlag; std::vector versionGroupId; + uint64_t blockHeight; //block height at which ZIP will be effective }; - extern LIBCORE_EXPORT const ZIP143Parameters ZIP143_PARAMETERS; - + extern LIBCORE_EXPORT const ZIPParameters ZIP143_PARAMETERS; + extern LIBCORE_EXPORT const ZIPParameters ZIP_SAPLING_PARAMETERS; template void serialize(Archive & archive, api::BitcoinLikeNetworkParameters & p) diff --git a/core/src/wallet/bitcoin/scripts/BitcoinLikeScript.cpp b/core/src/wallet/bitcoin/scripts/BitcoinLikeScript.cpp index 7b4c57b6a7..6e423db839 100644 --- a/core/src/wallet/bitcoin/scripts/BitcoinLikeScript.cpp +++ b/core/src/wallet/bitcoin/scripts/BitcoinLikeScript.cpp @@ -128,7 +128,7 @@ namespace ledger { } auto &additionalBIPS = currency.bitcoinLikeNetworkParameters.value().AdditionalBIPs; - auto it = std::find(additionalBIPS.begin(), additionalBIPS.end(), networks::BIP115); + auto it = std::find(additionalBIPS.begin(), additionalBIPS.end(), "BIP115"); if (it != additionalBIPS.end()) { script << hex::toByteArray(networks::BIP115_PARAMETERS.blockHash) << networks::BIP115_PARAMETERS.blockHeight diff --git a/core/src/wallet/bitcoin/synchronizers/BlockchainExplorerAccountSynchronizer.cpp b/core/src/wallet/bitcoin/synchronizers/BlockchainExplorerAccountSynchronizer.cpp index cd69be1abb..11d23c5b8f 100644 --- a/core/src/wallet/bitcoin/synchronizers/BlockchainExplorerAccountSynchronizer.cpp +++ b/core/src/wallet/bitcoin/synchronizers/BlockchainExplorerAccountSynchronizer.cpp @@ -223,6 +223,8 @@ namespace ledger { //Check if tx is pending auto it = buddy->savedState.getValue().pendingTxsHash.find(tx.first); if (it == buddy->savedState.getValue().pendingTxsHash.end()) { + buddy->logger->info("Drop transaction {}", tx.first); + buddy->logger->info("Deleting operation {}", tx.second); //delete tx.second from DB (from operations) sql << "DELETE FROM operations WHERE uid = :uid", soci::use(tx.second); } @@ -265,10 +267,12 @@ namespace ledger { return Future::successful(unit); }).recoverWith(ImmediateExecutionContext::INSTANCE, [=] (const Exception &exception) -> Future { + buddy->logger->info("Recovering from failing synchronization : {}", exception.getMessage()); //A block reorganization happened if (exception.getErrorCode() == api::ErrorCode::BLOCK_NOT_FOUND && buddy->savedState.nonEmpty()) { + buddy->logger->info("Recovering from reorganization"); //Get its block/block height auto& failedBatch = buddy->savedState.getValue().batches[currentBatchIndex]; auto failedBlockHeight = failedBatch.blockHeight; @@ -276,6 +280,7 @@ namespace ledger { if (failedBlockHeight > 0) { //Delete data related to failedBlock (and all blocks above it) + buddy->logger->info("Deleting blocks above blbock height: {}", failedBlockHeight); soci::session sql(buddy->wallet->getDatabase()->getPool()); sql << "DELETE FROM blocks where height >= :failedBlockHeight", soci::use(failedBlockHeight); @@ -305,6 +310,7 @@ namespace ledger { //Synchronize same batch now with an existing block (of hash lastBlockHash) //if failedBatch was not the deepest block part of that reorg, this recursive call //will ensure to get (and delete from DB) to the deepest failed block (part of reorg) + buddy->logger->info("Relaunch synchronization after recovering from reorganization"); return self->synchronizeBatches(currentBatchIndex, buddy); } } else { diff --git a/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeTransactionBuilder.cpp b/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeTransactionBuilder.cpp index cdb48a1b58..b8333132b2 100644 --- a/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeTransactionBuilder.cpp +++ b/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeTransactionBuilder.cpp @@ -188,7 +188,7 @@ namespace ledger { } auto &additionalBIPS = _currency.bitcoinLikeNetworkParameters.value().AdditionalBIPs; - auto it = std::find(additionalBIPS.begin(), additionalBIPS.end(), networks::BIP115); + auto it = std::find(additionalBIPS.begin(), additionalBIPS.end(), "BIP115"); if (it != additionalBIPS.end()) { script << hex::toByteArray(networks::BIP115_PARAMETERS.blockHash) << networks::BIP115_PARAMETERS.blockHeight diff --git a/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.cpp b/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.cpp index 354bec260d..41e398d281 100644 --- a/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.cpp +++ b/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.cpp @@ -51,13 +51,15 @@ namespace ledger { const BitcoinLikeGetTxFunction& getTransaction, const std::shared_ptr &explorer, const std::shared_ptr &keychain, + const uint64_t currentBlockHeight, const std::shared_ptr& logger ) { auto self = shared_from_this(); logger->info("Get build function"); return [=] (const BitcoinLikeTransactionBuildRequest& r) -> Future> { return self->async>([=] () { - auto tx = std::make_shared(self->_currency, keychain->isSegwit()); + logger->info("Constructing BitcoinLikeTransactionBuildFunction with blockHeight: {}", currentBlockHeight); + auto tx = std::make_shared(self->_currency, keychain->isSegwit(), currentBlockHeight); auto filteredGetUtxo = createFilteredUtxoFunction(r, getUtxo); return std::make_shared(r, filteredGetUtxo, getTransaction, explorer, keychain, logger, tx); }).flatMap>(ImmediateExecutionContext::INSTANCE, [=] (const std::shared_ptr& buddy) -> Future> { @@ -71,7 +73,7 @@ namespace ledger { return buddy->transaction; });; }); - }; + };; } const api::Currency &BitcoinLikeUtxoPicker::getCurrency() const { diff --git a/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.h b/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.h index ac33247a52..36e2a553f7 100644 --- a/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.h +++ b/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.h @@ -60,6 +60,7 @@ namespace ledger { const BitcoinLikeGetTxFunction& getTransaction, const std::shared_ptr& explorer, const std::shared_ptr& keychain, + const uint64_t currentBlockHeight, const std::shared_ptr& logger ); const api::Currency& getCurrency() const; diff --git a/core/src/wallet/common/database/AccountDatabaseHelper.cpp b/core/src/wallet/common/database/AccountDatabaseHelper.cpp index 1cf485b5a6..17a805e150 100644 --- a/core/src/wallet/common/database/AccountDatabaseHelper.cpp +++ b/core/src/wallet/common/database/AccountDatabaseHelper.cpp @@ -100,10 +100,10 @@ namespace ledger { Option AccountDatabaseHelper::getLastBlockWithOperations(soci::session &sql, const std::string &accountUid) { //Get block_uid of most recent operation from DB - rowset rows = (sql.prepare << "SELECT op.block_uid, b.hash, b.height, b.time, b.currency_name" + rowset rows = (sql.prepare << "SELECT op.block_uid, b.hash, b.height, b.time, b.currency_name " "FROM operations AS op " - "JOIN blocks AS b ON op.block_uid = b.uid" - "WHERE op.account_uid = :uid ORDER BY op.created_at DESC LIMIT 1", + "JOIN blocks AS b ON op.block_uid = b.uid " + "WHERE op.account_uid = :uid ORDER BY op.date DESC LIMIT 1", use(accountUid)); for (auto& row : rows) { auto block_uid = row.get(0); diff --git a/core/test/database/query_builder_tests.cpp b/core/test/database/query_builder_tests.cpp index 2c70122c50..5559766989 100644 --- a/core/test/database/query_builder_tests.cpp +++ b/core/test/database/query_builder_tests.cpp @@ -57,26 +57,8 @@ class QueryBuilderTest : public BaseFixture { }; TEST_F(QueryBuilderTest, SimpleOperationQuery) { - auto dispatcher = std::make_shared(); - auto resolver = std::make_shared(); - auto backend = std::static_pointer_cast(DatabaseBackend::getSqlite3Backend()); - auto printer = std::make_shared(dispatcher->getMainExecutionContext()); - auto newPool = [&]() -> std::shared_ptr { - return WalletPool::newInstance( - "my_pool", - Option::NONE, - nullptr, - nullptr, - resolver, - printer, - dispatcher, - nullptr, - backend, - api::DynamicObject::newInstance() - ); - }; + auto pool = newDefaultPool(); { - auto pool = newPool(); auto wallet = wait(pool->createWallet("my_wallet", "bitcoin", api::DynamicObject::newInstance())); auto nextIndex = wait(wallet->getNextAccountIndex()); EXPECT_EQ(nextIndex, 0); @@ -97,11 +79,11 @@ TEST_F(QueryBuilderTest, SimpleOperationQuery) { .select("uid") .from("operations") .to("o") - .where(api::QueryFilter::operationUidEq("1770fe39ddeef5ee97ad0ef19c1a26c0350316bb743b3a7d9f93c3fbadf3111e")) + .where(api::QueryFilter::operationUidEq("c099e0118230697140916ff925e4cd2dd9acdce97bbb80b31cab401a5b169ed1")) .execute(sql); auto count = 0; for (auto& row : rows) { - EXPECT_EQ(row.get(0), "1770fe39ddeef5ee97ad0ef19c1a26c0350316bb743b3a7d9f93c3fbadf3111e"); + EXPECT_EQ(row.get(0), "c099e0118230697140916ff925e4cd2dd9acdce97bbb80b31cab401a5b169ed1"); count += 1; } EXPECT_EQ(count, 1); diff --git a/core/test/integration/account_blockchain_observation.cpp b/core/test/integration/account_blockchain_observation.cpp index c918be4628..7930f9a2b9 100644 --- a/core/test/integration/account_blockchain_observation.cpp +++ b/core/test/integration/account_blockchain_observation.cpp @@ -150,6 +150,7 @@ TEST_F(AccountBlockchainObservationTests, EmitNewBlock) { ws->setOnConnectCallback([&] () { ws->push(NOTIF_WITH_BLOCK); }); + EXPECT_EQ(wait(account->getFreshPublicAddresses())[0]->toString(), "1DDBzjLyAmDr4qLRC2T2WJ831cxBM5v7G7"); account->getEventBus()->subscribe(dispatcher->getMainExecutionContext(), receiver); account->startBlockchainObservation(); dispatcher->waitUntilStopped(); diff --git a/core/test/integration/transactions/bitcoin_P2PKH_transaction_tests.cpp b/core/test/integration/transactions/bitcoin_P2PKH_transaction_tests.cpp index 0805978dd5..bd8ff4e7f6 100644 --- a/core/test/integration/transactions/bitcoin_P2PKH_transaction_tests.cpp +++ b/core/test/integration/transactions/bitcoin_P2PKH_transaction_tests.cpp @@ -62,7 +62,7 @@ TEST_F(BitcoinMakeP2PKHTransaction, CreateStandardP2PKHWithOneOutput) { builder->setFeesPerByte(api::Amount::fromLong(currency, 61)); auto f = builder->build(); auto tx = ::wait(f); - auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize()); + auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize(), 0); auto rawPrevious = ::wait(std::dynamic_pointer_cast(tx->getInputs()[0])->getPreviousTransaction()); EXPECT_EQ(tx->serialize(), parsedTx->serialize()); // EXPECT_EQ( @@ -128,7 +128,7 @@ TEST_F(BitcoinMakeP2PKHTransaction, Toto) { auto tx = ::wait(f); std::cout << hex::toString(tx->serialize()) << std::endl; std::cout << tx->getOutputs()[0]->getAddress().value_or("NOP") << std::endl; - auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize()); + auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize(), 0); auto rawPrevious = ::wait(std::dynamic_pointer_cast(tx->getInputs()[0])->getPreviousTransaction()); std::cout << hex::toString(parsedTx->serialize()) << std::endl; std::cout << parsedTx->getInputs().size() << std::endl; @@ -153,7 +153,7 @@ TEST_F(BCHMakeP2SHTransaction, CreateStandardP2SHWithOneOutput) { builder->setFeesPerByte(api::Amount::fromLong(currency, 41)); auto f = builder->build(); auto tx = ::wait(f); - auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize()); + auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize(), 0); //auto rawPrevious = ::wait(std::dynamic_pointer_cast(tx->getInputs()[0])->getPreviousTransaction()); EXPECT_EQ(tx->serialize(), parsedTx->serialize()); } @@ -168,6 +168,20 @@ struct ZCASHMakeP2SHTransaction : public BitcoinMakeBaseTransaction { }; TEST_F(ZCASHMakeP2SHTransaction, CreateStandardP2SHWithOneOutput) { + + auto bus = account->synchronize(); + bus->subscribe(dispatcher->getMainExecutionContext(), + make_receiver([=](const std::shared_ptr &event) { + fmt::print("Received event {}\n", api::to_string(event->getCode())); + if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED) + return; + EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED); + EXPECT_EQ(event->getCode(), + api::EventCode::SYNCHRONIZATION_SUCCEED); + dispatcher->stop(); + })); + dispatcher->waitUntilStopped(); + auto builder = tx_builder(); builder->sendToAddress(api::Amount::fromLong(currency, 2000), "t1MepQJABxoWarqMvgBHGiFprtuvA47Hiv8"); builder->pickInputs(api::BitcoinLikePickingStrategy::DEEP_OUTPUTS_FIRST, 0xFFFFFFFF); @@ -175,7 +189,8 @@ TEST_F(ZCASHMakeP2SHTransaction, CreateStandardP2SHWithOneOutput) { auto f = builder->build(); auto tx = ::wait(f); cout<serialize())<getCurrency(), tx->serialize()); - //auto rawPrevious = ::wait(std::dynamic_pointer_cast(tx->getInputs()[0])->getPreviousTransaction()); + auto parsedTx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(wallet->getCurrency(), tx->serialize(), 0); + cout<<" parsedTx = "<serialize())<>> Cleaning secp256k1" +rm -rf ../lib-ledger-core/core/lib/secp256k1/include ../lib-ledger-core/core/lib/secp256k1/src ../lib-ledger-core/core/lib/secp256k1/tmp ../lib-ledger-core/core/lib/secp256k1/lib + #Root to polly toolchains -export POLLY_ROOT="/Users/elkhalilbellakrid/Desktop/Playground_15/lib-ledger-core/toolchains/polly" -export ANDROID_NDK_r16b="/Users/elkhalilbellakrid/Library/Android/sdk/ndk-bundle" -export ANDROID_NDK_r14="/Users/elkhalilbellakrid/Library/Android/sdk/ndk-bundle" +export POLLY_ROOT=`pwd`/../lib-ledger-core/toolchains/polly +export ANDROID_NDK_r16b=${HOME}/Library/Android/sdk/ndk-bundle +export ANDROID_NDK_r14=${HOME}/Library/Android/sdk/ndk-bundle export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)" || export JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64/" export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)" -#export JAVA_INCLUDE_PATH2="$(echo $JAVA_HOME)"/include -#echo "************" -#echo $JAVA_HOME -#echo $JAVA_INCLUDE_PATH2 -#echo "************" -#-DCMAKE_CONFIGURATION_TYPES=Release -#-DTARGET_JNI=ON -#android-ndk-r16b-api-21-x86-clang-libcxx link with .dylib -#android-ndk-r14-api-21-x86-64 complains about std::strtoll in soci_sqlite3 -#android-ndk-r16b-api-16-x86-clang-libcxx14 link with .dylib -#android-ndk-r16b-api-21-x86-64-clang-libcxx -cmake -DCMAKE_BUILD_TYPE:STRING=Release -DTARGET_JNI=ON -DCMAKE_TOOLCHAIN_FILE=../lib-ledger-core/toolchains/polly/android-ndk-r16b-api-21-x86-clang-libcxx.cmake ../lib-ledger-core -#cmake -DCMAKE_BUILD_TYPE:STRING=Release -DANDROID_OSX=ON -DTARGET_JNI=ON -DCMAKE_TOOLCHAIN_FILE=../lib-ledger-core/toolchains/polly/android-ndk-r16b-api-24-arm64-v8a-clang-libcxx14.cmake ../lib-ledger-core +export ARCH=$1 +if [ "${ARCH}" == 'armeabi-v7a' ]; then + export TOOLCHAIN_NAME='android-ndk-r16b-api-21-armeabi-v7a-clang-libcxx14' +elif [ "${ARCH}" == 'arm64-v8a' ]; then + export TOOLCHAIN_NAME='android-ndk-r16b-api-24-arm64-v8a-clang-libcxx14' +else + export TOOLCHAIN_NAME='android-ndk-r16b-api-16-x86-clang-libcxx14' +fi +cmake -DCMAKE_BUILD_TYPE:STRING=Release -DTARGET_JNI=ON -DCMAKE_TOOLCHAIN_FILE=${POLLY_ROOT}/${TOOLCHAIN_NAME}.cmake ../lib-ledger-core cmake --build . --config Release diff --git a/tools/build_ios/framework.plist.in b/tools/build_ios/framework.plist.in new file mode 100644 index 0000000000..6e2d111373 --- /dev/null +++ b/tools/build_ios/framework.plist.in @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_FRAMEWORK_NAME} + CFBundleIconFile + ${MACOSX_FRAMEWORK_ICON_FILE} + CFBundleIdentifier + ${MACOSX_FRAMEWORK_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleShortVersionString + ${MACOSX_FRAMEWORK_SHORT_VERSION_STRING} + CFBundleVersion + ${MACOSX_FRAMEWORK_BUNDLE_VERSION} + CFBundleShortVersionString + ${MACOSX_FRAMEWORK_SHORT_VERSION_STRING} + CSResourcesFileMapped + + + \ No newline at end of file diff --git a/tools/build_ios/install_name.sh b/tools/build_ios/install_name.sh new file mode 100755 index 0000000000..9404a3ede7 --- /dev/null +++ b/tools/build_ios/install_name.sh @@ -0,0 +1,12 @@ +#!/bin/bash +echo $1 +echo $2 +if ! otool -l $1 | grep LC_RPATH; then + if [ "$2" == "x86_64" ]; then + install_name_tool -add_rpath "@executable_path/Frameworks/$2" $1; + else + install_name_tool -add_rpath "@executable_path/Frameworks" $1; + fi +else + echo 'Otool Operation Skipped'; +fi; diff --git a/tools/build_ios/ios_build.sh b/tools/build_ios/ios_build.sh index d74ad02927..2af6708202 100755 --- a/tools/build_ios/ios_build.sh +++ b/tools/build_ios/ios_build.sh @@ -1,11 +1,46 @@ +#!/usr/bin/env bash + +#Clean secp256k1 +echo " >>> Cleaning secp256k1" +rm -rf ../lib-ledger-core/core/lib/secp256k1/include ../lib-ledger-core/core/lib/secp256k1/src ../lib-ledger-core/core/lib/secp256k1/tmp ../lib-ledger-core/core/lib/secp256k1/lib + #WARNING: for iphonesimulator build don't forget to remove FORCE in iphone.cmake (polly toolchain) #ID used for bundle -export POLLY_IOS_BUNDLE_IDENTIFIER="com.ledger.ledgertestapp" +export POLLY_IOS_BUNDLE_IDENTIFIER='com.ledger.core' #Root to polly toolchains -export POLLY_ROOT="/Users/elkhalilbellakrid/Desktop/Playground_15/lib-ledger-core/toolchains/polly" +export POLLY_ROOT=`pwd`/../lib-ledger-core/toolchains/polly #Needed for nocodesign toolchains export XCODE_XCCONFIG_FILE=$POLLY_ROOT/scripts/NoCodeSign.xcconfig -#cmake -GXcode -DCMAKE_OSX_ARCHITECTURES:STRING="armv7" -DCMAKE_MACOSX_BUNDLE:BOOL=ON -DCMAKE_OSX_SYSROOT:STRING="iphoneos" -DCMAKE_TOOLCHAIN_FILE=../lib-ledger-core/toolchains/polly/ios-nocodesign-11-2-dep-9-3-arm64-armv7.cmake -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/qt/5.10.0_1 ../lib-ledger-core -#iOS simulator -cmake -GXcode -DCMAKE_OSX_ARCHITECTURES:STRING="x86_64" -DCMAKE_MACOSX_BUNDLE:BOOL=ON -DCMAKE_OSX_SYSROOT:STRING="iphonesimulator" -DCMAKE_TOOLCHAIN_FILE=../lib-ledger-core/toolchains/polly/ios-nocodesign-11-2-dep-9-3.cmake -DBUILD_TESTS=OFF ../lib-ledger-core + + +export ARCH=$1 +if [ "${ARCH}" == 'armv7' ]; then + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3-armv7' + export OSX_SYSROOT=iphoneos +elif [ "${ARCH}" == 'arm64' ]; then + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3-arm64' + export OSX_SYSROOT=iphoneos +elif [ "${ARCH}" == 'bitcode' ]; then + #ios-nocodesign-11-2-dep-9-0-bitcode-cxx11 + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-0-bitcode-cxx11' + #export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3-arm64-armv7' +else + export TOOLCHAIN_NAME='ios-nocodesign-11-2-dep-9-3' + export OSX_SYSROOT=iphonesimulator + export ARCH=x86_64 + cp `pwd`/../lib-ledger-core/tools/build_ios/iphone.cmake $POLLY_ROOT/os/ +fi + +cp `pwd`/../lib-ledger-core/tools/build_ios/framework.plist.in `pwd` + +cp `pwd`/../lib-ledger-core/tools/build_ios/install_name.sh `pwd` $ARCH + + + +echo " >>> Starting iOS build for architecture ${ARCH} with toolchain ${TOOLCHAIN_NAME} for ${OSX_SYSROOT}" +if [ "${ARCH}" == 'bitcode' ]; then + cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release -DCMAKE_MACOSX_BUNDLE:BOOL=ON -DCMAKE_TOOLCHAIN_FILE=${POLLY_ROOT}/${TOOLCHAIN_NAME}.cmake -DBUILD_TESTS=OFF ../lib-ledger-core +else + cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES:STRING=${ARCH} -DCMAKE_MACOSX_BUNDLE:BOOL=ON -DCMAKE_OSX_SYSROOT:STRING=${OSX_SYSROOT} -DCMAKE_TOOLCHAIN_FILE=${POLLY_ROOT}/${TOOLCHAIN_NAME}.cmake -DBUILD_TESTS=OFF ../lib-ledger-core +fi xcodebuild -project ledger-core.xcodeproj -configuration Release -jobs 4 diff --git a/tools/build_ios/iphone.cmake b/tools/build_ios/iphone.cmake new file mode 100644 index 0000000000..4d620c358b --- /dev/null +++ b/tools/build_ios/iphone.cmake @@ -0,0 +1,165 @@ +# Copyright (c) 2014, Ruslan Baratov +# All rights reserved. + +if(DEFINED POLLY_OS_IPHONE_CMAKE) + return() +else() + set(POLLY_OS_IPHONE_CMAKE 1) +endif() + +set(CMAKE_OSX_SYSROOT "iphoneos" CACHE STRING "System root for iOS") +set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator") +#set(IOS_SDK_VERSION "12.0" CACHE STRING "Updating Xcode leads to this" FORCE) +# find 'iphoneos' and 'iphonesimulator' roots and version +find_program(XCODE_SELECT_EXECUTABLE xcode-select) +if(NOT XCODE_SELECT_EXECUTABLE) + polly_fatal_error("xcode-select not found") +endif() + +if(XCODE_VERSION VERSION_LESS "5.0.0") + polly_fatal_error("Works since Xcode 5.0.0 (current ver: ${XCODE_VERSION})") +endif() + +if(CMAKE_VERSION VERSION_LESS "3.5") + polly_fatal_error( + "CMake minimum required version for iOS is 3.5 (current ver: ${CMAKE_VERSION})" + ) +endif() + +string(COMPARE EQUAL "$ENV{DEVELOPER_DIR}" "" _is_empty) +if(NOT _is_empty) + polly_status_debug("Developer root (env): $ENV{DEVELOPER_DIR}") +endif() + +execute_process( + COMMAND + ${XCODE_SELECT_EXECUTABLE} + "-print-path" + OUTPUT_VARIABLE + XCODE_DEVELOPER_ROOT # /.../Xcode.app/Contents/Developer + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +polly_status_debug("Developer root: ${XCODE_DEVELOPER_ROOT}") + +find_program(XCODEBUILD_EXECUTABLE xcodebuild) +if(NOT XCODEBUILD_EXECUTABLE) + polly_fatal_error("xcodebuild not found") +endif() + +# Check version exists +execute_process( + COMMAND + "${XCODEBUILD_EXECUTABLE}" + -showsdks + -sdk + "iphoneos${IOS_SDK_VERSION}" + RESULT_VARIABLE + IOS_SDK_VERSION_RESULT + OUTPUT_QUIET + ERROR_QUIET +) +if(NOT "${IOS_SDK_VERSION_RESULT}" EQUAL 0) + polly_fatal_error("iOS version `${IOS_SDK_VERSION}` not found (${IOS_SDK_VERSION_RESULT})") +endif() + +# iPhone simulator root +set( + IPHONESIMULATOR_ROOT + "${XCODE_DEVELOPER_ROOT}/Platforms/iPhoneSimulator.platform/Developer" +) +if(NOT EXISTS "${IPHONESIMULATOR_ROOT}") + polly_fatal_error( + "IPHONESIMULATOR_ROOT not found (${IPHONESIMULATOR_ROOT})\n" + "XCODE_DEVELOPER_ROOT: ${XCODE_DEVELOPER_ROOT}\n" + ) +endif() + +# iPhone simulator SDK root +set( + IPHONESIMULATOR_SDK_ROOT + "${IPHONESIMULATOR_ROOT}/SDKs/iPhoneSimulator${IOS_SDK_VERSION}.sdk" +) + +if(NOT EXISTS ${IPHONESIMULATOR_SDK_ROOT}) + polly_fatal_error( + "IPHONESIMULATOR_SDK_ROOT not found (${IPHONESIMULATOR_SDK_ROOT})\n" + "IPHONESIMULATOR_ROOT: ${IPHONESIMULATOR_ROOT}\n" + "IOS_SDK_VERSION: ${IOS_SDK_VERSION}\n" + ) +endif() + +# iPhone root +set( + IPHONEOS_ROOT + "${XCODE_DEVELOPER_ROOT}/Platforms/iPhoneOS.platform/Developer" +) +if(NOT EXISTS "${IPHONEOS_ROOT}") + polly_fatal_error( + "IPHONEOS_ROOT not found (${IPHONEOS_ROOT})\n" + "XCODE_DEVELOPER_ROOT: ${XCODE_DEVELOPER_ROOT}\n" + ) +endif() + +# iPhone SDK root +set(IPHONEOS_SDK_ROOT "${IPHONEOS_ROOT}/SDKs/iPhoneOS${IOS_SDK_VERSION}.sdk") + +if(NOT EXISTS ${IPHONEOS_SDK_ROOT}) + hunter_fatal_error( + "IPHONEOS_SDK_ROOT not found (${IPHONEOS_SDK_ROOT})\n" + "IPHONEOS_ROOT: ${IPHONEOS_ROOT}\n" + "IOS_SDK_VERSION: ${IOS_SDK_VERSION}\n" + ) +endif() + +string(COMPARE EQUAL "${IOS_DEPLOYMENT_SDK_VERSION}" "" _is_empty) +if(_is_empty) + set( + CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET + "${IOS_SDK_VERSION}" + ) +else() + set( + CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET + "${IOS_DEPLOYMENT_SDK_VERSION}" + ) +endif() + +# Emulate OpenCV toolchain -- +set(IOS YES) +# -- end + +# Set iPhoneOS architectures +set(archs "") +foreach(arch ${IPHONEOS_ARCHS}) + set(archs "${archs} ${arch}") +endforeach() +set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "${archs}") +set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "${archs}") + +# Set iPhoneSimulator architectures +set(archs "") +foreach(arch ${IPHONESIMULATOR_ARCHS}) + set(archs "${archs} ${arch}") +endforeach() +set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "${archs}") +set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "${archs}") + +# Introduced in iOS 9.0 +set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE NO) + +# This will set CMAKE_CROSSCOMPILING to TRUE. +# CMAKE_CROSSCOMPILING needed for try_run: +# * https://cmake.org/cmake/help/latest/command/try_run.html#behavior-when-cross-compiling +# (used in CURL) +set(CMAKE_SYSTEM_NAME "Darwin") + +# Set CMAKE_SYSTEM_PROCESSOR for one-arch toolchain +# (needed for OpenCV 3.3) +set(_all_archs ${IPHONESIMULATOR_ARCHS} ${IPHONEOS_ARCHS}) +list(LENGTH _all_archs _all_archs_len) +if(_all_archs_len EQUAL 1) + set(CMAKE_SYSTEM_PROCESSOR ${_all_archs}) +else() + set(CMAKE_SYSTEM_PROCESSOR "") +endif() diff --git a/tools/generateBindingsRN.sh b/tools/generateBindingsRN.sh index bacc12c844..61e213a009 100755 --- a/tools/generateBindingsRN.sh +++ b/tools/generateBindingsRN.sh @@ -5,42 +5,19 @@ DEST=../lib-ledger-core-react-native-bindings # CORE_BUILD=../lib-ledger-core-build CORE_CPP_API=core/src/api -CORE_CPP_JNI=core/src/jni - if [ ! -e $DEST/src/react-native ]; then + if [ ! -e $DEST/ios/Sources/react-native-ios ]; then ./djinni/src/run \ --idl ./core/core.djinni \ --cpp-out $CORE_CPP_API \ --cpp-namespace ledger::core::api \ --cpp-optional-template std::experimental::optional \ --cpp-optional-header "\"../utils/optional.hpp\"" \ - --jni-include-cpp-prefix "../../api/" \ - --jni-out $CORE_CPP_JNI/jni \ --objc-type-prefix LG \ - --react-native-objc-out $DEST/src/react-native \ + --react-native-objc-out $DEST/ios/Sources/react-native-ios \ --react-native-type-prefix RCTCore \ --react-include-objc-impl ../objc-impl \ --react-native-objc-impl-suffix Impl \ --trace true fi -# copy include files -# rm -rf $DEST/include -cp -r $CORE_CPP_API $DEST/include - -# copy util files -rm -rf $DEST/src/utils -mkdir $DEST/src/utils -cp -r core/src/utils/optional.hpp $DEST/src/utils - -# copy lib files -rm -rf $DEST/lib -mkdir $DEST/lib - -# copy dynamic library -# cp $CORE_BUILD/core/src/libledger-core.* $DEST/lib - -# create tmp folder if needed -# if [ ! -e $DEST/js/tmp ]; then -# mkdir $DEST/js/tmp -# fi