diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bitcoin-tx.cpp | 12 | ||||
-rw-r--r-- | src/core_io.h | 9 | ||||
-rw-r--r-- | src/core_read.cpp | 9 | ||||
-rw-r--r-- | src/crypto/sha256.cpp | 5 | ||||
-rw-r--r-- | src/init.h | 4 | ||||
-rw-r--r-- | src/qt/transactiontablemodel.cpp | 2 | ||||
-rw-r--r-- | src/qt/transactionview.cpp | 6 | ||||
-rw-r--r-- | src/rest.cpp | 44 | ||||
-rw-r--r-- | src/rpc/fees.cpp | 6 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 8 | ||||
-rw-r--r-- | src/test/blockfilter_tests.cpp | 9 | ||||
-rw-r--r-- | src/test/fuzz/coins_view.cpp | 4 | ||||
-rw-r--r-- | src/test/fuzz/hex.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/utxo_snapshot.cpp | 8 | ||||
-rw-r--r-- | src/test/pow_tests.cpp | 6 | ||||
-rw-r--r-- | src/test/uint256_tests.cpp | 18 | ||||
-rw-r--r-- | src/test/util/setup_common.cpp | 12 | ||||
-rw-r--r-- | src/test/util/setup_common.h | 2 | ||||
-rw-r--r-- | src/uint256.cpp | 6 | ||||
-rw-r--r-- | src/uint256.h | 33 | ||||
-rw-r--r-- | src/util/transaction_identifier.h | 7 |
21 files changed, 115 insertions, 98 deletions
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 89faa0123a..89c03c1647 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -264,8 +264,8 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu throw std::runtime_error("TX input missing separator"); // extract and validate TXID - uint256 txid; - if (!ParseHashStr(vStrInputParts[0], txid)) { + auto txid{Txid::FromHex(vStrInputParts[0])}; + if (!txid) { throw std::runtime_error("invalid TX input txid"); } @@ -285,7 +285,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu } // append to transaction input list - CTxIn txin(Txid::FromUint256(txid), vout, CScript(), nSequenceIn); + CTxIn txin(*txid, vout, CScript(), nSequenceIn); tx.vin.push_back(txin); } @@ -625,8 +625,8 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) if (!prevOut.checkObject(types)) throw std::runtime_error("prevtxs internal object typecheck fail"); - uint256 txid; - if (!ParseHashStr(prevOut["txid"].get_str(), txid)) { + auto txid{Txid::FromHex(prevOut["txid"].get_str())}; + if (!txid) { throw std::runtime_error("txid must be hexadecimal string (not '" + prevOut["txid"].get_str() + "')"); } @@ -634,7 +634,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) if (nOut < 0) throw std::runtime_error("vout cannot be negative"); - COutPoint out(Txid::FromUint256(txid), nOut); + COutPoint out(*txid, nOut); std::vector<unsigned char> pkData(ParseHexUV(prevOut["scriptPubKey"], "scriptPubKey")); CScript scriptPubKey(pkData.begin(), pkData.end()); diff --git a/src/core_io.h b/src/core_io.h index 4405f5c8f8..9305bb7239 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -37,15 +37,6 @@ std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDeco [[nodiscard]] bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header); -/** - * Parse a hex string into 256 bits - * @param[in] strHex a hex-formatted, 64-character string - * @param[out] result the result of the parsing - * @returns true if successful, false if not - * - * @see ParseHashV for an RPC-oriented version of this - */ -bool ParseHashStr(const std::string& strHex, uint256& result); [[nodiscard]] util::Result<int> SighashFromStr(const std::string& sighash); // core_write.cpp diff --git a/src/core_read.cpp b/src/core_read.cpp index 0ba271a8d2..23f341c230 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -234,15 +234,6 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk) return true; } -bool ParseHashStr(const std::string& strHex, uint256& result) -{ - if ((strHex.size() != 64) || !IsHex(strHex)) - return false; - - result.SetHex(strHex); - return true; -} - util::Result<int> SighashFromStr(const std::string& sighash) { static const std::map<std::string, int> map_sighash_values = { diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 89d7204808..deedc0a6d1 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -7,8 +7,9 @@ #include <crypto/sha256.h> #include <crypto/common.h> -#include <assert.h> -#include <string.h> +#include <algorithm> +#include <cassert> +#include <cstring> #if !defined(DISABLE_OPTIMIZED_SHA256) #include <compat/cpuid.h> diff --git a/src/init.h b/src/init.h index ead5f5e0d2..40a5da3c0b 100644 --- a/src/init.h +++ b/src/init.h @@ -6,9 +6,7 @@ #ifndef BITCOIN_INIT_H #define BITCOIN_INIT_H -#include <any> -#include <memory> -#include <string> +#include <atomic> //! Default value for -daemon option static constexpr bool DEFAULT_DAEMON = false; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index d4267fcf61..9214e7723d 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -277,7 +277,7 @@ void TransactionTableModel::updateAmountColumnTitle() void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction) { uint256 updated; - updated.SetHex(hash.toStdString()); + updated.SetHexDeprecated(hash.toStdString()); priv->updateWallet(walletModel->wallet(), updated, status, showTransaction); } diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 7e24dbd3ec..2aaa65c6f7 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -396,7 +396,7 @@ void TransactionView::contextualMenu(const QPoint &point) // check if transaction can be abandoned, disable context menu action in case it doesn't uint256 hash; - hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString()); + hash.SetHexDeprecated(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString()); abandonAction->setEnabled(model->wallet().transactionCanBeAbandoned(hash)); bumpFeeAction->setEnabled(model->wallet().transactionCanBeBumped(hash)); copyAddressAction->setEnabled(GUIUtil::hasEntryData(transactionView, 0, TransactionTableModel::AddressRole)); @@ -416,7 +416,7 @@ void TransactionView::abandonTx() // get the hash from the TxHashRole (QVariant / QString) uint256 hash; QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString(); - hash.SetHex(hashQStr.toStdString()); + hash.SetHexDeprecated(hashQStr.toStdString()); // Abandon the wallet transaction over the walletModel model->wallet().abandonTransaction(hash); @@ -431,7 +431,7 @@ void TransactionView::bumpFee([[maybe_unused]] bool checked) // get the hash from the TxHashRole (QVariant / QString) uint256 hash; QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString(); - hash.SetHex(hashQStr.toStdString()); + hash.SetHexDeprecated(hashQStr.toStdString()); // Bump tx fee over the walletModel uint256 newHash; diff --git a/src/rest.cpp b/src/rest.cpp index 3cf6ad343c..c42bc8e40c 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -217,9 +217,10 @@ static bool rest_headers(const std::any& context, return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Header count is invalid or out of acceptable range (1-%u): %s", MAX_REST_HEADERS_RESULTS, raw_count)); } - uint256 hash; - if (!ParseHashStr(hashStr, hash)) + auto hash{uint256::FromHex(hashStr)}; + if (!hash) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); + } const CBlockIndex* tip = nullptr; std::vector<const CBlockIndex*> headers; @@ -231,7 +232,7 @@ static bool rest_headers(const std::any& context, LOCK(cs_main); CChain& active_chain = chainman.ActiveChain(); tip = active_chain.Tip(); - const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash); + const CBlockIndex* pindex{chainman.m_blockman.LookupBlockIndex(*hash)}; while (pindex != nullptr && active_chain.Contains(pindex)) { headers.push_back(pindex); if (headers.size() == *parsed_count) { @@ -290,9 +291,10 @@ static bool rest_block(const std::any& context, std::string hashStr; const RESTResponseFormat rf = ParseDataFormat(hashStr, strURIPart); - uint256 hash; - if (!ParseHashStr(hashStr, hash)) + auto hash{uint256::FromHex(hashStr)}; + if (!hash) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); + } FlatFilePos pos{}; const CBlockIndex* pblockindex = nullptr; @@ -303,7 +305,7 @@ static bool rest_block(const std::any& context, { LOCK(cs_main); tip = chainman.ActiveChain().Tip(); - pblockindex = chainman.m_blockman.LookupBlockIndex(hash); + pblockindex = chainman.m_blockman.LookupBlockIndex(*hash); if (!pblockindex) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } @@ -390,8 +392,8 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Header count is invalid or out of acceptable range (1-%u): %s", MAX_REST_HEADERS_RESULTS, raw_count)); } - uint256 block_hash; - if (!ParseHashStr(raw_blockhash, block_hash)) { + auto block_hash{uint256::FromHex(raw_blockhash)}; + if (!block_hash) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + raw_blockhash); } @@ -413,7 +415,7 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const ChainstateManager& chainman = *maybe_chainman; LOCK(cs_main); CChain& active_chain = chainman.ActiveChain(); - const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block_hash); + const CBlockIndex* pindex{chainman.m_blockman.LookupBlockIndex(*block_hash)}; while (pindex != nullptr && active_chain.Contains(pindex)) { headers.push_back(pindex); if (headers.size() == *parsed_count) @@ -494,8 +496,8 @@ static bool rest_block_filter(const std::any& context, HTTPRequest* req, const s return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/blockfilter/<filtertype>/<blockhash>"); } - uint256 block_hash; - if (!ParseHashStr(uri_parts[1], block_hash)) { + auto block_hash{uint256::FromHex(uri_parts[1])}; + if (!block_hash) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + uri_parts[1]); } @@ -516,7 +518,7 @@ static bool rest_block_filter(const std::any& context, HTTPRequest* req, const s if (!maybe_chainman) return false; ChainstateManager& chainman = *maybe_chainman; LOCK(cs_main); - block_index = chainman.m_blockman.LookupBlockIndex(block_hash); + block_index = chainman.m_blockman.LookupBlockIndex(*block_hash); if (!block_index) { return RESTERR(req, HTTP_NOT_FOUND, uri_parts[1] + " not found"); } @@ -616,14 +618,14 @@ static bool rest_deploymentinfo(const std::any& context, HTTPRequest* req, const jsonRequest.params = UniValue(UniValue::VARR); if (!hash_str.empty()) { - uint256 hash; - if (!ParseHashStr(hash_str, hash)) { + auto hash{uint256::FromHex(hash_str)}; + if (!hash) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hash_str); } const ChainstateManager* chainman = GetChainman(context, req); if (!chainman) return false; - if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(ParseHashV(hash_str, "blockhash")))) { + if (!WITH_LOCK(::cs_main, return chainman->m_blockman.LookupBlockIndex(*hash))) { return RESTERR(req, HTTP_BAD_REQUEST, "Block not found"); } @@ -704,9 +706,10 @@ static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string std::string hashStr; const RESTResponseFormat rf = ParseDataFormat(hashStr, strURIPart); - uint256 hash; - if (!ParseHashStr(hashStr, hash)) + auto hash{uint256::FromHex(hashStr)}; + if (!hash) { return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); + } if (g_txindex) { g_txindex->BlockUntilSyncedToCurrentChain(); @@ -715,7 +718,7 @@ static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string const NodeContext* const node = GetNodeContext(context, req); if (!node) return false; uint256 hashBlock = uint256(); - const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, node->mempool.get(), hash, hashBlock, node->chainman->m_blockman); + const CTransactionRef tx{GetTransaction(/*block_index=*/nullptr, node->mempool.get(), *hash, hashBlock, node->chainman->m_blockman)}; if (!tx) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } @@ -792,13 +795,14 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std:: if (txid_out.size() != 2) { return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); } + auto txid{Txid::FromHex(txid_out.at(0))}; auto output{ToIntegral<uint32_t>(txid_out.at(1))}; - if (!output || !IsHex(txid_out.at(0))) { + if (!txid || !output) { return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); } - vOutPoints.emplace_back(TxidFromString(txid_out.at(0)), *output); + vOutPoints.emplace_back(*txid, *output); } if (vOutPoints.size() > 0) diff --git a/src/rpc/fees.cpp b/src/rpc/fees.cpp index aefe78162b..662d24ef81 100644 --- a/src/rpc/fees.cpp +++ b/src/rpc/fees.cpp @@ -36,7 +36,7 @@ static RPCHelpMan estimatesmartfee() "in BIP 141 (witness data is discounted).\n", { {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"}, - {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"conservative"}, "The fee estimate mode.\n" + {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"economical"}, "The fee estimate mode.\n" "Whether to return a more conservative estimate which also satisfies\n" "a longer history. A conservative estimate potentially returns a\n" "higher feerate and is more likely to be sufficient for the desired\n" @@ -71,13 +71,13 @@ static RPCHelpMan estimatesmartfee() CHECK_NONFATAL(mempool.m_opts.signals)->SyncWithValidationInterfaceQueue(); unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target); - bool conservative = true; + bool conservative = false; if (!request.params[1].isNull()) { FeeEstimateMode fee_mode; if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) { throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage()); } - if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false; + if (fee_mode == FeeEstimateMode::CONSERVATIVE) conservative = true; } UniValue result(UniValue::VOBJ); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 8482ce6eb2..d41ec5bdc6 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -345,13 +345,11 @@ static RPCHelpMan generateblock() std::vector<CTransactionRef> txs; const auto raw_txs_or_txids = request.params[1].get_array(); for (size_t i = 0; i < raw_txs_or_txids.size(); i++) { - const auto str(raw_txs_or_txids[i].get_str()); + const auto& str{raw_txs_or_txids[i].get_str()}; - uint256 hash; CMutableTransaction mtx; - if (ParseHashStr(str, hash)) { - - const auto tx = mempool.get(hash); + if (auto hash{uint256::FromHex(str)}) { + const auto tx{mempool.get(*hash)}; if (!tx) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Transaction %s not in mempool.", str)); } diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp index b372f25ea9..470fdde30a 100644 --- a/src/test/blockfilter_tests.cpp +++ b/src/test/blockfilter_tests.cpp @@ -149,8 +149,7 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test) unsigned int pos = 0; /*int block_height =*/ test[pos++].getInt<int>(); - uint256 block_hash; - BOOST_CHECK(ParseHashStr(test[pos++].get_str(), block_hash)); + BOOST_CHECK(uint256::FromHex(test[pos++].get_str())); CBlock block; BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str())); @@ -165,11 +164,9 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test) tx_undo.vprevout.emplace_back(txout, 0, false); } - uint256 prev_filter_header_basic; - BOOST_CHECK(ParseHashStr(test[pos++].get_str(), prev_filter_header_basic)); + uint256 prev_filter_header_basic{*Assert(uint256::FromHex(test[pos++].get_str()))}; std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str()); - uint256 filter_header_basic; - BOOST_CHECK(ParseHashStr(test[pos++].get_str(), filter_header_basic)); + uint256 filter_header_basic{*Assert(uint256::FromHex(test[pos++].get_str()))}; BlockFilter computed_filter_basic(BlockFilterType::BASIC, block, block_undo); BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic); diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 8f3e357a84..41c971c237 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -27,7 +27,6 @@ #include <vector> namespace { -const TestingSetup* g_setup; const Coin EMPTY_COIN{}; bool operator==(const Coin& a, const Coin& b) @@ -39,8 +38,7 @@ bool operator==(const Coin& a, const Coin& b) void initialize_coins_view() { - static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); - g_setup = testing_setup.get(); + static const auto testing_setup = MakeNoLogFileContext<>(); } FUZZ_TARGET(coins_view, .init = initialize_coins_view) diff --git a/src/test/fuzz/hex.cpp b/src/test/fuzz/hex.cpp index f67b820d11..bc46863f1d 100644 --- a/src/test/fuzz/hex.cpp +++ b/src/test/fuzz/hex.cpp @@ -27,8 +27,7 @@ FUZZ_TARGET(hex) assert(ToLower(random_hex_string) == hex_data); } (void)IsHexNumber(random_hex_string); - uint256 result; - (void)ParseHashStr(random_hex_string, result); + (void)uint256::FromHex(random_hex_string); (void)uint256S(random_hex_string); try { (void)HexToPubKey(random_hex_string); diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index 522c9c54ee..60d9d39b73 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -31,7 +31,13 @@ void initialize_chain() FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - std::unique_ptr<const TestingSetup> setup{MakeNoLogFileContext<const TestingSetup>()}; + std::unique_ptr<const TestingSetup> setup{ + MakeNoLogFileContext<const TestingSetup>( + ChainType::REGTEST, + TestOpts{ + .setup_net = false, + .setup_validation_interface = false, + })}; const auto& node = setup->m_node; auto& chainman{*node.chainman}; diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 3a44d1da49..efca540240 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_negative_target) uint256 hash; unsigned int nBits; nBits = UintToArith256(consensus.powLimit).GetCompact(true); - hash.SetHex("0x1"); + hash = uint256{1}; BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus)); } @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_overflow_target) const auto consensus = CreateChainParams(*m_node.args, ChainType::MAIN)->GetConsensus(); uint256 hash; unsigned int nBits{~0x00800000U}; - hash.SetHex("0x1"); + hash = uint256{1}; BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus)); } @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_too_easy_target) arith_uint256 nBits_arith = UintToArith256(consensus.powLimit); nBits_arith *= 2; nBits = nBits_arith.GetCompact(); - hash.SetHex("0x1"); + hash = uint256{1}; BOOST_CHECK(!CheckProofOfWork(hash, nBits, consensus)); } diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 669983c0e9..d280126cde 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -62,7 +62,7 @@ static std::string ArrayToString(const unsigned char A[], unsigned int width) inline uint160 uint160S(std::string_view str) { uint160 rv; - rv.SetHex(str); + rv.SetHexDeprecated(str); return rv; } @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > uint256S("1000000000000000000000000000000000000000000000000000000000000002")); } -BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize +BOOST_AUTO_TEST_CASE(methods) // GetHex SetHexDeprecated FromHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize { BOOST_CHECK_EQUAL(R1L.GetHex(), R1L.ToString()); BOOST_CHECK_EQUAL(R2L.GetHex(), R2L.ToString()); @@ -166,12 +166,12 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G uint256 TmpL(R1L); BOOST_CHECK_EQUAL(TmpL, R1L); // Verify previous values don't persist when setting to truncated string. - TmpL.SetHex("21"); + TmpL.SetHexDeprecated("21"); BOOST_CHECK_EQUAL(TmpL.ToString(), "0000000000000000000000000000000000000000000000000000000000000021"); - TmpL.SetHex(R2L.ToString()); BOOST_CHECK_EQUAL(TmpL, R2L); - TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK_EQUAL(TmpL, uint256()); + BOOST_CHECK_EQUAL(uint256::FromHex(R2L.ToString()).value(), R2L); + BOOST_CHECK_EQUAL(uint256::FromHex(ZeroL.ToString()).value(), uint256()); - TmpL.SetHex(R1L.ToString()); + TmpL = uint256::FromHex(R1L.ToString()).value(); BOOST_CHECK_EQUAL_COLLECTIONS(R1L.begin(), R1L.end(), R1Array, R1Array + R1L.size()); BOOST_CHECK_EQUAL_COLLECTIONS(TmpL.begin(), TmpL.end(), R1Array, R1Array + TmpL.size()); BOOST_CHECK_EQUAL_COLLECTIONS(R2L.begin(), R2L.end(), R2Array, R2Array + R2L.size()); @@ -214,10 +214,10 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK_EQUAL(MaxS.GetHex(), MaxS.ToString()); uint160 TmpS(R1S); BOOST_CHECK_EQUAL(TmpS, R1S); - TmpS.SetHex(R2S.ToString()); BOOST_CHECK_EQUAL(TmpS, R2S); - TmpS.SetHex(ZeroS.ToString()); BOOST_CHECK_EQUAL(TmpS, uint160()); + BOOST_CHECK_EQUAL(uint160::FromHex(R2S.ToString()).value(), R2S); + BOOST_CHECK_EQUAL(uint160::FromHex(ZeroS.ToString()).value(), uint160()); - TmpS.SetHex(R1S.ToString()); + TmpS = uint160::FromHex(R1S.ToString()).value(); BOOST_CHECK_EQUAL_COLLECTIONS(R1S.begin(), R1S.end(), R1Array, R1Array + R1S.size()); BOOST_CHECK_EQUAL_COLLECTIONS(TmpS.begin(), TmpS.end(), R1Array, R1Array + TmpS.size()); BOOST_CHECK_EQUAL_COLLECTIONS(R2S.begin(), R2S.end(), R2Array, R2Array + R2S.size()); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index d0c465d189..abe3d6a505 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -230,9 +230,11 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. - m_node.scheduler = std::make_unique<CScheduler>(); - m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); }); - m_node.validation_signals = std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(*m_node.scheduler)); + if (opts.setup_validation_interface) { + m_node.scheduler = std::make_unique<CScheduler>(); + m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); }); + m_node.validation_signals = std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(*m_node.scheduler)); + } m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES); bilingual_str error{}; @@ -267,7 +269,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, TestOpts opts) ChainTestingSetup::~ChainTestingSetup() { if (m_node.scheduler) m_node.scheduler->stop(); - m_node.validation_signals->FlushBackgroundCallbacks(); + if (m_node.validation_signals) m_node.validation_signals->FlushBackgroundCallbacks(); m_node.connman.reset(); m_node.banman.reset(); m_node.addrman.reset(); @@ -318,6 +320,8 @@ TestingSetup::TestingSetup( LoadVerifyActivateChainstate(); + if (!opts.setup_net) return; + m_node.netgroupman = std::make_unique<NetGroupManager>(/*asmap=*/std::vector<bool>()); m_node.addrman = std::make_unique<AddrMan>(*m_node.netgroupman, /*deterministic=*/false, diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 6d8fcbbbfb..9515f0255e 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -53,6 +53,8 @@ struct TestOpts { std::vector<const char*> extra_args{}; bool coins_db_in_memory{true}; bool block_tree_db_in_memory{true}; + bool setup_net{true}; + bool setup_validation_interface{true}; }; /** Basic testing setup. diff --git a/src/uint256.cpp b/src/uint256.cpp index f15150ca95..2756a7f5cd 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -18,7 +18,7 @@ std::string base_blob<BITS>::GetHex() const } template <unsigned int BITS> -void base_blob<BITS>::SetHex(const std::string_view str) +void base_blob<BITS>::SetHexDeprecated(const std::string_view str) { std::fill(m_data.begin(), m_data.end(), 0); @@ -52,12 +52,12 @@ std::string base_blob<BITS>::ToString() const // Explicit instantiations for base_blob<160> template std::string base_blob<160>::GetHex() const; template std::string base_blob<160>::ToString() const; -template void base_blob<160>::SetHex(std::string_view); +template void base_blob<160>::SetHexDeprecated(std::string_view); // Explicit instantiations for base_blob<256> template std::string base_blob<256>::GetHex() const; template std::string base_blob<256>::ToString() const; -template void base_blob<256>::SetHex(std::string_view); +template void base_blob<256>::SetHexDeprecated(std::string_view); const uint256 uint256::ZERO(0); const uint256 uint256::ONE(1); diff --git a/src/uint256.h b/src/uint256.h index 406a9c7203..f8e78b820f 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -8,12 +8,14 @@ #include <crypto/common.h> #include <span.h> +#include <util/strencodings.h> #include <algorithm> #include <array> #include <cassert> +#include <cstdint> #include <cstring> -#include <stdint.h> +#include <optional> #include <string> /** Template base class for fixed-sized opaque blobs. */ @@ -59,7 +61,8 @@ public: // Hex string representations are little-endian. std::string GetHex() const; - void SetHex(std::string_view str); + /** Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated */ + void SetHexDeprecated(std::string_view str); std::string ToString() const; constexpr const unsigned char* data() const { return m_data.data(); } @@ -88,12 +91,30 @@ public: } }; +namespace detail { +/** + * Writes the hex string (treated as little-endian) into a new uintN_t object + * and only returns a value iff all of the checks pass: + * - Input length is uintN_t::size()*2 + * - All characters are hex + */ +template <class uintN_t> +std::optional<uintN_t> FromHex(std::string_view str) +{ + if (uintN_t::size() * 2 != str.size() || !IsHex(str)) return std::nullopt; + uintN_t rv; + rv.SetHexDeprecated(str); + return rv; +} +} // namespace detail + /** 160-bit opaque blob. * @note This type is called uint160 for historical reasons only. It is an opaque * blob of 160 bits and has no integer operations. */ class uint160 : public base_blob<160> { public: + static std::optional<uint160> FromHex(std::string_view str) { return detail::FromHex<uint160>(str); } constexpr uint160() = default; constexpr explicit uint160(Span<const unsigned char> vch) : base_blob<160>(vch) {} }; @@ -105,6 +126,7 @@ public: */ class uint256 : public base_blob<256> { public: + static std::optional<uint256> FromHex(std::string_view str) { return detail::FromHex<uint256>(str); } constexpr uint256() = default; constexpr explicit uint256(uint8_t v) : base_blob<256>(v) {} constexpr explicit uint256(Span<const unsigned char> vch) : base_blob<256>(vch) {} @@ -113,13 +135,12 @@ public: }; /* uint256 from std::string_view, treated as little-endian. - * This is not a uint256 constructor because of historical fears of uint256(0) - * resolving to a NULL string and crashing. + * DEPRECATED. Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated! */ inline uint256 uint256S(std::string_view str) { uint256 rv; - rv.SetHex(str); + rv.SetHexDeprecated(str); return rv; } diff --git a/src/util/transaction_identifier.h b/src/util/transaction_identifier.h index 1ca48a0454..0e3251f4fc 100644 --- a/src/util/transaction_identifier.h +++ b/src/util/transaction_identifier.h @@ -42,6 +42,12 @@ public: /** Wrapped `uint256` methods. */ constexpr bool IsNull() const { return m_wrapped.IsNull(); } constexpr void SetNull() { m_wrapped.SetNull(); } + static std::optional<transaction_identifier> FromHex(std::string_view hex) + { + auto u{uint256::FromHex(hex)}; + if (!u) return std::nullopt; + return FromUint256(*u); + } std::string GetHex() const { return m_wrapped.GetHex(); } std::string ToString() const { return m_wrapped.ToString(); } static constexpr auto size() { return decltype(m_wrapped)::size(); } @@ -66,6 +72,7 @@ using Txid = transaction_identifier<false>; /** Wtxid commits to all transaction fields including the witness. */ using Wtxid = transaction_identifier<true>; +/** DEPRECATED due to missing length-check and hex-check, please use the safer FromHex, or FromUint256 */ inline Txid TxidFromString(std::string_view str) { return Txid::FromUint256(uint256S(str)); |