Skip to content
26 changes: 19 additions & 7 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ win64_native_common: &win64_native_common
windows_container:
cpu: 4
memory: 8G
image: cirrusci/windowsservercore:visualstudio2019
image: cirrusci/windowsservercore:visualstudio2022
timeout_in: 120m
env:
PATH: 'C:\jom;C:\Python39;C:\Python39\Scripts;C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin;%PATH%'
PATH: 'C:\jom;C:\Python39;C:\Python39\Scripts;C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin;%PATH%'
PYTHONUTF8: 1
CI_VCPKG_TAG: '2021.05.12'
VCPKG_DOWNLOADS: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\downloads'
Expand All @@ -98,7 +98,7 @@ win64_native_common: &win64_native_common
QT_LOCAL_PATH: 'C:\qt-everywhere-opensource-src-5.15.3.zip'
QT_SOURCE_DIR: 'C:\qt-everywhere-src-5.15.3'
QTBASEDIR: 'C:\Qt_static'
x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"'
x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat"'
IgnoreWarnIntDirInTempDetected: 'true'
merge_script:
- git config --global user.email "[email protected]"
Expand Down Expand Up @@ -161,19 +161,25 @@ win64_native_common: &win64_native_common
- msbuild build_msvc\bitcoin.sln -property:Configuration=Release -maxCpuCount -verbosity:minimal -noLogo

task:
name: "Win64 native [msvc] (Short running functional tests)"
name: "Win64 native [vs2022] (Short running functional tests)"
<<: *win64_native_common
functional_tests_script:
# Increase the dynamic port range to the maximum allowed value to mitigate "OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted".
# See: https://docs.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance
- netsh int ipv4 set dynamicport tcp start=1025 num=64511
- netsh int ipv6 set dynamicport tcp start=1025 num=64511
- mkdir artifactsdir
# Heavier tests are moved to a secondary task
# Exclude feature_dbcrash and feature_fee_estimation, failing https://github.com/ElementsProject/elements/pull/1298
- python test\functional\test_runner.py --nocleanup --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 --extended --exclude wallet_avoidreuse,feature_trim_headers,feature_dbcrash,feature_fee_estimation
- python test\functional\test_runner.py --tmpdirprefix=artifactsdir/ --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 --extended --exclude wallet_avoidreuse,feature_trim_headers,feature_dbcrash,feature_fee_estimation
artifacts:
paths:
- artifactsdir/**/*.log
- artifactsdir/**/tmp*
- artifactsdir/**/*.conf

task:
name: "Win64 native [msvc] (Long running functional tests + unit tests)"
name: "Win64 native [vs2022] (Long running functional tests + unit tests)"
<<: *win64_native_common
unit_tests_script:
- src\test_elements.exe -l test_suite
Expand All @@ -185,9 +191,15 @@ task:
# See: https://docs.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance
- netsh int ipv4 set dynamicport tcp start=1025 num=64511
- netsh int ipv6 set dynamicport tcp start=1025 num=64511
- mkdir artifactsdir
# Execute tests excluded from the main task
# Ignore failures for now until https://github.com/ElementsProject/elements/pull/1298 is merged
- python test\functional\test_runner.py --nocleanup --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 wallet_avoidreuse feature_trim_headers feature_dbcrash feature_fee_estimation || true
- python test\functional\test_runner.py --tmpdirprefix=artifactsdir/ --ci --quiet --combinedlogslen=4000 --jobs=4 --timeout-factor=8 wallet_avoidreuse feature_trim_headers feature_dbcrash feature_fee_estimation || true
artifacts:
paths:
- artifactsdir/**/*.log
- artifactsdir/**/tmp*
- artifactsdir/**/*.conf

task:
name: 'ARM [unit tests, no functional tests] [bullseye]'
Expand Down
1 change: 0 additions & 1 deletion ci/lint/06_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ test/lint/git-subtree-check.sh src/crypto/ctaes
test/lint/git-subtree-check.sh src/secp256k1
test/lint/git-subtree-check.sh src/simplicity
test/lint/git-subtree-check.sh src/minisketch
test/lint/git-subtree-check.sh src/univalue
test/lint/git-subtree-check.sh src/leveldb
test/lint/git-subtree-check.sh src/crc32c
test/lint/check-doc.py
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ if test "$CXXFLAGS_overridden" = "no"; then
AX_CHECK_COMPILE_FLAG([-Wthread-safety], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety"], [], [$CXXFLAG_WERROR])
AX_CHECK_COMPILE_FLAG([-Wloop-analysis], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"], [], [$CXXFLAG_WERROR])
AX_CHECK_COMPILE_FLAG([-Wredundant-decls], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wredundant-decls"], [], [$CXXFLAG_WERROR])
AX_CHECK_COMPILE_FLAG([-Wunused-result],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-result"],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-Wunused-member-function], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunused-member-function"], [], [$CXXFLAG_WERROR])
AX_CHECK_COMPILE_FLAG([-Wdate-time], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wdate-time"], [], [$CXXFLAG_WERROR])
AX_CHECK_COMPILE_FLAG([-Wconditional-uninitialized], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wconditional-uninitialized"], [], [$CXXFLAG_WERROR])
Expand Down
7 changes: 3 additions & 4 deletions src/addrdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ bool SerializeDB(Stream& stream, const Data& data)
{
// Write and commit header, data
try {
CHashWriter hasher(stream.GetType(), stream.GetVersion());
stream << Params().MessageStart() << data;
hasher << Params().MessageStart() << data;
stream << hasher.GetHash();
HashedSourceWriter hashwriter{stream};
hashwriter << Params().MessageStart() << data;
stream << hashwriter.GetHash();
} catch (const std::exception& e) {
return error("%s: Serialize or I/O error - %s", __func__, e.what());
}
Expand Down
3 changes: 1 addition & 2 deletions src/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1171,8 +1171,7 @@ void AddrMan::Unserialize(Stream& s_)
}

// explicit instantiation
template void AddrMan::Serialize(CHashWriter& s) const;
template void AddrMan::Serialize(CAutoFile& s) const;
template void AddrMan::Serialize(HashedSourceWriter<CAutoFile>& s) const;
template void AddrMan::Serialize(CDataStream& s) const;
template void AddrMan::Unserialize(CAutoFile& s);
template void AddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
Expand Down
22 changes: 11 additions & 11 deletions src/bitcoin-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& str
try {
response = CallRPC(rh, strMethod, args, rpcwallet);
if (fWait) {
const UniValue& error = find_value(response, "error");
const UniValue& error = response.find_value("error");
if (!error.isNull() && error["code"].get_int() == RPC_IN_WARMUP) {
throw CConnectionFailed("server in warmup");
}
Expand Down Expand Up @@ -877,8 +877,8 @@ static void ParseResult(const UniValue& result, std::string& strPrint)
static void ParseError(const UniValue& error, std::string& strPrint, int& nRet)
{
if (error.isObject()) {
const UniValue& err_code = find_value(error, "code");
const UniValue& err_msg = find_value(error, "message");
const UniValue& err_code = error.find_value("code");
const UniValue& err_msg = error.find_value("message");
if (!err_code.isNull()) {
strPrint = "error code: " + err_code.getValStr() + "\n";
}
Expand All @@ -904,15 +904,15 @@ static void GetWalletBalances(UniValue& result)
{
DefaultRequestHandler rh;
const UniValue listwallets = ConnectAndCallRPC(&rh, "listwallets", /* args=*/{});
if (!find_value(listwallets, "error").isNull()) return;
const UniValue& wallets = find_value(listwallets, "result");
if (!listwallets.find_value("error").isNull()) return;
const UniValue& wallets = listwallets.find_value("result");
if (wallets.size() <= 1) return;

UniValue balances(UniValue::VOBJ);
for (const UniValue& wallet : wallets.getValues()) {
const std::string wallet_name = wallet.get_str();
const UniValue getbalances = ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
const UniValue& balance = find_value(getbalances, "result")["mine"]["trusted"];
const UniValue& balance = getbalances.find_value("result")["mine"]["trusted"];
balances.pushKV(wallet_name, balance);
}
result.pushKV("balances", balances);
Expand Down Expand Up @@ -948,7 +948,7 @@ static void GetProgressBar(double progress, std::string& progress_bar)
*/
static void ParseGetInfoResult(UniValue& result)
{
if (!find_value(result, "error").isNull()) return;
if (!result.find_value("error").isNull()) return;

std::string RESET, GREEN, BLUE, YELLOW, MAGENTA, CYAN;
bool should_colorize = false;
Expand Down Expand Up @@ -1157,9 +1157,9 @@ static int CommandLineRPC(int argc, char *argv[])
rh.reset(new NetinfoRequestHandler());
} else if (gArgs.GetBoolArg("-generate", false)) {
const UniValue getnewaddress{GetNewAddress()};
const UniValue& error{find_value(getnewaddress, "error")};
const UniValue& error{getnewaddress.find_value("error")};
if (error.isNull()) {
SetGenerateToAddressArgs(find_value(getnewaddress, "result").get_str(), args);
SetGenerateToAddressArgs(getnewaddress.find_value("result").get_str(), args);
rh.reset(new GenerateToAddressRequestHandler());
} else {
ParseError(error, strPrint, nRet);
Expand All @@ -1181,8 +1181,8 @@ static int CommandLineRPC(int argc, char *argv[])
const UniValue reply = ConnectAndCallRPC(rh.get(), method, args, wallet_name);

// Parse reply
UniValue result = find_value(reply, "result");
const UniValue& error = find_value(reply, "error");
UniValue result = reply.find_value("result");
const UniValue& error = reply.find_value("error");
if (error.isNull()) {
if (gArgs.GetBoolArg("-getinfo", false)) {
if (!gArgs.IsArgSet("-rpcwallet")) {
Expand Down
14 changes: 7 additions & 7 deletions src/external_signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
}
for (UniValue signer : result.getValues()) {
// Check for error
const UniValue& error = find_value(signer, "error");
const UniValue& error = signer.find_value("error");
if (!error.isNull()) {
if (!error.isStr()) {
throw std::runtime_error(strprintf("'%s' error", command));
}
throw std::runtime_error(strprintf("'%s' error: %s", command, error.getValStr()));
}
// Check if fingerprint is present
const UniValue& fingerprint = find_value(signer, "fingerprint");
const UniValue& fingerprint = signer.find_value("fingerprint");
if (fingerprint.isNull()) {
throw std::runtime_error(strprintf("'%s' received invalid response, missing signer fingerprint", command));
}
Expand All @@ -50,7 +50,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
}
if (duplicate) break;
std::string name = "";
const UniValue& model_field = find_value(signer, "model");
const UniValue& model_field = signer.find_value("model");
if (model_field.isStr() && model_field.getValStr() != "") {
name += model_field.getValStr();
}
Expand Down Expand Up @@ -93,19 +93,19 @@ bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::str

const UniValue signer_result = RunCommandParseJSON(command, stdinStr);

if (find_value(signer_result, "error").isStr()) {
error = find_value(signer_result, "error").get_str();
if (signer_result.find_value("error").isStr()) {
error = signer_result.find_value("error").get_str();
return false;
}

if (!find_value(signer_result, "psbt").isStr()) {
if (!signer_result.find_value("psbt").isStr()) {
error = "Unexpected result from signer";
return false;
}

PartiallySignedTransaction signer_psbtx;
std::string signer_psbt_error;
if (!DecodeBase64PSBT(signer_psbtx, find_value(signer_result, "psbt").get_str(), signer_psbt_error)) {
if (!DecodeBase64PSBT(signer_psbtx, signer_result.find_value("psbt").get_str(), signer_psbt_error)) {
error = strprintf("TX decode failed %s", signer_psbt_error);
return false;
}
Expand Down
24 changes: 24 additions & 0 deletions src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,30 @@ class CHashVerifier : public CHashWriter
}
};

/** Writes data to an underlying source stream, while hashing the written data. */
template <typename Source>
class HashedSourceWriter : public CHashWriter
{
private:
Source& m_source;

public:
explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : CHashWriter{source.GetType(), source.GetVersion()}, m_source{source} {}

void write(Span<const std::byte> src)
{
m_source.write(src);
CHashWriter::write(src);
}

template <typename T>
HashedSourceWriter& operator<<(const T& obj)
{
::Serialize(*this, obj);
return *this;
}
};

/** Compute the 256-bit hash of an object's serialization, with optional sighash byte. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Expand Down
4 changes: 2 additions & 2 deletions src/httprpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static void JSONErrorReply(HTTPRequest* req, const UniValue& objError, const Uni
{
// Send error reply from json-rpc error object
int nStatus = HTTP_INTERNAL_SERVER_ERROR;
int code = find_value(objError, "code").get_int();
int code = objError.find_value("code").get_int();

if (code == RPC_INVALID_REQUEST)
nStatus = HTTP_BAD_REQUEST;
Expand Down Expand Up @@ -213,7 +213,7 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
} else {
const UniValue& request = valRequest[reqIdx].get_obj();
// Parse method
std::string strMethod = find_value(request, "method").get_str();
std::string strMethod = request.find_value("method").get_str();
if (!g_rpc_whitelist[jreq.authUser].count(strMethod)) {
LogPrintf("RPC User %s not allowed to call method %s\n", jreq.authUser, strMethod);
req->WriteReply(HTTP_FORBIDDEN);
Expand Down
8 changes: 4 additions & 4 deletions src/mainchainrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,26 +158,26 @@ bool IsConfirmedBitcoinBlock(const uint256& hash, const int nMinConfirmationDept
UniValue params(UniValue::VARR);
params.push_back(hash.GetHex());
UniValue reply = CallMainChainRPC("getblockheader", params);
UniValue errval = find_value(reply, "error");
UniValue errval = reply.find_value("error");
if (!errval.isNull()) {
LogPrintf("WARNING: Got error reply from bitcoind getblockheader: %s\n", errval.write());
return false;
}
UniValue result = find_value(reply, "result");
UniValue result = reply.find_value("result");
if (!result.isObject()) {
LogPrintf("ERROR: bitcoind getblockheader result was malformed (not object): %s\n", result.write());
return false;
}

UniValue confirmations = find_value(result.get_obj(), "confirmations");
UniValue confirmations = result.get_obj().find_value("confirmations");
if (!confirmations.isNum() || confirmations.get_int64() < nMinConfirmationDepth) {
LogPrintf("Insufficient confirmations (got %s, need at least %d).\n", confirmations.write(), nMinConfirmationDepth);
return false;
}

// Only perform extra test if nbTxs has been provided (non-zero).
if (nbTxs != 0) {
UniValue nTx = find_value(result.get_obj(), "nTx");
UniValue nTx = result.get_obj().find_value("nTx");
if (!nTx.isNum() || nTx.get_int64() != nbTxs) {
LogPrintf("ERROR: Invalid number of transactions in merkle block for %s (got %s, need exactly %d)\n",
hash.GetHex(), nTx.write(), nbTxs);
Expand Down
6 changes: 3 additions & 3 deletions src/qt/rpcconsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
subelement = lastResult[parsed.value()];
}
else if (lastResult.isObject())
subelement = find_value(lastResult, curarg);
subelement = lastResult.find_value( curarg);
else
throw std::runtime_error("Invalid result query"); //no array or object: abort
lastResult = subelement;
Expand Down Expand Up @@ -456,8 +456,8 @@ void RPCExecutor::request(const QString &command, const WalletModel* wallet_mode
{
try // Nice formatting for standard-format error
{
int code = find_value(objError, "code").get_int();
std::string message = find_value(objError, "message").get_str();
int code = objError.find_value("code").get_int();
std::string message = objError.find_value("message").get_str();
Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
}
catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message
Expand Down
10 changes: 5 additions & 5 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ static RPCHelpMan getblocktemplate()
if (!request.params[0].isNull())
{
const UniValue& oparam = request.params[0].get_obj();
const UniValue& modeval = find_value(oparam, "mode");
const UniValue& modeval = oparam.find_value("mode");
if (modeval.isStr())
strMode = modeval.get_str();
else if (modeval.isNull())
Expand All @@ -655,11 +655,11 @@ static RPCHelpMan getblocktemplate()
}
else
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
lpval = find_value(oparam, "longpollid");
lpval = oparam.find_value("longpollid");

if (strMode == "proposal")
{
const UniValue& dataval = find_value(oparam, "data");
const UniValue& dataval = oparam.find_value("data");
if (!dataval.isStr())
throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");

Expand All @@ -686,15 +686,15 @@ static RPCHelpMan getblocktemplate()
return BIP22ValidationResult(state);
}

const UniValue& aClientRules = find_value(oparam, "rules");
const UniValue& aClientRules = oparam.find_value("rules");
if (aClientRules.isArray()) {
for (unsigned int i = 0; i < aClientRules.size(); ++i) {
const UniValue& v = aClientRules[i];
setClientRules.insert(v.get_str());
}
} else {
// NOTE: It is important that this NOT be read if versionbits is supported
const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
const UniValue& uvMaxVersion = oparam.find_value("maxversion");
if (uvMaxVersion.isNum()) {
nMaxVersionPreVB = uvMaxVersion.get_int64();
}
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2166,7 +2166,7 @@ static RPCHelpMan createpsbt()
std::set<uint256> new_reissuance;
for (unsigned int i = 0; i < rawTx.vin.size(); ++i) {
if (!rawTx.vin[i].assetIssuance.IsNull()) {
const UniValue& blind_reissuance_v = find_value(request.params[0].get_array()[i].get_obj(), "blind_reissuance");
const UniValue& blind_reissuance_v = request.params[0].get_array()[i].get_obj().find_value("blind_reissuance");
bool blind_reissuance = blind_reissuance_v.isNull() ? true : blind_reissuance_v.get_bool();
uint256 entropy;
CAsset asset;
Expand Down
Loading