aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/qt/bitcoin.cpp3
-rw-r--r--src/qt/guiutil.cpp6
-rw-r--r--src/qt/guiutil.h5
-rw-r--r--src/test/fuzz/addrman.cpp147
-rw-r--r--src/test/script_parse_tests.cpp55
-rw-r--r--src/test/util_tests.cpp12
-rw-r--r--src/util/syscall_sandbox.cpp14
-rw-r--r--src/validation.cpp9
-rw-r--r--src/wallet/coincontrol.h2
-rw-r--r--src/wallet/rpcwallet.cpp6
-rw-r--r--src/wallet/spend.cpp4
12 files changed, 174 insertions, 92 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index be63214c23..d70793ffa9 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -119,8 +119,9 @@ BITCOIN_TESTS =\
test/sanity_tests.cpp \
test/scheduler_tests.cpp \
test/script_p2sh_tests.cpp \
- test/script_tests.cpp \
+ test/script_parse_tests.cpp \
test/script_standard_tests.cpp \
+ test/script_tests.cpp \
test/scriptnum_tests.cpp \
test/serfloat_tests.cpp \
test/serialize_tests.cpp \
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 00c9fd3059..7de56a648a 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -46,7 +46,6 @@
#include <QApplication>
#include <QDebug>
-#include <QFontDatabase>
#include <QLatin1String>
#include <QLibraryInfo>
#include <QLocale>
@@ -492,7 +491,7 @@ int GuiMain(int argc, char* argv[])
#endif
BitcoinApplication app;
- QFontDatabase::addApplicationFont(":/fonts/monospace");
+ GUIUtil::LoadFont(QStringLiteral(":/fonts/monospace"));
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence:
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 7b1384b485..12d3a48d01 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -272,6 +272,12 @@ bool hasEntryData(const QAbstractItemView *view, int column, int role)
return !selection.at(0).data(role).toString().isEmpty();
}
+void LoadFont(const QString& file_name)
+{
+ const int id = QFontDatabase::addApplicationFont(file_name);
+ assert(id != -1);
+}
+
QString getDefaultDataDirectory()
{
return boostPathToQString(GetDefaultDataDir());
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 6287f95192..211f3f506d 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -114,6 +114,11 @@ namespace GUIUtil
void setClipboard(const QString& str);
/**
+ * Loads the font from the file specified by file_name, aborts if it fails.
+ */
+ void LoadFont(const QString& file_name);
+
+ /**
* Determine default data directory for operating system.
*/
QString getDefaultDataDirectory();
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index cfeab9dcdc..8df3707fc9 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -7,6 +7,7 @@
#include <addrman_impl.h>
#include <chainparams.h>
#include <merkleblock.h>
+#include <random.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
@@ -35,92 +36,86 @@ FUZZ_TARGET_INIT(data_stream_addr_man, initialize_addrman)
}
}
-class AddrManDeterministic : public AddrMan
+/**
+ * Generate a random address. Always returns a valid address.
+ */
+CNetAddr RandAddr(FuzzedDataProvider& fuzzed_data_provider, FastRandomContext& fast_random_context)
{
-public:
- FuzzedDataProvider& m_fuzzed_data_provider;
-
- explicit AddrManDeterministic(std::vector<bool> asmap, FuzzedDataProvider& fuzzed_data_provider)
- : AddrMan(std::move(asmap), /* deterministic */ true, /* consistency_check_ratio */ 0)
- , m_fuzzed_data_provider(fuzzed_data_provider)
- {
- WITH_LOCK(m_impl->cs, m_impl->insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
- }
-
- /**
- * Generate a random address. Always returns a valid address.
- */
- CNetAddr RandAddr() EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs)
- {
- CNetAddr addr;
- if (m_fuzzed_data_provider.remaining_bytes() > 1 && m_fuzzed_data_provider.ConsumeBool()) {
- addr = ConsumeNetAddr(m_fuzzed_data_provider);
- } else {
- // The networks [1..6] correspond to CNetAddr::BIP155Network (private).
- static const std::map<uint8_t, uint8_t> net_len_map = {{1, ADDR_IPV4_SIZE},
- {2, ADDR_IPV6_SIZE},
- {4, ADDR_TORV3_SIZE},
- {5, ADDR_I2P_SIZE},
- {6, ADDR_CJDNS_SIZE}};
- uint8_t net = m_impl->insecure_rand.randrange(5) + 1; // [1..5]
- if (net == 3) {
- net = 6;
- }
-
- CDataStream s(SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
-
- s << net;
- s << m_impl->insecure_rand.randbytes(net_len_map.at(net));
-
- s >> addr;
- }
-
- // Return a dummy IPv4 5.5.5.5 if we generated an invalid address.
- if (!addr.IsValid()) {
- in_addr v4_addr = {};
- v4_addr.s_addr = 0x05050505;
- addr = CNetAddr{v4_addr};
+ CNetAddr addr;
+ if (fuzzed_data_provider.remaining_bytes() > 1 && fuzzed_data_provider.ConsumeBool()) {
+ addr = ConsumeNetAddr(fuzzed_data_provider);
+ } else {
+ // The networks [1..6] correspond to CNetAddr::BIP155Network (private).
+ static const std::map<uint8_t, uint8_t> net_len_map = {{1, ADDR_IPV4_SIZE},
+ {2, ADDR_IPV6_SIZE},
+ {4, ADDR_TORV3_SIZE},
+ {5, ADDR_I2P_SIZE},
+ {6, ADDR_CJDNS_SIZE}};
+ uint8_t net = fast_random_context.randrange(5) + 1; // [1..5]
+ if (net == 3) {
+ net = 6;
}
- return addr;
- }
-
- /**
- * Fill this addrman with lots of addresses from lots of sources.
- */
- void Fill()
- {
- LOCK(m_impl->cs);
+ CDataStream s(SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
- // Add some of the addresses directly to the "tried" table.
+ s << net;
+ s << fast_random_context.randbytes(net_len_map.at(net));
- // 0, 1, 2, 3 corresponding to 0%, 100%, 50%, 33%
- const size_t n = m_fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3);
+ s >> addr;
+ }
- const size_t num_sources = m_fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 50);
- CNetAddr prev_source;
- // Use insecure_rand inside the loops instead of m_fuzzed_data_provider because when
- // the latter is exhausted it just returns 0.
- for (size_t i = 0; i < num_sources; ++i) {
- const auto source = RandAddr();
- const size_t num_addresses = m_impl->insecure_rand.randrange(500) + 1; // [1..500]
+ // Return a dummy IPv4 5.5.5.5 if we generated an invalid address.
+ if (!addr.IsValid()) {
+ in_addr v4_addr = {};
+ v4_addr.s_addr = 0x05050505;
+ addr = CNetAddr{v4_addr};
+ }
- for (size_t j = 0; j < num_addresses; ++j) {
- const auto addr = CAddress{CService{RandAddr(), 8333}, NODE_NETWORK};
- const auto time_penalty = m_impl->insecure_rand.randrange(100000001);
- m_impl->Add_(addr, source, time_penalty);
+ return addr;
+}
- if (n > 0 && m_impl->mapInfo.size() % n == 0) {
- m_impl->Good_(addr, false, GetTime());
- }
+/** Fill addrman with lots of addresses from lots of sources. */
+void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
+{
+ // Add a fraction of the addresses to the "tried" table.
+ // 0, 1, 2, 3 corresponding to 0%, 100%, 50%, 33%
+ const size_t n = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3);
+
+ const size_t num_sources = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 50);
+ CNetAddr prev_source;
+ // Generate a FastRandomContext seed to use inside the loops instead of
+ // fuzzed_data_provider. When fuzzed_data_provider is exhausted it
+ // just returns 0.
+ FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
+ for (size_t i = 0; i < num_sources; ++i) {
+ const auto source = RandAddr(fuzzed_data_provider, fast_random_context);
+ const size_t num_addresses = fast_random_context.randrange(500) + 1; // [1..500]
+
+ for (size_t j = 0; j < num_addresses; ++j) {
+ const auto addr = CAddress{CService{RandAddr(fuzzed_data_provider, fast_random_context), 8333}, NODE_NETWORK};
+ const auto time_penalty = fast_random_context.randrange(100000001);
+ addrman.Add({addr}, source, time_penalty);
+
+ if (n > 0 && addrman.size() % n == 0) {
+ addrman.Good(addr, GetTime());
+ }
- // Add 10% of the addresses from more than one source.
- if (m_impl->insecure_rand.randrange(10) == 0 && prev_source.IsValid()) {
- m_impl->Add_({addr}, prev_source, time_penalty);
- }
+ // Add 10% of the addresses from more than one source.
+ if (fast_random_context.randrange(10) == 0 && prev_source.IsValid()) {
+ addrman.Add({addr}, prev_source, time_penalty);
}
- prev_source = source;
}
+ prev_source = source;
+ }
+}
+
+class AddrManDeterministic : public AddrMan
+{
+public:
+ explicit AddrManDeterministic(std::vector<bool> asmap, FuzzedDataProvider& fuzzed_data_provider)
+ : AddrMan(std::move(asmap), /* deterministic */ true, /* consistency_check_ratio */ 0)
+ {
+ WITH_LOCK(m_impl->cs, m_impl->insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
}
/**
@@ -307,7 +302,7 @@ FUZZ_TARGET_INIT(addrman_serdeser, initialize_addrman)
CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
- addr_man1.Fill();
+ FillAddrman(addr_man1, fuzzed_data_provider);
data_stream << addr_man1;
data_stream >> addr_man2;
assert(addr_man1 == addr_man2);
diff --git a/src/test/script_parse_tests.cpp b/src/test/script_parse_tests.cpp
new file mode 100644
index 0000000000..5b8b6a725f
--- /dev/null
+++ b/src/test/script_parse_tests.cpp
@@ -0,0 +1,55 @@
+// Copyright (c) 2021 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <core_io.h>
+#include <script/script.h>
+#include <util/strencodings.h>
+#include <test/util/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(script_parse_tests)
+BOOST_AUTO_TEST_CASE(parse_script)
+{
+ const std::vector<std::pair<std::string,std::string>> IN_OUT{
+ // {IN: script string , OUT: hex string }
+ {"", ""},
+ {"0", "00"},
+ {"1", "51"},
+ {"2", "52"},
+ {"3", "53"},
+ {"4", "54"},
+ {"5", "55"},
+ {"6", "56"},
+ {"7", "57"},
+ {"8", "58"},
+ {"9", "59"},
+ {"10", "5a"},
+ {"11", "5b"},
+ {"12", "5c"},
+ {"13", "5d"},
+ {"14", "5e"},
+ {"15", "5f"},
+ {"16", "60"},
+ {"17", "0111"},
+ {"-9", "0189"},
+ {"0x17", "17"},
+ {"'17'", "023137"},
+ {"ELSE", "67"},
+ {"NOP10", "b9"},
+ {"11111111111111111111", "00"},
+ };
+ std::string all_in;
+ std::string all_out;
+ for (const auto& [in, out] : IN_OUT) {
+ BOOST_CHECK_EQUAL(HexStr(ParseScript(in)), out);
+ all_in += " " + in + " ";
+ all_out += out;
+ }
+ BOOST_CHECK_EQUAL(HexStr(ParseScript(all_in)), all_out);
+
+ BOOST_CHECK_EXCEPTION(ParseScript("11111111111"), std::runtime_error, HasReason("script parse error: decimal numeric value only allowed in the range -0xFFFFFFFF...0xFFFFFFFF"));
+ BOOST_CHECK_EXCEPTION(ParseScript("OP_CHECKSIGADD"), std::runtime_error, HasReason("script parse error: unknown opcode"));
+}
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 51707310a2..b5088d3c33 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1239,6 +1239,11 @@ BOOST_AUTO_TEST_CASE(util_FormatMoney)
BOOST_AUTO_TEST_CASE(util_ParseMoney)
{
BOOST_CHECK_EQUAL(ParseMoney("0.0").value(), 0);
+ BOOST_CHECK_EQUAL(ParseMoney(".").value(), 0);
+ BOOST_CHECK_EQUAL(ParseMoney("0.").value(), 0);
+ BOOST_CHECK_EQUAL(ParseMoney(".0").value(), 0);
+ BOOST_CHECK_EQUAL(ParseMoney(".6789").value(), 6789'0000);
+ BOOST_CHECK_EQUAL(ParseMoney("12345.").value(), COIN * 12345);
BOOST_CHECK_EQUAL(ParseMoney("12345.6789").value(), (COIN/10000)*123456789);
@@ -1276,11 +1281,18 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK(!ParseMoney(" "));
// Parsing two numbers should fail
+ BOOST_CHECK(!ParseMoney(".."));
+ BOOST_CHECK(!ParseMoney("0..0"));
BOOST_CHECK(!ParseMoney("1 2"));
BOOST_CHECK(!ParseMoney(" 1 2 "));
BOOST_CHECK(!ParseMoney(" 1.2 3 "));
BOOST_CHECK(!ParseMoney(" 1 2.3 "));
+ // Embedded whitespace should fail
+ BOOST_CHECK(!ParseMoney(" -1 .2 "));
+ BOOST_CHECK(!ParseMoney(" 1 .2 "));
+ BOOST_CHECK(!ParseMoney(" +1 .2 "));
+
// Attempted 63 bit overflow should fail
BOOST_CHECK(!ParseMoney("92233720368.54775808"));
diff --git a/src/util/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp
index 746feb0835..7e76ecbf3a 100644
--- a/src/util/syscall_sandbox.cpp
+++ b/src/util/syscall_sandbox.cpp
@@ -58,6 +58,10 @@ bool g_syscall_sandbox_log_violation_before_terminating{false};
#define __NR_membarrier 324
#endif
+#ifndef __NR_copy_file_range
+#define __NR_copy_file_range 326
+#endif
+
// This list of syscalls in LINUX_SYSCALLS is only used to map syscall numbers to syscall names in
// order to be able to print user friendly error messages which include the syscall name in addition
// to the syscall number.
@@ -268,15 +272,23 @@ const std::map<uint32_t, std::string> LINUX_SYSCALLS{
{__NR_pipe, "pipe"},
{__NR_pipe2, "pipe2"},
{__NR_pivot_root, "pivot_root"},
+#ifdef __NR_pkey_alloc
{__NR_pkey_alloc, "pkey_alloc"},
+#endif
+#ifdef __NR_pkey_free
{__NR_pkey_free, "pkey_free"},
+#endif
+#ifdef __NR_pkey_mprotect
{__NR_pkey_mprotect, "pkey_mprotect"},
+#endif
{__NR_poll, "poll"},
{__NR_ppoll, "ppoll"},
{__NR_prctl, "prctl"},
{__NR_pread64, "pread64"},
{__NR_preadv, "preadv"},
+#ifdef __NR_preadv2
{__NR_preadv2, "preadv2"},
+#endif
{__NR_prlimit64, "prlimit64"},
{__NR_process_vm_readv, "process_vm_readv"},
{__NR_process_vm_writev, "process_vm_writev"},
@@ -285,7 +297,9 @@ const std::map<uint32_t, std::string> LINUX_SYSCALLS{
{__NR_putpmsg, "putpmsg"},
{__NR_pwrite64, "pwrite64"},
{__NR_pwritev, "pwritev"},
+#ifdef __NR_pwritev2
{__NR_pwritev2, "pwritev2"},
+#endif
{__NR_query_module, "query_module"},
{__NR_quotactl, "quotactl"},
{__NR_read, "read"},
diff --git a/src/validation.cpp b/src/validation.cpp
index 880a01eb7d..14dcd2c24b 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -474,7 +474,6 @@ private:
std::unique_ptr<CTxMemPoolEntry> m_entry;
std::list<CTransactionRef> m_replaced_transactions;
- bool m_replacement_transaction;
CAmount m_base_fees;
CAmount m_modified_fees;
/** Total modified fees of all transactions being replaced. */
@@ -556,7 +555,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
CTxMemPool::setEntries& allConflicting = ws.m_all_conflicting;
CTxMemPool::setEntries& setAncestors = ws.m_ancestors;
std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
- bool& fReplacementTransaction = ws.m_replacement_transaction;
CAmount& nModifiedFees = ws.m_modified_fees;
CAmount& nConflictingFees = ws.m_conflicting_fees;
size_t& nConflictingSize = ws.m_conflicting_size;
@@ -779,8 +777,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
}
- fReplacementTransaction = setConflicts.size();
- if (fReplacementTransaction) {
+ if (!setConflicts.empty()) {
CFeeRate newFeeRate(nModifiedFees, nSize);
// It's possible that the replacement pays more fees than its direct conflicts but not more
// than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
@@ -885,7 +882,6 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
const CAmount& nModifiedFees = ws.m_modified_fees;
const CAmount& nConflictingFees = ws.m_conflicting_fees;
const size_t& nConflictingSize = ws.m_conflicting_size;
- const bool fReplacementTransaction = ws.m_replacement_transaction;
std::unique_ptr<CTxMemPoolEntry>& entry = ws.m_entry;
// Remove conflicting transactions from the mempool
@@ -901,11 +897,10 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
m_pool.RemoveStaged(allConflicting, false, MemPoolRemovalReason::REPLACED);
// This transaction should only count for fee estimation if:
- // - it isn't a BIP 125 replacement transaction (may not be widely supported)
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
// - the node is not behind
// - the transaction is not dependent on any other transactions in the mempool
- bool validForFeeEstimation = !fReplacementTransaction && !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
+ bool validForFeeEstimation = !bypass_limits && IsCurrentForFeeEstimation(m_active_chainstate) && m_pool.HasNoInputsOf(tx);
// Store transaction in memory
m_pool.addUnchecked(*entry, setAncestors, validForFeeEstimation);
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index c989512d3e..edd81e590f 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -93,7 +93,7 @@ public:
setSelected.insert(output);
}
- void Select(const COutPoint& outpoint, const CTxOut& txout)
+ void SelectExternal(const COutPoint& outpoint, const CTxOut& txout)
{
setSelected.insert(outpoint);
m_external_txouts.emplace(outpoint, txout);
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 8ca8f87bca..8b481bc29c 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -3320,7 +3320,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
}
if (options.exists("solving_data")) {
- UniValue solving_data = options["solving_data"].get_obj();
+ const UniValue solving_data = options["solving_data"].get_obj();
if (solving_data.exists("pubkeys")) {
for (const UniValue& pk_univ : solving_data["pubkeys"].get_array().getValues()) {
const std::string& pk_str = pk_univ.get_str();
@@ -3328,7 +3328,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not hex", pk_str));
}
const std::vector<unsigned char> data(ParseHex(pk_str));
- CPubKey pubkey(data.begin(), data.end());
+ const CPubKey pubkey(data.begin(), data.end());
if (!pubkey.IsFullyValid()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not a valid public key", pk_str));
}
@@ -3393,7 +3393,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
wallet.chain().findCoins(coins);
for (const auto& coin : coins) {
if (!coin.second.out.IsNull()) {
- coinControl.Select(coin.first, coin.second.out);
+ coinControl.SelectExternal(coin.first, coin.second.out);
}
}
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 5bed09e067..5470177440 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -475,7 +475,7 @@ bool SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCo
CInputCoin coin(outpoint, txout, input_bytes);
nValueFromPresetInputs += coin.txout.nValue;
- if (coin.m_input_bytes <= 0) {
+ if (coin.m_input_bytes == -1) {
return false; // Not solvable, can't estimate size for fee
}
coin.effective_value = coin.txout.nValue - coin_selection_params.m_effective_feerate.GetFee(coin.m_input_bytes);
@@ -814,7 +814,7 @@ static bool CreateTransactionInternal(
// Calculate the transaction fee
TxSize tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control);
int nBytes = tx_sizes.vsize;
- if (nBytes < 0) {
+ if (nBytes == -1) {
error = _("Missing solving data for estimating transaction size");
return false;
}