Skip to content
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

backport: Merge bitcoin#20466,14604,15710,17458,18722,(partial) 17934 #5681

Merged
merged 6 commits into from
Dec 4, 2023
Merged
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
16 changes: 9 additions & 7 deletions depends/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ For example:

make HOST=x86_64-w64-mingw32 -j4

**Dash Core's configure script by default will ignore the depends output.** In
**Dash Core's `configure` script by default will ignore the depends output.** In
order for it to pick up libraries, tools, and settings from the depends build,
you must point it at the appropriate `--prefix` directory generated by the
build. In the above example, a prefix dir named x86_64-w64-mingw32 will be
created. To use it for Dash:
you must set the `CONFIG_SITE` environment variable to point to a `config.site` settings file.
In the above example, a file named `depends/x86_64-w64-mingw32/share/config.site` will be
created. To use it during compilation:

./configure --prefix=$PWD/depends/x86_64-w64-mingw32
CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site ./configure

Common `host-platform-triplets` for cross compilation are:
The default install prefix when using `config.site` is `--prefix=depends/<host-platform-triplet>`,
so depends build outputs will be installed in that location.

Common `host-platform-triplet`s for cross compilation are:

- `i686-pc-linux-gnu` for Linux 32 bit
- `x86_64-pc-linux-gnu` for x86 Linux
Expand Down Expand Up @@ -138,4 +141,3 @@ This is an example command for a default build with no disabled dependencies:

- [description.md](description.md): General description of the depends system
- [packages.md](packages.md): Steps for adding packages

3 changes: 2 additions & 1 deletion doc/build-unix.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ To build executables for ARM:
cd depends
make HOST=arm-linux-gnueabihf NO_QT=1
cd ..
./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-reduce-exports LDFLAGS=-static-libstdc++
./autogen.sh
CONFIG_SITE=$PWD/depends/arm-linux-gnueabihf/share/config.site ./configure --enable-reduce-exports LDFLAGS=-static-libstdc++
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

partial due to missing changes in doc/multiprocess.md
Can be done full only after bitcoin#18677

make


Expand Down
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ BITCOIN_TESTS += \
wallet/test/coinjoin_tests.cpp \
wallet/test/psbt_wallet_tests.cpp \
wallet/test/wallet_tests.cpp \
wallet/test/walletdb_tests.cpp \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/coinselector_tests.cpp \
wallet/test/init_tests.cpp \
Expand Down
10 changes: 6 additions & 4 deletions src/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#include <cmath>
#include <optional>
#include <unordered_map>
#include <unordered_set>

int CAddrInfo::GetTriedBucket(const uint256& nKey, const std::vector<bool> &asmap) const
{
Expand Down Expand Up @@ -115,12 +117,12 @@ CAddrInfo* CAddrMan::Find(const CService& addr, int* pnId)
addr2.SetPort(0);
}

std::map<CService, int>::iterator it = mapAddr.find(addr2);
const auto it = mapAddr.find(addr2);
if (it == mapAddr.end())
return nullptr;
if (pnId)
*pnId = (*it).second;
std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
const auto it2 = mapInfo.find((*it).second);
if (it2 != mapInfo.end())
return &(*it2).second;
return nullptr;
Expand Down Expand Up @@ -482,8 +484,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) const
int CAddrMan::Check_()
{
AssertLockHeld(cs);
std::set<int> setTried;
std::map<int, int> mapNew;
std::unordered_set<int> setTried;
std::unordered_map<int, int> mapNew;

if (vRandom.size() != (size_t)(nTried + nNew))
return -7;
Expand Down
22 changes: 11 additions & 11 deletions src/addrman.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@

#include <clientversion.h>
#include <config/bitcoin-config.h>
#include <fs.h>
#include <hash.h>
#include <netaddress.h>
#include <protocol.h>
#include <random.h>
#include <streams.h>
#include <sync.h>
#include <timedata.h>
#include <tinyformat.h>
#include <util/system.h>

#include <fs.h>
#include <hash.h>
#include <ios>
#include <map>
#include <optional>
#include <set>
#include <stdint.h>
#include <streams.h>
#include <unordered_map>
#include <vector>

/**
Expand Down Expand Up @@ -257,7 +257,7 @@ class CAddrMan

int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
s << nUBuckets;
std::map<int, int> mapUnkIds;
std::unordered_map<int, int> mapUnkIds;
int nIds = 0;
for (const auto& entry : mapInfo) {
mapUnkIds[entry.first] = nIds;
Expand Down Expand Up @@ -448,13 +448,13 @@ class CAddrMan

// Prune new entries with refcount 0 (as a result of collisions).
int nLostUnk = 0;
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
for (auto it = mapInfo.cbegin(); it != mapInfo.cend(); ) {
if (it->second.fInTried == false && it->second.nRefCount == 0) {
std::map<int, CAddrInfo>::const_iterator itCopy = it++;
const auto itCopy = it++;
Delete(itCopy->first);
nLostUnk++;
++nLostUnk;
} else {
it++;
++it;
}
}
if (nLost + nLostUnk > 0) {
Expand Down Expand Up @@ -682,10 +682,10 @@ class CAddrMan
int nIdCount GUARDED_BY(cs);

//! table with information about all nIds
std::map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
std::unordered_map<int, CAddrInfo> mapInfo GUARDED_BY(cs);

//! find an nId based on its network address
std::map<CService, int> mapAddr GUARDED_BY(cs);
std::unordered_map<CNetAddr, int, CNetAddrHash> mapAddr GUARDED_BY(cs);

//! randomly-ordered vector of all nIds
//! This is mutable because it is unobservable outside the class, so any
Expand Down
19 changes: 19 additions & 0 deletions src/netaddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

#include <attributes.h>
#include <compat.h>
#include <crypto/siphash.h>
#include <prevector.h>
#include <random.h>
#include <serialize.h>
#include <tinyformat.h>
#include <util/strencodings.h>
Expand Down Expand Up @@ -251,6 +253,7 @@ class CNetAddr
}
}

friend class CNetAddrHash;
friend class CSubNet;

private:
Expand Down Expand Up @@ -465,6 +468,22 @@ class CNetAddr
}
};

class CNetAddrHash
{
public:
size_t operator()(const CNetAddr& a) const noexcept
{
CSipHasher hasher(m_salt_k0, m_salt_k1);
hasher.Write(a.m_net);
hasher.Write(a.m_addr.data(), a.m_addr.size());
return static_cast<size_t>(hasher.Finalize());
}

private:
const uint64_t m_salt_k0 = GetRand(std::numeric_limits<uint64_t>::max());
const uint64_t m_salt_k1 = GetRand(std::numeric_limits<uint64_t>::max());
};

class CSubNet
{
protected:
Expand Down
43 changes: 40 additions & 3 deletions src/wallet/coinselection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <wallet/coinselection.h>

#include <policy/feerate.h>
#include <util/system.h>
#include <util/moneystr.h>

Expand Down Expand Up @@ -365,7 +366,7 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size_t ancestors, size_t descendants) {
m_outputs.push_back(output);
m_from_me &= from_me;
m_value += output.effective_value;
m_value += output.txout.nValue;
m_depth = std::min(m_depth, depth);
// ancestors here express the number of ancestors the new coin will end up having, which is
// the sum, rather than the max; this will overestimate in the cases where multiple inputs
Expand All @@ -374,15 +375,19 @@ void OutputGroup::Insert(const CInputCoin& output, int depth, bool from_me, size
// descendants is the count as seen from the top ancestor, not the descendants as seen from the
// coin itself; thus, this value is counted as the max, not the sum
m_descendants = std::max(m_descendants, descendants);
effective_value = m_value;
effective_value += output.effective_value;
fee += output.m_fee;
long_term_fee += output.m_long_term_fee;
}

std::vector<CInputCoin>::iterator OutputGroup::Discard(const CInputCoin& output) {
auto it = m_outputs.begin();
while (it != m_outputs.end() && it->outpoint != output.outpoint) ++it;
if (it == m_outputs.end()) return it;
m_value -= output.effective_value;
m_value -= output.txout.nValue;
effective_value -= output.effective_value;
fee -= output.m_fee;
long_term_fee -= output.m_long_term_fee;
return m_outputs.erase(it);
}

Expand All @@ -401,3 +406,35 @@ bool OutputGroup::EligibleForSpending(const CoinEligibilityFilter& eligibility_f
&& m_ancestors <= eligibility_filter.max_ancestors
&& m_descendants <= eligibility_filter.max_descendants;
}

void OutputGroup::SetFees(const CFeeRate effective_feerate, const CFeeRate long_term_feerate)
{
fee = 0;
long_term_fee = 0;
effective_value = 0;
for (CInputCoin& coin : m_outputs) {
coin.m_fee = coin.m_input_bytes < 0 ? 0 : effective_feerate.GetFee(coin.m_input_bytes);
fee += coin.m_fee;

coin.m_long_term_fee = coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes);
long_term_fee += coin.m_long_term_fee;

coin.effective_value = coin.txout.nValue - coin.m_fee;
effective_value += coin.effective_value;
}
}

OutputGroup OutputGroup::GetPositiveOnlyGroup()
{
OutputGroup group(*this);
for (auto it = group.m_outputs.begin(); it != group.m_outputs.end(); ) {
const CInputCoin& coin = *it;
// Only include outputs that are positive effective value (i.e. not dust)
if (coin.effective_value <= 0) {
it = group.Discard(coin);
} else {
++it;
}
}
return group;
}
8 changes: 8 additions & 0 deletions src/wallet/coinselection.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <primitives/transaction.h>
#include <random.h>

class CFeeRate;

//! target minimum change amount
static constexpr CAmount MIN_CHANGE{COIN / 100};
//! final minimum change amount after paying for fees
Expand Down Expand Up @@ -36,6 +38,8 @@ class CInputCoin {
COutPoint outpoint;
CTxOut txout;
CAmount effective_value;
CAmount m_fee{0};
CAmount m_long_term_fee{0};

/** Pre-computed estimated size of this output as a fully-signed input in a transaction. Can be -1 if it could not be calculated */
int m_input_bytes{-1};
Expand Down Expand Up @@ -92,6 +96,10 @@ struct OutputGroup
std::vector<CInputCoin>::iterator Discard(const CInputCoin& output);
bool IsLockedByInstantSend() const;
bool EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const;

//! Update the OutputGroup's fee, long_term_fee, and effective_value based on the given feerates
void SetFees(const CFeeRate effective_feerate, const CFeeRate long_term_feerate);
OutputGroup GetPositiveOnlyGroup();
};

bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& target_value, const CAmount& cost_of_change, std::set<CInputCoin>& out_set, CAmount& value_ret, CAmount not_input_fees);
Expand Down
29 changes: 29 additions & 0 deletions src/wallet/test/walletdb_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2012-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 <test/util/setup_common.h>
#include <clientversion.h>
#include <streams.h>
#include <uint256.h>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(walletdb_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(walletdb_readkeyvalue)
{
/**
* When ReadKeyValue() reads from either a "key" or "wkey" it first reads the CDataStream steam into a
* CPrivKey or CWalletKey respectively and then reads a hash of the pubkey and privkey into a uint256.
* Wallets from 0.8 or before do not store the pubkey/privkey hash, trying to read the hash from old
* wallets throws an exception, for backwards compatibility this read is wrapped in a try block to
* silently fail. The test here makes sure the type of exception thrown from CDataStream::read()
* matches the type we expect, otherwise we need to update the "key"/"wkey" exception type caught.
*/
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
uint256 dummy;
BOOST_CHECK_THROW(ssValue >> dummy, std::ios_base::failure);
}

BOOST_AUTO_TEST_SUITE_END()
28 changes: 8 additions & 20 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2745,27 +2745,15 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
for (OutputGroup& group : groups) {
if (!group.EligibleForSpending(eligibility_filter)) continue;

group.fee = 0;
group.long_term_fee = 0;
group.effective_value = 0;
for (auto it = group.m_outputs.begin(); it != group.m_outputs.end(); ) {
const CInputCoin& coin = *it;
CAmount effective_value = coin.txout.nValue - (coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes));
// Only include outputs that are positive effective value (i.e. not dust)
if (effective_value > 0) {
group.fee += coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes);
group.long_term_fee += coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes);
if (coin_selection_params.m_subtract_fee_outputs) {
group.effective_value += coin.txout.nValue;
} else {
group.effective_value += effective_value;
}
++it;
} else {
it = group.Discard(coin);
}
if (coin_selection_params.m_subtract_fee_outputs) {
// Set the effective feerate to 0 as we don't want to use the effective value since the fees will be deducted from the output
group.SetFees(CFeeRate(0) /* effective_feerate */, long_term_feerate);
} else {
group.SetFees(coin_selection_params.effective_fee, long_term_feerate);
}
if (group.effective_value > 0) utxo_pool.push_back(group);

OutputGroup pos_group = group.GetPositiveOnlyGroup();
if (pos_group.effective_value > 0) utxo_pool.push_back(pos_group);
}
// Calculate the fees for things that aren't inputs
CAmount not_input_fees = coin_selection_params.effective_fee.GetFee(coin_selection_params.tx_noinputs_size);
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
ssValue >> hash;
}
catch (...) {}
catch (const std::ios_base::failure&) {}

bool fSkipCheck = false;

Expand Down
Loading
Loading