Skip to content

Commit 7b6c1be

Browse files
Merge pull request dashpay#5681 from vijaydasmp/bp22_17
backport: Merge bitcoin#20466,14604,15710,17458,18722,(partial) 17934
2 parents 5783743 + 0181d2b commit 7b6c1be

File tree

13 files changed

+156
-50
lines changed

13 files changed

+156
-50
lines changed

depends/README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@ For example:
1212

1313
make HOST=x86_64-w64-mingw32 -j4
1414

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

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

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

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

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

doc/build-unix.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@ To build executables for ARM:
331331
cd depends
332332
make HOST=arm-linux-gnueabihf NO_QT=1
333333
cd ..
334-
./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-reduce-exports LDFLAGS=-static-libstdc++
334+
./autogen.sh
335+
CONFIG_SITE=$PWD/depends/arm-linux-gnueabihf/share/config.site ./configure --enable-reduce-exports LDFLAGS=-static-libstdc++
335336
make
336337

337338

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ BITCOIN_TESTS += \
182182
wallet/test/coinjoin_tests.cpp \
183183
wallet/test/psbt_wallet_tests.cpp \
184184
wallet/test/wallet_tests.cpp \
185+
wallet/test/walletdb_tests.cpp \
185186
wallet/test/wallet_crypto_tests.cpp \
186187
wallet/test/coinselector_tests.cpp \
187188
wallet/test/init_tests.cpp \

src/addrman.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#include <cmath>
1515
#include <optional>
16+
#include <unordered_map>
17+
#include <unordered_set>
1618

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

118-
std::map<CService, int>::iterator it = mapAddr.find(addr2);
120+
const auto it = mapAddr.find(addr2);
119121
if (it == mapAddr.end())
120122
return nullptr;
121123
if (pnId)
122124
*pnId = (*it).second;
123-
std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
125+
const auto it2 = mapInfo.find((*it).second);
124126
if (it2 != mapInfo.end())
125127
return &(*it2).second;
126128
return nullptr;
@@ -482,8 +484,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) const
482484
int CAddrMan::Check_()
483485
{
484486
AssertLockHeld(cs);
485-
std::set<int> setTried;
486-
std::map<int, int> mapNew;
487+
std::unordered_set<int> setTried;
488+
std::unordered_map<int, int> mapNew;
487489

488490
if (vRandom.size() != (size_t)(nTried + nNew))
489491
return -7;

src/addrman.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@
88

99
#include <clientversion.h>
1010
#include <config/bitcoin-config.h>
11+
#include <fs.h>
12+
#include <hash.h>
1113
#include <netaddress.h>
1214
#include <protocol.h>
1315
#include <random.h>
16+
#include <streams.h>
1417
#include <sync.h>
1518
#include <timedata.h>
1619
#include <tinyformat.h>
1720
#include <util/system.h>
1821

19-
#include <fs.h>
20-
#include <hash.h>
2122
#include <ios>
22-
#include <map>
2323
#include <optional>
2424
#include <set>
2525
#include <stdint.h>
26-
#include <streams.h>
26+
#include <unordered_map>
2727
#include <vector>
2828

2929
/**
@@ -257,7 +257,7 @@ class CAddrMan
257257

258258
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
259259
s << nUBuckets;
260-
std::map<int, int> mapUnkIds;
260+
std::unordered_map<int, int> mapUnkIds;
261261
int nIds = 0;
262262
for (const auto& entry : mapInfo) {
263263
mapUnkIds[entry.first] = nIds;
@@ -448,13 +448,13 @@ class CAddrMan
448448

449449
// Prune new entries with refcount 0 (as a result of collisions).
450450
int nLostUnk = 0;
451-
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
451+
for (auto it = mapInfo.cbegin(); it != mapInfo.cend(); ) {
452452
if (it->second.fInTried == false && it->second.nRefCount == 0) {
453-
std::map<int, CAddrInfo>::const_iterator itCopy = it++;
453+
const auto itCopy = it++;
454454
Delete(itCopy->first);
455-
nLostUnk++;
455+
++nLostUnk;
456456
} else {
457-
it++;
457+
++it;
458458
}
459459
}
460460
if (nLost + nLostUnk > 0) {
@@ -682,10 +682,10 @@ class CAddrMan
682682
int nIdCount GUARDED_BY(cs);
683683

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

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

690690
//! randomly-ordered vector of all nIds
691691
//! This is mutable because it is unobservable outside the class, so any

src/netaddress.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
#include <attributes.h>
1313
#include <compat.h>
14+
#include <crypto/siphash.h>
1415
#include <prevector.h>
16+
#include <random.h>
1517
#include <serialize.h>
1618
#include <tinyformat.h>
1719
#include <util/strencodings.h>
@@ -251,6 +253,7 @@ class CNetAddr
251253
}
252254
}
253255

256+
friend class CNetAddrHash;
254257
friend class CSubNet;
255258

256259
private:
@@ -465,6 +468,22 @@ class CNetAddr
465468
}
466469
};
467470

471+
class CNetAddrHash
472+
{
473+
public:
474+
size_t operator()(const CNetAddr& a) const noexcept
475+
{
476+
CSipHasher hasher(m_salt_k0, m_salt_k1);
477+
hasher.Write(a.m_net);
478+
hasher.Write(a.m_addr.data(), a.m_addr.size());
479+
return static_cast<size_t>(hasher.Finalize());
480+
}
481+
482+
private:
483+
const uint64_t m_salt_k0 = GetRand(std::numeric_limits<uint64_t>::max());
484+
const uint64_t m_salt_k1 = GetRand(std::numeric_limits<uint64_t>::max());
485+
};
486+
468487
class CSubNet
469488
{
470489
protected:

src/wallet/coinselection.cpp

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <wallet/coinselection.h>
66

7+
#include <policy/feerate.h>
78
#include <util/system.h>
89
#include <util/moneystr.h>
910

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

380383
std::vector<CInputCoin>::iterator OutputGroup::Discard(const CInputCoin& output) {
381384
auto it = m_outputs.begin();
382385
while (it != m_outputs.end() && it->outpoint != output.outpoint) ++it;
383386
if (it == m_outputs.end()) return it;
384-
m_value -= output.effective_value;
387+
m_value -= output.txout.nValue;
385388
effective_value -= output.effective_value;
389+
fee -= output.m_fee;
390+
long_term_fee -= output.m_long_term_fee;
386391
return m_outputs.erase(it);
387392
}
388393

@@ -401,3 +406,35 @@ bool OutputGroup::EligibleForSpending(const CoinEligibilityFilter& eligibility_f
401406
&& m_ancestors <= eligibility_filter.max_ancestors
402407
&& m_descendants <= eligibility_filter.max_descendants;
403408
}
409+
410+
void OutputGroup::SetFees(const CFeeRate effective_feerate, const CFeeRate long_term_feerate)
411+
{
412+
fee = 0;
413+
long_term_fee = 0;
414+
effective_value = 0;
415+
for (CInputCoin& coin : m_outputs) {
416+
coin.m_fee = coin.m_input_bytes < 0 ? 0 : effective_feerate.GetFee(coin.m_input_bytes);
417+
fee += coin.m_fee;
418+
419+
coin.m_long_term_fee = coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes);
420+
long_term_fee += coin.m_long_term_fee;
421+
422+
coin.effective_value = coin.txout.nValue - coin.m_fee;
423+
effective_value += coin.effective_value;
424+
}
425+
}
426+
427+
OutputGroup OutputGroup::GetPositiveOnlyGroup()
428+
{
429+
OutputGroup group(*this);
430+
for (auto it = group.m_outputs.begin(); it != group.m_outputs.end(); ) {
431+
const CInputCoin& coin = *it;
432+
// Only include outputs that are positive effective value (i.e. not dust)
433+
if (coin.effective_value <= 0) {
434+
it = group.Discard(coin);
435+
} else {
436+
++it;
437+
}
438+
}
439+
return group;
440+
}

src/wallet/coinselection.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <primitives/transaction.h>
1010
#include <random.h>
1111

12+
class CFeeRate;
13+
1214
//! target minimum change amount
1315
static constexpr CAmount MIN_CHANGE{COIN / 100};
1416
//! final minimum change amount after paying for fees
@@ -36,6 +38,8 @@ class CInputCoin {
3638
COutPoint outpoint;
3739
CTxOut txout;
3840
CAmount effective_value;
41+
CAmount m_fee{0};
42+
CAmount m_long_term_fee{0};
3943

4044
/** Pre-computed estimated size of this output as a fully-signed input in a transaction. Can be -1 if it could not be calculated */
4145
int m_input_bytes{-1};
@@ -92,6 +96,10 @@ struct OutputGroup
9296
std::vector<CInputCoin>::iterator Discard(const CInputCoin& output);
9397
bool IsLockedByInstantSend() const;
9498
bool EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const;
99+
100+
//! Update the OutputGroup's fee, long_term_fee, and effective_value based on the given feerates
101+
void SetFees(const CFeeRate effective_feerate, const CFeeRate long_term_feerate);
102+
OutputGroup GetPositiveOnlyGroup();
95103
};
96104

97105
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);

src/wallet/test/walletdb_tests.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2012-2019 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <test/util/setup_common.h>
6+
#include <clientversion.h>
7+
#include <streams.h>
8+
#include <uint256.h>
9+
10+
#include <boost/test/unit_test.hpp>
11+
12+
BOOST_FIXTURE_TEST_SUITE(walletdb_tests, BasicTestingSetup)
13+
14+
BOOST_AUTO_TEST_CASE(walletdb_readkeyvalue)
15+
{
16+
/**
17+
* When ReadKeyValue() reads from either a "key" or "wkey" it first reads the CDataStream steam into a
18+
* CPrivKey or CWalletKey respectively and then reads a hash of the pubkey and privkey into a uint256.
19+
* Wallets from 0.8 or before do not store the pubkey/privkey hash, trying to read the hash from old
20+
* wallets throws an exception, for backwards compatibility this read is wrapped in a try block to
21+
* silently fail. The test here makes sure the type of exception thrown from CDataStream::read()
22+
* matches the type we expect, otherwise we need to update the "key"/"wkey" exception type caught.
23+
*/
24+
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
25+
uint256 dummy;
26+
BOOST_CHECK_THROW(ssValue >> dummy, std::ios_base::failure);
27+
}
28+
29+
BOOST_AUTO_TEST_SUITE_END()

src/wallet/wallet.cpp

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,27 +2745,15 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibil
27452745
for (OutputGroup& group : groups) {
27462746
if (!group.EligibleForSpending(eligibility_filter)) continue;
27472747

2748-
group.fee = 0;
2749-
group.long_term_fee = 0;
2750-
group.effective_value = 0;
2751-
for (auto it = group.m_outputs.begin(); it != group.m_outputs.end(); ) {
2752-
const CInputCoin& coin = *it;
2753-
CAmount effective_value = coin.txout.nValue - (coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes));
2754-
// Only include outputs that are positive effective value (i.e. not dust)
2755-
if (effective_value > 0) {
2756-
group.fee += coin.m_input_bytes < 0 ? 0 : coin_selection_params.effective_fee.GetFee(coin.m_input_bytes);
2757-
group.long_term_fee += coin.m_input_bytes < 0 ? 0 : long_term_feerate.GetFee(coin.m_input_bytes);
2758-
if (coin_selection_params.m_subtract_fee_outputs) {
2759-
group.effective_value += coin.txout.nValue;
2760-
} else {
2761-
group.effective_value += effective_value;
2762-
}
2763-
++it;
2764-
} else {
2765-
it = group.Discard(coin);
2766-
}
2748+
if (coin_selection_params.m_subtract_fee_outputs) {
2749+
// 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
2750+
group.SetFees(CFeeRate(0) /* effective_feerate */, long_term_feerate);
2751+
} else {
2752+
group.SetFees(coin_selection_params.effective_fee, long_term_feerate);
27672753
}
2768-
if (group.effective_value > 0) utxo_pool.push_back(group);
2754+
2755+
OutputGroup pos_group = group.GetPositiveOnlyGroup();
2756+
if (pos_group.effective_value > 0) utxo_pool.push_back(pos_group);
27692757
}
27702758
// Calculate the fees for things that aren't inputs
27712759
CAmount not_input_fees = coin_selection_params.effective_fee.GetFee(coin_selection_params.tx_noinputs_size);

0 commit comments

Comments
 (0)