diff --git a/ci/test/00_setup_env_native_previous_releases.sh b/ci/test/00_setup_env_native_previous_releases.sh index a83a4031ab..92540e0aa9 100755 --- a/ci/test/00_setup_env_native_previous_releases.sh +++ b/ci/test/00_setup_env_native_previous_releases.sh @@ -11,7 +11,7 @@ export CI_IMAGE_NAME_TAG="mirror.gcr.io/ubuntu:22.04" # Use minimum supported python3.10 and gcc-11, see doc/dependencies.md export PACKAGES="gcc-11 g++-11 python3-zmq" export DEP_OPTS="DEBUG=1 CC=gcc-11 CXX=g++-11" -export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash +export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude wallet_inactive_hdchains" # Run extended tests so that coverage does not fail export RUN_UNIT_TESTS_SEQUENTIAL="true" export RUN_UNIT_TESTS="false" export GOAL="install" @@ -25,4 +25,4 @@ export BITCOIN_CONFIG="\ -DCMAKE_CXX_FLAGS_DEBUG='-g0 -O2' \ -DAPPEND_CPPFLAGS='-DBOOST_MULTI_INDEX_ENABLE_SAFE_MODE' \ " -export TEST_RUNNER_EXTRA="${TEST_RUNNER_EXTRA},feature_fee_estimation,wallet_inactive_hdchains,wallet_elements_regression_fundrawtransaction,feature_txindex_compatibility,feature_unsupported_utxo_db" # ELEMENTS +export TEST_RUNNER_EXTRA="${TEST_RUNNER_EXTRA},wallet_elements_regression_fundrawtransaction,feature_unsupported_utxo_db" # ELEMENTS diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index 69410b78af..4ede8e4311 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -109,6 +109,9 @@ if [ -z "$NO_DEPENDS" ]; then esac bash -c "$SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS LOG=1" fi +if [ "$DOWNLOAD_PREVIOUS_RELEASES" = "true" ]; then + test/get_previous_releases.py -b -t "$PREVIOUS_RELEASES_DIR" +fi BITCOIN_CONFIG_ALL="-DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON" if [ -z "$NO_DEPENDS" ]; then @@ -121,62 +124,12 @@ fi ccache --zero-stats PRINT_CCACHE_STATISTICS="ccache --version | head -n 1 && ccache --show-stats" -if [ -z "$NO_DEPENDS" ]; then - # legacy autotools path (depends builds) - BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-external-signer --prefix=$BASE_OUTDIR" -else - # modern CMake path (native macOS + NO_DEPENDS=1) - BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} -DENABLE_EXTERNAL_SIGNER=ON" -fi - -# === CMake build (modern path used by the fork) === -if [ -n "$NO_DEPENDS" ]; then - echo "Building with CMake (NO_DEPENDS=1)..." - # shellcheck disable=SC2086 - cmake -B build -S . ${CMAKE_GENERATOR:+-G "$CMAKE_GENERATOR"} $BITCOIN_CONFIG_ALL -else - # depends path (still uses configure in some jobs) - ./autogen.sh - # shellcheck disable=SC2086 - ./configure $BITCOIN_CONFIG_ALL -fi - -cmake --build build --config Release --parallel "$MAKEJOBS" - -if [ -n "$NO_DEPENDS" ]; then - bash -c "${PRINT_CCACHE_STATISTICS}" - - if [ "$RUN_UNIT_TESTS" = "true" ]; then - DIR_UNIT_TEST_DATA="${DIR_UNIT_TEST_DATA}" CTEST_OUTPUT_ON_FAILURE=ON ctest --stop-on-failure "${MAKEJOBS}" --timeout $(( TEST_RUNNER_TIMEOUT_FACTOR * 60 )) - fi - - if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then - eval "TEST_RUNNER_EXTRA=($TEST_RUNNER_EXTRA)" - test/functional/test_runner.py --ci "${MAKEJOBS}" --tmpdirprefix "${BASE_SCRATCH_DIR}"/test_runner/ --ansi --combinedlogslen=99999999 --timeout-factor="${TEST_RUNNER_TIMEOUT_FACTOR}" "${TEST_RUNNER_EXTRA[@]}" --quiet --failfast - fi - - exit 0 -fi - +# Folder where the build is done. +BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build-$HOST} mkdir -p "${BASE_BUILD_DIR}" cd "${BASE_BUILD_DIR}" -bash -c "${BASE_ROOT_DIR}/configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG" || ( (cat config.log) && false) - -make distdir VERSION="$HOST" - -cd "${BASE_BUILD_DIR}/elements-$HOST" - -bash -c "./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG" || ( (cat config.log) && false) - -# ELEMENTS FIXME: fix fix in order to correctly run it #30454 -# # Folder where the build is done. -# BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build-$HOST} -# mkdir -p "${BASE_BUILD_DIR}" -# cd "${BASE_BUILD_DIR}" -# -# BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DENABLE_EXTERNAL_SIGNER=ON -DCMAKE_INSTALL_PREFIX=$BASE_OUTDIR" - +BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DENABLE_EXTERNAL_SIGNER=ON -DCMAKE_INSTALL_PREFIX=$BASE_OUTDIR" if [[ "${RUN_TIDY}" == "true" ]]; then BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" @@ -233,17 +186,17 @@ if [ "${RUN_TIDY}" = "true" ]; then jq 'map(select(.file | test("src/qt/.*_autogen/.*\\.cpp$") | not))' "${BASE_BUILD_DIR}/compile_commands.json" > tmp.json mv tmp.json "${BASE_BUILD_DIR}/compile_commands.json" - cd "${BASE_BUILD_DIR}/elements-$HOST/src/" + cd "${BASE_BUILD_DIR}/src/" if ! ( run-clang-tidy-"${TIDY_LLVM_V}" -quiet -load="/tidy-build/libbitcoin-tidy.so" "${MAKEJOBS}" | tee tmp.tidy-out.txt ); then grep -C5 "error: " tmp.tidy-out.txt echo "^^^ ⚠️ Failure generated from clang-tidy" false fi - cd "${BASE_BUILD_DIR}/elements-$HOST/" + cd "${BASE_ROOT_DIR}" python3 "/include-what-you-use/iwyu_tool.py" \ - -p . "${MAKEJOBS}" \ - -- -Xiwyu --cxx17ns -Xiwyu --mapping_file="${BASE_BUILD_DIR}/elements-$HOST/contrib/devtools/iwyu/bitcoin.core.imp" \ + -p "${BASE_BUILD_DIR}" "${MAKEJOBS}" \ + -- -Xiwyu --cxx17ns -Xiwyu --mapping_file="${BASE_ROOT_DIR}/contrib/devtools/iwyu/bitcoin.core.imp" \ -Xiwyu --max_line_length=160 \ 2>&1 | tee /tmp/iwyu_ci.out cd "${BASE_ROOT_DIR}/src" @@ -254,4 +207,4 @@ fi if [ "$RUN_FUZZ_TESTS" = "true" ]; then # shellcheck disable=SC2086 LD_LIBRARY_PATH="${DEPENDS_DIR}/${HOST}/lib" test/fuzz/test_runner.py ${FUZZ_TESTS_CONFIG} "${MAKEJOBS}" -l DEBUG "${DIR_FUZZ_IN}" --empty_min_time=60 -fi +fi \ No newline at end of file diff --git a/contrib/devtools/check-deps.sh b/contrib/devtools/check-deps.sh index 25e948647c..04c7fad88e 100755 --- a/contrib/devtools/check-deps.sh +++ b/contrib/devtools/check-deps.sh @@ -51,6 +51,69 @@ SUPPRESS["init.cpp.o bdb.cpp.o _ZN6wallet27BerkeleyDatabaseSanityCheckEv"]=1 SUPPRESS["common.cpp.o interface_ui.cpp.o _Z11InitWarningRK13bilingual_str"]=1 SUPPRESS["common.cpp.o interface_ui.cpp.o _Z9InitErrorRK13bilingual_str"]=1 +# ELEMENTS: wallet fee/balance verification depends on confidential-transaction +# validation logic (fee map, amount/CT-balance checks), which lives alongside +# consensus validation rather than in the wallet library. +SUPPRESS["transactions.cpp.o confidential_validation.cpp.o _Z11HasValidFeeRK12CTransaction"]=1 +SUPPRESS["wallet.cpp.o confidential_validation.cpp.o _Z13VerifyAmountsRKSt6vectorI6CTxOutSaIS0_EERK12CTransactionPS_IP6CCheckSaIS9_EEb"]=1 +SUPPRESS["feebumper.cpp.o confidential_validation.cpp.o _Z9GetFeeMapRK12CTransaction"]=1 +SUPPRESS["receive.cpp.o confidential_validation.cpp.o _Z9GetFeeMapRK12CTransaction"]=1 +SUPPRESS["transactions.cpp.o confidential_validation.cpp.o _Z9GetFeeMapRK12CTransaction"]=1 + +# ELEMENTS: RPC and wallet code that constructs or verifies peg-in transactions +# depends directly on the peg-in logic (SPV proof checking, fedpeg script +# resolution, witness construction/decomposition). +SUPPRESS["elements.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIK12CTransactionERK12CMerkleBlock"]=1 +SUPPRESS["wallet.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIK12CTransactionERK12CMerkleBlock"]=1 +SUPPRESS["psbt.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIK12CTransactionERK12CMerkleBlock"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIK12CTransactionERK12CMerkleBlock"]=1 +SUPPRESS["wallet.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIKN9Sidechain7Bitcoin12CTransactionEERKNSC_12CMerkleBlockE"]=1 +SUPPRESS["psbt.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIKN9Sidechain7Bitcoin12CTransactionEERKNSC_12CMerkleBlockE"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z18CreatePeginWitnessRKlRK6CAssetRK7uint256RK7CScriptRKSt10shared_ptrIKN9Sidechain7Bitcoin12CTransactionEERKNSC_12CMerkleBlockE"]=1 +SUPPRESS["elements.cpp.o pegins.cpp.o _Z18calculate_contractRK7CScriptS1_"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z18calculate_contractRK7CScriptS1_"]=1 +SUPPRESS["elements.cpp.o pegins.cpp.o _Z19IsValidPeginWitnessRK14CScriptWitnessRKSt6vectorISt4pairI7CScriptS4_ESaIS5_EERK9COutPointRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbPb"]=1 +SUPPRESS["spend.cpp.o pegins.cpp.o _Z19IsValidPeginWitnessRK14CScriptWitnessRKSt6vectorISt4pairI7CScriptS4_ESaIS5_EERK9COutPointRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbPb"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z19IsValidPeginWitnessRK14CScriptWitnessRKSt6vectorISt4pairI7CScriptS4_ESaIS5_EERK9COutPointRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbPb"]=1 +SUPPRESS["elements.cpp.o pegins.cpp.o _Z21GetValidFedpegScriptsPK11CBlockIndexRKN9Consensus6ParamsEb"]=1 +SUPPRESS["spend.cpp.o pegins.cpp.o _Z21GetValidFedpegScriptsPK11CBlockIndexRKN9Consensus6ParamsEb"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z21GetValidFedpegScriptsPK11CBlockIndexRKN9Consensus6ParamsEb"]=1 +SUPPRESS["psbt.cpp.o pegins.cpp.o _Z21DecomposePeginWitnessRK14CScriptWitnessRlR6CAssetR7uint256R7CScriptRSt7variantIJSt9monostateSt10shared_ptrIKN9Sidechain7Bitcoin12CTransactionEESB_IK12CTransactionEEERS9_IJSA_NSD_12CMerkleBlockE12CMerkleBlockEE"]=1 +SUPPRESS["elements.cpp.o pegins.cpp.o _Z22CheckParentProofOfWork7uint256jRKN9Consensus6ParamsE"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z22CheckParentProofOfWork7uint256jRKN9Consensus6ParamsE"]=1 +SUPPRESS["elements.cpp.o pegins.cpp.o _Z29GetAmountFromParentChainPeginRlRK12CTransactionj"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z29GetAmountFromParentChainPeginRlRK12CTransactionj"]=1 +SUPPRESS["elements.cpp.o pegins.cpp.o _Z29GetAmountFromParentChainPeginRlRKN9Sidechain7Bitcoin12CTransactionEj"]=1 +SUPPRESS["rawtransaction_util.cpp.o pegins.cpp.o _Z29GetAmountFromParentChainPeginRlRKN9Sidechain7Bitcoin12CTransactionEj"]=1 + +# ELEMENTS: RPC's peg-in verification needs a client to query the parent +# (mainchain) node for block confirmation in the non-SPV verification path. +SUPPRESS["elements.cpp.o mainchainrpc.cpp.o _Z16CallMainChainRPCRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERK8UniValue"]=1 +SUPPRESS["elements.cpp.o mainchainrpc.cpp.o _Z23IsConfirmedBitcoinBlockRK7uint256ii"]=1 + +# ELEMENTS: RPC needs the active Pegout Authorization Key list and PAK-proof +# verification for pegout-related RPCs. +SUPPRESS["elements.cpp.o pak.cpp.o _Z16GetActivePAKListPK11CBlockIndexRKN9Consensus6ParamsE"]=1 +SUPPRESS["elements.cpp.o pak.cpp.o _Z22ScriptHasValidPAKProofRK7CScriptRK7uint256RK8CPAKList"]=1 + +# ELEMENTS: RPC needs to parse the federation quorum out of a fedpeg script +# for dynamic federation RPCs. +SUPPRESS["elements.cpp.o dynafed.cpp.o _Z17ParseFedPegQuorumRK7CScriptRiS2_"]=1 + +# ELEMENTS: RPC needs to verify the parent chain's proof-of-work signature +# for federated peg verification. +SUPPRESS["elements.cpp.o block_proof.cpp.o _Z22CheckProofSignedParentRK12CBlockHeaderRKN9Consensus6ParamsE"]=1 +SUPPRESS["rawtransaction_util.cpp.o block_proof.cpp.o _Z22CheckProofSignedParentRK12CBlockHeaderRKN9Consensus6ParamsE"]=1 + +# ELEMENTS: RPC needs deployment/versionbits state for dynamic federation +# related RPCs. +SUPPRESS["elements.cpp.o versionbits.cpp.o _ZN16VersionBitsCache5StateEPK11CBlockIndexRKN9Consensus6ParamsENS3_13DeploymentPosE"]=1 + +# Upstream gap: node/chain.cpp depends on kernel/blockstorage.cpp's block-index +# regeneration helper. Not yet suppressed upstream as of this merge; worth +# checking if a newer upstream commit already added this suppression. +SUPPRESS["chain.cpp.o blockstorage.cpp.o _ZNK6kernel11BlockTreeDB19RegenerateFullIndexEPK11CBlockIndexPS1_"]=1 + usage() { echo "Usage: $(basename "${BASH_SOURCE[0]}") [BUILD_DIR]" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 806566e45e..bf3bb441dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -113,14 +113,24 @@ target_link_libraries(elementssimplicity core_interface ) -# macOS Apple Clang is stricter than Linux GCC on this vendored code -if(APPLE) +# Clang (Apple of upstream) is stricter than Linux GCC on this vendored code +if(CMAKE_C_COMPILER_ID MATCHES "Clang") target_compile_options(elementssimplicity PRIVATE -Wno-error=conditional-uninitialized -Wno-error=implicit-fallthrough ) endif() +# GCC's -Wtype-limits (via -Wextra) flags some of Simplicity's defensive +# runtime asserts as tautological on LLP64 targets (e.g. mingw-w64 win64), +# where uint_fast32_t is narrower than size_t. The checks are intentional, +# not bugs. +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(elementssimplicity PRIVATE + -Wno-error=type-limits + ) +endif() + # Set top-level target output locations. if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) @@ -267,6 +277,9 @@ if(ENABLE_WALLET) init/bitcoin-wallet.cpp wallet/wallettool.cpp ) + set_target_properties(elements-wallet PROPERTIES + SKIP_BUILD_RPATH OFF + ) add_windows_resources(elements-wallet bitcoin-wallet-res.rc) target_link_libraries(elements-wallet core_interface @@ -408,6 +421,9 @@ if(BUILD_DAEMON) bitcoind.cpp init/bitcoind.cpp ) + set_target_properties(elementsd PROPERTIES + SKIP_BUILD_RPATH OFF + ) add_windows_resources(elementsd bitcoind-res.rc) target_link_libraries(elementsd core_interface @@ -422,6 +438,9 @@ if(WITH_MULTIPROCESS AND BUILD_DAEMON) bitcoind.cpp init/bitcoin-node.cpp ) + set_target_properties(elements-node PROPERTIES + SKIP_BUILD_RPATH OFF + ) target_link_libraries(elements-node core_interface bitcoin_node @@ -463,6 +482,9 @@ target_link_libraries(bitcoin_cli # Elements Core RPC client if(BUILD_CLI) add_executable(elements-cli bitcoin-cli.cpp) + set_target_properties(elements-cli PROPERTIES + SKIP_BUILD_RPATH OFF + ) add_windows_resources(elements-cli bitcoin-cli-res.rc) target_link_libraries(elements-cli core_interface @@ -479,6 +501,9 @@ endif() if(BUILD_TX) add_executable(elements-tx bitcoin-tx.cpp) add_windows_resources(elements-tx bitcoin-tx-res.rc) + set_target_properties(elements-tx PROPERTIES + SKIP_BUILD_RPATH OFF + ) target_link_libraries(elements-tx core_interface bitcoin_common @@ -493,6 +518,9 @@ endif() if(BUILD_UTIL) add_executable(elements-util bitcoin-util.cpp) add_windows_resources(elements-util bitcoin-util-res.rc) + set_target_properties(elements-util PROPERTIES + SKIP_BUILD_RPATH OFF + ) target_link_libraries(elements-util core_interface bitcoin_common diff --git a/src/assetsdir.cpp b/src/assetsdir.cpp index f69aab80e1..39d8ee6506 100644 --- a/src/assetsdir.cpp +++ b/src/assetsdir.cpp @@ -36,7 +36,7 @@ void CAssetsDir::SetHex(const std::string& assetHex, const std::string& label) void CAssetsDir::InitFromStrings(const std::vector& assetsToInit, const std::string& pegged_asset_name) { - for (std::string strToSplit : assetsToInit) { + for (const std::string& strToSplit : assetsToInit) { std::vector vAssets; const auto pos = strToSplit.find(':'); if (pos != std::string::npos) { diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt index 1556cc9412..f22f18480c 100644 --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -52,6 +52,10 @@ add_executable(bench_bitcoin xor.cpp ) +set_target_properties(bench_bitcoin PROPERTIES + SKIP_BUILD_RPATH OFF +) + include(TargetDataSources) target_raw_data_sources(bench_bitcoin NAMESPACE benchmark::data data/block413567.raw diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 10bd25b699..6d779d9050 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -52,14 +52,22 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::Bench& bench) vChecks.reserve(BATCH_SIZE); // ELEMENTS: allocate new jobs... for (size_t x = 0; x < BATCH_SIZE; ++x) - vChecks[x] = new PrevectorJob(insecure_rand); + vChecks.push_back(new PrevectorJob(insecure_rand)); } bench.minEpochIterations(10).batch(BATCH_SIZE * BATCHES).unit("job").run([&] { // Make insecure_rand here so that each iteration is identical. CCheckQueueControl control(&queue); - for (auto vChecks : vBatches) { - control.Add(std::move(vChecks)); + for (const auto& vChecks : vBatches) { + // ELEMENTS: the queue takes ownership and deletes each check after + // processing it, so we must give it fresh copies every iteration — + // vBatches itself must stay untouched as the template for all runs. + std::vector vChecksCopy; + vChecksCopy.reserve(vChecks.size()); + for (const auto* check : vChecks) { + vChecksCopy.push_back(new PrevectorJob(*check)); + } + control.Add(std::move(vChecksCopy)); } // control waits for completion by RAII, but // it is done explicitly here for clarity diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 83e6435fc4..8e91a1f772 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -467,20 +467,20 @@ static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strIn CAsset asset(Params().GetConsensus().pegged_asset); if (vStrInputParts.size()==1) { - std::string strData = vStrInputParts[0]; + const std::string& strData = vStrInputParts[0]; if (!IsHex(strData)) throw std::runtime_error("invalid TX output data"); data = ParseHex(strData); } else { value = ExtractAndValidateValue(vStrInputParts[0]); - std::string strData = vStrInputParts[1]; + const std::string& strData = vStrInputParts[1]; if (!IsHex(strData)) throw std::runtime_error("invalid TX output data"); data = ParseHex(strData); if (vStrInputParts.size()==3) { - std::string strAsset = vStrInputParts[2]; + const std::string& strAsset = vStrInputParts[2]; if (!IsHex(strAsset)) throw std::runtime_error("invalid TX output asset type"); diff --git a/src/checkqueue.h b/src/checkqueue.h index 44d4b30874..0309f82cd9 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -128,10 +128,13 @@ private: // execute work if (do_work) { for (T* check : vChecks) { - local_result = (*check)(); - if (local_result.has_value()) break; - delete check; + if (!local_result.has_value()) { + local_result = (*check)(); + } + delete check; // ELEMENTS: always take ownership of popped checks, even ones skipped after a failure } + } else { + for (T* check : vChecks) delete check; // ELEMENTS: queue already failed; still own and free these } vChecks.clear(); } while (true); diff --git a/src/coins.h b/src/coins.h index 8e79708783..83055bb539 100644 --- a/src/coins.h +++ b/src/coins.h @@ -131,7 +131,7 @@ private: //! Adding a flag requires a reference to the sentinel of the flagged pair linked list. static void AddFlags(uint8_t flags, CoinsCachePair& pair, CoinsCachePair& sentinel) noexcept { - Assume(flags & (DIRTY | FRESH)); + Assume(flags & (DIRTY | FRESH | PEGIN)); // ELEMENTS: PEGIN may be set on its own if (!pair.second.m_flags) { Assume(!pair.second.m_prev && !pair.second.m_next); pair.second.m_prev = sentinel.second.m_prev; @@ -388,7 +388,7 @@ protected: * declared as "const". */ mutable uint256 hashBlock; - mutable CCoinsMapMemoryResource m_cache_coins_memory_resource{}; + mutable CCoinsMapMemoryResource m_cache_coins_memory_resource{ /*chunk_size_bytes=*/(sizeof(CoinsCachePair) + sizeof(void*) * 4) * 1024}; /* The starting sentinel of the flagged entry circular doubly linked list. */ mutable CoinsCachePair m_sentinel; mutable CCoinsMap cacheCoins; diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt index dd9333fbb8..692cac0af4 100644 --- a/src/kernel/CMakeLists.txt +++ b/src/kernel/CMakeLists.txt @@ -27,6 +27,13 @@ add_library(bitcoinkernel ../chainparams.cpp ../coins.cpp ../common/bloom.cpp + ../common/args.cpp + ../mainchainrpc.cpp + ../chainparams.cpp + ../chainparamsbase.cpp + ../coins.cpp + ../common/config.cpp + ../common/settings.cpp ../compressor.cpp ../confidential_validation.cpp ../consensus/merkle.cpp @@ -41,7 +48,8 @@ add_library(bitcoinkernel ../hash.cpp ../issuance.cpp ../logging.cpp - ../mainchainrpc.cpp + ../addresstype.cpp + ../key.cpp ../merkleblock.cpp ../node/blockstorage.cpp ../node/chainstate.cpp @@ -76,6 +84,7 @@ add_library(bitcoinkernel ../script/sign.cpp ../script/signingprovider.cpp ../script/solver.cpp + ../script/miniscript.cpp ../signet.cpp ../streams.cpp ../support/lockedpool.cpp @@ -113,6 +122,10 @@ target_link_libraries(bitcoinkernel elementssimplicity univalue $ + $ + $ + $ + $ PUBLIC Boost::headers ) diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index 1f912a5352..a704746ba2 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -542,6 +542,20 @@ public: consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000001d6dce8651b6094e4c1"}; consensus.defaultAssumeValid = uint256{"0000000000003ed4f08dbdf6f7d6b271a6bcffce25675cb40aa9fa43179a89f3"}; // 72600 + consensus.genesis_subsidy = 50*COIN; + consensus.connect_genesis_outputs = false; + consensus.subsidy_asset = CAsset(); + anyonecanspend_aremine = false; + enforce_pak = false; + accept_unlimited_issuances = false; + multi_data_permitted = false; + accept_discount_ct = false; + create_discount_ct = false; + pegin_subsidy = PeginSubsidy(); + pegin_minimum = PeginMinimum(); + consensus.has_parent_chain = false; + g_signed_blocks = false; + pchMessageStart[0] = 0x1c; pchMessageStart[1] = 0x16; pchMessageStart[2] = 0x3f; diff --git a/src/kernel/chainparams.h b/src/kernel/chainparams.h index 4b584810a1..b71d1ac459 100644 --- a/src/kernel/chainparams.h +++ b/src/kernel/chainparams.h @@ -107,6 +107,7 @@ struct PeginMinimum { class CChainParams { public: + virtual ~CChainParams() = default; // required: subclasses are stored and destroyed via std::unique_ptr enum Base58Type { PUBKEY_ADDRESS, SCRIPT_ADDRESS, diff --git a/src/kernel/mempool_entry.h b/src/kernel/mempool_entry.h index d776130874..08eff52fff 100644 --- a/src/kernel/mempool_entry.h +++ b/src/kernel/mempool_entry.h @@ -105,7 +105,7 @@ private: int64_t nSizeWithAncestors; CAmount nModFeesWithAncestors; int64_t nSigOpCostWithAncestors; - uint64_t discountSizeWithAncestors; // ELEMENTS + int64_t discountSizeWithAncestors; // ELEMENTS public: CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee, @@ -129,7 +129,7 @@ public: nSizeWithAncestors{GetTxSize()}, nModFeesWithAncestors{nFee}, nSigOpCostWithAncestors{sigOpCost}, - discountSizeWithAncestors{GetDiscountTxSize()}, + discountSizeWithAncestors{static_cast(GetDiscountTxSize())}, setPeginsSpent(setPeginsSpent) {}; CTxMemPoolEntry(ExplicitCopyTag, const CTxMemPoolEntry& entry) : CTxMemPoolEntry(entry) {} @@ -190,7 +190,7 @@ public: uint64_t GetCountWithAncestors() const { return m_count_with_ancestors; } int64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } - uint64_t GetDiscountSizeWithAncestors() const { return discountSizeWithAncestors; } + int64_t GetDiscountSizeWithAncestors() const { return discountSizeWithAncestors; } CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; } diff --git a/src/primitives/bitcoin/merkleblock.cpp b/src/primitives/bitcoin/merkleblock.cpp index 7267af4f94..d78cf930fc 100644 --- a/src/primitives/bitcoin/merkleblock.cpp +++ b/src/primitives/bitcoin/merkleblock.cpp @@ -39,7 +39,7 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std: txn = CPartialMerkleTree(vHashes, vMatch); } */ -uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector &vTxid) { +uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector &vTxid) { // NOLINT(misc-no-recursion) //we can never have zero txs in a merkle block, we always need the coinbase tx //if we do not have this assert, we can hit a memory access violation when indexing into vTxid assert(vTxid.size() != 0); @@ -59,7 +59,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve } } -void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector &vTxid, const std::vector &vMatch) { +void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector &vTxid, const std::vector &vMatch) { // NOLINT(misc-no-recursion) // determine whether this node is the parent of at least one matched txid bool fParentOfMatch = false; for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++) @@ -77,7 +77,7 @@ void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const st } } -uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector &vMatch, std::vector &vnIndex) { +uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector &vMatch, std::vector &vnIndex) { // NOLINT(misc-no-recursion) if (nBitsUsed >= vBits.size()) { // overflowed the bits array - failure fBad = true; diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 909c54eee8..88559831d2 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -232,7 +232,7 @@ bool XOnlyPubKey::VerifySchnorr(const Span msg, SpanspawnProcess("bitcoin-node"); + auto init = ipc->spawnProcess("elements-node"); echo = init->makeEcho(); ipc->addCleanup(*echo, [init = init.release()] { delete init; }); } else { diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index d783204eb9..022f6bde52 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -1406,7 +1406,7 @@ std::vector EvalDescriptorStringOrObject(const UniValue& scanobject, Fl class BlindingPubkeyVisitor { public: - explicit BlindingPubkeyVisitor() {} + explicit BlindingPubkeyVisitor() = default; CPubKey operator()(const CNoDestination& dest) const { @@ -1466,7 +1466,7 @@ class DescribeBlindAddressVisitor { public: - explicit DescribeBlindAddressVisitor() {} + explicit DescribeBlindAddressVisitor() = default; UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const PubKeyDestination& dest) const { return UniValue(UniValue::VOBJ); } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 073bea6304..0adeb970b0 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -129,6 +129,10 @@ add_executable(test_elements versionbits_tests.cpp ) +set_target_properties(test_elements PROPERTIES + SKIP_BUILD_RPATH OFF +) + include(TargetDataSources) target_json_data_sources(test_elements data/base58_encode_decode.json diff --git a/src/test/blind_tests.cpp b/src/test/blind_tests.cpp index 42dded0ddc..46d7a4c462 100644 --- a/src/test/blind_tests.cpp +++ b/src/test/blind_tests.cpp @@ -320,6 +320,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test) input_amounts.push_back(500); input_assets.push_back(bitcoinID); input_assets.push_back(otherID); + output_pubkeys.reserve(6); for (unsigned int i = 0; i < 6; i++) { output_pubkeys.push_back(pubkey2); } diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 54f639ff5d..9164ced405 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -1081,7 +1081,7 @@ BOOST_FIXTURE_TEST_CASE(coins_db_leveldb_layout, FlushTest) BOOST_AUTO_TEST_CASE(coins_resource_is_used) { - CCoinsMapMemoryResource resource; + CCoinsMapMemoryResource resource{/*chunk_size_bytes=*/(sizeof(CoinsCachePair) + sizeof(void*) * 4) * 1024}; PoolResourceTester::CheckAllDataAccountedFor(resource); { diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 0cc46622f1..2da0b5dd7e 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -233,7 +233,16 @@ FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, { }) FUZZ_TARGET_DESERIALIZE(coins_deserialize, { Coin coin; - DeserializeFromFuzzingInput(buffer, coin); + DataStream ds{buffer}; + try { + ds >> coin; + } catch (const std::ios_base::failure&) { + throw invalid_fuzzing_input_exception(); + } + // ELEMENTS: Coin::Serialize() asserts !IsSpent(), which arbitrary fuzzed + // bytes can trivially violate via a decompressed null CTxOut. Skip the + // generic deserialize-then-reserialize round-trip check that + // DeserializeFromFuzzingInput() performs for other types. }) FUZZ_TARGET(netaddr_deserialize, .init = initialize_deserialize) { diff --git a/src/test/fuzz/package_eval.cpp b/src/test/fuzz/package_eval.cpp index 92430c6f80..3b232d865f 100644 --- a/src/test/fuzz/package_eval.cpp +++ b/src/test/fuzz/package_eval.cpp @@ -267,9 +267,9 @@ FUZZ_TARGET(ephemeral_package_eval, .init = initialize_tx_pool) // Create input CTxIn in; in.prevout = outpoint; - tx_mut.witness.vtxinwit[&in - &tx_mut.vin[0]].scriptWitness.stack = P2WSH_EMPTY_TRUE_STACK; - tx_mut.vin.push_back(in); + tx_mut.witness.vtxinwit.emplace_back(); + tx_mut.witness.vtxinwit.back().scriptWitness.stack = P2WSH_EMPTY_TRUE_STACK; } const auto amount_fee = fuzzed_data_provider.ConsumeIntegralInRange(0, amount_in); diff --git a/src/test/fuzz/simplicity_tx.cpp b/src/test/fuzz/simplicity_tx.cpp index fe4001b0e9..236473ab87 100644 --- a/src/test/fuzz/simplicity_tx.cpp +++ b/src/test/fuzz/simplicity_tx.cpp @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #include #include @@ -66,6 +67,7 @@ void initialize_simplicity_tx() FUZZ_TARGET(simplicity_tx, .init = initialize_simplicity_tx) { + SeedRandomStateForTest(SeedRand::ZEROS); simplicity_err error; // 1. (no-op) run through Rust code diff --git a/src/test/ipc_test.cpp b/src/test/ipc_test.cpp index d78d6695e7..bac9baadd0 100644 --- a/src/test/ipc_test.cpp +++ b/src/test/ipc_test.cpp @@ -93,7 +93,7 @@ void IpcPipeTest() mtx.version = 2; mtx.nLockTime = 3; mtx.vin.emplace_back(txout1); - mtx.vout.emplace_back(COIN, CScript()); + mtx.vout.emplace_back(CAsset(), COIN, CScript()); CTransactionRef tx1{MakeTransactionRef(mtx)}; CTransactionRef tx2{foo->passTransaction(tx1)}; BOOST_CHECK(*Assert(tx1) == *Assert(tx2)); diff --git a/src/test/validation_flush_tests.cpp b/src/test/validation_flush_tests.cpp index 5055877090..8ad616cb3a 100644 --- a/src/test/validation_flush_tests.cpp +++ b/src/test/validation_flush_tests.cpp @@ -36,8 +36,10 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) BOOST_TEST_MESSAGE("CCoinsViewCache memory usage: " << view.DynamicMemoryUsage()); }; - // PoolResource defaults to 256 KiB that will be allocated, so we'll take that and make it a bit larger. - constexpr size_t MAX_COINS_CACHE_BYTES = 262144 + 512; + // PoolResource for CCoinsMap sizes its chunk relative to sizeof(CoinsCachePair) + // (see CCoinsMapMemoryResource in coins.h) rather than a fixed byte count. + // Mirror that calculation here instead of hardcoding the old 256 KiB default. + constexpr size_t MAX_COINS_CACHE_BYTES = (sizeof(CoinsCachePair) + sizeof(void*) * 4) * 1024 + 512; // Without any coins in the cache, we shouldn't need to flush. BOOST_TEST( @@ -49,7 +51,8 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate) if (view.DynamicMemoryUsage() != 32 && view.DynamicMemoryUsage() != 16) { // Add a bunch of coins to see that we at least flip over to CRITICAL. - for (int i{0}; i < 1000; ++i) { + const int num_coins_to_add = static_cast(MAX_COINS_CACHE_BYTES / COIN_SIZE) + 100; // margin to guarantee crossing the threshold + for (int i{0}; i < num_coins_to_add; ++i) { const COutPoint res = AddTestCoin(m_rng, view); BOOST_CHECK_EQUAL(view.AccessCoin(res).DynamicMemoryUsage(), COIN_SIZE); } diff --git a/src/validation.cpp b/src/validation.cpp index 06806a5f38..368027cee6 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2487,17 +2487,15 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state, CCheck* check = new CScriptCheck(txdata.m_spent_outputs[i], tx, validation_cache.m_signature_cache, i, flags, cacheSigStore, &txdata); if (pvChecks) { pvChecks->emplace_back(std::move(check)); - } else if (auto result = (*check)(); result.has_value()) { - // Tx failures never trigger disconnections/bans. - // This is so that network splits aren't triggered - // either due to non-consensus relay policies (such as - // non-standard DER encodings or non-null dummy - // arguments) or due to new consensus rules introduced in - // soft forks. - if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { - return state.Invalid(TxValidationResult::TX_NOT_STANDARD, strprintf("mempool-script-verify-flag-failed (%s)", ScriptErrorString(result->first)), result->second); - } else { - return state.Invalid(TxValidationResult::TX_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(result->first)), result->second); + } else { + auto result = (*check)(); + delete check; // ELEMENTS: synchronous path owns `check`; queued path (above) transfers ownership instead. + if (result.has_value()) { + if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { + return state.Invalid(TxValidationResult::TX_NOT_STANDARD, strprintf("mempool-script-verify-flag-failed (%s)", ScriptErrorString(result->first)), result->second); + } else { + return state.Invalid(TxValidationResult::TX_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(result->first)), result->second); + } } } } @@ -2982,6 +2980,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state, // for as long as `control`. std::vector txsdata; CCheckQueueControl control(fScriptChecks && parallel_script_checks ? &m_chainman.GetCheckQueue() : nullptr); + txsdata.reserve(block.vtx.size()); for (unsigned int i = 0; i < block.vtx.size(); i++){ txsdata.emplace_back(m_chainman.GetParams().HashGenesisBlock()); } @@ -6272,7 +6271,14 @@ double GuessVerificationProgress(const CBlockIndex* pindex, int64_t blockInterva int64_t nNow = GetTime(); int64_t moreBlocksExpected = (nNow - pindex->GetBlockTime()) / blockInterval; - double progress = (pindex->nHeight + 0.0) / (pindex->nHeight + moreBlocksExpected); + int64_t totalBlocksExpected = pindex->nHeight + moreBlocksExpected; + if (totalBlocksExpected <= 0) { + // The block's timestamp is far enough ahead of nNow (relative to + // blockInterval) that the naive extrapolation is degenerate; + // treat this the same as "caught up". + return 1.0; + } + double progress = (pindex->nHeight + 0.0) / totalBlocksExpected; // Round to 3 digits to avoid 0.999999 when finished. progress = ceil(progress * 1000.0) / 1000.0; // Avoid higher than one if last block is newer than current time. diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp index 2b814d92b0..1172216dc4 100644 --- a/src/wallet/coinselection.cpp +++ b/src/wallet/coinselection.cpp @@ -788,7 +788,7 @@ util::Result KnapsackSolver(std::vector& groups, c for (const OutputGroup& g : groups) { bool add = true; for (const std::shared_ptr& c : g.m_outputs) { - auto input_set = result.GetInputSet(); + const auto& input_set = result.GetInputSet(); if (input_set.find(c) != input_set.end()) { add = false; break; @@ -811,7 +811,7 @@ util::Result KnapsackSolver(std::vector& groups, c } if (auto inner_result = KnapsackSolver(inner_groups, it->second, change_target, rng, max_selection_weight, it->first)) { - auto set = inner_result->GetInputSet(); + const auto& set = inner_result->GetInputSet(); for (const std::shared_ptr& ic : set) { non_policy_effective_value += ic->GetEffectiveValue(); } @@ -837,7 +837,7 @@ util::Result KnapsackSolver(std::vector& groups, c for (const OutputGroup& g : groups) { bool add = true; for (const std::shared_ptr& c : g.m_outputs) { - auto set = result.GetInputSet(); + const auto& set = result.GetInputSet(); if (set.find(c) != set.end()) { add = false; break; diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index aab9bedc1b..84798b213f 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -1288,7 +1288,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name) } else { PartiallySignedTransaction psbtx(mtx, 2 /* version */); bool complete = false; - const auto err{pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true)}; + const auto err{pwallet->FillPSBT(psbtx, complete, SIGHASH_DEFAULT, /*sign=*/false, /*bip32derivs=*/true, /*imbalance_ok=*/true)}; CHECK_NONFATAL(!err); CHECK_NONFATAL(!complete); DataStream ssTx{}; diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 73abd0fe61..445b1bd43b 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -1734,6 +1734,7 @@ static util::Result CreateTransactionInternal( use_anti_fee_sniping = false; } txNew.vin.emplace_back(coin->outpoint, CScript{}, sequence.value_or(default_sequence)); + txNew.witness.vtxinwit.emplace_back(); // ELEMENTS: keep vtxinwit in lockstep with vin auto scripts = coin_control.GetScripts(coin->outpoint); if (scripts.first) { @@ -1746,7 +1747,6 @@ static util::Result CreateTransactionInternal( auto pegin_witness = coin_control.GetPeginWitness(coin->outpoint); if (pegin_witness) { txNew.vin.back().m_is_pegin = true; - txNew.witness.vtxinwit.emplace_back(); txNew.witness.vtxinwit.back().m_pegin_witness = *pegin_witness; } if (issuance_details && coin->asset == issuance_details->reissuance_token) { diff --git a/src/wallet/spend.h b/src/wallet/spend.h index 9c6403b913..08035dfcf1 100644 --- a/src/wallet/spend.h +++ b/src/wallet/spend.h @@ -131,7 +131,7 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, * single OutputType, fallback to running `ChooseSelectionResult()` over all available coins. * * @param[in] chain The chain interface to get information on bump fees for unconfirmed UTXOs - * @param[in] nTargetValue The target value + * @param[in] mapTargetValue The target value * @param[in] groups The grouped outputs mapped by coin eligibility filters * @param[in] coin_selection_params Parameters for the coin selection * @param[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType @@ -149,7 +149,7 @@ util::Result AttemptSelection(interfaces::Chain& chain, const C * (according to the waste metric) will be chosen. * * @param[in] chain The chain interface to get information on bump fees for unconfirmed UTXOs - * @param[in] nTargetValue The target value + * @param[in] mapTargetValue The target value * @param[in] groups The struct containing the outputs grouped by script and divided by (1) positive only outputs and (2) all outputs (positive + negative). * @param[in] coin_selection_params Parameters for the coin selection * returns If successful, a SelectionResult containing the input set @@ -188,10 +188,10 @@ util::Result FetchSelectedInputs(const CWallet& wallet, const const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); /** - * Select a set of coins such that nTargetValue is met; never select unconfirmed coins if they are not ours + * Select a set of coins such that mapTargetValue is met; never select unconfirmed coins if they are not ours * @param[in] wallet The wallet which provides data necessary to spend the selected coins * @param[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering - * @param[in] nTargetValue The target value + * @param[in] mapTargetValue The target value * @param[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends, * and whether to subtract the fee from the outputs. * returns If successful, a SelectionResult containing the selected coins @@ -204,7 +204,7 @@ util::Result AutomaticCoinSelection(const CWallet& wallet, Coin /** * Select all coins from coin_control, and if coin_control 'm_allow_other_inputs=true', call 'AutomaticCoinSelection' to - * select a set of coins such that nTargetValue - pre_set_inputs.total_amount is met. + * select a set of coins such that mapTargetValue - pre_set_inputs.total_amount is met. */ util::Result SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs, const CAmountMap& mapTargetValue, const CCoinControl& coin_control, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 45d4724341..24e42a9470 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2550,6 +2550,7 @@ std::optional CWallet::SignPSBT(PartiallySignedTransaction& psbtx, bo CMutableTransaction tx = psbtx.GetUnsignedTx(); tx.witness.vtxoutwit.resize(tx.vout.size()); + tx.witness.vtxinwit.resize(tx.vin.size()); // ELEMENTS: keep vtxinwit in lockstep with vin, mirroring vtxoutwit above // Stuff in auxiliary CA blinding data, if we have it for (unsigned int i = 0; i < tx.vout.size(); ++i) { diff --git a/test/functional/p2p_headers_presync.py b/test/functional/p2p_headers_presync.py index aa61d8262c..ada6fc0dd5 100755 --- a/test/functional/p2p_headers_presync.py +++ b/test/functional/p2p_headers_presync.py @@ -49,6 +49,7 @@ class PreSyncHeadersTest(BitcoinTestFramework): self.connect_nodes(0, 3) def run_test(self): + self.skip_if_no_wallet() # ELEMENTS: this test taken from p2p_headers_sync_with_mainchainwork.py to run on elements regtest self.nodes[0].createwallet("miner") wallet = self.nodes[0].get_wallet_rpc("miner") diff --git a/test/functional/p2p_headers_sync_with_minchainwork.py b/test/functional/p2p_headers_sync_with_minchainwork.py index c7c8cb2576..86fd4900b4 100755 --- a/test/functional/p2p_headers_sync_with_minchainwork.py +++ b/test/functional/p2p_headers_sync_with_minchainwork.py @@ -127,6 +127,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): def run_test(self): + self.skip_if_no_wallet() # ELEMENTS: setup a bcrt1 address to mine to, since our deterministic privkeys are invalid for bitcoin regtest # calls to self.generate have been replaced with self.generatetoaddress with this global address self.nodes[0].createwallet("miner") diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 9c7feda5a6..0cec811719 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -986,8 +986,14 @@ class CTransaction: def is_valid(self): self.calc_sha256() for tout in self.vout: - if tout.nValue < 0 or tout.nValue > 21000000 * COIN: - return False + value = tout.nValue + # ELEMENTS: nValue is a CTxOutValue. Only explicit (unblinded) + # amounts can be range-checked here; confidential outputs are + # validated via rangeproofs elsewhere, not by this sanity check. + if value.vchCommitment[0] == 1: + amount = value.getAmount() + if amount < 0 or amount > 21000000 * COIN: + return False return True # Calculate the transaction weight using witness and non-witness