From 47101bbb27d0e13ea2b40ce1c7ff0dba9030f369 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Thu, 12 Apr 2018 13:30:04 -0700 Subject: [PATCH 001/502] scripted-diff: Rename CPubKey and CKey::*_KEY_SIZE and COMPRESSED_*_KEY_SIZE To SIZE and COMPRESSED_SIZE -BEGIN VERIFY SCRIPT- sed -i 's/PRIVATE_KEY_SIZE/SIZE/g' src/*.h src/*.cpp src/**/*.h src/**/*.cpp sed -i 's/COMPRESSED_PRIVATE_KEY_SIZE/COMPRESSED_SIZE/g' src/*.h src/**/*.cpp src/**/*.h src/**/*.cpp sed -i 's/PUBLIC_KEY_SIZE/SIZE/g' src/*.h src/*.cpp src/**/*.h src/**/*.cpp sed -i 's/COMPRESSED_PUBLIC_KEY_SIZE/COMPRESSED_SIZE/g' src/*.h src/*.cpp src/**/*.h src/**/*.cpp -END VERIFY SCRIPT- --- src/key.cpp | 20 ++++++++++---------- src/key.h | 10 +++++----- src/psbt.h | 2 +- src/pubkey.cpp | 18 +++++++++--------- src/pubkey.h | 18 +++++++++--------- src/script/interpreter.cpp | 8 ++++---- src/script/sign.h | 2 +- src/script/standard.cpp | 8 ++++---- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 9d982fc44f566..652041f4fbfe8 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -84,13 +84,13 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou * . The optional parameters and publicKey fields are * included. * - * privkey must point to an output buffer of length at least CKey::PRIVATE_KEY_SIZE bytes. + * privkey must point to an output buffer of length at least CKey::SIZE bytes. * privkeylen must initially be set to the size of the privkey buffer. Upon return it * will be set to the number of bytes used in the buffer. * key32 must point to a 32-byte raw private key. */ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, bool compressed) { - assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE); + assert(*privkeylen >= CKey::SIZE); secp256k1_pubkey pubkey; size_t pubkeylen = 0; if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { @@ -116,11 +116,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = CPubKey::COMPRESSED_PUBLIC_KEY_SIZE; + pubkeylen = CPubKey::COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; - assert(*privkeylen == CKey::COMPRESSED_PRIVATE_KEY_SIZE); + assert(*privkeylen == CKey::COMPRESSED_SIZE); } else { static const unsigned char begin[] = { 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 @@ -142,11 +142,11 @@ static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *pr memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = CPubKey::PUBLIC_KEY_SIZE; + pubkeylen = CPubKey::SIZE; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; - assert(*privkeylen == CKey::PRIVATE_KEY_SIZE); + assert(*privkeylen == CKey::SIZE); } return 1; } @@ -168,8 +168,8 @@ CPrivKey CKey::GetPrivKey() const { CPrivKey privkey; int ret; size_t privkeylen; - privkey.resize(PRIVATE_KEY_SIZE); - privkeylen = PRIVATE_KEY_SIZE; + privkey.resize(SIZE); + privkeylen = SIZE; ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed); assert(ret); privkey.resize(privkeylen); @@ -179,7 +179,7 @@ CPrivKey CKey::GetPrivKey() const { CPubKey CKey::GetPubKey() const { assert(fValid); secp256k1_pubkey pubkey; - size_t clen = CPubKey::PUBLIC_KEY_SIZE; + size_t clen = CPubKey::SIZE; CPubKey result; int ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, begin()); assert(ret); @@ -271,7 +271,7 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const std::vector> vout(64); if ((nChild >> 31) == 0) { CPubKey pubkey = GetPubKey(); - assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data()); } else { assert(size() == 32); diff --git a/src/key.h b/src/key.h index 0f695c07b7985..3a935d70f1a1b 100644 --- a/src/key.h +++ b/src/key.h @@ -19,7 +19,7 @@ /** * secure_allocator is defined in allocators.h * CPrivKey is a serialized private key, with all parameters included - * (PRIVATE_KEY_SIZE bytes) + * (SIZE bytes) */ typedef std::vector > CPrivKey; @@ -30,15 +30,15 @@ class CKey /** * secp256k1: */ - static const unsigned int PRIVATE_KEY_SIZE = 279; - static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214; + static const unsigned int SIZE = 279; + static const unsigned int COMPRESSED_SIZE = 214; /** * see www.keylength.com * script supports up to 75 for single byte push */ static_assert( - PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE, - "COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE"); + SIZE >= COMPRESSED_SIZE, + "COMPRESSED_SIZE is larger than SIZE"); private: //! Whether this private key is valid. We check for correctness when modifying the key diff --git a/src/psbt.h b/src/psbt.h index c889dad361cda..99a56b3b3d0d9 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -165,7 +165,7 @@ struct PSBTInput case PSBT_IN_PARTIAL_SIG: { // Make sure that the key is the size of pubkey + 1 - if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) { + if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) { throw std::ios_base::failure("Size of key was not the expected size for the type partial signature pubkey"); } // Read in the pubkey from key diff --git a/src/pubkey.cpp b/src/pubkey.cpp index d38df716bd561..10953adc35291 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -196,8 +196,8 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector> 31) == 0); - assert(size() == COMPRESSED_PUBLIC_KEY_SIZE); + assert(size() == COMPRESSED_SIZE); unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild.begin(), out+32, 32); @@ -238,8 +238,8 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) { return false; } - unsigned char pub[COMPRESSED_PUBLIC_KEY_SIZE]; - size_t publen = COMPRESSED_PUBLIC_KEY_SIZE; + unsigned char pub[COMPRESSED_SIZE]; + size_t publen = COMPRESSED_SIZE; secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED); pubkeyChild.Set(pub, pub + publen); return true; @@ -251,8 +251,8 @@ void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const { code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; memcpy(code+9, chaincode.begin(), 32); - assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); - memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE); + assert(pubkey.size() == CPubKey::COMPRESSED_SIZE); + memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_SIZE); } void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) { diff --git a/src/pubkey.h b/src/pubkey.h index 089324ffda8ad..918aba273f4ec 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -33,8 +33,8 @@ class CPubKey /** * secp256k1: */ - static constexpr unsigned int PUBLIC_KEY_SIZE = 65; - static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; + static constexpr unsigned int SIZE = 65; + static constexpr unsigned int COMPRESSED_SIZE = 33; static constexpr unsigned int SIGNATURE_SIZE = 72; static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; /** @@ -42,8 +42,8 @@ class CPubKey * script supports up to 75 for single byte push */ static_assert( - PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE, - "COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE"); + SIZE >= COMPRESSED_SIZE, + "COMPRESSED_SIZE is larger than SIZE"); private: @@ -51,15 +51,15 @@ class CPubKey * Just store the serialized data. * Its length can very cheaply be computed from the first byte. */ - unsigned char vch[PUBLIC_KEY_SIZE]; + unsigned char vch[SIZE]; //! Compute the length of a pubkey with a given first byte. unsigned int static GetLen(unsigned char chHeader) { if (chHeader == 2 || chHeader == 3) - return COMPRESSED_PUBLIC_KEY_SIZE; + return COMPRESSED_SIZE; if (chHeader == 4 || chHeader == 6 || chHeader == 7) - return PUBLIC_KEY_SIZE; + return SIZE; return 0; } @@ -140,7 +140,7 @@ class CPubKey void Unserialize(Stream& s) { unsigned int len = ::ReadCompactSize(s); - if (len <= PUBLIC_KEY_SIZE) { + if (len <= SIZE) { s.read((char*)vch, len); } else { // invalid pubkey, skip available data @@ -179,7 +179,7 @@ class CPubKey //! Check whether this is a compressed public key. bool IsCompressed() const { - return size() == COMPRESSED_PUBLIC_KEY_SIZE; + return size() == COMPRESSED_SIZE; } /** diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 95b25b491199b..7f9db59c45496 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -61,17 +61,17 @@ static inline void popstack(std::vector& stack) } bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() < CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() < CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: too short return false; } if (vchPubKey[0] == 0x04) { - if (vchPubKey.size() != CPubKey::PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::SIZE) { // Non-canonical public key: invalid length for uncompressed key return false; } } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { - if (vchPubKey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: invalid length for compressed key return false; } @@ -83,7 +83,7 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { } bool static IsCompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE) { + if (vchPubKey.size() != CPubKey::COMPRESSED_SIZE) { // Non-canonical public key: invalid length for compressed key return false; } diff --git a/src/script/sign.h b/src/script/sign.h index 491fb54c453f5..ed65397d6bce0 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -168,7 +168,7 @@ template void DeserializeHDKeypaths(Stream& s, const std::vector& key, std::map& hd_keypaths) { // Make sure that the key is the size of pubkey + 1 - if (key.size() != CPubKey::PUBLIC_KEY_SIZE + 1 && key.size() != CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1) { + if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) { throw std::ios_base::failure("Size of key was not the expected size for the type BIP32 keypath"); } // Read in the pubkey from key diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 31bfd04b0f4d7..eb704ebb19144 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -43,12 +43,12 @@ const char* GetTxnOutputType(txnouttype t) static bool MatchPayToPubkey(const CScript& script, valtype& pubkey) { - if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { - pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1); + if (script.size() == CPubKey::SIZE + 2 && script[0] == CPubKey::SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::SIZE + 1); return CPubKey::ValidSize(pubkey); } - if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { - pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1); + if (script.size() == CPubKey::COMPRESSED_SIZE + 2 && script[0] == CPubKey::COMPRESSED_SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_SIZE + 1); return CPubKey::ValidSize(pubkey); } return false; From 0580f86bb48004b797d4cb6273e7ffee0b0a0584 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Mon, 4 Mar 2019 01:26:31 -0800 Subject: [PATCH 002/502] Fixup whitespace --- src/pubkey.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pubkey.h b/src/pubkey.h index 918aba273f4ec..c2900f0b079e8 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -33,10 +33,10 @@ class CPubKey /** * secp256k1: */ - static constexpr unsigned int SIZE = 65; - static constexpr unsigned int COMPRESSED_SIZE = 33; - static constexpr unsigned int SIGNATURE_SIZE = 72; - static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; + static constexpr unsigned int SIZE = 65; + static constexpr unsigned int COMPRESSED_SIZE = 33; + static constexpr unsigned int SIGNATURE_SIZE = 72; + static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; /** * see www.keylength.com * script supports up to 75 for single byte push From 0b0cff3c61610fb56f8c5c9451ace01598117a8d Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Tue, 28 May 2019 03:12:59 +0200 Subject: [PATCH 003/502] Add support for building Android dependencies --- depends/Makefile | 5 +++++ depends/hosts/android.mk | 3 +++ depends/packages/openssl.mk | 1 + 3 files changed, 9 insertions(+) create mode 100644 depends/hosts/android.mk diff --git a/depends/Makefile b/depends/Makefile index b7e9a9213edb5..6643b664f37de 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -55,6 +55,11 @@ full_host_os:=$(subst $(host_arch)-$(host_vendor)-,,$(canonical_host)) host_os:=$(findstring linux,$(full_host_os)) host_os+=$(findstring darwin,$(full_host_os)) host_os+=$(findstring mingw32,$(full_host_os)) + +ifeq (android,$(findstring android,$(full_host_os))) +host_os:=android +endif + host_os:=$(strip $(host_os)) ifeq ($(host_os),) host_os=$(full_host_os) diff --git a/depends/hosts/android.mk b/depends/hosts/android.mk new file mode 100644 index 0000000000000..ff1b07d55ba1a --- /dev/null +++ b/depends/hosts/android.mk @@ -0,0 +1,3 @@ +android_AR=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)-ar +android_CXX=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)$(ANDROID_API_LEVEL)-clang++ +android_CC=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)$(ANDROID_API_LEVEL)-clang diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index db47113b2f9b8..6a316a308e07a 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -57,6 +57,7 @@ $(package)_config_opts_riscv64_linux=linux-generic64 $(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc $(package)_config_opts_x86_64_mingw32=mingw64 $(package)_config_opts_i686_mingw32=mingw +$(package)_config_opts_android=linux-generic64 endef define $(package)_preprocess_cmds From c2a749c9c16697e744ecfb283fdf4095d0278066 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Tue, 28 May 2019 03:28:01 +0200 Subject: [PATCH 004/502] Add example Android host-platform-triplet and options --- depends/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/depends/README.md b/depends/README.md index cfb9bbfeb0d57..a2fb592f344e7 100644 --- a/depends/README.md +++ b/depends/README.md @@ -30,8 +30,12 @@ Common `host-platform-triplets` for cross compilation are: - `aarch64-linux-gnu` for Linux ARM 64 bit - `riscv32-linux-gnu` for Linux RISC-V 32 bit - `riscv64-linux-gnu` for Linux RISC-V 64 bit +- `aarch64-linux-android` for Android ARM 64 bit -No other options are needed, the paths are automatically configured. +The paths are automatically configured and no other options are needed unless targeting Android. +In that case one needs to set `ANDROID_API_LEVEL` and `ANDROID_TOOLCHAIN_BIN`: + + make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin NO_QT=1 NO_WALLET=1 ### Install the required dependencies: Ubuntu & Debian From 9c4cb0166e801471f8cb3d82656c86bacf051db6 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Wed, 10 Jul 2019 13:56:00 +0200 Subject: [PATCH 005/502] Add ranlib to android.mk hosts file (fix OSX Android NDK build) --- depends/hosts/android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/hosts/android.mk b/depends/hosts/android.mk index ff1b07d55ba1a..c2a30d7a4d65d 100644 --- a/depends/hosts/android.mk +++ b/depends/hosts/android.mk @@ -1,3 +1,4 @@ android_AR=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)-ar android_CXX=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)$(ANDROID_API_LEVEL)-clang++ android_CC=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)$(ANDROID_API_LEVEL)-clang +android_RANLIB=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)-ranlib From b68f2a68c211aa2264e9ca824d10a90f4a5a5af4 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Mon, 16 Sep 2019 13:34:14 +0200 Subject: [PATCH 006/502] Add config opts and patch for aarch64_android build of Qt --- depends/packages/packages.mk | 1 + depends/packages/qt.mk | 18 ++++++++++++++++- .../patches/qt/fix_android_qmake_conf.patch | 20 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 depends/patches/qt/fix_android_qmake_conf.patch diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 667fde5271a74..61b4b53ab335b 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -6,6 +6,7 @@ protobuf_packages = protobuf qt_packages = qrencode zlib qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig +qt_android_packages=qt rapidcheck_packages = rapidcheck diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 56045ade5043a..ff80eb2648812 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -8,7 +8,7 @@ $(package)_dependencies=openssl zlib $(package)_linux_dependencies=freetype fontconfig libxcb $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch +$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch fix_android_qmake_conf.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) $(package)_qttranslations_sha256_hash=fb5a47799754af73d3bf501fe513342cfe2fc37f64e80df5533f6110e804220c @@ -19,6 +19,8 @@ $(package)_qttools_sha256_hash=a97556eb7b2f30252cdd8a598c396cfce2b2f79d2bae883af $(package)_extra_sources = $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) +$(package)_config_opts_aarch64_android = -xplatform android-clang -android-sdk $(ANDROID_SDK) -android-ndk $(ANDROID_NDK) -android-ndk-platform android-$(ANDROID_API_LEVEL) -device-option CROSS_COMPILE="$(host)-" -egl -qpa xcb -no-eglfs -opengl es2 -qt-freetype -no-fontconfig -L $(host_prefix)/lib -I $(host_prefix)/include + define $(package)_set_vars $(package)_config_opts_release = -release $(package)_config_opts_debug = -debug @@ -127,6 +129,19 @@ $(package)_config_opts_x86_64_linux = -xplatform linux-g++-64 $(package)_config_opts_aarch64_linux = -xplatform linux-aarch64-gnu-g++ $(package)_config_opts_riscv64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ $(package)_config_opts_mingw32 = -no-opengl -xplatform win32-g++ -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_aarch64_android = -xplatform android-clang +$(package)_config_opts_aarch64_android += -android-sdk $(ANDROID_SDK) +$(package)_config_opts_aarch64_android += -android-ndk $(ANDROID_NDK) +$(package)_config_opts_aarch64_android += -android-ndk-platform android-$(ANDROID_API_LEVEL) +$(package)_config_opts_aarch64_android += -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_aarch64_android += -egl +$(package)_config_opts_aarch64_android += -qpa xcb +$(package)_config_opts_aarch64_android += -no-eglfs +$(package)_config_opts_aarch64_android += -opengl es2 +$(package)_config_opts_aarch64_android += -qt-freetype +$(package)_config_opts_aarch64_android += -no-fontconfig +$(package)_config_opts_aarch64_android += -L $(host_prefix)/lib +$(package)_config_opts_aarch64_android += -I $(host_prefix)/include $(package)_build_env = QT_RCC_TEST=1 $(package)_build_env += QT_RCC_SOURCE_DATE_OVERRIDE=1 endef @@ -169,6 +184,7 @@ define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch &&\ patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch &&\ patch -p1 -i $($(package)_patch_dir)/xkb-default.patch &&\ + patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch &&\ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ diff --git a/depends/patches/qt/fix_android_qmake_conf.patch b/depends/patches/qt/fix_android_qmake_conf.patch new file mode 100644 index 0000000000000..13bfff9776474 --- /dev/null +++ b/depends/patches/qt/fix_android_qmake_conf.patch @@ -0,0 +1,20 @@ +--- old/qtbase/mkspecs/android-clang/qmake.conf ++++ new/qtbase/mkspecs/android-clang/qmake.conf +@@ -30,7 +30,7 @@ + QMAKE_CFLAGS += -target mips64el-none-linux-android + + QMAKE_CFLAGS += -gcc-toolchain $$NDK_TOOLCHAIN_PATH +-QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a ++QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a -nostdlib++ + QMAKE_CFLAGS += -DANDROID_HAS_WSTRING --sysroot=$$NDK_ROOT/sysroot \ + -isystem $$NDK_ROOT/sysroot/usr/include/$$NDK_TOOLS_PREFIX \ + -isystem $$NDK_ROOT/sources/cxx-stl/llvm-libc++/include \ +@@ -40,7 +40,7 @@ + ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH + + ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++_shared.so +-ANDROID_CXX_STL_LIBS = -lc++ ++ANDROID_CXX_STL_LIBS = -lc++_shared + + QMAKE_ARM_CFLAGS_RELEASE = -Oz + QMAKE_ARM_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -Oz From 45f82190150b3feef333724ea7395ba080e700b1 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Tue, 17 Sep 2019 11:15:08 +0200 Subject: [PATCH 007/502] Add full Android build example command and instructions on getting SDK/NDK --- depends/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/depends/README.md b/depends/README.md index a2fb592f344e7..bf140f9c11d6b 100644 --- a/depends/README.md +++ b/depends/README.md @@ -33,9 +33,14 @@ Common `host-platform-triplets` for cross compilation are: - `aarch64-linux-android` for Android ARM 64 bit The paths are automatically configured and no other options are needed unless targeting Android. -In that case one needs to set `ANDROID_API_LEVEL` and `ANDROID_TOOLCHAIN_BIN`: +Before proceeding with an Android build one needs to get the [Android SDK](https://developer.android.com/studio) and use the "SDK Manager" tool to download the NDK and one or more "Platform packages" (these are Android versions and have a corresponding API level). +In order to build `ANDROID_API_LEVEL` (API level corresponding to the Android version targeted, e.g. Android 9.0 Pie is 28 and its "Platform package" needs to be available) and `ANDROID_TOOLCHAIN_BIN` (path to toolchain binaries depending on the platform the build is being performed on) need to be set. +If the build includes Qt, environment variables `ANDROID_SDK` and `ANDROID_NDK` need to be set as well but can otherwise be omitted. +This is an example command for a default build with no disabled dependencies: + + ANDROID_SDK=/home/user/Android/Sdk ANDROID_NDK=/home/user/Android/Sdk/ndk-bundle make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin + - make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin NO_QT=1 NO_WALLET=1 ### Install the required dependencies: Ubuntu & Debian From 80b475f159525737e242161397f35d0729449545 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Thu, 19 Sep 2019 11:43:10 +0200 Subject: [PATCH 008/502] Fix Android zlib cross compilation issue (https://stackoverflow.com/questions/21396988/zlib-build-not-configuring-properly-with-cross-compiler-ignores-ar) --- depends/packages/zlib.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/packages/zlib.mk b/depends/packages/zlib.mk index 168f85e65ee9a..017e7b2cf1121 100644 --- a/depends/packages/zlib.mk +++ b/depends/packages/zlib.mk @@ -11,6 +11,7 @@ $(package)_config_opts+=RANLIB="$($(package)_ranlib)" $(package)_config_opts+=AR="$($(package)_ar)" $(package)_config_opts_darwin+=AR="$($(package)_libtool)" $(package)_config_opts_darwin+=ARFLAGS="-o" +$(package)_config_opts_aarch64_android+=CHOST=$(host) endef # zlib has its own custom configure script that takes in options like CC, From b4057d82618a21720f39f448b689cebf475cc2dc Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Sun, 22 Sep 2019 14:35:41 +0200 Subject: [PATCH 009/502] Define TARGET_OS when host is android --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 2445b72683ef8..78873f38594e7 100644 --- a/configure.ac +++ b/configure.ac @@ -590,6 +590,7 @@ case $host in ;; *android*) dnl make sure android stays above linux for hosts like *linux-android* + TARGET_OS=android LEVELDB_TARGET_FLAGS="-DOS_ANDROID" ;; *linux*) From f1e40b3e7114b18bc03f45c3a97f9f673543ddef Mon Sep 17 00:00:00 2001 From: BlockMechanic Date: Thu, 19 Sep 2019 15:09:47 +0200 Subject: [PATCH 010/502] Update bitcoin_qt.m4 Fix to allow configure to detect at --- build-aux/m4/bitcoin_qt.m4 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 675fb6d3fb63d..8a5bdd840e643 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -116,8 +116,10 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ if test "x$bitcoin_cv_static_qt" = xyes; then _BITCOIN_QT_FIND_STATIC_PLUGINS AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static]) - _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal]) - AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists]) + if test "x$TARGET_OS" != xandroid; then + _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal]) + AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists]) + fi if test "x$TARGET_OS" = xwindows; then _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows]) AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows]) From 24ffef0c271739a2ca75feecb816f3218c1850bf Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Sun, 22 Sep 2019 15:40:15 +0200 Subject: [PATCH 011/502] Patch libevent when building for Android (fix arc4random_addrandom) --- depends/packages/libevent.mk | 13 +++- .../fix_android_arc4random_addrandom.patch | 68 +++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 depends/patches/libevent/fix_android_arc4random_addrandom.patch diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index a3ade899b7321..df6029828d82a 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -3,10 +3,17 @@ $(package)_version=2.1.8-stable $(package)_download_path=https://github.com/libevent/libevent/archive/ $(package)_file_name=release-$($(package)_version).tar.gz $(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d +$(package)_patches=fix_android_arc4random_addrandom.patch -define $(package)_preprocess_cmds - ./autogen.sh -endef +ifneq (,$(findstring android,$(host))) + define $(package)_preprocess_cmds + ./autogen.sh && patch -p1 < $($(package)_patch_dir)/fix_android_arc4random_addrandom.patch + endef +else + define $(package)_preprocess_cmds + ./autogen.sh + endef +endif define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples diff --git a/depends/patches/libevent/fix_android_arc4random_addrandom.patch b/depends/patches/libevent/fix_android_arc4random_addrandom.patch new file mode 100644 index 0000000000000..5bcc64bef6bc8 --- /dev/null +++ b/depends/patches/libevent/fix_android_arc4random_addrandom.patch @@ -0,0 +1,68 @@ +From cadae3ab7abf45e61ecae8aac39d97d1f3cbd336 Mon Sep 17 00:00:00 2001 +From: Lawrence Nahum +Date: Sun, 3 Dec 2017 22:56:09 +0100 +Subject: [PATCH] fixup + +--- + configure.ac | 1 + + evutil_rand.c | 3 +++ + include/event2/util.h | 4 ++-- + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 7528d37..3bb2121 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -341,6 +341,7 @@ dnl Checks for library functions. + AC_CHECK_FUNCS([ \ + accept4 \ + arc4random \ ++ arc4random_addrandom \ + arc4random_buf \ + eventfd \ + epoll_create1 \ +diff --git a/evutil_rand.c b/evutil_rand.c +index 046a14b..3f0bf2c 100644 +--- a/evutil_rand.c ++++ b/evutil_rand.c +@@ -191,6 +191,7 @@ evutil_secure_rng_get_bytes(void *buf, size_t n) + { + ev_arc4random_buf(buf, n); + } ++#ifdef HAVE_ARC4RANDOM_ADDRANDOM + + void + evutil_secure_rng_add_bytes(const char *buf, size_t n) +@@ -199,6 +200,8 @@ evutil_secure_rng_add_bytes(const char *buf, size_t n) + n>(size_t)INT_MAX ? INT_MAX : (int)n); + } + ++#endif ++ + void + evutil_free_secure_rng_globals_(void) + { +diff --git a/include/event2/util.h b/include/event2/util.h +index dd4bbb6..a9a169d 100644 +--- a/include/event2/util.h ++++ b/include/event2/util.h +@@ -841,7 +841,7 @@ int evutil_secure_rng_init(void); + */ + EVENT2_EXPORT_SYMBOL + int evutil_secure_rng_set_urandom_device_file(char *fname); +- ++#ifdef HAVE_ARC4RANDOM_ADDRANDOM + /** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be +@@ -858,7 +858,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname); + */ + EVENT2_EXPORT_SYMBOL + void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); +- ++#endif + #ifdef __cplusplus + } + #endif +-- +2.14.3 From e4c319e8a1c6e40a953036b942bd5d732b0bbf69 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Mon, 23 Sep 2019 14:44:49 +0200 Subject: [PATCH 012/502] builds: remove superfluous config_opts_aarch64_android --- depends/packages/qt.mk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index ff80eb2648812..a0cf930a710a3 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -19,8 +19,6 @@ $(package)_qttools_sha256_hash=a97556eb7b2f30252cdd8a598c396cfce2b2f79d2bae883af $(package)_extra_sources = $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) -$(package)_config_opts_aarch64_android = -xplatform android-clang -android-sdk $(ANDROID_SDK) -android-ndk $(ANDROID_NDK) -android-ndk-platform android-$(ANDROID_API_LEVEL) -device-option CROSS_COMPILE="$(host)-" -egl -qpa xcb -no-eglfs -opengl es2 -qt-freetype -no-fontconfig -L $(host_prefix)/lib -I $(host_prefix)/include - define $(package)_set_vars $(package)_config_opts_release = -release $(package)_config_opts_debug = -debug @@ -134,6 +132,7 @@ $(package)_config_opts_aarch64_android += -android-sdk $(ANDROID_SDK) $(package)_config_opts_aarch64_android += -android-ndk $(ANDROID_NDK) $(package)_config_opts_aarch64_android += -android-ndk-platform android-$(ANDROID_API_LEVEL) $(package)_config_opts_aarch64_android += -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_aarch64_android += -android-arch arm64-v8a $(package)_config_opts_aarch64_android += -egl $(package)_config_opts_aarch64_android += -qpa xcb $(package)_config_opts_aarch64_android += -no-eglfs From fae43a97ca947cd0802392e9bb86d9d0572c0fba Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 26 Sep 2019 09:14:19 -0400 Subject: [PATCH 013/502] test: Seed test RNG context for each test case, print seed --- src/test/bloom_tests.cpp | 2 +- src/test/coins_tests.cpp | 2 +- src/test/cuckoocache_tests.cpp | 10 +++++----- src/test/pmt_tests.cpp | 1 - src/test/setup_common.cpp | 24 +++++++++++++++++++++++- src/test/setup_common.h | 16 ++++++++++++++-- src/test/sighash_tests.cpp | 2 -- src/test/streams_tests.cpp | 2 +- src/test/util_tests.cpp | 2 +- 9 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 4421494007acf..8ab6da3ce1112 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -461,7 +461,7 @@ static std::vector RandomData() BOOST_AUTO_TEST_CASE(rolling_bloom) { - SeedInsecureRand(/* deterministic */ true); + SeedInsecureRand(SeedRand::ZEROS); g_mock_deterministic_tests = true; // last-100-entry, 1% false positive: diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 948591196c4f3..f9682b1d56e04 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -279,7 +279,7 @@ UtxoData::iterator FindRandomFrom(const std::set &utxoSet) { // has the expected effect (the other duplicate is overwritten at all cache levels) BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) { - SeedInsecureRand(/* deterministic */ true); + SeedInsecureRand(SeedRand::ZEROS); g_mock_deterministic_tests = true; bool spent_a_duplicate_coinbase = false; diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index d38ede691a50c..abae05a1901e7 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -29,7 +29,7 @@ BOOST_AUTO_TEST_SUITE(cuckoocache_tests); */ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); CuckooCache::cache cc{}; size_t megabytes = 4; cc.setup_bytes(megabytes << 20); @@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) template static double test_cache(size_t megabytes, double load) { - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -118,7 +118,7 @@ template static void test_cache_erase(size_t megabytes) { double load = 1; - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -181,7 +181,7 @@ template static void test_cache_erase_parallel(size_t megabytes) { double load = 1; - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -285,7 +285,7 @@ static void test_cache_generations() // iterations with non-deterministic values, so it isn't "overfit" to the // specific entropy in FastRandomContext(true) and implementation of the // cache. - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); // block_activity models a chunk of network activity. n_insert elements are // added to the cache. The first and last n/4 are stored for removal later diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index c5513ae9fa819..b886b512e8e9d 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -30,7 +30,6 @@ BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(pmt_test1) { - SeedInsecureRand(false); static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095}; for (int i = 0; i < 12; i++) { diff --git a/src/test/setup_common.cpp b/src/test/setup_common.cpp index bbdf1ef830ee4..46aef0cc8c101 100644 --- a/src/test/setup_common.cpp +++ b/src/test/setup_common.cpp @@ -33,6 +33,27 @@ const std::function G_TRANSLATION_FUN = nullptr; FastRandomContext g_insecure_rand_ctx; +/** Random context to get unique temp data dirs. Separate from g_insecure_rand_ctx, which can be seeded from a const env var */ +static FastRandomContext g_insecure_rand_ctx_temp_path; + +/** Return the unsigned from the environment var if available, otherwise 0 */ +static uint256 GetUintFromEnv(const std::string& env_name) +{ + const char* num = std::getenv(env_name.c_str()); + if (!num) return {}; + return uint256S(num); +} + +void Seed(FastRandomContext& ctx) +{ + // Should be enough to get the seed once for the process + static uint256 seed{}; + static const std::string RANDOM_CTX_SEED{"RANDOM_CTX_SEED"}; + if (seed.IsNull()) seed = GetUintFromEnv(RANDOM_CTX_SEED); + if (seed.IsNull()) seed = GetRandHash(); + LogPrintf("%s: Setting random seed for current tests to %s=%s\n", __func__, RANDOM_CTX_SEED, seed.GetHex()); + ctx = FastRandomContext(seed); +} std::ostream& operator<<(std::ostream& os, const uint256& num) { @@ -41,12 +62,13 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) } BasicTestingSetup::BasicTestingSetup(const std::string& chainName) - : m_path_root(fs::temp_directory_path() / "test_common_" PACKAGE_NAME / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) + : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / std::to_string(g_insecure_rand_ctx_temp_path.rand32())} { fs::create_directories(m_path_root); gArgs.ForceSetArg("-datadir", m_path_root.string()); ClearDatadirCache(); SelectParams(chainName); + SeedInsecureRand(); gArgs.ForceSetArg("-printtoconsole", "0"); InitLogging(); LogInstance().StartLogging(); diff --git a/src/test/setup_common.h b/src/test/setup_common.h index 6c9494898cdc3..f9f7bcdcc910b 100644 --- a/src/test/setup_common.h +++ b/src/test/setup_common.h @@ -38,9 +38,21 @@ extern FastRandomContext g_insecure_rand_ctx; */ extern bool g_mock_deterministic_tests; -static inline void SeedInsecureRand(bool deterministic = false) +enum class SeedRand { + ZEROS, //!< Seed with a compile time constant of zeros + SEED, //!< Call the Seed() helper +}; + +/** Seed the given random ctx or use the seed passed in via an environment var */ +void Seed(FastRandomContext& ctx); + +static inline void SeedInsecureRand(SeedRand seed = SeedRand::SEED) { - g_insecure_rand_ctx = FastRandomContext(deterministic); + if (seed == SeedRand::ZEROS) { + g_insecure_rand_ctx = FastRandomContext(/* deterministic */ true); + } else { + Seed(g_insecure_rand_ctx); + } } static inline uint32_t InsecureRand32() { return g_insecure_rand_ctx.rand32(); } diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 15f8db899b0a9..64f59aa06da48 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -119,8 +119,6 @@ BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sighash_test) { - SeedInsecureRand(false); - #if defined(PRINT_SIGHASH_JSON) std::cout << "[\n"; std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n"; diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 638819d564a44..83903ca11239d 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -339,7 +339,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file) BOOST_AUTO_TEST_CASE(streams_buffered_file_rand) { // Make this test deterministic. - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); for (int rep = 0; rep < 50; ++rep) { FILE* file = fsbridge::fopen("streams_test_tmp", "w+b"); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index d0cd4b0a03d2d..d18db86a5c547 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1036,7 +1036,7 @@ BOOST_AUTO_TEST_CASE(util_IsHexNumber) BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); for (int mod=2;mod<11;mod++) { int mask = 1; From ed30684d03d3a1d5496e69c488d848fe92ae6fb4 Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Sat, 12 Oct 2019 12:49:25 +0200 Subject: [PATCH 014/502] Qt: patch androidjnimain.cpp to make sure JNI is initialised when statically compiled --- depends/packages/qt.mk | 3 ++- .../patches/qt/fix_android_jni_static.patch | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 depends/patches/qt/fix_android_jni_static.patch diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index a0cf930a710a3..2f10a587c4c1c 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -8,7 +8,7 @@ $(package)_dependencies=openssl zlib $(package)_linux_dependencies=freetype fontconfig libxcb $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch fix_android_qmake_conf.patch +$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch fix_android_qmake_conf.patch fix_android_jni_static.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) $(package)_qttranslations_sha256_hash=fb5a47799754af73d3bf501fe513342cfe2fc37f64e80df5533f6110e804220c @@ -184,6 +184,7 @@ define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch &&\ patch -p1 -i $($(package)_patch_dir)/xkb-default.patch &&\ patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch &&\ + patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch &&\ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ diff --git a/depends/patches/qt/fix_android_jni_static.patch b/depends/patches/qt/fix_android_jni_static.patch new file mode 100644 index 0000000000000..2f6ff00f40c25 --- /dev/null +++ b/depends/patches/qt/fix_android_jni_static.patch @@ -0,0 +1,18 @@ +--- old/qtbase/src/plugins/platforms/android/androidjnimain.cpp ++++ new/qtbase/src/plugins/platforms/android/androidjnimain.cpp +@@ -890,6 +890,14 @@ + __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); + return -1; + } ++ ++ const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, env)); ++ if (ret != 0) ++ { ++ __android_log_print(ANDROID_LOG_FATAL, "Qt", "initJNI failed"); ++ return ret; ++ } ++ + QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); + + m_javaVM = vm; + From d419ca7e32bfc71e8dd1f1b91870463eacd6ad8e Mon Sep 17 00:00:00 2001 From: Igor Cota Date: Sat, 12 Oct 2019 13:25:06 +0200 Subject: [PATCH 015/502] depends: export dynamic JNI symbols from static qtforandroid.a --- build-aux/m4/bitcoin_qt.m4 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 8a5bdd840e643..bab89a3dcc366 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -130,6 +130,9 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)]) _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa]) AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa]) + elif test "x$TARGET_OS" = xandroid; then + QT_LIBS="-Wl,--export-dynamic,--undefined=JNI_OnLoad -lqtforandroid -ljnigraphics -landroid -lqtfreetype -lQt5EglSupport $QT_LIBS" + AC_DEFINE(QT_QPA_PLATFORM_ANDROID, 1, [Define this symbol if the qt platform is android]) fi fi CPPFLAGS=$TEMP_CPPFLAGS @@ -343,6 +346,9 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ if test -d "$qt_plugin_path/accessible"; then QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" fi + if test -d "$qt_plugin_path/platforms/android"; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms/android -lqtfreetype -lEGL" + fi if test "x$use_pkgconfig" = xyes; then : dnl m4_ifdef([PKG_CHECK_MODULES],[ From 090b75c14be6b9ba2efe38a17d141c6e6af575cb Mon Sep 17 00:00:00 2001 From: User Date: Wed, 16 Oct 2019 17:06:20 -0400 Subject: [PATCH 016/502] p2p: Avoid allocating memory for addrKnown where we don't need it --- src/bloom.h | 3 --- src/net.cpp | 5 ++++- src/net.h | 6 +++--- src/net_processing.cpp | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bloom.h b/src/bloom.h index 7d3aa878b07f9..c3f64ba4bc4f8 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -115,9 +115,6 @@ class CBloomFilter class CRollingBloomFilter { public: - // A random bloom filter calls GetRand() at creation time. - // Don't create global CRollingBloomFilter objects, as they may be - // constructed before the randomizer is properly initialized. CRollingBloomFilter(const unsigned int nElements, const double nFPRate); void insert(const std::vector& vKey); diff --git a/src/net.cpp b/src/net.cpp index 63b78338226c5..df52689092902 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2652,7 +2652,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn addrBind(addrBindIn), fInbound(fInboundIn), nKeyedNetGroup(nKeyedNetGroupIn), - addrKnown(5000, 0.001), // Don't relay addr messages to peers that we connect to as block-relay-only // peers (to prevent adversaries from inferring these links from addr // traffic). @@ -2669,6 +2668,10 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn m_tx_relay = MakeUnique(); } + if (m_addr_relay_peer) { + m_addr_known = MakeUnique(5000, 0.001); + } + for (const std::string &msg : getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; diff --git a/src/net.h b/src/net.h index 44655abf80d33..4a7f7bc093a73 100644 --- a/src/net.h +++ b/src/net.h @@ -729,7 +729,7 @@ class CNode // flood relay std::vector vAddrToSend; - CRollingBloomFilter addrKnown; + std::unique_ptr m_addr_known; bool fGetAddr{false}; int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0}; int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0}; @@ -884,7 +884,7 @@ class CNode void AddAddressKnown(const CAddress& _addr) { - addrKnown.insert(_addr.GetKey()); + m_addr_known->insert(_addr.GetKey()); } void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand) @@ -892,7 +892,7 @@ class CNode // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. - if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) { + if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr; } else { diff --git a/src/net_processing.cpp b/src/net_processing.cpp index b6839dcf2154e..188c3d777e195 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1315,7 +1315,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma // Relay to a limited number of other nodes // Use deterministic randomness to send to the same nodes for 24 hours - // at a time so the addrKnowns of the chosen nodes prevent repeats + // at a time so the m_addr_knowns of the chosen nodes prevent repeats uint64_t hashAddr = addr.GetHash(); const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60)); FastRandomContext insecure_rand; @@ -3563,9 +3563,9 @@ bool PeerLogicValidation::SendMessages(CNode* pto) vAddr.reserve(pto->vAddrToSend.size()); for (const CAddress& addr : pto->vAddrToSend) { - if (!pto->addrKnown.contains(addr.GetKey())) + if (!pto->m_addr_known->contains(addr.GetKey())) { - pto->addrKnown.insert(addr.GetKey()); + pto->m_addr_known->insert(addr.GetKey()); vAddr.push_back(addr); // receiver rejects addr messages larger than 1000 if (vAddr.size() >= 1000) From f9af3ced1c69d65c5c530ec5526f5eefaf786126 Mon Sep 17 00:00:00 2001 From: Block Mechanic Date: Fri, 18 Oct 2019 22:03:51 +0200 Subject: [PATCH 017/502] Android: add all arch support Add support for armv7a, i686 and x86_64 archs to android.mk Add -fPIC to depends file as anddroid requires it see https://stackoverflow.com/questions/30498776/position-independent-executables-and-android --- depends/hosts/android.mk | 7 +++++++ depends/packages/boost.mk | 5 +++++ depends/packages/libevent.mk | 1 + depends/packages/openssl.mk | 6 +++++- depends/packages/qrencode.mk | 1 + depends/packages/qt.mk | 32 +++++++++++++++++++------------- depends/packages/zeromq.mk | 1 + depends/packages/zlib.mk | 2 +- 8 files changed, 40 insertions(+), 15 deletions(-) diff --git a/depends/hosts/android.mk b/depends/hosts/android.mk index c2a30d7a4d65d..969ec2a1cb047 100644 --- a/depends/hosts/android.mk +++ b/depends/hosts/android.mk @@ -1,4 +1,11 @@ +ifeq ($(HOST),armv7a-linux-android) +android_AR=$(ANDROID_TOOLCHAIN_BIN)/arm-linux-androideabi-ar +android_CXX=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)eabi$(ANDROID_API_LEVEL)-clang++ +android_CC=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)eabi$(ANDROID_API_LEVEL)-clang +android_RANLIB=$(ANDROID_TOOLCHAIN_BIN)/arm-linux-androideabi-ranlib +else android_AR=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)-ar android_CXX=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)$(ANDROID_API_LEVEL)-clang++ android_CC=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)$(ANDROID_API_LEVEL)-clang android_RANLIB=$(ANDROID_TOOLCHAIN_BIN)/$(HOST)-ranlib +endif diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 5df49b2af8509..5dfa1d2cdf368 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -15,6 +15,10 @@ $(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win3 $(package)_config_opts_x86_64_mingw32=address-model=64 $(package)_config_opts_i686_mingw32=address-model=32 $(package)_config_opts_i686_linux=address-model=32 architecture=x86 +$(package)_config_opts_i686_android=address-model=32 +$(package)_config_opts_aarch64_android=address-model=64 +$(package)_config_opts_x86_64_android=address-model=64 +$(package)_config_opts_armv7a_android=address-model=32 $(package)_toolset_$(host_os)=gcc $(package)_archiver_$(host_os)=$($(package)_ar) $(package)_toolset_darwin=darwin @@ -22,6 +26,7 @@ $(package)_archiver_darwin=$($(package)_libtool) $(package)_config_libraries=chrono,filesystem,system,thread,test $(package)_cxxflags=-std=c++11 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC +$(package)_cxxflags_android=-fPIC endef define $(package)_preprocess_cmds diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index df6029828d82a..bf5de610290b5 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -19,6 +19,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples $(package)_config_opts_release=--disable-debug-mode $(package)_config_opts_linux=--with-pic + $(package)_config_opts_android=--with-pic endef define $(package)_config_cmds diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index 6a316a308e07a..ad922778acb81 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -57,7 +57,11 @@ $(package)_config_opts_riscv64_linux=linux-generic64 $(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc $(package)_config_opts_x86_64_mingw32=mingw64 $(package)_config_opts_i686_mingw32=mingw -$(package)_config_opts_android=linux-generic64 +$(package)_config_opts_android=-fPIC +$(package)_config_opts_aarch64_android=linux-generic64 +$(package)_config_opts_x86_64_android=linux-generic64 +$(package)_config_opts_armv7a_android=linux-generic32 +$(package)_config_opts_i686_android=linux-generic32 endef define $(package)_preprocess_cmds diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index 3bc2cb768cc02..eed2bcd98031a 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -8,6 +8,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --without-tools --without-tests --disable-sdltest $(package)_config_opts += --disable-gprof --disable-gcov --disable-mudflap $(package)_config_opts_linux=--with-pic +$(package)_config_opts_android=--with-pic endef define $(package)_preprocess_cmds diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 2f10a587c4c1c..d4c4ab0ae8abf 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -127,20 +127,26 @@ $(package)_config_opts_x86_64_linux = -xplatform linux-g++-64 $(package)_config_opts_aarch64_linux = -xplatform linux-aarch64-gnu-g++ $(package)_config_opts_riscv64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ $(package)_config_opts_mingw32 = -no-opengl -xplatform win32-g++ -device-option CROSS_COMPILE="$(host)-" -$(package)_config_opts_aarch64_android = -xplatform android-clang -$(package)_config_opts_aarch64_android += -android-sdk $(ANDROID_SDK) -$(package)_config_opts_aarch64_android += -android-ndk $(ANDROID_NDK) -$(package)_config_opts_aarch64_android += -android-ndk-platform android-$(ANDROID_API_LEVEL) -$(package)_config_opts_aarch64_android += -device-option CROSS_COMPILE="$(host)-" + +$(package)_config_opts_android = -xplatform android-clang +$(package)_config_opts_android += -android-sdk $(ANDROID_SDK) +$(package)_config_opts_android += -android-ndk $(ANDROID_NDK) +$(package)_config_opts_android += -android-ndk-platform android-$(ANDROID_API_LEVEL) +$(package)_config_opts_android += -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_android += -egl +$(package)_config_opts_android += -qpa xcb +$(package)_config_opts_android += -no-eglfs +$(package)_config_opts_android += -opengl es2 +$(package)_config_opts_android += -qt-freetype +$(package)_config_opts_android += -no-fontconfig +$(package)_config_opts_android += -L $(host_prefix)/lib +$(package)_config_opts_android += -I $(host_prefix)/include + $(package)_config_opts_aarch64_android += -android-arch arm64-v8a -$(package)_config_opts_aarch64_android += -egl -$(package)_config_opts_aarch64_android += -qpa xcb -$(package)_config_opts_aarch64_android += -no-eglfs -$(package)_config_opts_aarch64_android += -opengl es2 -$(package)_config_opts_aarch64_android += -qt-freetype -$(package)_config_opts_aarch64_android += -no-fontconfig -$(package)_config_opts_aarch64_android += -L $(host_prefix)/lib -$(package)_config_opts_aarch64_android += -I $(host_prefix)/include +$(package)_config_opts_armv7a_android += -android-arch armeabi-v7a +$(package)_config_opts_x86_64_android += -android-arch x86_64 +$(package)_config_opts_i686_android += -android-arch i686 + $(package)_build_env = QT_RCC_TEST=1 $(package)_build_env += QT_RCC_SOURCE_DATE_OVERRIDE=1 endef diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 9ac037ebb5cd5..eb60f7dee0ab7 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -10,6 +10,7 @@ define $(package)_set_vars $(package)_config_opts += --without-libsodium --without-libgssapi_krb5 --without-pgm --without-norm --without-vmci $(package)_config_opts += --disable-libunwind --disable-radix-tree --without-gcov $(package)_config_opts_linux=--with-pic + $(package)_config_opts_android=--with-pic $(package)_cxxflags=-std=c++11 endef diff --git a/depends/packages/zlib.mk b/depends/packages/zlib.mk index 017e7b2cf1121..acb02020a80b2 100644 --- a/depends/packages/zlib.mk +++ b/depends/packages/zlib.mk @@ -11,7 +11,7 @@ $(package)_config_opts+=RANLIB="$($(package)_ranlib)" $(package)_config_opts+=AR="$($(package)_ar)" $(package)_config_opts_darwin+=AR="$($(package)_libtool)" $(package)_config_opts_darwin+=ARFLAGS="-o" -$(package)_config_opts_aarch64_android+=CHOST=$(host) +$(package)_config_opts_android+=CHOST=$(host) endef # zlib has its own custom configure script that takes in options like CC, From dce032ce294fe0d531770f540b1de00dc1d13f4b Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 30 Aug 2019 12:39:41 -0700 Subject: [PATCH 018/502] Make IsTrusted scan parents recursively --- src/wallet/wallet.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6adcf15167bc8..5acd0dbf0c35f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2319,8 +2319,12 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const if (parent == nullptr) return false; const CTxOut& parentOut = parent->tx->vout[txin.prevout.n]; + // Check that this specific input being spent is trusted if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false; + // Recurse to check that the parent is also trusted + if (!parent->IsTrusted(locked_chain)) + return false; } return true; } From 595f09d6de7f1b94428cdd1310777aa6a4c584e5 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 30 Aug 2019 13:25:41 -0700 Subject: [PATCH 019/502] Cache tx Trust per-call to avoid DoS --- src/wallet/wallet.cpp | 12 +++++++++++- src/wallet/wallet.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5acd0dbf0c35f..ae6c268484cf2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2294,6 +2294,12 @@ bool CWalletTx::InMempool() const } bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const +{ + std::set s; + return IsTrusted(locked_chain, s); +} + +bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trustedParents) const { // Quick answer in most cases if (!locked_chain.checkFinalTx(*tx)) { @@ -2322,9 +2328,13 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const // Check that this specific input being spent is trusted if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false; + // If we've already trusted this parent, continue + if (trustedParents.count(parent->GetHash())) + continue; // Recurse to check that the parent is also trusted - if (!parent->IsTrusted(locked_chain)) + if (!parent->IsTrusted(locked_chain, trustedParents)) return false; + trustedParents.insert(parent->GetHash()); } return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f9e2230a6ffb0..986baa89ee88a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -616,6 +616,7 @@ class CWalletTx bool InMempool() const; bool IsTrusted(interfaces::Chain::Lock& locked_chain) const; + bool IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trustedParents) const; int64_t GetTxTime() const; From 5dd7da4ccd1354f09e2d00bab29288db0d5665d0 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 30 Aug 2019 13:31:11 -0700 Subject: [PATCH 020/502] Reuse trustedParents in looped calls to IsTrusted --- src/wallet/wallet.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ae6c268484cf2..a14d538fe6d57 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2420,10 +2420,11 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons { auto locked_chain = chain().lock(); LOCK(cs_wallet); + std::set trustedParents; for (const auto& entry : mapWallet) { const CWalletTx& wtx = entry.second; - const bool is_trusted{wtx.IsTrusted(*locked_chain)}; + const bool is_trusted{wtx.IsTrusted(*locked_chain, trustedParents)}; const int tx_depth{wtx.GetDepthInMainChain(*locked_chain)}; const CAmount tx_credit_mine{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)}; const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)}; @@ -2470,6 +2471,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< const int min_depth = {coinControl ? coinControl->m_min_depth : DEFAULT_MIN_DEPTH}; const int max_depth = {coinControl ? coinControl->m_max_depth : DEFAULT_MAX_DEPTH}; + std::set trustedParents; for (const auto& entry : mapWallet) { const uint256& wtxid = entry.first; @@ -2491,7 +2493,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< if (nDepth == 0 && !wtx.InMempool()) continue; - bool safeTx = wtx.IsTrusted(locked_chain); + bool safeTx = wtx.IsTrusted(locked_chain, trustedParents); // We should not consider coins from transactions that are replacing // other transactions. @@ -3776,11 +3778,12 @@ std::map CWallet::GetAddressBalances(interfaces::Chain: { LOCK(cs_wallet); + std::set trustedParents; for (const auto& walletEntry : mapWallet) { const CWalletTx& wtx = walletEntry.second; - if (!wtx.IsTrusted(locked_chain)) + if (!wtx.IsTrusted(locked_chain, trustedParents)) continue; if (wtx.IsImmatureCoinBase(locked_chain)) From a550c58267f50c59c2eea1d46edaa5019a8ad5d8 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Tue, 3 Sep 2019 10:24:10 -0700 Subject: [PATCH 021/502] Update wallet_balance.py test to reflect new behavior --- test/functional/wallet_balance.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py index c50dcd987a896..9cf55dc65a05b 100755 --- a/test/functional/wallet_balance.py +++ b/test/functional/wallet_balance.py @@ -112,10 +112,10 @@ def run_test(self): def test_balances(*, fee_node_1=0): # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send - assert_equal(self.nodes[1].getbalance(), Decimal('30') - fee_node_1) # change from node 1's send + assert_equal(self.nodes[1].getbalance(), Decimal('0')) # change from node 1's send # Same with minconf=0 assert_equal(self.nodes[0].getbalance(minconf=0), Decimal('9.99')) - assert_equal(self.nodes[1].getbalance(minconf=0), Decimal('30') - fee_node_1) + assert_equal(self.nodes[1].getbalance(minconf=0), Decimal('0')) # getbalance with a minconf incorrectly excludes coins that have been spent more recently than the minconf blocks ago # TODO: fix getbalance tracking of coin spentness depth assert_equal(self.nodes[0].getbalance(minconf=1), Decimal('0')) @@ -125,9 +125,9 @@ def test_balances(*, fee_node_1=0): assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('60')) assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60')) - assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) # Doesn't include output of node 0's send since it was spent - assert_equal(self.nodes[1].getbalances()['mine']['untrusted_pending'], Decimal('0')) - assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('0')) + assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('30') - fee_node_1) # Doesn't include output of node 0's send since it was spent + assert_equal(self.nodes[1].getbalances()['mine']['untrusted_pending'], Decimal('30') - fee_node_1) + assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('30') - fee_node_1) test_balances(fee_node_1=Decimal('0.01')) From 5ffe0d144923f365cb1c2fad181eca15d1668692 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Wed, 4 Sep 2019 11:40:53 -0700 Subject: [PATCH 022/502] Update comment in test/functional/wallet_balance.py Co-Authored-By: MarcoFalke --- test/functional/wallet_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py index 9cf55dc65a05b..1325681c9cffc 100755 --- a/test/functional/wallet_balance.py +++ b/test/functional/wallet_balance.py @@ -112,7 +112,7 @@ def run_test(self): def test_balances(*, fee_node_1=0): # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send - assert_equal(self.nodes[1].getbalance(), Decimal('0')) # change from node 1's send + assert_equal(self.nodes[1].getbalance(), Decimal('0')) # node 1's send had an unsafe input # Same with minconf=0 assert_equal(self.nodes[0].getbalance(minconf=0), Decimal('9.99')) assert_equal(self.nodes[1].getbalance(minconf=0), Decimal('0')) From b49dcbedf79613f0e0f61bfd742ed265213ed280 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 6 Sep 2019 09:15:49 -0700 Subject: [PATCH 023/502] update variable naming conventions for IsTrusted --- src/wallet/wallet.cpp | 20 ++++++++++---------- src/wallet/wallet.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a14d538fe6d57..220438107958e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2299,7 +2299,7 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const return IsTrusted(locked_chain, s); } -bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trustedParents) const +bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trusted_parents) const { // Quick answer in most cases if (!locked_chain.checkFinalTx(*tx)) { @@ -2329,12 +2329,12 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::setIsMine(parentOut) != ISMINE_SPENDABLE) return false; // If we've already trusted this parent, continue - if (trustedParents.count(parent->GetHash())) + if (trusted_parents.count(parent->GetHash())) continue; // Recurse to check that the parent is also trusted - if (!parent->IsTrusted(locked_chain, trustedParents)) + if (!parent->IsTrusted(locked_chain, trusted_parents)) return false; - trustedParents.insert(parent->GetHash()); + trusted_parents.insert(parent->GetHash()); } return true; } @@ -2420,11 +2420,11 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons { auto locked_chain = chain().lock(); LOCK(cs_wallet); - std::set trustedParents; + std::set trusted_parents; for (const auto& entry : mapWallet) { const CWalletTx& wtx = entry.second; - const bool is_trusted{wtx.IsTrusted(*locked_chain, trustedParents)}; + const bool is_trusted{wtx.IsTrusted(*locked_chain, trusted_parents)}; const int tx_depth{wtx.GetDepthInMainChain(*locked_chain)}; const CAmount tx_credit_mine{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)}; const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)}; @@ -2471,7 +2471,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< const int min_depth = {coinControl ? coinControl->m_min_depth : DEFAULT_MIN_DEPTH}; const int max_depth = {coinControl ? coinControl->m_max_depth : DEFAULT_MAX_DEPTH}; - std::set trustedParents; + std::set trusted_parents; for (const auto& entry : mapWallet) { const uint256& wtxid = entry.first; @@ -2493,7 +2493,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector< if (nDepth == 0 && !wtx.InMempool()) continue; - bool safeTx = wtx.IsTrusted(locked_chain, trustedParents); + bool safeTx = wtx.IsTrusted(locked_chain, trusted_parents); // We should not consider coins from transactions that are replacing // other transactions. @@ -3778,12 +3778,12 @@ std::map CWallet::GetAddressBalances(interfaces::Chain: { LOCK(cs_wallet); - std::set trustedParents; + std::set trusted_parents; for (const auto& walletEntry : mapWallet) { const CWalletTx& wtx = walletEntry.second; - if (!wtx.IsTrusted(locked_chain, trustedParents)) + if (!wtx.IsTrusted(locked_chain, trusted_parents)) continue; if (wtx.IsImmatureCoinBase(locked_chain)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 986baa89ee88a..3513ebb91c698 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -616,7 +616,7 @@ class CWalletTx bool InMempool() const; bool IsTrusted(interfaces::Chain::Lock& locked_chain) const; - bool IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trustedParents) const; + bool IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trusted_parents) const; int64_t GetTxTime() const; From 8f174ef112199aa4e98d756039855cc561687c2e Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Fri, 6 Sep 2019 09:24:35 -0700 Subject: [PATCH 024/502] Systematize style of IsTrusted single line if --- src/wallet/wallet.cpp | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 220438107958e..96ae7bbb1e55a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2302,38 +2302,29 @@ bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain) const bool CWalletTx::IsTrusted(interfaces::Chain::Lock& locked_chain, std::set& trusted_parents) const { // Quick answer in most cases - if (!locked_chain.checkFinalTx(*tx)) { - return false; - } + if (!locked_chain.checkFinalTx(*tx)) return false; int nDepth = GetDepthInMainChain(locked_chain); - if (nDepth >= 1) - return true; - if (nDepth < 0) - return false; - if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit - return false; + if (nDepth >= 1) return true; + if (nDepth < 0) return false; + // using wtx's cached debit + if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) return false; // Don't trust unconfirmed transactions from us unless they are in the mempool. - if (!InMempool()) - return false; + if (!InMempool()) return false; // Trusted if all inputs are from us and are in the mempool: for (const CTxIn& txin : tx->vin) { // Transactions not sent by us: not trusted const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); - if (parent == nullptr) - return false; + if (parent == nullptr) return false; const CTxOut& parentOut = parent->tx->vout[txin.prevout.n]; // Check that this specific input being spent is trusted - if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) - return false; + if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false; // If we've already trusted this parent, continue - if (trusted_parents.count(parent->GetHash())) - continue; + if (trusted_parents.count(parent->GetHash())) continue; // Recurse to check that the parent is also trusted - if (!parent->IsTrusted(locked_chain, trusted_parents)) - return false; + if (!parent->IsTrusted(locked_chain, trusted_parents)) return false; trusted_parents.insert(parent->GetHash()); } return true; From 91f3073f08aff395dd813296bf99fd8ccc81bb27 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Mon, 21 Oct 2019 13:22:56 -0700 Subject: [PATCH 025/502] Update release notes to mention changes to IsTrusted and impact on wallet --- doc/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index ea82962e755e1..a47c8802b0cd4 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -85,6 +85,7 @@ Wallet ------ - The wallet now by default uses bech32 addresses when using RPC, and creates native segwit change outputs. +- The way that output trust was computed has been fixed in #16766, which impacts confirmed/unconfirmed balance status and coin selection. Low-level changes ================= From 4671fc3d9e669da8b8781f0cbefee43cb9acd527 Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Mon, 21 Oct 2019 13:43:44 -0700 Subject: [PATCH 026/502] Expand on wallet_balance.py comment from https://github.com/bitcoin/bitcoin/pull/16766\#issuecomment-527563982 --- test/functional/wallet_balance.py | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py index 1325681c9cffc..a5f9a047edcc9 100755 --- a/test/functional/wallet_balance.py +++ b/test/functional/wallet_balance.py @@ -109,6 +109,44 @@ def run_test(self): self.log.info("Test getbalance and getunconfirmedbalance with unconfirmed inputs") + # Before `test_balance()`, we have had two nodes with a balance of 50 + # each and then we: + # + # 1) Sent 40 from node A to node B with fee 0.01 + # 2) Sent 60 from node B to node A with fee 0.01 + # + # Then we check the balances: + # + # 1) As is + # 2) With transaction 2 from above with 2x the fee + # + # Prior to #16766, in this situation, the node would immediately report + # a balance of 30 on node B as unconfirmed and trusted. + # + # After #16766, we show that balance as unconfirmed. + # + # The balance is indeed "trusted" and "confirmed" insofar as removing + # the mempool transactions would return at least that much money. But + # the algorithm after #16766 marks it as unconfirmed because the 'taint' + # tracking of transaction trust for summing balances doesn't consider + # which inputs belong to a user. In this case, the change output in + # question could be "destroyed" by replace the 1st transaction above. + # + # The post #16766 behavior is correct; we shouldn't be treating those + # funds as confirmed. If you want to rely on that specific UTXO existing + # which has given you that balance, you cannot, as a third party + # spending the other input would destroy that unconfirmed. + # + # For example, if the test transactions were: + # + # 1) Sent 40 from node A to node B with fee 0.01 + # 2) Sent 10 from node B to node A with fee 0.01 + # + # Then our node would report a confirmed balance of 40 + 50 - 10 = 80 + # BTC, which is more than would be available if transaction 1 were + # replaced. + + def test_balances(*, fee_node_1=0): # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send From feb507577797518d0bee1774327d215e19d1ba34 Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 20 Aug 2019 14:33:39 +0800 Subject: [PATCH 027/502] build: use osslsigncode 2.0 in gitian The original osslsigncode project (https://sourceforge.net/projects/osslsigncode/) has been marked as abandonware, "This is now - and has been for a long while - abandonware. Feel free to create your own forks etc.". However, a fork at https://github.com/mtrojnar/osslsigncode has emerged that has incorporated theuni's patches, updated the tool to work with OpenSSL 1.1 and made other improvements. This commit switches the windows signer descriptor to use this new version of osslsigncode. --- contrib/gitian-build.py | 6 ++---- .../gitian-descriptors/gitian-win-signer.yml | 17 ++++++++--------- doc/release-process.md | 6 ++---- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py index 570d4906cd69d..712352d6b791b 100755 --- a/contrib/gitian-build.py +++ b/contrib/gitian-build.py @@ -51,10 +51,8 @@ def build(): os.chdir('gitian-builder') os.makedirs('inputs', exist_ok=True) - subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz']) - subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch']) - subprocess.check_call(["echo 'a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 inputs/osslsigncode-Backports-to-1.7.1.patch' | sha256sum -c"], shell=True) - subprocess.check_call(["echo 'f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 inputs/osslsigncode-1.7.1.tar.gz' | sha256sum -c"], shell=True) + subprocess.check_call(['wget', '-O' 'osslsigncode-2.0.tar.gz' '-N', '-P', 'inputs', 'https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz']) + subprocess.check_call(["echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c"], shell=True) subprocess.check_call(['make', '-C', '../bitcoin/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) if args.linux: diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml index 656c6d9b7a80d..b151caa3cc8e3 100644 --- a/contrib/gitian-descriptors/gitian-win-signer.yml +++ b/contrib/gitian-descriptors/gitian-win-signer.yml @@ -6,15 +6,15 @@ suites: architectures: - "amd64" packages: -# Once osslsigncode supports openssl 1.1, we can change this back to libssl-dev -- "libssl1.0-dev" +- "libssl-dev" - "autoconf" +- "libtool" +- "pkg-config" remotes: - "url": "https://github.com/bitcoin-core/bitcoin-detached-sigs.git" "dir": "signature" files: -- "osslsigncode-1.7.1.tar.gz" -- "osslsigncode-Backports-to-1.7.1.patch" +- "osslsigncode-2.0.tar.gz" - "bitcoin-win-unsigned.tar.gz" script: | set -e -o pipefail @@ -23,16 +23,15 @@ script: | SIGDIR=${BUILD_DIR}/signature/win UNSIGNED_DIR=${BUILD_DIR}/unsigned - echo "f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 osslsigncode-1.7.1.tar.gz" | sha256sum -c - echo "a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 osslsigncode-Backports-to-1.7.1.patch" | sha256sum -c + echo "5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f osslsigncode-2.0.tar.gz" | sha256sum -c mkdir -p ${UNSIGNED_DIR} tar -C ${UNSIGNED_DIR} -xf bitcoin-win-unsigned.tar.gz - tar xf osslsigncode-1.7.1.tar.gz - cd osslsigncode-1.7.1 - patch -p1 < ${BUILD_DIR}/osslsigncode-Backports-to-1.7.1.patch + tar xf osslsigncode-2.0.tar.gz + cd osslsigncode-2.0 + ./autogen.sh ./configure --without-gsf --without-curl --disable-dependency-tracking make find ${UNSIGNED_DIR} -name "*-unsigned.exe" | while read i; do diff --git a/doc/release-process.md b/doc/release-process.md index 2c3c4e3869a6f..6d1e7c69e99ac 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -116,10 +116,8 @@ Ensure gitian-builder is up-to-date: pushd ./gitian-builder mkdir -p inputs - wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch - echo 'a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 inputs/osslsigncode-Backports-to-1.7.1.patch' | sha256sum -c - wget -P inputs https://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz - echo 'f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 inputs/osslsigncode-1.7.1.tar.gz' | sha256sum -c + wget -O osslsigncode-2.0.tar.gz -P inputs https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz + echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c popd Create the macOS SDK tarball, see the [macOS build instructions](build-osx.md#deterministic-macos-dmg-notes) for details, and copy it into the inputs directory. From 8d8e5a79d09d9027e5b68fecfc713e7b135320ba Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 20 Oct 2019 02:03:13 +0200 Subject: [PATCH 028/502] test: use default address type (bech32) for wallet_bumpfee tests The use of native segwit addresses (pure p2wpkh instead of p2sh-p2wpkh) leads to smaller transaction sizes, needing adaption of some constants in the following test cases: - test_dust_to_fee(): adaption of dust calculation (p2wpkh spend estimate of 67 is taken from src/policy/policy.cpp:GetDustThreshold()) - test_maxtxfee_fails(): lowering -maxtxfee setting to trigger fail --- test/functional/wallet_bumpfee.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 0948d47653238..95d51adebbbe6 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -38,7 +38,7 @@ def set_test_params(self): "-walletrbf={}".format(i), "-mintxfee=0.00002", "-deprecatedrpc=totalFee", - "-addresstype=p2sh-segwit", # TODO update constants in test and remove + "-addresstype=bech32", ] for i in range(self.num_nodes)] def skip_test_if_missing_module(self): @@ -246,10 +246,8 @@ def test_dust_to_fee(rbf_node, dest_address): # the bumped tx sets fee=49,900, but it converts to 50,000 rbfid = spend_one_input(rbf_node, dest_address) fulltx = rbf_node.getrawtransaction(rbfid, 1) - # (32-byte p2sh-pwpkh output size + 148 p2pkh spend estimate) * 10k(discard_rate) / 1000 = 1800 - # P2SH outputs are slightly "over-discarding" due to the IsDust calculation assuming it will - # be spent as a P2PKH. - bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 50000 - 1800}) + # (31-vbyte p2wpkh output size + 67-vbyte p2wpkh spend estimate) * 10k(discard_rate) / 1000 = 980 + bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 50000 - 980}) full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1) assert_equal(bumped_tx["fee"], Decimal("0.00050000")) assert_equal(len(fulltx["vout"]), 2) @@ -272,7 +270,9 @@ def test_settxfee(rbf_node, dest_address): def test_maxtxfee_fails(test, rbf_node, dest_address): - test.restart_node(1, ['-maxtxfee=0.00003'] + test.extra_args[1]) + # size of bumped transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes + # expected bumping feerate of 20 sats/vbyte => 141*20 sats = 0.00002820 btc + test.restart_node(1, ['-maxtxfee=0.000025'] + test.extra_args[1]) rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) rbfid = spend_one_input(rbf_node, dest_address) assert_raises_rpc_error(-4, "Unable to create transaction: Fee exceeds maximum configured by -maxtxfee", rbf_node.bumpfee, rbfid) From 8734c856f85cb506fa97596383dd7e7b9edd7e03 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Tue, 22 Oct 2019 10:06:02 -0700 Subject: [PATCH 029/502] Replace the LogPrint function with a macro Calling LogPrint with a category that is not enabled results in evaluating the remaining function arguments, which may be arbitrarily complex (and possibly expensive) expressions. Defining LogPrint as a macro prevents this unnecessary expression evaluation. This is a partial revert of #14209. The decision to revert is discussed in #16688, which adds verbose logging for validation event notification. --- src/logging.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/logging.h b/src/logging.h index 75cd5353c0ecf..e37c0c823b732 100644 --- a/src/logging.h +++ b/src/logging.h @@ -155,12 +155,13 @@ static inline void LogPrintf(const char* fmt, const Args&... args) } } -template -static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args) -{ - if (LogAcceptCategory((category))) { - LogPrintf(args...); - } -} +// Use a macro instead of a function for conditional logging to prevent +// evaluating arguments when logging for the category is not enabled. +#define LogPrint(category, ...) \ + do { \ + if (LogAcceptCategory((category))) { \ + LogPrintf(__VA_ARGS__); \ + } \ + } while (0) #endif // BITCOIN_LOGGING_H From fafa064d2a8dbe24303545ab582ec84cde52ab5b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 10 Oct 2019 19:03:51 -0400 Subject: [PATCH 030/502] ci: Remove ccache requirement on the host ccache is only needed to create the cache dir on the host, if it didn't already exist. The same can be achieved with mkdir, so just use that instead. --- .cirrus.yml | 2 -- ci/README.md | 2 +- ci/test/04_install.sh | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 9464ec1685056..517cd935855dd 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -45,8 +45,6 @@ task: folder: "/tmp/ccache_dir" depends_built_cache: folder: "/tmp/cirrus-ci-build/depends/built" - depends_sdk_cache: - folder: "/tmp/cirrus-ci-build/depends/sdk-sources" install_script: - apt-get update - apt-get -y install git bash ccache diff --git a/ci/README.md b/ci/README.md index 16c481158f33c..fb1cd7460b655 100644 --- a/ci/README.md +++ b/ci/README.md @@ -12,7 +12,7 @@ To allow for a wide range of tested environments, but also ensure reproducibilit requires `docker` to be installed. To install all requirements on Ubuntu, run ``` -sudo apt install docker.io ccache bash git +sudo apt install docker.io bash git ``` To run the default test stage, diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index d0831a4c13c39..df07b8fe5cdb7 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -33,7 +33,7 @@ if [ "$TRAVIS_OS_NAME" == "osx" ]; then fi mkdir -p "${BASE_SCRATCH_DIR}" -ccache echo "Creating ccache dir if it didn't already exist" +mkdir -p "${CCACHE_DIR}" if [ ! -d ${DIR_QA_ASSETS} ]; then git clone https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS} From 5710dadf9b282524fddf42c682351cd8022ed7bf Mon Sep 17 00:00:00 2001 From: kodslav Date: Thu, 10 Jan 2019 16:10:05 +0100 Subject: [PATCH 031/502] test: fix script_p2sh_tests OP_PUSHBACK2/4 missing Fixes commit 6b25f29a91 where opcodes where lost in translation. --- src/test/script_p2sh_tests.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index f451d80984272..ec28d6a0ada71 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -209,20 +209,21 @@ BOOST_AUTO_TEST_CASE(is) p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL; BOOST_CHECK(p2sh.IsPayToScriptHash()); - // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes: std::vector direct = {OP_HASH160, 20}; direct.insert(direct.end(), 20, 0); direct.push_back(OP_EQUAL); BOOST_CHECK(CScript(direct.begin(), direct.end()).IsPayToScriptHash()); + + // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes: std::vector pushdata1 = {OP_HASH160, OP_PUSHDATA1, 20}; pushdata1.insert(pushdata1.end(), 20, 0); pushdata1.push_back(OP_EQUAL); BOOST_CHECK(!CScript(pushdata1.begin(), pushdata1.end()).IsPayToScriptHash()); - std::vector pushdata2 = {OP_HASH160, 20, 0}; + std::vector pushdata2 = {OP_HASH160, OP_PUSHDATA2, 20, 0}; pushdata2.insert(pushdata2.end(), 20, 0); pushdata2.push_back(OP_EQUAL); BOOST_CHECK(!CScript(pushdata2.begin(), pushdata2.end()).IsPayToScriptHash()); - std::vector pushdata4 = {OP_HASH160, 20, 0, 0, 0}; + std::vector pushdata4 = {OP_HASH160, OP_PUSHDATA4, 20, 0, 0, 0}; pushdata4.insert(pushdata4.end(), 20, 0); pushdata4.push_back(OP_EQUAL); BOOST_CHECK(!CScript(pushdata4.begin(), pushdata4.end()).IsPayToScriptHash()); From a552e8477c5bcd22a5457f4f73a2fd6db8acd2c2 Mon Sep 17 00:00:00 2001 From: User Date: Fri, 25 Oct 2019 16:28:14 -0400 Subject: [PATCH 032/502] added asserts to check m_addr_known when it's used --- src/net.h | 2 ++ src/net_processing.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/net.h b/src/net.h index 4a7f7bc093a73..95193a09db541 100644 --- a/src/net.h +++ b/src/net.h @@ -884,6 +884,7 @@ class CNode void AddAddressKnown(const CAddress& _addr) { + assert(m_addr_known); m_addr_known->insert(_addr.GetKey()); } @@ -892,6 +893,7 @@ class CNode // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. + assert(m_addr_known); if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 188c3d777e195..c1743c2e32ccf 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3561,6 +3561,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL); std::vector vAddr; vAddr.reserve(pto->vAddrToSend.size()); + assert(pto->m_addr_known); for (const CAddress& addr : pto->vAddrToSend) { if (!pto->m_addr_known->contains(addr.GetKey())) From 81ea66c30e2953dee24d5b127c28daa0d9452a28 Mon Sep 17 00:00:00 2001 From: Russell Yanofsky Date: Fri, 27 Sep 2019 07:31:44 -0400 Subject: [PATCH 033/502] Drop signal CClientUIInterface::LoadWallet --- src/dummywallet.cpp | 10 ++++++++-- src/interfaces/chain.cpp | 1 - src/interfaces/chain.h | 5 +---- src/interfaces/handler.cpp | 14 ++++++++++++++ src/interfaces/handler.h | 4 ++++ src/interfaces/node.cpp | 5 ++--- src/ui_interface.cpp | 3 --- src/ui_interface.h | 7 ------- src/wallet/wallet.cpp | 15 ++++++++++++++- src/wallet/wallet.h | 3 +++ 10 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp index 0edcb0286dca8..100f2d5dde91c 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -11,6 +11,8 @@ enum class WalletCreationStatus; namespace interfaces { class Chain; +class Handler; +class Wallet; } class DummyWalletInit : public WalletInitInterface { @@ -80,9 +82,13 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& throw std::logic_error("Wallet function called in non-wallet build."); } -namespace interfaces { +using LoadWalletFn = std::function wallet)>; +std::unique_ptr HandleLoadWallet(LoadWalletFn load_wallet) +{ + throw std::logic_error("Wallet function called in non-wallet build."); +} -class Wallet; +namespace interfaces { std::unique_ptr MakeWallet(const std::shared_ptr& wallet) { diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index b2c20573fb667..9d54e64ec26b9 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -342,7 +342,6 @@ class ChainImpl : public Chain void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } void initWarning(const std::string& message) override { InitWarning(message); } void initError(const std::string& message) override { InitError(message); } - void loadWallet(std::unique_ptr wallet) override { ::uiInterface.LoadWallet(wallet); } void showProgress(const std::string& title, int progress, bool resume_possible) override { ::uiInterface.ShowProgress(title, progress, resume_possible); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 73a78e21fb31e..894a7c433ec58 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -43,7 +43,7 @@ class Wallet; //! asynchronously //! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269). //! -//! * The initMessages() and loadWallet() methods which the wallet uses to send +//! * The initMessage() and showProgress() methods which the wallet uses to send //! notifications to the GUI should go away when GUI and wallet can directly //! communicate with each other without going through the node //! (https://github.com/bitcoin/bitcoin/pull/15288#discussion_r253321096). @@ -213,9 +213,6 @@ class Chain //! Send init error. virtual void initError(const std::string& message) = 0; - //! Send wallet load notification to the GUI. - virtual void loadWallet(std::unique_ptr wallet) = 0; - //! Send progress indicator. virtual void showProgress(const std::string& title, int progress, bool resume_possible) = 0; diff --git a/src/interfaces/handler.cpp b/src/interfaces/handler.cpp index 92601fc4e99c8..4e235688fee69 100644 --- a/src/interfaces/handler.cpp +++ b/src/interfaces/handler.cpp @@ -22,6 +22,15 @@ class HandlerImpl : public Handler boost::signals2::scoped_connection m_connection; }; +class CleanupHandler : public Handler +{ +public: + explicit CleanupHandler(std::function cleanup) : m_cleanup(std::move(cleanup)) {} + ~CleanupHandler() override { if (!m_cleanup) return; m_cleanup(); m_cleanup = nullptr; } + void disconnect() override { if (!m_cleanup) return; m_cleanup(); m_cleanup = nullptr; } + std::function m_cleanup; +}; + } // namespace std::unique_ptr MakeHandler(boost::signals2::connection connection) @@ -29,4 +38,9 @@ std::unique_ptr MakeHandler(boost::signals2::connection connection) return MakeUnique(std::move(connection)); } +std::unique_ptr MakeHandler(std::function cleanup) +{ + return MakeUnique(std::move(cleanup)); +} + } // namespace interfaces diff --git a/src/interfaces/handler.h b/src/interfaces/handler.h index c4c674cac5aeb..46918bc22e79b 100644 --- a/src/interfaces/handler.h +++ b/src/interfaces/handler.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_INTERFACES_HANDLER_H #define BITCOIN_INTERFACES_HANDLER_H +#include #include namespace boost { @@ -30,6 +31,9 @@ class Handler //! Return handler wrapping a boost signal connection. std::unique_ptr MakeHandler(boost::signals2::connection connection); +//! Return handler wrapping a cleanup function. +std::unique_ptr MakeHandler(std::function cleanup); + } // namespace interfaces #endif // BITCOIN_INTERFACES_HANDLER_H diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index 227ac9f7b914c..2c24b02f2362d 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -42,11 +42,10 @@ std::vector ListWalletDir(); std::vector> GetWallets(); std::shared_ptr LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector& warnings); WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector& warnings, std::shared_ptr& result); +std::unique_ptr HandleLoadWallet(interfaces::Node::LoadWalletFn load_wallet); namespace interfaces { -class Wallet; - namespace { class NodeImpl : public Node @@ -282,7 +281,7 @@ class NodeImpl : public Node } std::unique_ptr handleLoadWallet(LoadWalletFn fn) override { - return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::unique_ptr& wallet) { fn(std::move(wallet)); })); + return HandleLoadWallet(std::move(fn)); } std::unique_ptr handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override { diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index d310637145b3a..3968464efc5e1 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -16,7 +16,6 @@ struct UISignals { boost::signals2::signal NotifyNumConnectionsChanged; boost::signals2::signal NotifyNetworkActiveChanged; boost::signals2::signal NotifyAlertChanged; - boost::signals2::signal LoadWallet; boost::signals2::signal ShowProgress; boost::signals2::signal NotifyBlockTip; boost::signals2::signal NotifyHeaderTip; @@ -36,7 +35,6 @@ ADD_SIGNALS_IMPL_WRAPPER(InitMessage); ADD_SIGNALS_IMPL_WRAPPER(NotifyNumConnectionsChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyNetworkActiveChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyAlertChanged); -ADD_SIGNALS_IMPL_WRAPPER(LoadWallet); ADD_SIGNALS_IMPL_WRAPPER(ShowProgress); ADD_SIGNALS_IMPL_WRAPPER(NotifyBlockTip); ADD_SIGNALS_IMPL_WRAPPER(NotifyHeaderTip); @@ -48,7 +46,6 @@ void CClientUIInterface::InitMessage(const std::string& message) { return g_ui_s void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { return g_ui_signals.NotifyNumConnectionsChanged(newNumConnections); } void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); } void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); } -void CClientUIInterface::LoadWallet(std::unique_ptr& wallet) { return g_ui_signals.LoadWallet(wallet); } void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); } void CClientUIInterface::NotifyBlockTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(b, i); } void CClientUIInterface::NotifyHeaderTip(bool b, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(b, i); } diff --git a/src/ui_interface.h b/src/ui_interface.h index 9efc2db391f86..f47b56c281d23 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -17,10 +17,6 @@ class connection; } } // namespace boost -namespace interfaces { -class Wallet; -} // namespace interfaces - /** General change type (added, updated, removed). */ enum ChangeType { @@ -105,9 +101,6 @@ class CClientUIInterface */ ADD_SIGNALS_DECL_WRAPPER(NotifyAlertChanged, void, ); - /** A wallet has been loaded. */ - ADD_SIGNALS_DECL_WRAPPER(LoadWallet, void, std::unique_ptr& wallet); - /** * Show progress e.g. for verifychain. * resume_possible indicates shutting down now will result in the current progress action resuming upon restart. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 159d4f78c6db1..e19ed95b9da7a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -47,6 +47,7 @@ static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10; static CCriticalSection cs_wallets; static std::vector> vpwallets GUARDED_BY(cs_wallets); +static std::list g_load_wallet_fns GUARDED_BY(cs_wallets); bool AddWallet(const std::shared_ptr& wallet) { @@ -89,6 +90,13 @@ std::shared_ptr GetWallet(const std::string& name) return nullptr; } +std::unique_ptr HandleLoadWallet(LoadWalletFn load_wallet) +{ + LOCK(cs_wallets); + auto it = g_load_wallet_fns.emplace(g_load_wallet_fns.end(), std::move(load_wallet)); + return interfaces::MakeHandler([it] { LOCK(cs_wallets); g_load_wallet_fns.erase(it); }); +} + static Mutex g_wallet_release_mutex; static std::condition_variable g_wallet_release_cv; static std::set g_unloading_wallet_set; @@ -4562,7 +4570,12 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, } } - chain.loadWallet(interfaces::MakeWallet(walletInstance)); + { + LOCK(cs_wallets); + for (auto& load_wallet : g_load_wallet_fns) { + load_wallet(interfaces::MakeWallet(walletInstance)); + } + } // Register with the validation interface. It's ok to do this after rescan since we're still holding locked_chain. walletInstance->handleNotifications(); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 85c277ff506e8..954e74df05e3e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -35,6 +35,8 @@ #include +using LoadWalletFn = std::function wallet)>; + //! Explicitly unload and delete the wallet. //! Blocks the current thread after signaling the unload intent so that all //! wallet clients release the wallet. @@ -48,6 +50,7 @@ bool HasWallets(); std::vector> GetWallets(); std::shared_ptr GetWallet(const std::string& name); std::shared_ptr LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector& warnings); +std::unique_ptr HandleLoadWallet(LoadWalletFn load_wallet); enum class WalletCreationStatus { SUCCESS, From 6d6a7a8403ae923f189812edebdd95761de0e7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 26 Sep 2019 21:43:44 +0100 Subject: [PATCH 034/502] gui: Fix duplicate wallet showing up The slot BitcoinGUI::addWallet can be invoked twice for the same WalletModel due to a concurrent wallet being loaded after the first `connect()`: ```cpp connect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet); connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet); for (WalletModel* wallet_model : m_wallet_controller->getOpenWallets()) { addWallet(wallet_model); ``` --- src/qt/bitcoingui.cpp | 2 +- src/qt/walletframe.cpp | 8 +++++--- src/qt/walletframe.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2aeba6d82c336..bbf1faa13cf99 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -632,10 +632,10 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller) void BitcoinGUI::addWallet(WalletModel* walletModel) { if (!walletFrame) return; + if (!walletFrame->addWallet(walletModel)) return; const QString display_name = walletModel->getDisplayName(); setWalletActionsEnabled(true); rpcConsole->addWallet(walletModel); - walletFrame->addWallet(walletModel); m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel)); if (m_wallet_selector->count() == 2) { m_wallet_selector_label_action->setVisible(true); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index d7f0617315adb..704a85ccc7a96 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -39,11 +39,11 @@ void WalletFrame::setClientModel(ClientModel *_clientModel) this->clientModel = _clientModel; } -void WalletFrame::addWallet(WalletModel *walletModel) +bool WalletFrame::addWallet(WalletModel *walletModel) { - if (!gui || !clientModel || !walletModel) return; + if (!gui || !clientModel || !walletModel) return false; - if (mapWalletViews.count(walletModel) > 0) return; + if (mapWalletViews.count(walletModel) > 0) return false; WalletView *walletView = new WalletView(platformStyle, this); walletView->setBitcoinGUI(gui); @@ -67,6 +67,8 @@ void WalletFrame::addWallet(WalletModel *walletModel) }); connect(walletView, &WalletView::outOfSyncWarningClicked, this, &WalletFrame::outOfSyncWarningClicked); + + return true; } void WalletFrame::setCurrentWallet(WalletModel* wallet_model) diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 156653f47dfa8..20fad08b0ef8e 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -36,7 +36,7 @@ class WalletFrame : public QFrame void setClientModel(ClientModel *clientModel); - void addWallet(WalletModel *walletModel); + bool addWallet(WalletModel *walletModel); void setCurrentWallet(WalletModel* wallet_model); void removeWallet(WalletModel* wallet_model); void removeAllWallets(); From 9cae3d5e94f4481e0d251c924314e57187a07a60 Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 27 Oct 2019 21:14:42 +0000 Subject: [PATCH 035/502] tests: Add fuzzer initialization (hold ECCVerifyHandle) --- src/test/fuzz/eval_script.cpp | 9 ++++++++- src/test/fuzz/script_flags.cpp | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp index 9444cd489ea44..7acdd76857c9f 100644 --- a/src/test/fuzz/eval_script.cpp +++ b/src/test/fuzz/eval_script.cpp @@ -2,12 +2,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include