This commit is contained in:
Tom Trevethan 2026-07-16 14:57:58 +01:00
parent 8c0ec580c9
commit 292a9378ca
No known key found for this signature in database
38 changed files with 248 additions and 119 deletions

View file

@ -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

View file

@ -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

View file

@ -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]"
}

View file

@ -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

View file

@ -36,7 +36,7 @@ void CAssetsDir::SetHex(const std::string& assetHex, const std::string& label)
void CAssetsDir::InitFromStrings(const std::vector<std::string>& assetsToInit, const std::string& pegged_asset_name)
{
for (std::string strToSplit : assetsToInit) {
for (const std::string& strToSplit : assetsToInit) {
std::vector<std::string> vAssets;
const auto pos = strToSplit.find(':');
if (pos != std::string::npos) {

View file

@ -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

View file

@ -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<PrevectorJob> 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<PrevectorJob*> 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

View file

@ -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");

View file

@ -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);

View file

@ -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;

View file

@ -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
$<TARGET_NAME_IF_EXISTS:USDT::headers>
$<TARGET_NAME_IF_EXISTS:libevent::libevent>
$<TARGET_NAME_IF_EXISTS:libevent::core>
$<TARGET_NAME_IF_EXISTS:libevent::extra>
$<TARGET_NAME_IF_EXISTS:libevent::pthreads>
PUBLIC
Boost::headers
)

View file

@ -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;

View file

@ -107,6 +107,7 @@ struct PeginMinimum {
class CChainParams
{
public:
virtual ~CChainParams() = default; // required: subclasses are stored and destroyed via std::unique_ptr<const CChainParams>
enum Base58Type {
PUBKEY_ADDRESS,
SCRIPT_ADDRESS,

View file

@ -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<int64_t>(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; }

View file

@ -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<uint256> &vTxid) {
uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<uint256> &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<uint256> &vTxid, const std::vector<bool> &vMatch) {
void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &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<uint256> &vMatch, std::vector<unsigned int> &vnIndex) {
uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex) { // NOLINT(misc-no-recursion)
if (nBitsUsed >= vBits.size()) {
// overflowed the bits array - failure
fBad = true;

View file

@ -232,7 +232,7 @@ bool XOnlyPubKey::VerifySchnorr(const Span<const unsigned char> msg, Span<const
assert(sigbytes.size() == 64);
secp256k1_xonly_pubkey pubkey;
if (!secp256k1_xonly_pubkey_parse(secp256k1_context_static, &pubkey, m_keydata.data())) return false;
return secp256k1_schnorrsig_verify(secp256k1_context_static, sigbytes.data(), msg.begin(), 32, &pubkey);
return secp256k1_schnorrsig_verify(secp256k1_context_static, sigbytes.data(), msg.begin(), msg.size(), &pubkey);
}
// ELEMENTS: this is preserved from an old version of the Taproot code for use in OP_TWEAKVERIFY

View file

@ -227,6 +227,10 @@ add_executable(elements-qt
../init/bitcoin-qt.cpp
)
set_target_properties(elements-qt PROPERTIES
SKIP_BUILD_RPATH OFF
)
add_windows_resources(elements-qt res/bitcoin-qt-res.rc)
target_link_libraries(elements-qt
@ -252,7 +256,7 @@ if(WITH_MULTIPROCESS)
bitcoin_node
bitcoin_ipc
)
import_plugins(bitcoin-gui)
import_plugins(elements-gui)
install_binary_component(elements-gui)
if(WIN32)
set_target_properties(elements-gui PROPERTIES WIN32_EXECUTABLE TRUE)

View file

@ -85,7 +85,7 @@ NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift,
trayAndWindowIcon = QIcon(pixmap.scaled(QSize(256,256)));
}
const NetworkStyle* NetworkStyle::instantiate(const ChainType networkId)
const NetworkStyle* NetworkStyle::instantiate(const ChainType networkId) // NOLINT(misc-no-recursion)
{
std::string titleAddText = networkId == ChainType::LIQUID1 ? "" : strprintf("[%s]", ChainTypeToString(networkId));
for (const auto& network_style : network_styles) {

View file

@ -14,6 +14,10 @@ add_executable(test_elements-qt
../../init/bitcoin-qt.cpp
)
set_target_properties(test_elements-qt PROPERTIES
SKIP_BUILD_RPATH OFF
)
target_link_libraries(test_elements-qt
core_interface
bitcoinqt

View file

@ -333,7 +333,7 @@ static RPCHelpMan echoipc()
// and spawn bitcoin-echo below instead of bitcoin-node. But
// using bitcoin-node avoids the need to build and install a
// new executable just for this one test.
auto init = ipc->spawnProcess("bitcoin-node");
auto init = ipc->spawnProcess("elements-node");
echo = init->makeEcho();
ipc->addCleanup(*echo, [init = init.release()] { delete init; });
} else {

View file

@ -1406,7 +1406,7 @@ std::vector<CScript> 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); }

View file

@ -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

View file

@ -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);
}

View file

@ -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);
{

View file

@ -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)
{

View file

@ -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<CAmount>(0, amount_in);

View file

@ -15,6 +15,7 @@ extern "C" {
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/random.h>
#include <cstdint>
#include <optional>
@ -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

View file

@ -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));

View file

@ -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<int>(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);
}

View file

@ -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<PrecomputedTransactionData> txsdata;
CCheckQueueControl<CCheck> 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.

View file

@ -788,7 +788,7 @@ util::Result<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, c
for (const OutputGroup& g : groups) {
bool add = true;
for (const std::shared_ptr<wallet::COutput>& 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<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& 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<wallet::COutput>& ic : set) {
non_policy_effective_value += ic->GetEffectiveValue();
}
@ -837,7 +837,7 @@ util::Result<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, c
for (const OutputGroup& g : groups) {
bool add = true;
for (const std::shared_ptr<wallet::COutput>& c : g.m_outputs) {
auto set = result.GetInputSet();
const auto& set = result.GetInputSet();
if (set.find(c) != set.end()) {
add = false;
break;

View file

@ -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{};

View file

@ -1734,6 +1734,7 @@ static util::Result<CreatedTransactionResult> 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<CreatedTransactionResult> 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) {

View file

@ -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<SelectionResult> 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<PreSelectedInputs> 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<SelectionResult> 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<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
const CAmountMap& mapTargetValue, const CCoinControl& coin_control,

View file

@ -2550,6 +2550,7 @@ std::optional<PSBTError> 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) {

View file

@ -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")

View file

@ -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")

View file

@ -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