Skip to content

backport: Merge bitcoin#18554 #6715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions src/Makefile.bench.include
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,46 @@ GENERATED_BENCH_FILES = $(RAW_BENCH_FILES:.raw=.raw.h)
bench_bench_dash_SOURCES = \
$(RAW_BENCH_FILES) \
bench/addrman.cpp \
bench/bench_bitcoin.cpp \
bench/base58.cpp \
bench/bech32.cpp \
bench/bench.cpp \
bench/bench.h \
bench/bip324_ecdh.cpp \
bench/bench_bitcoin.cpp \
bench/block_assemble.cpp \
bench/ccoins_caching.cpp \
bench/chacha20.cpp \
bench/chacha_poly_aead.cpp \
bench/bls.cpp \
bench/bls_dkg.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
bench/data.h \
bench/crypto_hash.cpp \
bench/data.cpp \
bench/data.h \
bench/duplicate_inputs.cpp \
bench/ecdsa.cpp \
bench/ellswift.cpp \
bench/examples.cpp \
bench/rollingbloom.cpp \
bench/chacha20.cpp \
bench/crypto_hash.cpp \
bench/ccoins_caching.cpp \
bench/gcs_filter.cpp \
bench/hashpadding.cpp \
bench/load_external.cpp \
bench/merkle_root.cpp \
bench/lockedpool.cpp \
bench/logging.cpp \
bench/mempool_eviction.cpp \
bench/mempool_stress.cpp \
bench/nanobench.h \
bench/merkle_root.cpp \
bench/nanobench.cpp \
bench/nanobench.h \
bench/peer_eviction.cpp \
bench/pool.cpp \
bench/poly1305.cpp \
bench/prevector.cpp \
bench/rollingbloom.cpp \
bench/rpc_blockchain.cpp \
bench/rpc_mempool.cpp \
bench/strencodings.cpp \
bench/util_time.cpp \
bench/base58.cpp \
bench/bech32.cpp \
bench/lockedpool.cpp \
bench/poly1305.cpp \
bench/prevector.cpp \
bench/string_cast.cpp \
bench/verify_script.cpp

Expand Down
48 changes: 48 additions & 0 deletions src/bench/logging.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2020 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 <bench/bench.h>
#include <logging.h>
#include <test/util/setup_common.h>


static void Logging(benchmark::Bench& bench, const std::vector<const char*>& extra_args, const std::function<void()>& log)
{
TestingSetup test_setup{
CBaseChainParams::REGTEST,
extra_args,
};

bench.run([&] { log(); });
}

static void LoggingYoThreadNames(benchmark::Bench& bench)
{
Logging(bench, {"-logthreadnames=1"}, [] { LogPrintf("%s\n", "test"); });
}
static void LoggingNoThreadNames(benchmark::Bench& bench)
{
Logging(bench, {"-logthreadnames=0"}, [] { LogPrintf("%s\n", "test"); });
}
static void LoggingYoCategory(benchmark::Bench& bench)
{
Logging(bench, {"-logthreadnames=0", "-debug=net"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); });
}
static void LoggingNoCategory(benchmark::Bench& bench)
{
Logging(bench, {"-logthreadnames=0", "-debug=0"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); });
}
static void LoggingNoFile(benchmark::Bench& bench)
{
Logging(bench, {"-nodebuglogfile", "-debug=1"}, [] {
LogPrintf("%s\n", "test");
LogPrint(BCLog::NET, "%s\n", "test");
});
}

BENCHMARK(LoggingYoThreadNames);
BENCHMARK(LoggingNoThreadNames);
BENCHMARK(LoggingYoCategory);
BENCHMARK(LoggingNoCategory);
BENCHMARK(LoggingNoFile);
1 change: 1 addition & 0 deletions src/dummywallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
"-flushwallet",
"-privdb",
"-walletrejectlongchains",
"-walletcrosschain",
"-unsafesqlitesync"
});
}
Expand Down
4 changes: 3 additions & 1 deletion src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ class Wallet
virtual WalletTx getWalletTx(const uint256& txid) = 0;

//! Get list of all wallet transactions.
virtual std::vector<WalletTx> getWalletTxs() = 0;
virtual std::set<WalletTx> getWalletTxs() = 0;

//! Try to get updated status for a particular transaction, if possible without blocking.
virtual bool tryGetTxStatus(const uint256& txid,
Expand Down Expand Up @@ -423,6 +423,8 @@ struct WalletTx
bool is_coinbase;
bool is_platform_transfer{false};
bool is_denominate;

bool operator<(const WalletTx& a) const { return tx->GetHash() < a.tx->GetHash(); }
};

//! Updated transaction status.
Expand Down
1 change: 1 addition & 0 deletions src/wallet/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
#endif

argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
argsman.AddArg("-walletcrosschain", strprintf("Allow reusing wallet files across chains (default: %u)", DEFAULT_WALLETCROSSCHAIN), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);

argsman.AddHiddenArgs({"-zapwallettxes"});
}
Expand Down
7 changes: 3 additions & 4 deletions src/wallet/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,13 +338,12 @@ class WalletImpl : public Wallet
}
return {};
}
std::vector<WalletTx> getWalletTxs() override
std::set<WalletTx> getWalletTxs() override
{
LOCK(m_wallet->cs_wallet);
std::vector<WalletTx> result;
result.reserve(m_wallet->mapWallet.size());
std::set<WalletTx> result;
for (const auto& entry : m_wallet->mapWallet) {
result.emplace_back(MakeWalletTx(*m_wallet, entry.second));
result.emplace(MakeWalletTx(*m_wallet, entry.second));
}
return result;
}
Expand Down
17 changes: 14 additions & 3 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2161,10 +2161,21 @@ std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvid
std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
{
AssertLockHeld(cs_desc_man);
// Get the scripts, keys, and key origins for this script

std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();
std::vector<CScript> scripts_temp;
if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;

// Fetch SigningProvider from cache to avoid re-deriving
auto it = m_map_signing_providers.find(index);
if (it != m_map_signing_providers.end()) {
*out_keys = Merge(*out_keys, it->second);
} else {
// Get the scripts, keys, and key origins for this script
std::vector<CScript> scripts_temp;
if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;

// Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again
m_map_signing_providers[index] = *out_keys;
}

if (HavePrivateKeys() && include_private) {
FlatSigningProvider master_provider;
Expand Down
2 changes: 2 additions & 0 deletions src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan

KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);

// Cached FlatSigningProviders to avoid regenerating them each time they are needed.
mutable std::map<int32_t, FlatSigningProvider> m_map_signing_providers;
// Fetch the SigningProvider for the given script and optionally include private keys
std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
// Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.
Expand Down
6 changes: 4 additions & 2 deletions src/wallet/spend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,11 @@ void AvailableCoins(const CWallet& wallet, std::vector<COutput>& vCoins, const C

std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(wtx.tx->vout[i].scriptPubKey);

bool solvable = provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey) : false;
int input_bytes = CalculateMaximumSignedInputSize(wtx.tx->vout[i], COutPoint(), provider.get(), coinControl);
// Because CalculateMaximumSignedInputSize just uses ProduceSignature and makes a dummy signature,
// it is safe to assume that this input is solvable if input_bytes is greater -1.
bool solvable = input_bytes > -1;
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
int input_bytes = GetTxSpendSize(wallet, wtx, i, (coinControl && coinControl->fAllowWatchOnly));

vCoins.emplace_back(COutPoint(wtx.GetHash(), i), wtx.tx->vout.at(i), nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me);

Expand Down
6 changes: 3 additions & 3 deletions src/wallet/test/wallet_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,16 +850,16 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)

{
auto block_hash = block_tx.GetHash();
auto prev_hash = m_coinbase_txns[0]->GetHash();
auto prev_tx = m_coinbase_txns[0];

LOCK(wallet->cs_wallet);
BOOST_CHECK(wallet->HasWalletSpend(prev_hash));
BOOST_CHECK(wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 1u);

std::vector<uint256> vHashIn{ block_hash }, vHashOut;
BOOST_CHECK_EQUAL(wallet->ZapSelectTx(vHashIn, vHashOut), DBErrors::LOAD_OK);

BOOST_CHECK(!wallet->HasWalletSpend(prev_hash));
BOOST_CHECK(!wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 0u);
}

Expand Down
60 changes: 41 additions & 19 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& b
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
{
AssertLockHeld(cs_wallet);
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
const auto it = mapWallet.find(hash);
if (it == mapWallet.end())
return nullptr;
return &(it->second);
Expand Down Expand Up @@ -525,7 +525,7 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
std::set<uint256> result;
AssertLockHeld(cs_wallet);

std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
const auto it = mapWallet.find(txid);
if (it == mapWallet.end())
return result;
const CWalletTx& wtx = it->second;
Expand All @@ -543,11 +543,17 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
return result;
}

bool CWallet::HasWalletSpend(const uint256& txid) const
bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
{
AssertLockHeld(cs_wallet);
auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
return (iter != mapTxSpends.end() && iter->first.hash == txid);
const uint256& txid = tx->GetHash();
for (unsigned int i = 0; i < tx->vout.size(); ++i) {
auto iter = mapTxSpends.find(COutPoint(txid, i));
if (iter != mapTxSpends.end()) {
return true;
}
}
return false;
}

void CWallet::Flush()
Expand Down Expand Up @@ -612,7 +618,7 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
{
const uint256& wtxid = it->second;
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
const auto mit = mapWallet.find(wtxid);
if (mit != mapWallet.end()) {
int depth = GetTxDepthInMainChain(mit->second);
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
Expand Down Expand Up @@ -1154,12 +1160,13 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
batch.WriteTx(wtx);
NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
// Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
while (iter != mapTxSpends.end() && iter->first.hash == now) {
if (!done.count(iter->second)) {
todo.insert(iter->second);
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
if (!done.count(iter->second)) {
todo.insert(iter->second);
}
}
iter++;
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
Expand Down Expand Up @@ -1220,12 +1227,13 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
wtx.MarkDirty();
batch.WriteTx(wtx);
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
while (iter != mapTxSpends.end() && iter->first.hash == now) {
if (!done.count(iter->second)) {
todo.insert(iter->second);
}
iter++;
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
if (!done.count(iter->second)) {
todo.insert(iter->second);
}
}
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
Expand Down Expand Up @@ -1362,7 +1370,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
{
{
LOCK(cs_wallet);
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
const auto mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
Expand Down Expand Up @@ -1934,7 +1942,7 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const
// Build coins map
std::map<COutPoint, Coin> coins;
for (auto& input : tx.vin) {
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
const auto mi = mapWallet.find(input.prevout.hash);
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
return false;
}
Expand Down Expand Up @@ -3018,6 +3026,20 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
walletInstance->m_chain = &chain;

// Unless allowed, ensure wallet files are not reused across chains:
if (!gArgs.GetBoolArg("-walletcrosschain", DEFAULT_WALLETCROSSCHAIN)) {
WalletBatch batch(walletInstance->GetDatabase());
CBlockLocator locator;
if (batch.ReadBestBlock(locator) && locator.vHave.size() > 0 && chain.getHeight()) {
// Wallet is assumed to be from another chain, if genesis block in the active
// chain differs from the genesis block known to the wallet.
if (chain.getBlockHash(0) != locator.vHave.back()) {
error = Untranslated("Wallet files should not be reused across chains. Restart bitcoind with -walletcrosschain to override.");
return false;
}
}
}

// Register wallet with validationinterface. It's done before rescan to avoid
// missing block connections between end of rescan and validation subscribing.
// Because of wallet lock being hold, block connection notifications are going to
Expand Down
Loading
Loading