Auto merge of #5026 - str4d:bloom-filter-backports, r=str4d
Backport bloom filter improvements Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#7113 - bitcoin/bitcoin#7818 - Only the second commit (to resolve conflicts). - bitcoin/bitcoin#7934 - bitcoin/bitcoin#8655 - Partial backport to help resolve conflicts. - bitcoin/bitcoin#9060 - bitcoin/bitcoin#9223 - bitcoin/bitcoin#9644 - Partial backport to help resolve conflicts. - bitcoin/bitcoin#9916 - bitcoin/bitcoin#9750 - bitcoin/bitcoin#13176 - bitcoin/bitcoin#13948 - bitcoin/bitcoin#16073 - bitcoin/bitcoin#18670 - bitcoin/bitcoin#18806 - Reveals upstream's covert fix for CVE-2013-5700. - bitcoin/bitcoin#19968
This commit is contained in:
commit
78de0cdf46
|
@ -39,4 +39,13 @@ static void RollingBloom(benchmark::State& state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void RollingBloomReset(benchmark::State& state)
|
||||||
|
{
|
||||||
|
CRollingBloomFilter filter(120000, 0.000001);
|
||||||
|
while (state.KeepRunning()) {
|
||||||
|
filter.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BENCHMARK(RollingBloom);
|
BENCHMARK(RollingBloom);
|
||||||
|
BENCHMARK(RollingBloomReset); // To-backport: 20000
|
||||||
|
|
179
src/bloom.cpp
179
src/bloom.cpp
|
@ -14,52 +14,38 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
|
#define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455
|
||||||
#define LN2 0.6931471805599453094172321214581765680755001343602552
|
#define LN2 0.6931471805599453094172321214581765680755001343602552
|
||||||
|
|
||||||
using namespace std;
|
CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn, unsigned char nFlagsIn) :
|
||||||
|
|
||||||
CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn, unsigned char nFlagsIn) :
|
|
||||||
/**
|
/**
|
||||||
* The ideal size for a bloom filter with a given number of elements and false positive rate is:
|
* The ideal size for a bloom filter with a given number of elements and false positive rate is:
|
||||||
* - nElements * log(fp rate) / ln(2)^2
|
* - nElements * log(fp rate) / ln(2)^2
|
||||||
* We ignore filter parameters which will create a bloom filter larger than the protocol limits
|
* We ignore filter parameters which will create a bloom filter larger than the protocol limits
|
||||||
*/
|
*/
|
||||||
vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
|
vData(std::min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8),
|
||||||
/**
|
/**
|
||||||
* The ideal number of hash functions is filter size * ln(2) / number of elements
|
* The ideal number of hash functions is filter size * ln(2) / number of elements
|
||||||
* Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
|
* Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits
|
||||||
* See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
|
* See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas
|
||||||
*/
|
*/
|
||||||
isFull(false),
|
nHashFuncs(std::min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
|
||||||
isEmpty(false),
|
|
||||||
nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)),
|
|
||||||
nTweak(nTweakIn),
|
nTweak(nTweakIn),
|
||||||
nFlags(nFlagsIn)
|
nFlags(nFlagsIn)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private constructor used by CRollingBloomFilter
|
|
||||||
CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn) :
|
|
||||||
vData((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)) / 8),
|
|
||||||
isFull(false),
|
|
||||||
isEmpty(true),
|
|
||||||
nHashFuncs((unsigned int)(vData.size() * 8 / nElements * LN2)),
|
|
||||||
nTweak(nTweakIn),
|
|
||||||
nFlags(BLOOM_UPDATE_NONE)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
|
inline unsigned int CBloomFilter::Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const
|
||||||
{
|
{
|
||||||
// 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
|
// 0xFBA4C795 chosen as it guarantees a reasonable bit difference between nHashNum values.
|
||||||
return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.size() * 8);
|
return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash) % (vData.size() * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBloomFilter::insert(const vector<unsigned char>& vKey)
|
void CBloomFilter::insert(const std::vector<unsigned char>& vKey)
|
||||||
{
|
{
|
||||||
if (isFull)
|
if (vData.empty()) // Avoid divide-by-zero (CVE-2013-5700)
|
||||||
return;
|
return;
|
||||||
for (unsigned int i = 0; i < nHashFuncs; i++)
|
for (unsigned int i = 0; i < nHashFuncs; i++)
|
||||||
{
|
{
|
||||||
|
@ -67,29 +53,26 @@ void CBloomFilter::insert(const vector<unsigned char>& vKey)
|
||||||
// Sets bit nIndex of vData
|
// Sets bit nIndex of vData
|
||||||
vData[nIndex >> 3] |= (1 << (7 & nIndex));
|
vData[nIndex >> 3] |= (1 << (7 & nIndex));
|
||||||
}
|
}
|
||||||
isEmpty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBloomFilter::insert(const COutPoint& outpoint)
|
void CBloomFilter::insert(const COutPoint& outpoint)
|
||||||
{
|
{
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
stream << outpoint;
|
stream << outpoint;
|
||||||
vector<unsigned char> data(stream.begin(), stream.end());
|
std::vector<unsigned char> data(stream.begin(), stream.end());
|
||||||
insert(data);
|
insert(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBloomFilter::insert(const uint256& hash)
|
void CBloomFilter::insert(const uint256& hash)
|
||||||
{
|
{
|
||||||
vector<unsigned char> data(hash.begin(), hash.end());
|
std::vector<unsigned char> data(hash.begin(), hash.end());
|
||||||
insert(data);
|
insert(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBloomFilter::contains(const vector<unsigned char>& vKey) const
|
bool CBloomFilter::contains(const std::vector<unsigned char>& vKey) const
|
||||||
{
|
{
|
||||||
if (isFull)
|
if (vData.empty()) // Avoid divide-by-zero (CVE-2013-5700)
|
||||||
return true;
|
return true;
|
||||||
if (isEmpty)
|
|
||||||
return false;
|
|
||||||
for (unsigned int i = 0; i < nHashFuncs; i++)
|
for (unsigned int i = 0; i < nHashFuncs; i++)
|
||||||
{
|
{
|
||||||
unsigned int nIndex = Hash(i, vKey);
|
unsigned int nIndex = Hash(i, vKey);
|
||||||
|
@ -104,29 +87,16 @@ bool CBloomFilter::contains(const COutPoint& outpoint) const
|
||||||
{
|
{
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
stream << outpoint;
|
stream << outpoint;
|
||||||
vector<unsigned char> data(stream.begin(), stream.end());
|
std::vector<unsigned char> data(stream.begin(), stream.end());
|
||||||
return contains(data);
|
return contains(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBloomFilter::contains(const uint256& hash) const
|
bool CBloomFilter::contains(const uint256& hash) const
|
||||||
{
|
{
|
||||||
vector<unsigned char> data(hash.begin(), hash.end());
|
std::vector<unsigned char> data(hash.begin(), hash.end());
|
||||||
return contains(data);
|
return contains(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBloomFilter::clear()
|
|
||||||
{
|
|
||||||
vData.assign(vData.size(),0);
|
|
||||||
isFull = false;
|
|
||||||
isEmpty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBloomFilter::reset(unsigned int nNewTweak)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
nTweak = nNewTweak;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBloomFilter::IsWithinSizeConstraints() const
|
bool CBloomFilter::IsWithinSizeConstraints() const
|
||||||
{
|
{
|
||||||
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
|
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
|
||||||
|
@ -137,10 +107,8 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||||
bool fFound = false;
|
bool fFound = false;
|
||||||
// Match if the filter contains the hash of tx
|
// Match if the filter contains the hash of tx
|
||||||
// for finding tx when they appear in a block
|
// for finding tx when they appear in a block
|
||||||
if (isFull)
|
if (vData.empty()) // zero-size = "match-all" filter
|
||||||
return true;
|
return true;
|
||||||
if (isEmpty)
|
|
||||||
return false;
|
|
||||||
const uint256& hash = tx.GetHash();
|
const uint256& hash = tx.GetHash();
|
||||||
if (contains(hash))
|
if (contains(hash))
|
||||||
fFound = true;
|
fFound = true;
|
||||||
|
@ -153,7 +121,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||||
// This means clients don't have to update the filter themselves when a new relevant tx
|
// This means clients don't have to update the filter themselves when a new relevant tx
|
||||||
// is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
|
// is discovered in order to find spending transactions, which avoids round-tripping and race conditions.
|
||||||
CScript::const_iterator pc = txout.scriptPubKey.begin();
|
CScript::const_iterator pc = txout.scriptPubKey.begin();
|
||||||
vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
while (pc < txout.scriptPubKey.end())
|
while (pc < txout.scriptPubKey.end())
|
||||||
{
|
{
|
||||||
opcodetype opcode;
|
opcodetype opcode;
|
||||||
|
@ -167,7 +135,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||||
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
|
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
|
||||||
{
|
{
|
||||||
txnouttype type;
|
txnouttype type;
|
||||||
vector<vector<unsigned char> > vSolutions;
|
std::vector<std::vector<unsigned char> > vSolutions;
|
||||||
if (Solver(txout.scriptPubKey, type, vSolutions) &&
|
if (Solver(txout.scriptPubKey, type, vSolutions) &&
|
||||||
(type == TX_PUBKEY || type == TX_MULTISIG))
|
(type == TX_PUBKEY || type == TX_MULTISIG))
|
||||||
insert(COutPoint(hash, i));
|
insert(COutPoint(hash, i));
|
||||||
|
@ -188,7 +156,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||||
|
|
||||||
// Match if the filter contains any arbitrary script data element in any scriptSig in tx
|
// Match if the filter contains any arbitrary script data element in any scriptSig in tx
|
||||||
CScript::const_iterator pc = txin.scriptSig.begin();
|
CScript::const_iterator pc = txin.scriptSig.begin();
|
||||||
vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
while (pc < txin.scriptSig.end())
|
while (pc < txin.scriptSig.end())
|
||||||
{
|
{
|
||||||
opcodetype opcode;
|
opcodetype opcode;
|
||||||
|
@ -202,70 +170,107 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBloomFilter::UpdateEmptyFull()
|
CRollingBloomFilter::CRollingBloomFilter(const unsigned int nElements, const double fpRate)
|
||||||
{
|
{
|
||||||
bool full = true;
|
double logFpRate = log(fpRate);
|
||||||
bool empty = true;
|
/* The optimal number of hash functions is log(fpRate) / log(0.5), but
|
||||||
for (unsigned int i = 0; i < vData.size(); i++)
|
* restrict it to the range 1-50. */
|
||||||
{
|
nHashFuncs = std::max(1, std::min((int)round(logFpRate / log(0.5)), 50));
|
||||||
full &= vData[i] == 0xff;
|
/* In this rolling bloom filter, we'll store between 2 and 3 generations of nElements / 2 entries. */
|
||||||
empty &= vData[i] == 0;
|
nEntriesPerGeneration = (nElements + 1) / 2;
|
||||||
}
|
uint32_t nMaxElements = nEntriesPerGeneration * 3;
|
||||||
isFull = full;
|
/* The maximum fpRate = pow(1.0 - exp(-nHashFuncs * nMaxElements / nFilterBits), nHashFuncs)
|
||||||
isEmpty = empty;
|
* => pow(fpRate, 1.0 / nHashFuncs) = 1.0 - exp(-nHashFuncs * nMaxElements / nFilterBits)
|
||||||
|
* => 1.0 - pow(fpRate, 1.0 / nHashFuncs) = exp(-nHashFuncs * nMaxElements / nFilterBits)
|
||||||
|
* => log(1.0 - pow(fpRate, 1.0 / nHashFuncs)) = -nHashFuncs * nMaxElements / nFilterBits
|
||||||
|
* => nFilterBits = -nHashFuncs * nMaxElements / log(1.0 - pow(fpRate, 1.0 / nHashFuncs))
|
||||||
|
* => nFilterBits = -nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs))
|
||||||
|
*/
|
||||||
|
uint32_t nFilterBits = (uint32_t)ceil(-1.0 * nHashFuncs * nMaxElements / log(1.0 - exp(logFpRate / nHashFuncs)));
|
||||||
|
data.clear();
|
||||||
|
/* For each data element we need to store 2 bits. If both bits are 0, the
|
||||||
|
* bit is treated as unset. If the bits are (01), (10), or (11), the bit is
|
||||||
|
* treated as set in generation 1, 2, or 3 respectively.
|
||||||
|
* These bits are stored in separate integers: position P corresponds to bit
|
||||||
|
* (P & 63) of the integers data[(P >> 6) * 2] and data[(P >> 6) * 2 + 1]. */
|
||||||
|
data.resize(((nFilterBits + 63) / 64) << 1);
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate) :
|
/* Similar to CBloomFilter::Hash */
|
||||||
b1(nElements * 2, fpRate, 0), b2(nElements * 2, fpRate, 0)
|
static inline uint32_t RollingBloomHash(unsigned int nHashNum, uint32_t nTweak, const std::vector<unsigned char>& vDataToHash) {
|
||||||
{
|
return MurmurHash3(nHashNum * 0xFBA4C795 + nTweak, vDataToHash);
|
||||||
// Implemented using two bloom filters of 2 * nElements each.
|
}
|
||||||
// We fill them up, and clear them, staggered, every nElements
|
|
||||||
// inserted, so at least one always contains the last nElements
|
|
||||||
// inserted.
|
|
||||||
nInsertions = 0;
|
|
||||||
nBloomSize = nElements * 2;
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
// A replacement for x % n. This assumes that x and n are 32bit integers, and x is a uniformly random distributed 32bit value
|
||||||
|
// which should be the case for a good hash.
|
||||||
|
// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
||||||
|
static inline uint32_t FastMod(uint32_t x, size_t n) {
|
||||||
|
return ((uint64_t)x * (uint64_t)n) >> 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
|
void CRollingBloomFilter::insert(const std::vector<unsigned char>& vKey)
|
||||||
{
|
{
|
||||||
if (nInsertions == 0) {
|
if (nEntriesThisGeneration == nEntriesPerGeneration) {
|
||||||
b1.clear();
|
nEntriesThisGeneration = 0;
|
||||||
} else if (nInsertions == nBloomSize / 2) {
|
nGeneration++;
|
||||||
b2.clear();
|
if (nGeneration == 4) {
|
||||||
|
nGeneration = 1;
|
||||||
|
}
|
||||||
|
uint64_t nGenerationMask1 = 0 - (uint64_t)(nGeneration & 1);
|
||||||
|
uint64_t nGenerationMask2 = 0 - (uint64_t)(nGeneration >> 1);
|
||||||
|
/* Wipe old entries that used this generation number. */
|
||||||
|
for (uint32_t p = 0; p < data.size(); p += 2) {
|
||||||
|
uint64_t p1 = data[p], p2 = data[p + 1];
|
||||||
|
uint64_t mask = (p1 ^ nGenerationMask1) | (p2 ^ nGenerationMask2);
|
||||||
|
data[p] = p1 & mask;
|
||||||
|
data[p + 1] = p2 & mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
b1.insert(vKey);
|
nEntriesThisGeneration++;
|
||||||
b2.insert(vKey);
|
|
||||||
if (++nInsertions == nBloomSize) {
|
for (int n = 0; n < nHashFuncs; n++) {
|
||||||
nInsertions = 0;
|
uint32_t h = RollingBloomHash(n, nTweak, vKey);
|
||||||
|
int bit = h & 0x3F;
|
||||||
|
/* FastMod works with the upper bits of h, so it is safe to ignore that the lower bits of h are already used for bit. */
|
||||||
|
uint32_t pos = FastMod(h, data.size());
|
||||||
|
/* The lowest bit of pos is ignored, and set to zero for the first bit, and to one for the second. */
|
||||||
|
data[pos & ~1] = (data[pos & ~1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration & 1)) << bit;
|
||||||
|
data[pos | 1] = (data[pos | 1] & ~(((uint64_t)1) << bit)) | ((uint64_t)(nGeneration >> 1)) << bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRollingBloomFilter::insert(const uint256& hash)
|
void CRollingBloomFilter::insert(const uint256& hash)
|
||||||
{
|
{
|
||||||
vector<unsigned char> data(hash.begin(), hash.end());
|
std::vector<unsigned char> vData(hash.begin(), hash.end());
|
||||||
insert(data);
|
insert(vData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
|
bool CRollingBloomFilter::contains(const std::vector<unsigned char>& vKey) const
|
||||||
{
|
{
|
||||||
if (nInsertions < nBloomSize / 2) {
|
for (int n = 0; n < nHashFuncs; n++) {
|
||||||
return b2.contains(vKey);
|
uint32_t h = RollingBloomHash(n, nTweak, vKey);
|
||||||
|
int bit = h & 0x3F;
|
||||||
|
uint32_t pos = FastMod(h, data.size());
|
||||||
|
/* If the relevant bit is not set in either data[pos & ~1] or data[pos | 1], the filter does not contain vKey */
|
||||||
|
if (!(((data[pos & ~1] | data[pos | 1]) >> bit) & 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return b1.contains(vKey);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRollingBloomFilter::contains(const uint256& hash) const
|
bool CRollingBloomFilter::contains(const uint256& hash) const
|
||||||
{
|
{
|
||||||
vector<unsigned char> data(hash.begin(), hash.end());
|
std::vector<unsigned char> vData(hash.begin(), hash.end());
|
||||||
return contains(data);
|
return contains(vData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRollingBloomFilter::reset()
|
void CRollingBloomFilter::reset()
|
||||||
{
|
{
|
||||||
unsigned int nNewTweak = GetRand(std::numeric_limits<unsigned int>::max());
|
nTweak = GetRand(std::numeric_limits<unsigned int>::max());
|
||||||
b1.reset(nNewTweak);
|
nEntriesThisGeneration = 0;
|
||||||
b2.reset(nNewTweak);
|
nGeneration = 1;
|
||||||
nInsertions = 0;
|
std::fill(data.begin(), data.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
44
src/bloom.h
44
src/bloom.h
|
@ -45,18 +45,12 @@ class CBloomFilter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<unsigned char> vData;
|
std::vector<unsigned char> vData;
|
||||||
bool isFull;
|
|
||||||
bool isEmpty;
|
|
||||||
unsigned int nHashFuncs;
|
unsigned int nHashFuncs;
|
||||||
unsigned int nTweak;
|
unsigned int nTweak;
|
||||||
unsigned char nFlags;
|
unsigned char nFlags;
|
||||||
|
|
||||||
unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
|
unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const;
|
||||||
|
|
||||||
// Private constructor for CRollingBloomFilter, no restrictions on size
|
|
||||||
CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak);
|
|
||||||
friend class CRollingBloomFilter;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements
|
* Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements
|
||||||
|
@ -67,8 +61,8 @@ public:
|
||||||
* It should generally always be a random value (and is largely only exposed for unit testing)
|
* It should generally always be a random value (and is largely only exposed for unit testing)
|
||||||
* nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK)
|
* nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK)
|
||||||
*/
|
*/
|
||||||
CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn);
|
CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn);
|
||||||
CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {}
|
CBloomFilter() : nHashFuncs(0), nTweak(0), nFlags(0) {}
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
@ -88,18 +82,12 @@ public:
|
||||||
bool contains(const COutPoint& outpoint) const;
|
bool contains(const COutPoint& outpoint) const;
|
||||||
bool contains(const uint256& hash) const;
|
bool contains(const uint256& hash) const;
|
||||||
|
|
||||||
void clear();
|
|
||||||
void reset(unsigned int nNewTweak);
|
|
||||||
|
|
||||||
//! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
|
//! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
|
||||||
//! (catch a filter which was just deserialized which was too big)
|
//! (catch a filter which was just deserialized which was too big)
|
||||||
bool IsWithinSizeConstraints() const;
|
bool IsWithinSizeConstraints() const;
|
||||||
|
|
||||||
//! Also adds any outputs which match the filter to the filter (to match their spending txes)
|
//! Also adds any outputs which match the filter to the filter (to match their spending txes)
|
||||||
bool IsRelevantAndUpdate(const CTransaction& tx);
|
bool IsRelevantAndUpdate(const CTransaction& tx);
|
||||||
|
|
||||||
//! Checks for empty and full filters to avoid wasting cpu
|
|
||||||
void UpdateEmptyFull();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,8 +98,22 @@ public:
|
||||||
* reset() is provided, which also changes nTweak to decrease the impact of
|
* reset() is provided, which also changes nTweak to decrease the impact of
|
||||||
* false-positives.
|
* false-positives.
|
||||||
*
|
*
|
||||||
* contains(item) will always return true if item was one of the last N things
|
* contains(item) will always return true if item was one of the last N to 1.5*N
|
||||||
* insert()'ed ... but may also return true for items that were not inserted.
|
* insert()'ed ... but may also return true for items that were not inserted.
|
||||||
|
*
|
||||||
|
* It needs around 1.8 bytes per element per factor 0.1 of false positive rate.
|
||||||
|
* For example, if we want 1000 elements, we'd need:
|
||||||
|
* - ~1800 bytes for a false positive rate of 0.1
|
||||||
|
* - ~3600 bytes for a false positive rate of 0.01
|
||||||
|
* - ~5400 bytes for a false positive rate of 0.001
|
||||||
|
*
|
||||||
|
* If we make these simplifying assumptions:
|
||||||
|
* - logFpRate / log(0.5) doesn't get rounded or clamped in the nHashFuncs calculation
|
||||||
|
* - nElements is even, so that nEntriesPerGeneration == nElements / 2
|
||||||
|
*
|
||||||
|
* Then we get a more accurate estimate for filter bytes:
|
||||||
|
*
|
||||||
|
* 3/(log(256)*log(2)) * log(1/fpRate) * nElements
|
||||||
*/
|
*/
|
||||||
class CRollingBloomFilter
|
class CRollingBloomFilter
|
||||||
{
|
{
|
||||||
|
@ -119,7 +121,7 @@ public:
|
||||||
// A random bloom filter calls GetRand() at creation time.
|
// A random bloom filter calls GetRand() at creation time.
|
||||||
// Don't create global CRollingBloomFilter objects, as they may be
|
// Don't create global CRollingBloomFilter objects, as they may be
|
||||||
// constructed before the randomizer is properly initialized.
|
// constructed before the randomizer is properly initialized.
|
||||||
CRollingBloomFilter(unsigned int nElements, double nFPRate);
|
CRollingBloomFilter(const unsigned int nElements, const double nFPRate);
|
||||||
|
|
||||||
void insert(const std::vector<unsigned char>& vKey);
|
void insert(const std::vector<unsigned char>& vKey);
|
||||||
void insert(const uint256& hash);
|
void insert(const uint256& hash);
|
||||||
|
@ -129,10 +131,12 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int nBloomSize;
|
int nEntriesPerGeneration;
|
||||||
unsigned int nInsertions;
|
int nEntriesThisGeneration;
|
||||||
CBloomFilter b1, b2;
|
int nGeneration;
|
||||||
|
std::vector<uint64_t> data;
|
||||||
|
unsigned int nTweak;
|
||||||
|
int nHashFuncs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // BITCOIN_BLOOM_H
|
#endif // BITCOIN_BLOOM_H
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
#include "chain.h"
|
#include "chain.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CChain implementation
|
* CChain implementation
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,13 +20,11 @@
|
||||||
#include <boost/algorithm/string/split.hpp>
|
#include <boost/algorithm/string/split.hpp>
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
CScript ParseScript(const std::string& s)
|
CScript ParseScript(const std::string& s)
|
||||||
{
|
{
|
||||||
CScript result;
|
CScript result;
|
||||||
|
|
||||||
static map<string, opcodetype> mapOpNames;
|
static std::map<std::string, opcodetype> mapOpNames;
|
||||||
|
|
||||||
if (mapOpNames.empty())
|
if (mapOpNames.empty())
|
||||||
{
|
{
|
||||||
|
@ -39,7 +37,7 @@ CScript ParseScript(const std::string& s)
|
||||||
const char* name = GetOpName((opcodetype)op);
|
const char* name = GetOpName((opcodetype)op);
|
||||||
if (strcmp(name, "OP_UNKNOWN") == 0)
|
if (strcmp(name, "OP_UNKNOWN") == 0)
|
||||||
continue;
|
continue;
|
||||||
string strName(name);
|
std::string strName(name);
|
||||||
mapOpNames[strName] = (opcodetype)op;
|
mapOpNames[strName] = (opcodetype)op;
|
||||||
// Convenience: OP_ADD and just ADD are both recognized:
|
// Convenience: OP_ADD and just ADD are both recognized:
|
||||||
boost::algorithm::replace_first(strName, "OP_", "");
|
boost::algorithm::replace_first(strName, "OP_", "");
|
||||||
|
@ -47,7 +45,7 @@ CScript ParseScript(const std::string& s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> words;
|
std::vector<std::string> words;
|
||||||
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
|
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
|
for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w)
|
||||||
|
@ -57,16 +55,16 @@ CScript ParseScript(const std::string& s)
|
||||||
// Empty string, ignore. (boost::split given '' will return one word)
|
// Empty string, ignore. (boost::split given '' will return one word)
|
||||||
}
|
}
|
||||||
else if (all(*w, boost::algorithm::is_digit()) ||
|
else if (all(*w, boost::algorithm::is_digit()) ||
|
||||||
(boost::algorithm::starts_with(*w, "-") && all(string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
|
(boost::algorithm::starts_with(*w, "-") && all(std::string(w->begin()+1, w->end()), boost::algorithm::is_digit())))
|
||||||
{
|
{
|
||||||
// Number
|
// Number
|
||||||
int64_t n = atoi64(*w);
|
int64_t n = atoi64(*w);
|
||||||
result << n;
|
result << n;
|
||||||
}
|
}
|
||||||
else if (boost::algorithm::starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end())))
|
else if (boost::algorithm::starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(std::string(w->begin()+2, w->end())))
|
||||||
{
|
{
|
||||||
// Raw hex data, inserted NOT pushed onto stack:
|
// Raw hex data, inserted NOT pushed onto stack:
|
||||||
std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end()));
|
std::vector<unsigned char> raw = ParseHex(std::string(w->begin()+2, w->end()));
|
||||||
result.insert(result.end(), raw.begin(), raw.end());
|
result.insert(result.end(), raw.begin(), raw.end());
|
||||||
}
|
}
|
||||||
else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::ends_with(*w, "'"))
|
else if (w->size() >= 2 && boost::algorithm::starts_with(*w, "'") && boost::algorithm::ends_with(*w, "'"))
|
||||||
|
@ -83,7 +81,7 @@ CScript ParseScript(const std::string& s)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw runtime_error("script parse error");
|
throw std::runtime_error("script parse error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +93,7 @@ bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
|
||||||
if (!IsHex(strHexTx))
|
if (!IsHex(strHexTx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
vector<unsigned char> txData(ParseHex(strHexTx));
|
std::vector<unsigned char> txData(ParseHex(strHexTx));
|
||||||
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
try {
|
try {
|
||||||
ssData >> tx;
|
ssData >> tx;
|
||||||
|
@ -124,9 +122,9 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 ParseHashUV(const UniValue& v, const string& strName)
|
uint256 ParseHashUV(const UniValue& v, const std::string& strName)
|
||||||
{
|
{
|
||||||
string strHex;
|
std::string strHex;
|
||||||
if (v.isStr())
|
if (v.isStr())
|
||||||
strHex = v.getValStr();
|
strHex = v.getValStr();
|
||||||
return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
|
return ParseHashStr(strHex, strName); // Note: ParseHashStr("") throws a runtime_error
|
||||||
|
@ -135,19 +133,19 @@ uint256 ParseHashUV(const UniValue& v, const string& strName)
|
||||||
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
|
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
|
||||||
{
|
{
|
||||||
if (!IsHex(strHex)) // Note: IsHex("") is false
|
if (!IsHex(strHex)) // Note: IsHex("") is false
|
||||||
throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
|
throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')");
|
||||||
|
|
||||||
uint256 result;
|
uint256 result;
|
||||||
result.SetHex(strHex);
|
result.SetHex(strHex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<unsigned char> ParseHexUV(const UniValue& v, const string& strName)
|
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName)
|
||||||
{
|
{
|
||||||
string strHex;
|
std::string strHex;
|
||||||
if (v.isStr())
|
if (v.isStr())
|
||||||
strHex = v.getValStr();
|
strHex = v.getValStr();
|
||||||
if (!IsHex(strHex))
|
if (!IsHex(strHex))
|
||||||
throw runtime_error(strName+" must be hexadecimal string (not '"+strHex+"')");
|
throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')");
|
||||||
return ParseHex(strHex);
|
return ParseHex(strHex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,14 @@
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
|
||||||
using namespace std;
|
std::string FormatScript(const CScript& script)
|
||||||
|
|
||||||
string FormatScript(const CScript& script)
|
|
||||||
{
|
{
|
||||||
string ret;
|
std::string ret;
|
||||||
CScript::const_iterator it = script.begin();
|
CScript::const_iterator it = script.begin();
|
||||||
opcodetype op;
|
opcodetype op;
|
||||||
while (it != script.end()) {
|
while (it != script.end()) {
|
||||||
CScript::const_iterator it2 = it;
|
CScript::const_iterator it2 = it;
|
||||||
vector<unsigned char> vch;
|
std::vector<unsigned char> vch;
|
||||||
if (script.GetOp2(it, op, &vch)) {
|
if (script.GetOp2(it, op, &vch)) {
|
||||||
if (op == OP_0) {
|
if (op == OP_0) {
|
||||||
ret += "0 ";
|
ret += "0 ";
|
||||||
|
@ -34,17 +32,17 @@ string FormatScript(const CScript& script)
|
||||||
} else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
|
} else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
|
||||||
ret += strprintf("%i ", op - OP_1NEGATE - 1);
|
ret += strprintf("%i ", op - OP_1NEGATE - 1);
|
||||||
continue;
|
continue;
|
||||||
} else if (op >= OP_NOP && op <= OP_CHECKMULTISIGVERIFY) {
|
} else if (op >= OP_NOP && op <= OP_NOP10) {
|
||||||
string str(GetOpName(op));
|
std::string str(GetOpName(op));
|
||||||
if (str.substr(0, 3) == string("OP_")) {
|
if (str.substr(0, 3) == std::string("OP_")) {
|
||||||
ret += str.substr(3, string::npos) + " ";
|
ret += str.substr(3, std::string::npos) + " ";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vch.size() > 0) {
|
if (vch.size() > 0) {
|
||||||
ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it));
|
ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it));
|
||||||
} else {
|
} else {
|
||||||
ret += strprintf("0x%x", HexStr(it2, it));
|
ret += strprintf("0x%x ", HexStr(it2, it));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -54,14 +52,14 @@ string FormatScript(const CScript& script)
|
||||||
return ret.substr(0, ret.size() - 1);
|
return ret.substr(0, ret.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const map<unsigned char, string> mapSigHashTypes =
|
const std::map<unsigned char, std::string> mapSigHashTypes =
|
||||||
boost::assign::map_list_of
|
boost::assign::map_list_of
|
||||||
(static_cast<unsigned char>(SIGHASH_ALL), string("ALL"))
|
(static_cast<unsigned char>(SIGHASH_ALL), std::string("ALL"))
|
||||||
(static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), string("ALL|ANYONECANPAY"))
|
(static_cast<unsigned char>(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY"))
|
||||||
(static_cast<unsigned char>(SIGHASH_NONE), string("NONE"))
|
(static_cast<unsigned char>(SIGHASH_NONE), std::string("NONE"))
|
||||||
(static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), string("NONE|ANYONECANPAY"))
|
(static_cast<unsigned char>(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY"))
|
||||||
(static_cast<unsigned char>(SIGHASH_SINGLE), string("SINGLE"))
|
(static_cast<unsigned char>(SIGHASH_SINGLE), std::string("SINGLE"))
|
||||||
(static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), string("SINGLE|ANYONECANPAY"))
|
(static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY"))
|
||||||
;
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,11 +69,11 @@ const map<unsigned char, string> mapSigHashTypes =
|
||||||
* of a signature. Only pass true for scripts you believe could contain signatures. For example,
|
* of a signature. Only pass true for scripts you believe could contain signatures. For example,
|
||||||
* pass false, or omit the this argument (defaults to false), for scriptPubKeys.
|
* pass false, or omit the this argument (defaults to false), for scriptPubKeys.
|
||||||
*/
|
*/
|
||||||
string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
|
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
|
||||||
{
|
{
|
||||||
string str;
|
std::string str;
|
||||||
opcodetype opcode;
|
opcodetype opcode;
|
||||||
vector<unsigned char> vch;
|
std::vector<unsigned char> vch;
|
||||||
CScript::const_iterator pc = script.begin();
|
CScript::const_iterator pc = script.begin();
|
||||||
while (pc < script.end()) {
|
while (pc < script.end()) {
|
||||||
if (!str.empty()) {
|
if (!str.empty()) {
|
||||||
|
@ -86,12 +84,12 @@ string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
if (0 <= opcode && opcode <= OP_PUSHDATA4) {
|
if (0 <= opcode && opcode <= OP_PUSHDATA4) {
|
||||||
if (vch.size() <= static_cast<vector<unsigned char>::size_type>(4)) {
|
if (vch.size() <= static_cast<std::vector<unsigned char>::size_type>(4)) {
|
||||||
str += strprintf("%d", CScriptNum(vch, false).getint());
|
str += strprintf("%d", CScriptNum(vch, false).getint());
|
||||||
} else {
|
} else {
|
||||||
// the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
|
// the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
|
||||||
if (fAttemptSighashDecode && !script.IsUnspendable()) {
|
if (fAttemptSighashDecode && !script.IsUnspendable()) {
|
||||||
string strSigHashDecode;
|
std::string strSigHashDecode;
|
||||||
// goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
|
// goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
|
||||||
// this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
|
// this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
|
||||||
// the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
|
// the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
|
||||||
|
@ -115,7 +113,7 @@ string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
string EncodeHexTx(const CTransaction& tx)
|
std::string EncodeHexTx(const CTransaction& tx)
|
||||||
{
|
{
|
||||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ssTx << tx;
|
ssTx << tx;
|
||||||
|
@ -126,7 +124,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
||||||
UniValue& out, bool fIncludeHex)
|
UniValue& out, bool fIncludeHex)
|
||||||
{
|
{
|
||||||
txnouttype type;
|
txnouttype type;
|
||||||
vector<CTxDestination> addresses;
|
std::vector<CTxDestination> addresses;
|
||||||
int nRequired;
|
int nRequired;
|
||||||
|
|
||||||
out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
|
out.pushKV("asm", ScriptToAsmStr(scriptPubKey));
|
||||||
|
|
27
src/init.cpp
27
src/init.cpp
|
@ -68,7 +68,6 @@
|
||||||
|
|
||||||
#include "librustzcash.h"
|
#include "librustzcash.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace boost::placeholders;
|
using namespace boost::placeholders;
|
||||||
|
|
||||||
extern void ThreadSendAlert();
|
extern void ThreadSendAlert();
|
||||||
|
@ -313,10 +312,10 @@ void OnRPCStopped()
|
||||||
void OnRPCPreCommand(const CRPCCommand& cmd)
|
void OnRPCPreCommand(const CRPCCommand& cmd)
|
||||||
{
|
{
|
||||||
// Observe safe mode
|
// Observe safe mode
|
||||||
string strWarning = GetWarnings("rpc").first;
|
std::string strWarning = GetWarnings("rpc").first;
|
||||||
if (strWarning != "" && !GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) &&
|
if (strWarning != "" && !GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) &&
|
||||||
!cmd.okSafeMode)
|
!cmd.okSafeMode)
|
||||||
throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
|
throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + strWarning);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HelpMessage(HelpMessageMode mode)
|
std::string HelpMessage(HelpMessageMode mode)
|
||||||
|
@ -326,7 +325,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
// When adding new options to the categories, please keep and ensure alphabetical ordering.
|
// When adding new options to the categories, please keep and ensure alphabetical ordering.
|
||||||
// Do not translate _(...) -help-debug options, many technical terms, and only a very small audience, so is unnecessary stress to translators
|
// Do not translate _(...) -help-debug options, many technical terms, and only a very small audience, so is unnecessary stress to translators
|
||||||
|
|
||||||
string strUsage = HelpMessageGroup(_("Options:"));
|
std::string strUsage = HelpMessageGroup(_("Options:"));
|
||||||
strUsage += HelpMessageOpt("-?", _("This help message"));
|
strUsage += HelpMessageOpt("-?", _("This help message"));
|
||||||
strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
|
strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
|
||||||
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
|
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
|
||||||
|
@ -440,7 +439,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
"-fundingstream=streamId:startHeight:endHeight:comma_delimited_addresses",
|
"-fundingstream=streamId:startHeight:endHeight:comma_delimited_addresses",
|
||||||
"Use given addresses for block subsidy share paid to the funding stream with id <streamId> (regtest-only)");
|
"Use given addresses for block subsidy share paid to the funding stream with id <streamId> (regtest-only)");
|
||||||
}
|
}
|
||||||
string debugCategories = "addrman, alert, bench, coindb, db, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, "
|
std::string debugCategories = "addrman, alert, bench, coindb, db, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, "
|
||||||
"rand, receiveunsafe, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these
|
"rand, receiveunsafe, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these
|
||||||
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
|
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
|
||||||
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + debugCategories + ". " +
|
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + debugCategories + ". " +
|
||||||
|
@ -566,7 +565,7 @@ struct CImportingNow
|
||||||
void CleanupBlockRevFiles()
|
void CleanupBlockRevFiles()
|
||||||
{
|
{
|
||||||
using namespace fs;
|
using namespace fs;
|
||||||
map<string, path> mapBlockFiles;
|
std::map<std::string, path> mapBlockFiles;
|
||||||
|
|
||||||
// Glob all blk?????.dat and rev?????.dat files from the blocks directory.
|
// Glob all blk?????.dat and rev?????.dat files from the blocks directory.
|
||||||
// Remove the rev files immediately and insert the blk file paths into an
|
// Remove the rev files immediately and insert the blk file paths into an
|
||||||
|
@ -590,7 +589,7 @@ void CleanupBlockRevFiles()
|
||||||
// keeping a separate counter. Once we hit a gap (or if 0 doesn't exist)
|
// keeping a separate counter. Once we hit a gap (or if 0 doesn't exist)
|
||||||
// start removing block files.
|
// start removing block files.
|
||||||
int nContigCounter = 0;
|
int nContigCounter = 0;
|
||||||
for (const std::pair<string, path>& item : mapBlockFiles) {
|
for (const std::pair<std::string, path>& item : mapBlockFiles) {
|
||||||
if (atoi(item.first) == nContigCounter) {
|
if (atoi(item.first) == nContigCounter) {
|
||||||
nContigCounter++;
|
nContigCounter++;
|
||||||
continue;
|
continue;
|
||||||
|
@ -988,15 +987,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
|
|
||||||
fDebug = !mapMultiArgs["-debug"].empty();
|
fDebug = !mapMultiArgs["-debug"].empty();
|
||||||
// Special-case: if -debug=0/-nodebug is set, turn off debugging messages
|
// Special-case: if -debug=0/-nodebug is set, turn off debugging messages
|
||||||
const vector<string>& categories = mapMultiArgs["-debug"];
|
const std::vector<std::string>& categories = mapMultiArgs["-debug"];
|
||||||
if (GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), string("0")) != categories.end())
|
if (GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end())
|
||||||
fDebug = false;
|
fDebug = false;
|
||||||
|
|
||||||
// Special case: if debug=zrpcunsafe, implies debug=zrpc, so add it to debug categories
|
// Special case: if debug=zrpcunsafe, implies debug=zrpc, so add it to debug categories
|
||||||
if (find(categories.begin(), categories.end(), string("zrpcunsafe")) != categories.end()) {
|
if (find(categories.begin(), categories.end(), std::string("zrpcunsafe")) != categories.end()) {
|
||||||
if (find(categories.begin(), categories.end(), string("zrpc")) == categories.end()) {
|
if (find(categories.begin(), categories.end(), std::string("zrpc")) == categories.end()) {
|
||||||
LogPrintf("%s: parameter interaction: setting -debug=zrpcunsafe -> -debug=zrpc\n", __func__);
|
LogPrintf("%s: parameter interaction: setting -debug=zrpcunsafe -> -debug=zrpc\n", __func__);
|
||||||
vector<string>& v = mapMultiArgs["-debug"];
|
std::vector<std::string>& v = mapMultiArgs["-debug"];
|
||||||
v.push_back("zrpc");
|
v.push_back("zrpc");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1121,7 +1120,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
if (chainparams.NetworkIDString() != "regtest") {
|
if (chainparams.NetworkIDString() != "regtest") {
|
||||||
return InitError("Network upgrade parameters may only be overridden on regtest.");
|
return InitError("Network upgrade parameters may only be overridden on regtest.");
|
||||||
}
|
}
|
||||||
const vector<string>& deployments = mapMultiArgs["-nuparams"];
|
const std::vector<std::string>& deployments = mapMultiArgs["-nuparams"];
|
||||||
for (auto i : deployments) {
|
for (auto i : deployments) {
|
||||||
std::vector<std::string> vDeploymentParams;
|
std::vector<std::string> vDeploymentParams;
|
||||||
boost::split(vDeploymentParams, i, boost::is_any_of(":"));
|
boost::split(vDeploymentParams, i, boost::is_any_of(":"));
|
||||||
|
@ -1320,7 +1319,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
|
|
||||||
// sanitize comments per BIP-0014, format user agent and check total size
|
// sanitize comments per BIP-0014, format user agent and check total size
|
||||||
std::vector<string> uacomments;
|
std::vector<string> uacomments;
|
||||||
for (string cmt : mapMultiArgs["-uacomment"])
|
for (std::string cmt : mapMultiArgs["-uacomment"])
|
||||||
{
|
{
|
||||||
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
|
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
|
||||||
return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt));
|
return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt));
|
||||||
|
|
|
@ -274,12 +274,12 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
|
bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
|
||||||
out.nDepth = nDepth + 1;
|
out.nDepth = nDepth + 1;
|
||||||
CKeyID id = key.GetPubKey().GetID();
|
CKeyID id = key.GetPubKey().GetID();
|
||||||
memcpy(&out.vchFingerprint[0], &id, 4);
|
memcpy(&out.vchFingerprint[0], &id, 4);
|
||||||
out.nChild = nChild;
|
out.nChild = _nChild;
|
||||||
return key.Derive(out.key, out.chaincode, nChild, chaincode);
|
return key.Derive(out.key, out.chaincode, _nChild, chaincode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
|
void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -235,7 +235,7 @@ namespace {
|
||||||
* million to make it highly unlikely for users to have issues with this
|
* million to make it highly unlikely for users to have issues with this
|
||||||
* filter.
|
* filter.
|
||||||
*
|
*
|
||||||
* Memory used: 1.7MB
|
* Memory used: 1.3 MB
|
||||||
*/
|
*/
|
||||||
boost::scoped_ptr<CRollingBloomFilter> recentRejects;
|
boost::scoped_ptr<CRollingBloomFilter> recentRejects;
|
||||||
uint256 hashRecentRejectsChainTip;
|
uint256 hashRecentRejectsChainTip;
|
||||||
|
@ -3065,14 +3065,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS))
|
if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS))
|
||||||
{
|
{
|
||||||
if (pindex->GetUndoPos().IsNull()) {
|
if (pindex->GetUndoPos().IsNull()) {
|
||||||
CDiskBlockPos pos;
|
CDiskBlockPos _pos;
|
||||||
if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
|
if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
|
||||||
return error("ConnectBlock(): FindUndoPos failed");
|
return error("ConnectBlock(): FindUndoPos failed");
|
||||||
if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
|
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
|
||||||
return AbortNode(state, "Failed to write undo data");
|
return AbortNode(state, "Failed to write undo data");
|
||||||
|
|
||||||
// update nUndoPos in block index
|
// update nUndoPos in block index
|
||||||
pindex->nUndoPos = pos.nPos;
|
pindex->nUndoPos = _pos.nPos;
|
||||||
pindex->nStatus |= BLOCK_HAVE_UNDO;
|
pindex->nStatus |= BLOCK_HAVE_UNDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6642,7 +6642,6 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string
|
||||||
LOCK(pfrom->cs_filter);
|
LOCK(pfrom->cs_filter);
|
||||||
delete pfrom->pfilter;
|
delete pfrom->pfilter;
|
||||||
pfrom->pfilter = new CBloomFilter(filter);
|
pfrom->pfilter = new CBloomFilter(filter);
|
||||||
pfrom->pfilter->UpdateEmptyFull();
|
|
||||||
pfrom->fRelayTxes = true;
|
pfrom->fRelayTxes = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,12 @@
|
||||||
#include "consensus/consensus.h"
|
#include "consensus/consensus.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
|
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
|
||||||
{
|
{
|
||||||
header = block.GetBlockHeader();
|
header = block.GetBlockHeader();
|
||||||
|
|
||||||
vector<bool> vMatch;
|
std::vector<bool> vMatch;
|
||||||
vector<uint256> vHashes;
|
std::vector<uint256> vHashes;
|
||||||
|
|
||||||
vMatch.reserve(block.vtx.size());
|
vMatch.reserve(block.vtx.size());
|
||||||
vHashes.reserve(block.vtx.size());
|
vHashes.reserve(block.vtx.size());
|
||||||
|
@ -27,7 +25,7 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
|
||||||
if (filter.IsRelevantAndUpdate(block.vtx[i]))
|
if (filter.IsRelevantAndUpdate(block.vtx[i]))
|
||||||
{
|
{
|
||||||
vMatch.push_back(true);
|
vMatch.push_back(true);
|
||||||
vMatchedTxn.push_back(make_pair(i, hash));
|
vMatchedTxn.push_back(std::make_pair(i, hash));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vMatch.push_back(false);
|
vMatch.push_back(false);
|
||||||
|
@ -41,8 +39,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, const std::set<uint256>& txids)
|
||||||
{
|
{
|
||||||
header = block.GetBlockHeader();
|
header = block.GetBlockHeader();
|
||||||
|
|
||||||
vector<bool> vMatch;
|
std::vector<bool> vMatch;
|
||||||
vector<uint256> vHashes;
|
std::vector<uint256> vHashes;
|
||||||
|
|
||||||
vMatch.reserve(block.vtx.size());
|
vMatch.reserve(block.vtx.size());
|
||||||
vHashes.reserve(block.vtx.size());
|
vHashes.reserve(block.vtx.size());
|
||||||
|
|
|
@ -116,12 +116,12 @@ void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
|
||||||
pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
|
pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
|
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
|
||||||
out.nDepth = nDepth + 1;
|
out.nDepth = nDepth + 1;
|
||||||
CKeyID id = pubkey.GetID();
|
CKeyID id = pubkey.GetID();
|
||||||
memcpy(&out.vchFingerprint[0], &id, 4);
|
memcpy(&out.vchFingerprint[0], &id, 4);
|
||||||
out.nChild = nChild;
|
out.nChild = _nChild;
|
||||||
return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode);
|
return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
|
/* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
|
||||||
|
|
|
@ -100,9 +100,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Construct a public key from a byte vector.
|
//! Construct a public key from a byte vector.
|
||||||
CPubKey(const std::vector<unsigned char>& vch)
|
CPubKey(const std::vector<unsigned char>& _vch)
|
||||||
{
|
{
|
||||||
Set(vch.begin(), vch.end());
|
Set(_vch.begin(), _vch.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Simple read-only vector-like interface to the pubkey data.
|
//! Simple read-only vector-like interface to the pubkey data.
|
||||||
|
|
|
@ -13,9 +13,9 @@ class reverse_lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit reverse_lock(Lock& lock) : lock(lock) {
|
explicit reverse_lock(Lock& _lock) : lock(_lock) {
|
||||||
lock.unlock();
|
_lock.unlock();
|
||||||
lock.swap(templock);
|
_lock.swap(templock);
|
||||||
}
|
}
|
||||||
|
|
||||||
~reverse_lock() {
|
~reverse_lock() {
|
||||||
|
|
|
@ -29,16 +29,17 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
|
||||||
{
|
{
|
||||||
CBloomFilter filter(3, 0.01, 0, BLOOM_UPDATE_ALL);
|
CBloomFilter filter(3, 0.01, 0, BLOOM_UPDATE_ALL);
|
||||||
|
|
||||||
|
BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter should be empty!");
|
||||||
filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
|
filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
|
||||||
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
|
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
|
||||||
// One bit different in first byte
|
// One bit different in first byte
|
||||||
BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter contains something it shouldn't!");
|
BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter contains something it shouldn't!");
|
||||||
|
|
||||||
filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
|
filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
|
||||||
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "BloomFilter doesn't contain just-inserted object (2)!");
|
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "Bloom filter doesn't contain just-inserted object (2)!");
|
||||||
|
|
||||||
filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
|
filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
|
||||||
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");
|
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!");
|
||||||
|
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
stream << filter;
|
stream << filter;
|
||||||
|
@ -51,9 +52,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
|
||||||
|
|
||||||
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
|
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
|
||||||
filter.clear();
|
|
||||||
BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter should be empty!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
|
BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
|
||||||
|
@ -62,15 +61,15 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
|
||||||
CBloomFilter filter(3, 0.01, 2147483649UL, BLOOM_UPDATE_ALL);
|
CBloomFilter filter(3, 0.01, 2147483649UL, BLOOM_UPDATE_ALL);
|
||||||
|
|
||||||
filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
|
filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
|
||||||
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
|
BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
|
||||||
// One bit different in first byte
|
// One bit different in first byte
|
||||||
BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter contains something it shouldn't!");
|
BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter contains something it shouldn't!");
|
||||||
|
|
||||||
filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
|
filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
|
||||||
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "BloomFilter doesn't contain just-inserted object (2)!");
|
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "Bloom filter doesn't contain just-inserted object (2)!");
|
||||||
|
|
||||||
filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
|
filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
|
||||||
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");
|
BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!");
|
||||||
|
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
stream << filter;
|
stream << filter;
|
||||||
|
@ -507,11 +506,14 @@ BOOST_AUTO_TEST_CASE(rolling_bloom)
|
||||||
if (i >= 100)
|
if (i >= 100)
|
||||||
BOOST_CHECK(rb1.contains(data[i-100]));
|
BOOST_CHECK(rb1.contains(data[i-100]));
|
||||||
rb1.insert(data[i]);
|
rb1.insert(data[i]);
|
||||||
|
BOOST_CHECK(rb1.contains(data[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert 999 more random entries:
|
// Insert 999 more random entries:
|
||||||
for (int i = 0; i < 999; i++) {
|
for (int i = 0; i < 999; i++) {
|
||||||
rb1.insert(RandomData());
|
std::vector<unsigned char> d = RandomData();
|
||||||
|
rb1.insert(d);
|
||||||
|
BOOST_CHECK(rb1.contains(d));
|
||||||
}
|
}
|
||||||
// Sanity check to make sure the filter isn't just filling up:
|
// Sanity check to make sure the filter isn't just filling up:
|
||||||
nHits = 0;
|
nHits = 0;
|
||||||
|
|
|
@ -132,13 +132,13 @@ void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> sub(i, in.end());
|
std::vector<unsigned char> sub(i, in.end());
|
||||||
std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
|
std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
|
||||||
int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]);
|
int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]);
|
||||||
if (size != 0)
|
if (_size != 0)
|
||||||
{
|
{
|
||||||
subout.resize(size);
|
subout.resize(_size);
|
||||||
std::vector<unsigned char> subdecrypted(subout.size());
|
std::vector<unsigned char> subdecrypted(subout.size());
|
||||||
size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]);
|
_size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]);
|
||||||
subdecrypted.resize(size);
|
subdecrypted.resize(_size);
|
||||||
BOOST_CHECK(decrypted.size() == in.size());
|
BOOST_CHECK(decrypted.size() == in.size());
|
||||||
BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
|
BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
|
||||||
}
|
}
|
||||||
|
@ -173,13 +173,13 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> sub(i, in.end());
|
std::vector<unsigned char> sub(i, in.end());
|
||||||
std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
|
std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
|
||||||
int size = enc.Encrypt(&sub[0], sub.size(), &subout[0]);
|
int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]);
|
||||||
if (size != 0)
|
if (_size != 0)
|
||||||
{
|
{
|
||||||
subout.resize(size);
|
subout.resize(_size);
|
||||||
std::vector<unsigned char> subdecrypted(subout.size());
|
std::vector<unsigned char> subdecrypted(subout.size());
|
||||||
size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]);
|
_size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]);
|
||||||
subdecrypted.resize(size);
|
subdecrypted.resize(_size);
|
||||||
BOOST_CHECK(decrypted.size() == in.size());
|
BOOST_CHECK(decrypted.size() == in.size());
|
||||||
BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
|
BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,11 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CDataStream AddrmanToStream(CAddrManSerializationMock& addrman)
|
CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
|
||||||
{
|
{
|
||||||
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
|
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
|
||||||
ssPeersIn << FLATDATA(Params().MessageStart());
|
ssPeersIn << FLATDATA(Params().MessageStart());
|
||||||
ssPeersIn << addrman;
|
ssPeersIn << _addrman;
|
||||||
std::string str = ssPeersIn.str();
|
std::string str = ssPeersIn.str();
|
||||||
vector<unsigned char> vchData(str.begin(), str.end());
|
vector<unsigned char> vchData(str.begin(), str.end());
|
||||||
return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
|
return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
|
||||||
|
|
|
@ -208,10 +208,10 @@ public:
|
||||||
spendTx = BuildSpendingTransaction(CScript(), creditTx);
|
spendTx = BuildSpendingTransaction(CScript(), creditTx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestBuilder& Add(const CScript& script)
|
TestBuilder& Add(const CScript& _script)
|
||||||
{
|
{
|
||||||
DoPush();
|
DoPush();
|
||||||
spendTx.vin[0].scriptSig += script;
|
spendTx.vin[0].scriptSig += _script;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -312,7 +312,7 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
|
||||||
BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
|
BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
|
||||||
BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
|
BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
|
||||||
BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
|
BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
|
||||||
BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648);
|
BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
|
||||||
BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
|
BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
|
||||||
// Invalid values
|
// Invalid values
|
||||||
BOOST_CHECK(!ParseInt32("", &n));
|
BOOST_CHECK(!ParseInt32("", &n));
|
||||||
|
|
|
@ -122,8 +122,8 @@ private:
|
||||||
static void eventcb(struct bufferevent *bev, short what, void *ctx);
|
static void eventcb(struct bufferevent *bev, short what, void *ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
TorControlConnection::TorControlConnection(struct event_base *base):
|
TorControlConnection::TorControlConnection(struct event_base *_base):
|
||||||
base(base), b_conn(0)
|
base(_base), b_conn(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& connected, const ConnectionCB& disconnected)
|
bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& _connected, const ConnectionCB& _disconnected)
|
||||||
{
|
{
|
||||||
if (b_conn)
|
if (b_conn)
|
||||||
Disconnect();
|
Disconnect();
|
||||||
|
@ -213,8 +213,8 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB
|
||||||
return false;
|
return false;
|
||||||
bufferevent_setcb(b_conn, TorControlConnection::readcb, NULL, TorControlConnection::eventcb, this);
|
bufferevent_setcb(b_conn, TorControlConnection::readcb, NULL, TorControlConnection::eventcb, this);
|
||||||
bufferevent_enable(b_conn, EV_READ|EV_WRITE);
|
bufferevent_enable(b_conn, EV_READ|EV_WRITE);
|
||||||
this->connected = connected;
|
this->connected = _connected;
|
||||||
this->disconnected = disconnected;
|
this->disconnected = _disconnected;
|
||||||
|
|
||||||
// Finally, connect to target
|
// Finally, connect to target
|
||||||
if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) {
|
if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) {
|
||||||
|
@ -452,18 +452,18 @@ private:
|
||||||
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
|
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
TorController::TorController(struct event_base* baseIn, const std::string& target):
|
TorController::TorController(struct event_base* _base, const std::string& _target):
|
||||||
base(baseIn),
|
base(_base),
|
||||||
target(target), conn(base), reconnect(true), reconnect_ev(0),
|
target(_target), conn(base), reconnect(true), reconnect_ev(0),
|
||||||
reconnect_timeout(RECONNECT_TIMEOUT_START)
|
reconnect_timeout(RECONNECT_TIMEOUT_START)
|
||||||
{
|
{
|
||||||
reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
|
reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
|
||||||
if (!reconnect_ev)
|
if (!reconnect_ev)
|
||||||
LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
|
LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
|
||||||
// Start connection attempts immediately
|
// Start connection attempts immediately
|
||||||
if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1),
|
if (!conn.Connect(_target, boost::bind(&TorController::connected_cb, this, _1),
|
||||||
boost::bind(&TorController::disconnected_cb, this, _1) )) {
|
boost::bind(&TorController::disconnected_cb, this, _1) )) {
|
||||||
LogPrintf("tor: Initiating connection to Tor control port %s failed\n", target);
|
LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target);
|
||||||
}
|
}
|
||||||
// Read service private key if cached
|
// Read service private key if cached
|
||||||
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
|
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
|
||||||
|
@ -484,7 +484,7 @@ TorController::~TorController()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorController::add_onion_cb(TorControlConnection& conn, const TorControlReply& reply)
|
void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||||
{
|
{
|
||||||
if (reply.code == 250) {
|
if (reply.code == 250) {
|
||||||
LogPrint("tor", "tor: ADD_ONION successful\n");
|
LogPrint("tor", "tor: ADD_ONION successful\n");
|
||||||
|
@ -520,7 +520,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& reply)
|
void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||||
{
|
{
|
||||||
if (reply.code == 250) {
|
if (reply.code == 250) {
|
||||||
LogPrint("tor", "tor: Authentication successful\n");
|
LogPrint("tor", "tor: Authentication successful\n");
|
||||||
|
@ -539,7 +539,7 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r
|
||||||
// Request hidden service, redirect port.
|
// Request hidden service, redirect port.
|
||||||
// Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient
|
// Note that the 'virtual' port doesn't have to be the same as our internal port, but this is just a convenient
|
||||||
// choice. TODO; refactor the shutdown sequence some day.
|
// choice. TODO; refactor the shutdown sequence some day.
|
||||||
conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()),
|
_conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, GetListenPort(), GetListenPort()),
|
||||||
boost::bind(&TorController::add_onion_cb, this, _1, _2));
|
boost::bind(&TorController::add_onion_cb, this, _1, _2));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("tor: Authentication failed\n");
|
LogPrintf("tor: Authentication failed\n");
|
||||||
|
@ -573,7 +573,7 @@ static std::vector<uint8_t> ComputeResponse(const std::string &key, const std::v
|
||||||
return computedHash;
|
return computedHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorController::authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply)
|
void TorController::authchallenge_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||||
{
|
{
|
||||||
if (reply.code == 250) {
|
if (reply.code == 250) {
|
||||||
LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n");
|
LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n");
|
||||||
|
@ -599,7 +599,7 @@ void TorController::authchallenge_cb(TorControlConnection& conn, const TorContro
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce);
|
std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce);
|
||||||
conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2));
|
_conn.Command("AUTHENTICATE " + HexStr(computedClientHash), boost::bind(&TorController::auth_cb, this, _1, _2));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n");
|
LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n");
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ void TorController::authchallenge_cb(TorControlConnection& conn, const TorContro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply)
|
void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||||
{
|
{
|
||||||
if (reply.code == 250) {
|
if (reply.code == 250) {
|
||||||
std::set<std::string> methods;
|
std::set<std::string> methods;
|
||||||
|
@ -648,23 +648,23 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl
|
||||||
if (methods.count("HASHEDPASSWORD")) {
|
if (methods.count("HASHEDPASSWORD")) {
|
||||||
LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n");
|
LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n");
|
||||||
boost::replace_all(torpassword, "\"", "\\\"");
|
boost::replace_all(torpassword, "\"", "\\\"");
|
||||||
conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2));
|
_conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2));
|
||||||
} else {
|
} else {
|
||||||
LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n");
|
LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n");
|
||||||
}
|
}
|
||||||
} else if (methods.count("NULL")) {
|
} else if (methods.count("NULL")) {
|
||||||
LogPrint("tor", "tor: Using NULL authentication\n");
|
LogPrint("tor", "tor: Using NULL authentication\n");
|
||||||
conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2));
|
_conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2));
|
||||||
} else if (methods.count("SAFECOOKIE")) {
|
} else if (methods.count("SAFECOOKIE")) {
|
||||||
// Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie
|
// Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie
|
||||||
LogPrint("tor", "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile);
|
LogPrint("tor", "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile);
|
||||||
std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE);
|
std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE);
|
||||||
if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) {
|
if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) {
|
||||||
// conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2));
|
// _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2));
|
||||||
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
|
cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
|
||||||
clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
|
clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
|
||||||
GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE);
|
GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE);
|
||||||
conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2));
|
_conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&TorController::authchallenge_cb, this, _1, _2));
|
||||||
} else {
|
} else {
|
||||||
if (status_cookie.first) {
|
if (status_cookie.first) {
|
||||||
LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE);
|
LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE);
|
||||||
|
@ -682,15 +682,15 @@ void TorController::protocolinfo_cb(TorControlConnection& conn, const TorControl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorController::connected_cb(TorControlConnection& conn)
|
void TorController::connected_cb(TorControlConnection& _conn)
|
||||||
{
|
{
|
||||||
reconnect_timeout = RECONNECT_TIMEOUT_START;
|
reconnect_timeout = RECONNECT_TIMEOUT_START;
|
||||||
// First send a PROTOCOLINFO command to figure out what authentication is expected
|
// First send a PROTOCOLINFO command to figure out what authentication is expected
|
||||||
if (!conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2)))
|
if (!_conn.Command("PROTOCOLINFO 1", boost::bind(&TorController::protocolinfo_cb, this, _1, _2)))
|
||||||
LogPrintf("tor: Error sending initial protocolinfo command\n");
|
LogPrintf("tor: Error sending initial protocolinfo command\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorController::disconnected_cb(TorControlConnection& conn)
|
void TorController::disconnected_cb(TorControlConnection& _conn)
|
||||||
{
|
{
|
||||||
// Stop advertizing service when disconnected
|
// Stop advertizing service when disconnected
|
||||||
if (service.IsValid())
|
if (service.IsValid())
|
||||||
|
|
|
@ -506,7 +506,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate);
|
const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
list<const CTxMemPoolEntry*> waitingOnDependants;
|
std::list<const CTxMemPoolEntry*> waitingOnDependants;
|
||||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
checkTotal += it->GetTxSize();
|
checkTotal += it->GetTxSize();
|
||||||
|
@ -628,7 +628,7 @@ void CTxMemPool::checkNullifiers(ShieldedType type) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPool::queryHashes(vector<uint256>& vtxid)
|
void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
|
||||||
{
|
{
|
||||||
vtxid.clear();
|
vtxid.clear();
|
||||||
|
|
||||||
|
@ -693,7 +693,7 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, const CAmount& nFeeDelta)
|
void CTxMemPool::PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
|
@ -824,8 +824,8 @@ set<uint256> CWallet::GetConflicts(const uint256& txid) const
|
||||||
if (mapTxSpends.count(txin.prevout) <= 1)
|
if (mapTxSpends.count(txin.prevout) <= 1)
|
||||||
continue; // No conflict if zero or one spends
|
continue; // No conflict if zero or one spends
|
||||||
range = mapTxSpends.equal_range(txin.prevout);
|
range = mapTxSpends.equal_range(txin.prevout);
|
||||||
for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
|
for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it)
|
||||||
result.insert(it->second);
|
result.insert(_it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
|
std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_n;
|
||||||
|
@ -2521,9 +2521,9 @@ int CWalletTx::GetRequestCount() const
|
||||||
// How about the block it's in?
|
// How about the block it's in?
|
||||||
if (nRequests == 0 && !hashBlock.IsNull())
|
if (nRequests == 0 && !hashBlock.IsNull())
|
||||||
{
|
{
|
||||||
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
|
map<uint256, int>::const_iterator _mi = pwallet->mapRequestCount.find(hashBlock);
|
||||||
if (mi != pwallet->mapRequestCount.end())
|
if (_mi != pwallet->mapRequestCount.end())
|
||||||
nRequests = (*mi).second;
|
nRequests = (*_mi).second;
|
||||||
else
|
else
|
||||||
nRequests = 1; // If it's in someone else's block it must have got out
|
nRequests = 1; // If it's in someone else's block it must have got out
|
||||||
}
|
}
|
||||||
|
@ -4309,17 +4309,17 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||||
|
|
||||||
set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
|
set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
|
||||||
map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
|
map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
|
||||||
for (set<CTxDestination> grouping : groupings)
|
for (set<CTxDestination> _grouping : groupings)
|
||||||
{
|
{
|
||||||
// make a set of all the groups hit by this new group
|
// make a set of all the groups hit by this new group
|
||||||
set< set<CTxDestination>* > hits;
|
set< set<CTxDestination>* > hits;
|
||||||
map< CTxDestination, set<CTxDestination>* >::iterator it;
|
map< CTxDestination, set<CTxDestination>* >::iterator it;
|
||||||
for (CTxDestination address : grouping)
|
for (CTxDestination address : _grouping)
|
||||||
if ((it = setmap.find(address)) != setmap.end())
|
if ((it = setmap.find(address)) != setmap.end())
|
||||||
hits.insert((*it).second);
|
hits.insert((*it).second);
|
||||||
|
|
||||||
// merge all hit groups into a new single group and delete old groups
|
// merge all hit groups into a new single group and delete old groups
|
||||||
set<CTxDestination>* merged = new set<CTxDestination>(grouping);
|
set<CTxDestination>* merged = new set<CTxDestination>(_grouping);
|
||||||
for (set<CTxDestination>* hit : hits)
|
for (set<CTxDestination>* hit : hits)
|
||||||
{
|
{
|
||||||
merged->insert(hit->begin(), hit->end());
|
merged->insert(hit->begin(), hit->end());
|
||||||
|
|
Loading…
Reference in New Issue