mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge pull request #4432 from PastaPastaPasta/backport-trivial-pr18
Backport trivial pr18
This commit is contained in:
commit
8491e925d9
@ -732,8 +732,6 @@ if test x$ac_cv_sys_large_files != x &&
|
||||
CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
|
||||
fi
|
||||
|
||||
AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"])
|
||||
|
||||
AX_GCC_FUNC_ATTRIBUTE([visibility])
|
||||
AX_GCC_FUNC_ATTRIBUTE([dllexport])
|
||||
AX_GCC_FUNC_ATTRIBUTE([dllimport])
|
||||
@ -814,10 +812,13 @@ if test x$use_hardening != xno; then
|
||||
esac
|
||||
fi
|
||||
|
||||
dnl this flag screws up non-darwin gcc even when the check fails. special-case it.
|
||||
dnl These flags are specific to ld64, and may cause issues with other linkers.
|
||||
dnl For example: GNU ld will intepret -dead_strip as -de and then try and use
|
||||
dnl "ad_strip" as the symbol for the entry point.
|
||||
if test x$TARGET_OS = xdarwin; then
|
||||
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,-dead_strip_dylibs]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip_dylibs"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,-bind_at_load]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-bind_at_load"])
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h])
|
||||
|
@ -47,7 +47,8 @@ MAX_VERSIONS = {
|
||||
|
||||
# Ignore symbols that are exported as part of every executable
|
||||
IGNORE_EXPORTS = {
|
||||
'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr'
|
||||
'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr',
|
||||
'environ', '_environ', '__environ',
|
||||
}
|
||||
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
|
||||
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
|
||||
|
@ -43,7 +43,7 @@ script: |
|
||||
FAKETIME_PROGS="date ar ranlib nm"
|
||||
HOST_CFLAGS="-O2 -g"
|
||||
HOST_CXXFLAGS="-O2 -g"
|
||||
HOST_LDFLAGS=-static-libstdc++
|
||||
HOST_LDFLAGS_BASE="-static-libstdc++"
|
||||
|
||||
export QT_RCC_TEST=1
|
||||
export QT_RCC_SOURCE_DATE_OVERRIDE=1
|
||||
@ -182,6 +182,13 @@ script: |
|
||||
# Extract the release tarball into a dir for each host and build
|
||||
for i in ${HOSTS}; do
|
||||
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
|
||||
if [ "${i}" = "riscv64-linux-gnu" ]; then
|
||||
# Workaround for https://bugs.launchpad.net/ubuntu/+source/gcc-8-cross-ports/+bug/1853740
|
||||
# TODO: remove this when no longer needed
|
||||
HOST_LDFLAGS="${HOST_LDFLAGS_BASE} -Wl,-z,noexecstack"
|
||||
else
|
||||
HOST_LDFLAGS="${HOST_LDFLAGS_BASE}"
|
||||
fi
|
||||
mkdir -p distsrc-${i}
|
||||
cd distsrc-${i}
|
||||
INSTALLPATH="${PWD}/installed/${DISTNAME}"
|
||||
|
@ -36,6 +36,6 @@ script: |
|
||||
make
|
||||
find ${UNSIGNED_DIR} -name "*-unsigned.exe" | while read i; do
|
||||
INFILE="$(basename "${i}")"
|
||||
OUTFILE="${INFILE/%-unsigned}"
|
||||
OUTFILE="${INFILE/-unsigned}"
|
||||
./osslsigncode attach-signature -in "${i}" -out "${OUTDIR}/${OUTFILE}" -sigin "${SIGDIR}/${INFILE}.pem"
|
||||
done
|
||||
|
@ -40,7 +40,7 @@ Import trusted keys
|
||||
In order to check the commit signatures, you must add the trusted PGP keys to your machine. [GnuPG](https://gnupg.org/) may be used to import the trusted keys by running the following command:
|
||||
|
||||
```sh
|
||||
gpg --recv-keys $(<contrib/verify-commits/trusted-keys)
|
||||
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys $(<contrib/verify-commits/trusted-keys)
|
||||
```
|
||||
|
||||
Key expiry/revocation
|
||||
|
@ -42,7 +42,9 @@ FUZZ_TARGETS = \
|
||||
test/fuzz/service_deserialize \
|
||||
test/fuzz/sub_net_deserialize \
|
||||
test/fuzz/transaction \
|
||||
test/fuzz/tx_in \
|
||||
test/fuzz/tx_in_deserialize \
|
||||
test/fuzz/tx_out \
|
||||
test/fuzz/txoutcompressor_deserialize \
|
||||
test/fuzz/txundo_deserialize
|
||||
|
||||
@ -466,6 +468,18 @@ test_fuzz_tx_in_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_fuzz_tx_in_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(LDFLAGS_WRAP_EXCEPTIONS)
|
||||
test_fuzz_tx_in_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||
|
||||
test_fuzz_tx_in_SOURCES = $(FUZZ_SUITE) test/fuzz/tx_in.cpp
|
||||
test_fuzz_tx_in_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
test_fuzz_tx_in_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_fuzz_tx_in_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
test_fuzz_tx_in_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||
|
||||
test_fuzz_tx_out_SOURCES = $(FUZZ_SUITE) test/fuzz/tx_out.cpp
|
||||
test_fuzz_tx_out_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
test_fuzz_tx_out_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_fuzz_tx_out_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
test_fuzz_tx_out_LDADD = $(FUZZ_SUITE_LD_COMMON)
|
||||
|
||||
endif # ENABLE_FUZZ
|
||||
|
||||
nodist_test_test_dash_SOURCES = $(GENERATED_TEST_FILES)
|
||||
|
@ -92,8 +92,7 @@ private:
|
||||
nTotal--;
|
||||
bool fRet = fAllOk;
|
||||
// reset the status for new work later
|
||||
if (fMaster)
|
||||
fAllOk = true;
|
||||
fAllOk = true;
|
||||
// return the current status
|
||||
return fRet;
|
||||
}
|
||||
|
@ -76,8 +76,21 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
|
||||
}
|
||||
if (!possible_overwrite) {
|
||||
if (!it->second.coin.IsSpent()) {
|
||||
throw std::logic_error("Adding new coin that replaces non-pruned entry");
|
||||
throw std::logic_error("Attempted to overwrite an unspent coin (when possible_overwrite is false)");
|
||||
}
|
||||
// If the coin exists in this cache as a spent coin and is DIRTY, then
|
||||
// its spentness hasn't been flushed to the parent cache. We're
|
||||
// re-adding the coin to this cache now but we can't mark it as FRESH.
|
||||
// If we mark it FRESH and then spend it before the cache is flushed
|
||||
// we would remove it from this cache and would never flush spentness
|
||||
// to the parent cache.
|
||||
//
|
||||
// Re-adding a spent coin can happen in the case of a re-org (the coin
|
||||
// is 'spent' when the block adding it is disconnected and then
|
||||
// re-added when it is also added in a newly connected block).
|
||||
//
|
||||
// If the coin doesn't exist in the current cache, or is spent but not
|
||||
// DIRTY, then it can be marked FRESH.
|
||||
fresh = !(it->second.flags & CCoinsCacheEntry::DIRTY);
|
||||
}
|
||||
it->second.coin = std::move(coin);
|
||||
@ -85,12 +98,12 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
|
||||
cachedCoinsUsage += it->second.coin.DynamicMemoryUsage();
|
||||
}
|
||||
|
||||
void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check) {
|
||||
void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight, bool check_for_overwrite) {
|
||||
bool fCoinbase = tx.IsCoinBase();
|
||||
const uint256& txid = tx.GetHash();
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i) {
|
||||
bool overwrite = check ? cache.HaveCoin(COutPoint(txid, i)) : fCoinbase;
|
||||
// Always set the possible_overwrite flag to AddCoin for coinbase txn, in order to correctly
|
||||
bool overwrite = check_for_overwrite ? cache.HaveCoin(COutPoint(txid, i)) : fCoinbase;
|
||||
// Coinbase transactions can always be overwritten, in order to correctly
|
||||
// deal with the pre-BIP30 occurrences of duplicate coinbase transactions.
|
||||
cache.AddCoin(COutPoint(txid, i), Coin(tx.vout[i], nHeight, fCoinbase), overwrite);
|
||||
}
|
||||
@ -151,11 +164,11 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
|
||||
}
|
||||
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
|
||||
if (itUs == cacheCoins.end()) {
|
||||
// The parent cache does not have an entry, while the child does
|
||||
// We can ignore it if it's both FRESH and pruned in the child
|
||||
// The parent cache does not have an entry, while the child cache does.
|
||||
// We can ignore it if it's both spent and FRESH in the child
|
||||
if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coin.IsSpent())) {
|
||||
// Otherwise we will need to create it in the parent
|
||||
// and move the data up and mark it as dirty
|
||||
// Create the coin in the parent cache, move the data up
|
||||
// and mark it as dirty.
|
||||
CCoinsCacheEntry& entry = cacheCoins[it->first];
|
||||
entry.coin = std::move(it->second.coin);
|
||||
cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
|
||||
@ -168,19 +181,18 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Assert that the child cache entry was not marked FRESH if the
|
||||
// parent cache entry has unspent outputs. If this ever happens,
|
||||
// it means the FRESH flag was misapplied and there is a logic
|
||||
// error in the calling code.
|
||||
// Found the entry in the parent cache
|
||||
if ((it->second.flags & CCoinsCacheEntry::FRESH) && !itUs->second.coin.IsSpent()) {
|
||||
throw std::logic_error("FRESH flag misapplied to cache entry for base transaction with spendable outputs");
|
||||
// The coin was marked FRESH in the child cache, but the coin
|
||||
// exists in the parent cache. If this ever happens, it means
|
||||
// the FRESH flag was misapplied and there is a logic error in
|
||||
// the calling code.
|
||||
throw std::logic_error("FRESH flag misapplied to coin that exists in parent cache");
|
||||
}
|
||||
|
||||
// Found the entry in the parent cache
|
||||
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coin.IsSpent()) {
|
||||
// The grandparent does not have an entry, and the child is
|
||||
// modified and being pruned. This means we can just delete
|
||||
// it from the parent.
|
||||
// The grandparent cache does not have an entry, and the coin
|
||||
// has been spent. We can just delete it from the parent cache.
|
||||
cachedCoinsUsage -= itUs->second.coin.DynamicMemoryUsage();
|
||||
cacheCoins.erase(itUs);
|
||||
} else {
|
||||
@ -189,11 +201,10 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
|
||||
itUs->second.coin = std::move(it->second.coin);
|
||||
cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
|
||||
itUs->second.flags |= CCoinsCacheEntry::DIRTY;
|
||||
// NOTE: It is possible the child has a FRESH flag here in
|
||||
// the event the entry we found in the parent is pruned. But
|
||||
// we must not copy that FRESH flag to the parent as that
|
||||
// pruned state likely still needs to be communicated to the
|
||||
// grandparent.
|
||||
// NOTE: It isn't safe to mark the coin as FRESH in the parent
|
||||
// cache. If it already existed and was spent in the parent
|
||||
// cache then marking it FRESH would prevent that spentness
|
||||
// from being flushed to the grandparent.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
src/coins.h
46
src/coins.h
@ -111,19 +111,45 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A Coin in one level of the coins database caching hierarchy.
|
||||
*
|
||||
* A coin can either be:
|
||||
* - unspent or spent (in which case the Coin object will be nulled out - see Coin.Clear())
|
||||
* - DIRTY or not DIRTY
|
||||
* - FRESH or not FRESH
|
||||
*
|
||||
* Out of these 2^3 = 8 states, only some combinations are valid:
|
||||
* - unspent, FRESH, DIRTY (e.g. a new coin created in the cache)
|
||||
* - unspent, not FRESH, DIRTY (e.g. a coin changed in the cache during a reorg)
|
||||
* - unspent, not FRESH, not DIRTY (e.g. an unspent coin fetched from the parent cache)
|
||||
* - spent, FRESH, not DIRTY (e.g. a spent coin fetched from the parent cache)
|
||||
* - spent, not FRESH, DIRTY (e.g. a coin is spent and spentness needs to be flushed to the parent)
|
||||
*/
|
||||
struct CCoinsCacheEntry
|
||||
{
|
||||
Coin coin; // The actual cached data.
|
||||
unsigned char flags;
|
||||
|
||||
enum Flags {
|
||||
DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
|
||||
FRESH = (1 << 1), // The parent view does not have this entry (or it is pruned).
|
||||
/* Note that FRESH is a performance optimization with which we can
|
||||
* erase coins that are fully spent if we know we do not need to
|
||||
* flush the changes to the parent cache. It is always safe to
|
||||
* not mark FRESH if that condition is not guaranteed.
|
||||
/**
|
||||
* DIRTY means the CCoinsCacheEntry is potentially different from the
|
||||
* version in the parent cache. Failure to mark a coin as DIRTY when
|
||||
* it is potentially different from the parent cache will cause a
|
||||
* consensus failure, since the coin's state won't get written to the
|
||||
* parent when the cache is flushed.
|
||||
*/
|
||||
DIRTY = (1 << 0),
|
||||
/**
|
||||
* FRESH means the parent cache does not have this coin or that it is a
|
||||
* spent coin in the parent cache. If a FRESH coin in the cache is
|
||||
* later spent, it can be deleted entirely and doesn't ever need to be
|
||||
* flushed to the parent. This is a performance optimization. Marking a
|
||||
* coin as FRESH when it exists unspent in the parent cache will cause a
|
||||
* consensus failure, since it might not be deleted from the parent
|
||||
* when this cache is flushed.
|
||||
*/
|
||||
FRESH = (1 << 1),
|
||||
};
|
||||
|
||||
CCoinsCacheEntry() : flags(0) {}
|
||||
@ -248,7 +274,7 @@ public:
|
||||
bool HaveCoinInCache(const COutPoint &outpoint) const;
|
||||
|
||||
/**
|
||||
* Return a reference to Coin in the cache, or a pruned one if not found. This is
|
||||
* Return a reference to Coin in the cache, or coinEmpty if not found. This is
|
||||
* more efficient than GetCoin.
|
||||
*
|
||||
* Generally, do not hold the reference returned for more than a short scope.
|
||||
@ -260,10 +286,10 @@ public:
|
||||
const Coin& AccessCoin(const COutPoint &output) const;
|
||||
|
||||
/**
|
||||
* Add a coin. Set potential_overwrite to true if a non-pruned version may
|
||||
* already exist.
|
||||
* Add a coin. Set possible_overwrite to true if an unspent version may
|
||||
* already exist in the cache.
|
||||
*/
|
||||
void AddCoin(const COutPoint& outpoint, Coin&& coin, bool potential_overwrite);
|
||||
void AddCoin(const COutPoint& outpoint, Coin&& coin, bool possible_overwrite);
|
||||
|
||||
/**
|
||||
* Spend a coin. Pass moveto in order to get the deleted data.
|
||||
|
@ -520,7 +520,7 @@ void BitcoinGUI::createMenuBar()
|
||||
QAction* minimize_action = window_menu->addAction(tr("Minimize"));
|
||||
minimize_action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
|
||||
connect(minimize_action, &QAction::triggered, [] {
|
||||
qApp->focusWindow()->showMinimized();
|
||||
QApplication::activeWindow()->showMinimized();
|
||||
});
|
||||
connect(qApp, &QApplication::focusWindowChanged, [minimize_action] (QWindow* window) {
|
||||
minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
|
||||
|
@ -263,8 +263,9 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, int heig
|
||||
clientmodel->cachedBestHeaderHeight = height;
|
||||
clientmodel->cachedBestHeaderTime = blockTime;
|
||||
}
|
||||
// if we are in-sync or if we notify a header update, update the UI regardless of last update time
|
||||
if (fHeader || !initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
|
||||
|
||||
// During initial sync, block notifications, and header notifications from reindexing are both throttled.
|
||||
if (!initialSync || (fHeader && !clientmodel->node().getReindex()) || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
|
||||
//pass an async signal to the UI thread
|
||||
QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
|
||||
Q_ARG(int, height),
|
||||
|
@ -1059,12 +1059,8 @@ void RPCConsole::on_lineEdit_returnPressed()
|
||||
|
||||
cmdBeforeBrowsing = QString();
|
||||
|
||||
WalletModel* wallet_model{nullptr};
|
||||
#ifdef ENABLE_WALLET
|
||||
const int wallet_index = ui->WalletSelector->currentIndex();
|
||||
if (wallet_index > 0) {
|
||||
wallet_model = ui->WalletSelector->itemData(wallet_index).value<WalletModel*>();
|
||||
}
|
||||
WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
|
||||
|
||||
if (m_last_wallet_model != wallet_model) {
|
||||
if (wallet_model) {
|
||||
|
@ -23,6 +23,17 @@ BOOST_AUTO_TEST_CASE(base32_testvectors)
|
||||
std::string strDec = DecodeBase32(vstrOut[i]);
|
||||
BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
|
||||
}
|
||||
|
||||
// Decoding strings with embedded NUL characters should fail
|
||||
bool failure;
|
||||
(void)DecodeBase32(std::string("invalid", 7), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, true);
|
||||
(void)DecodeBase32(std::string("AWSX3VPP", 8), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, false);
|
||||
(void)DecodeBase32(std::string("AWSX3VPP\0invalid", 16), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, true);
|
||||
(void)DecodeBase32(std::string("AWSX3VPPinvalid", 15), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -20,6 +20,17 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
|
||||
std::string strDec = DecodeBase64(strEnc);
|
||||
BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
|
||||
}
|
||||
|
||||
// Decoding strings with embedded NUL characters should fail
|
||||
bool failure;
|
||||
(void)DecodeBase64(std::string("invalid", 7), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, true);
|
||||
(void)DecodeBase64(std::string("nQB/pZw=", 8), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, false);
|
||||
(void)DecodeBase64(std::string("nQB/pZw=\0invalid", 16), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, true);
|
||||
(void)DecodeBase64(std::string("nQB/pZw=invalid", 15), &failure);
|
||||
BOOST_CHECK_EQUAL(failure, true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -532,7 +532,7 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization)
|
||||
}
|
||||
|
||||
const static COutPoint OUTPOINT;
|
||||
const static CAmount PRUNED = -1;
|
||||
const static CAmount SPENT = -1;
|
||||
const static CAmount ABSENT = -2;
|
||||
const static CAmount FAIL = -3;
|
||||
const static CAmount VALUE1 = 100;
|
||||
@ -551,7 +551,7 @@ static void SetCoinsValue(CAmount value, Coin& coin)
|
||||
assert(value != ABSENT);
|
||||
coin.Clear();
|
||||
assert(coin.IsSpent());
|
||||
if (value != PRUNED) {
|
||||
if (value != SPENT) {
|
||||
coin.out.nValue = value;
|
||||
coin.nHeight = 1;
|
||||
assert(!coin.IsSpent());
|
||||
@ -581,7 +581,7 @@ void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags)
|
||||
flags = NO_ENTRY;
|
||||
} else {
|
||||
if (it->second.coin.IsSpent()) {
|
||||
value = PRUNED;
|
||||
value = SPENT;
|
||||
} else {
|
||||
value = it->second.coin.out.nValue;
|
||||
}
|
||||
@ -634,28 +634,28 @@ BOOST_AUTO_TEST_CASE(ccoins_access)
|
||||
* Value Value Value Flags Flags
|
||||
*/
|
||||
CheckAccessCoin(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckAccessCoin(ABSENT, PRUNED, PRUNED, 0 , 0 );
|
||||
CheckAccessCoin(ABSENT, PRUNED, PRUNED, FRESH , FRESH );
|
||||
CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(ABSENT, SPENT , SPENT , 0 , 0 );
|
||||
CheckAccessCoin(ABSENT, SPENT , SPENT , FRESH , FRESH );
|
||||
CheckAccessCoin(ABSENT, SPENT , SPENT , DIRTY , DIRTY );
|
||||
CheckAccessCoin(ABSENT, SPENT , SPENT , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(ABSENT, VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 );
|
||||
CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH );
|
||||
CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(PRUNED, VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoin(PRUNED, VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(SPENT , ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckAccessCoin(SPENT , SPENT , SPENT , 0 , 0 );
|
||||
CheckAccessCoin(SPENT , SPENT , SPENT , FRESH , FRESH );
|
||||
CheckAccessCoin(SPENT , SPENT , SPENT , DIRTY , DIRTY );
|
||||
CheckAccessCoin(SPENT , SPENT , SPENT , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(SPENT , VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoin(SPENT , VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoin(SPENT , VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
CheckAccessCoin(SPENT , VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(VALUE1, ABSENT, VALUE1, NO_ENTRY , 0 );
|
||||
CheckAccessCoin(VALUE1, PRUNED, PRUNED, 0 , 0 );
|
||||
CheckAccessCoin(VALUE1, PRUNED, PRUNED, FRESH , FRESH );
|
||||
CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(VALUE1, SPENT , SPENT , 0 , 0 );
|
||||
CheckAccessCoin(VALUE1, SPENT , SPENT , FRESH , FRESH );
|
||||
CheckAccessCoin(VALUE1, SPENT , SPENT , DIRTY , DIRTY );
|
||||
CheckAccessCoin(VALUE1, SPENT , SPENT , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckAccessCoin(VALUE1, VALUE2, VALUE2, 0 , 0 );
|
||||
CheckAccessCoin(VALUE1, VALUE2, VALUE2, FRESH , FRESH );
|
||||
CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY );
|
||||
@ -685,31 +685,31 @@ BOOST_AUTO_TEST_CASE(ccoins_spend)
|
||||
* Value Value Value Flags Flags
|
||||
*/
|
||||
CheckSpendCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckSpendCoins(ABSENT, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckSpendCoins(ABSENT, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(ABSENT, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(ABSENT, VALUE2, PRUNED, 0 , DIRTY );
|
||||
CheckSpendCoins(ABSENT, SPENT , SPENT , 0 , DIRTY );
|
||||
CheckSpendCoins(ABSENT, SPENT , ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(ABSENT, SPENT , SPENT , DIRTY , DIRTY );
|
||||
CheckSpendCoins(ABSENT, SPENT , ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(ABSENT, VALUE2, SPENT , 0 , DIRTY );
|
||||
CheckSpendCoins(ABSENT, VALUE2, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(ABSENT, VALUE2, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(ABSENT, VALUE2, SPENT , DIRTY , DIRTY );
|
||||
CheckSpendCoins(ABSENT, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckSpendCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckSpendCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(PRUNED, VALUE2, PRUNED, 0 , DIRTY );
|
||||
CheckSpendCoins(PRUNED, VALUE2, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(PRUNED, VALUE2, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(PRUNED, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, ABSENT, PRUNED, NO_ENTRY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY );
|
||||
CheckSpendCoins(VALUE1, PRUNED, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, PRUNED, 0 , DIRTY );
|
||||
CheckSpendCoins(SPENT , ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
|
||||
CheckSpendCoins(SPENT , SPENT , SPENT , 0 , DIRTY );
|
||||
CheckSpendCoins(SPENT , SPENT , ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(SPENT , SPENT , SPENT , DIRTY , DIRTY );
|
||||
CheckSpendCoins(SPENT , SPENT , ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(SPENT , VALUE2, SPENT , 0 , DIRTY );
|
||||
CheckSpendCoins(SPENT , VALUE2, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(SPENT , VALUE2, SPENT , DIRTY , DIRTY );
|
||||
CheckSpendCoins(SPENT , VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, ABSENT, SPENT , NO_ENTRY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, SPENT , SPENT , 0 , DIRTY );
|
||||
CheckSpendCoins(VALUE1, SPENT , ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, SPENT , SPENT , DIRTY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, SPENT , ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, SPENT , 0 , DIRTY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, ABSENT, FRESH , NO_ENTRY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, SPENT , DIRTY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
}
|
||||
|
||||
@ -742,7 +742,7 @@ static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount mo
|
||||
template <typename... Args>
|
||||
static void CheckAddCoin(Args&&... args)
|
||||
{
|
||||
for (const CAmount base_value : {ABSENT, PRUNED, VALUE1})
|
||||
for (const CAmount base_value : {ABSENT, SPENT, VALUE1})
|
||||
CheckAddCoinBase(base_value, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@ -751,21 +751,21 @@ BOOST_AUTO_TEST_CASE(ccoins_add)
|
||||
/* Check AddCoin behavior, requesting a new coin from a cache view,
|
||||
* writing a modification to the coin, and then checking the resulting
|
||||
* entry in the cache after the modification. Verify behavior with the
|
||||
* with the AddCoin potential_overwrite argument set to false, and to true.
|
||||
* AddCoin possible_overwrite argument set to false, and to true.
|
||||
*
|
||||
* Cache Write Result Cache Result potential_overwrite
|
||||
* Cache Write Result Cache Result possible_overwrite
|
||||
* Value Value Value Flags Flags
|
||||
*/
|
||||
CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false);
|
||||
CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY , DIRTY , false);
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY , DIRTY , true );
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
|
||||
CheckAddCoin(SPENT , VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
|
||||
CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false);
|
||||
CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false);
|
||||
@ -805,42 +805,42 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
|
||||
* Value Value Value Flags Flags Flags
|
||||
*/
|
||||
CheckWriteCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY , NO_ENTRY );
|
||||
CheckWriteCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(ABSENT, SPENT , SPENT , NO_ENTRY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(ABSENT, SPENT , ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, 0 , NO_ENTRY , 0 );
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, FRESH , NO_ENTRY , FRESH );
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY , NO_ENTRY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(SPENT , ABSENT, SPENT , 0 , NO_ENTRY , 0 );
|
||||
CheckWriteCoins(SPENT , ABSENT, SPENT , FRESH , NO_ENTRY , FRESH );
|
||||
CheckWriteCoins(SPENT , ABSENT, SPENT , DIRTY , NO_ENTRY , DIRTY );
|
||||
CheckWriteCoins(SPENT , ABSENT, SPENT , DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckWriteCoins(SPENT , SPENT , SPENT , 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(SPENT , SPENT , SPENT , 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(SPENT , SPENT , ABSENT, FRESH , DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(SPENT , SPENT , ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(SPENT , SPENT , SPENT , DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(SPENT , SPENT , SPENT , DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(SPENT , SPENT , ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(SPENT , SPENT , ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
|
||||
CheckWriteCoins(SPENT , VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, 0 , NO_ENTRY , 0 );
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, FRESH , NO_ENTRY , FRESH );
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY , NO_ENTRY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
|
||||
CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, SPENT , SPENT , 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, SPENT , FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, SPENT , ABSENT, FRESH , DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, SPENT , FAIL , FRESH , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, SPENT , SPENT , DIRTY , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, SPENT , FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, SPENT , ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, SPENT , FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
|
||||
CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
|
||||
@ -854,8 +854,8 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
|
||||
// they would be too repetitive (the parent cache is never updated in these
|
||||
// cases). The loop below covers these cases and makes sure the parent cache
|
||||
// is always left unchanged.
|
||||
for (const CAmount parent_value : {ABSENT, PRUNED, VALUE1})
|
||||
for (const CAmount child_value : {ABSENT, PRUNED, VALUE2})
|
||||
for (const CAmount parent_value : {ABSENT, SPENT, VALUE1})
|
||||
for (const CAmount child_value : {ABSENT, SPENT, VALUE2})
|
||||
for (const char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS)
|
||||
for (const char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS)
|
||||
CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags);
|
||||
|
33
src/test/fuzz/tx_in.cpp
Normal file
33
src/test/fuzz/tx_in.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2019 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 <consensus/validation.h>
|
||||
#include <core_memusage.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <streams.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||
{
|
||||
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
|
||||
CTxIn tx_in;
|
||||
try {
|
||||
int version;
|
||||
ds >> version;
|
||||
ds.SetVersion(version);
|
||||
ds >> tx_in;
|
||||
} catch (const std::ios_base::failure&) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)GetTransactionInputWeight(tx_in);
|
||||
(void)GetVirtualTransactionInputSize(tx_in);
|
||||
(void)RecursiveDynamicUsage(tx_in);
|
||||
|
||||
(void)tx_in.ToString();
|
||||
}
|
35
src/test/fuzz/tx_out.cpp
Normal file
35
src/test/fuzz/tx_out.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2019 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 <consensus/validation.h>
|
||||
#include <core_memusage.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <streams.h>
|
||||
#include <test/fuzz/fuzz.h>
|
||||
#include <version.h>
|
||||
|
||||
void test_one_input(const std::vector<uint8_t>& buffer)
|
||||
{
|
||||
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
|
||||
CTxOut tx_out;
|
||||
try {
|
||||
int version;
|
||||
ds >> version;
|
||||
ds.SetVersion(version);
|
||||
ds >> tx_out;
|
||||
} catch (const std::ios_base::failure&) {
|
||||
return;
|
||||
}
|
||||
|
||||
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
||||
(void)GetDustThreshold(tx_out, dust_relay_fee);
|
||||
(void)IsDust(tx_out, dust_relay_fee);
|
||||
(void)RecursiveDynamicUsage(tx_out);
|
||||
|
||||
(void)tx_out.ToString();
|
||||
(void)tx_out.IsNull();
|
||||
tx_out.SetNull();
|
||||
assert(tx_out.IsNull());
|
||||
}
|
@ -640,6 +640,11 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
|
||||
|
||||
// Parsing negative amounts must fail
|
||||
BOOST_CHECK(!ParseMoney("-1", ret));
|
||||
|
||||
// Parsing strings with embedded NUL characters should fail
|
||||
BOOST_CHECK(!ParseMoney(std::string("\0-1", 3), ret));
|
||||
BOOST_CHECK(!ParseMoney(std::string("\01", 2), ret));
|
||||
BOOST_CHECK(!ParseMoney(std::string("1\0", 2), ret));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_IsHex)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <primitives/transaction.h>
|
||||
#include <tinyformat.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/string.h>
|
||||
|
||||
std::string FormatMoney(const CAmount& n)
|
||||
{
|
||||
@ -33,6 +34,9 @@ std::string FormatMoney(const CAmount& n)
|
||||
|
||||
bool ParseMoney(const std::string& str, CAmount& nRet)
|
||||
{
|
||||
if (!ValidAsCString(str)) {
|
||||
return false;
|
||||
}
|
||||
return ParseMoney(str.c_str(), nRet);
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,12 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pf_invalid)
|
||||
|
||||
std::string DecodeBase64(const std::string& str, bool* pf_invalid)
|
||||
{
|
||||
if (!ValidAsCString(str)) {
|
||||
if (pf_invalid) {
|
||||
*pf_invalid = true;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
std::vector<unsigned char> vchRet = DecodeBase64(str.c_str(), pf_invalid);
|
||||
return std::string((const char*)vchRet.data(), vchRet.size());
|
||||
}
|
||||
@ -264,6 +270,12 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pf_invalid)
|
||||
|
||||
std::string DecodeBase32(const std::string& str, bool* pf_invalid)
|
||||
{
|
||||
if (!ValidAsCString(str)) {
|
||||
if (pf_invalid) {
|
||||
*pf_invalid = true;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
std::vector<unsigned char> vchRet = DecodeBase32(str.c_str(), pf_invalid);
|
||||
return std::string((const char*)vchRet.data(), vchRet.size());
|
||||
}
|
||||
|
@ -1159,17 +1159,19 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
|
||||
SetEndOfFile(hFile);
|
||||
#elif defined(MAC_OSX)
|
||||
// OSX specific version
|
||||
// NOTE: Contrary to other OS versions, the OSX version assumes that
|
||||
// NOTE: offset is the size of the file.
|
||||
fstore_t fst;
|
||||
fst.fst_flags = F_ALLOCATECONTIG;
|
||||
fst.fst_posmode = F_PEOFPOSMODE;
|
||||
fst.fst_offset = 0;
|
||||
fst.fst_length = (off_t)offset + length;
|
||||
fst.fst_length = length; // mac os fst_length takes the # of free bytes to allocate, not desired file size
|
||||
fst.fst_bytesalloc = 0;
|
||||
if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
|
||||
fst.fst_flags = F_ALLOCATEALL;
|
||||
fcntl(fileno(file), F_PREALLOCATE, &fst);
|
||||
}
|
||||
ftruncate(fileno(file), fst.fst_length);
|
||||
ftruncate(fileno(file), static_cast<off_t>(offset) + length);
|
||||
#else
|
||||
#if defined(__linux__)
|
||||
// Version using posix_fallocate
|
||||
|
@ -1655,10 +1655,11 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
|
||||
return DISCONNECT_FAILED; // adding output for transaction without known metadata
|
||||
}
|
||||
}
|
||||
// The potential_overwrite parameter to AddCoin is only allowed to be false if we know for
|
||||
// sure that the coin did not already exist in the cache. As we have queried for that above
|
||||
// using HaveCoin, we don't need to guess. When fClean is false, a coin already existed and
|
||||
// it is an overwrite.
|
||||
// If the coin already exists as an unspent coin in the cache, then the
|
||||
// possible_overwrite parameter to AddCoin must be set to true. We have
|
||||
// already checked whether an unspent coin exists above using HaveCoin, so
|
||||
// we don't need to guess. When fClean is false, an unspent coin already
|
||||
// existed and it is an overwrite.
|
||||
view.AddCoin(out, std::move(undo), !fClean);
|
||||
|
||||
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
|
||||
|
@ -110,6 +110,9 @@ bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& target_v
|
||||
best_selection = curr_selection;
|
||||
best_selection.resize(utxo_pool.size());
|
||||
best_waste = curr_waste;
|
||||
if (best_waste == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
curr_waste -= (curr_value - actual_target); // Remove the excess value as we will be selecting different coins now
|
||||
backtrack = true;
|
||||
|
@ -164,8 +164,8 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
|
||||
selection.clear();
|
||||
|
||||
// Select 5 Cent
|
||||
add_coin(3 * CENT, 3, actual_selection);
|
||||
add_coin(2 * CENT, 2, actual_selection);
|
||||
add_coin(4 * CENT, 4, actual_selection);
|
||||
add_coin(1 * CENT, 1, actual_selection);
|
||||
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 5 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
|
||||
BOOST_CHECK(equal_sets(selection, actual_selection));
|
||||
BOOST_CHECK_EQUAL(value_ret, 5 * CENT);
|
||||
@ -177,11 +177,23 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
|
||||
actual_selection.clear();
|
||||
selection.clear();
|
||||
|
||||
// Cost of change is greater than the difference between target value and utxo sum
|
||||
add_coin(1 * CENT, 1, actual_selection);
|
||||
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 0.9 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
|
||||
BOOST_CHECK_EQUAL(value_ret, 1 * CENT);
|
||||
BOOST_CHECK(equal_sets(selection, actual_selection));
|
||||
actual_selection.clear();
|
||||
selection.clear();
|
||||
|
||||
// Cost of change is less than the difference between target value and utxo sum
|
||||
BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), 0.9 * CENT, 0, selection, value_ret, not_input_fees));
|
||||
actual_selection.clear();
|
||||
selection.clear();
|
||||
|
||||
// Select 10 Cent
|
||||
add_coin(5 * CENT, 5, utxo_pool);
|
||||
add_coin(5 * CENT, 5, actual_selection);
|
||||
add_coin(4 * CENT, 4, actual_selection);
|
||||
add_coin(3 * CENT, 3, actual_selection);
|
||||
add_coin(2 * CENT, 2, actual_selection);
|
||||
add_coin(1 * CENT, 1, actual_selection);
|
||||
BOOST_CHECK(SelectCoinsBnB(GroupCoins(utxo_pool), 10 * CENT, 0.5 * CENT, selection, value_ret, not_input_fees));
|
||||
BOOST_CHECK(equal_sets(selection, actual_selection));
|
||||
|
@ -21,6 +21,7 @@ FUZZERS_MISSING_CORPORA = [
|
||||
"fee_rate_deserialize",
|
||||
"flat_file_pos_deserialize",
|
||||
"key_origin_info_deserialize",
|
||||
"locale",
|
||||
"merkle_block_deserialize",
|
||||
"out_point_deserialize",
|
||||
"partial_merkle_tree_deserialize",
|
||||
@ -32,6 +33,8 @@ FUZZERS_MISSING_CORPORA = [
|
||||
"script_deserialize",
|
||||
"sub_net_deserialize",
|
||||
"tx_in_deserialize",
|
||||
"tx_in",
|
||||
"tx_out",
|
||||
]
|
||||
|
||||
def main():
|
||||
@ -48,6 +51,11 @@ def main():
|
||||
action='store_true',
|
||||
help='If true, export coverage information to files in the seed corpus',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--valgrind',
|
||||
action='store_true',
|
||||
help='If true, run fuzzing binaries under the valgrind memory error detector. Valgrind 3.14 or later required.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'seed_dir',
|
||||
help='The seed corpus to run on (must contain subfolders for each fuzz target).',
|
||||
@ -116,10 +124,11 @@ def main():
|
||||
test_list=test_list_selection,
|
||||
build_dir=config["environment"]["BUILDDIR"],
|
||||
export_coverage=args.export_coverage,
|
||||
use_valgrind=args.valgrind,
|
||||
)
|
||||
|
||||
|
||||
def run_once(*, corpus, test_list, build_dir, export_coverage):
|
||||
def run_once(*, corpus, test_list, build_dir, export_coverage, use_valgrind):
|
||||
for t in test_list:
|
||||
corpus_path = os.path.join(corpus, t)
|
||||
if t in FUZZERS_MISSING_CORPORA:
|
||||
@ -130,6 +139,8 @@ def run_once(*, corpus, test_list, build_dir, export_coverage):
|
||||
'-detect_leaks=0',
|
||||
corpus_path,
|
||||
]
|
||||
if use_valgrind:
|
||||
args = ['valgrind', '--quiet', '--error-exitcode=1', '--exit-on-first-error=yes'] + args
|
||||
logging.debug('Run {} with args {}'.format(t, args))
|
||||
result = subprocess.run(args, stderr=subprocess.PIPE, universal_newlines=True)
|
||||
output = result.stderr
|
||||
|
Loading…
Reference in New Issue
Block a user