mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-13 00:48:59 +00:00
fa4cb13b52030c2e55c6bea170649ab69d75f758 test: [doc] Manually unify stale headers (MarcoFalke)
fa5f29774872d18febc0df38831a6e45f3de69cc scripted-diff: [doc] Unify stale copyright headers (MarcoFalke)
Pull request description:
Historically, the upper year range in file headers was bumped manually
or with a script.
This has many issues:
* The script is causing churn. See for example commit 306ccd4, or
drive-by first-time contributions bumping them one-by-one. (A few from
this year: https://github.com/bitcoin/bitcoin/pull/32008,
https://github.com/bitcoin/bitcoin/pull/31642,
https://github.com/bitcoin/bitcoin/pull/32963, ...)
* Some, or likely most, upper year values were wrong. Reasons for
incorrect dates could be code moves, cherry-picks, or simply bugs in
the script.
* The upper range is not needed for anything.
* Anyone who wants to find the initial file creation date, or file
history, can use `git log` or `git blame` to get more accurate
results.
* Many places are already using the `-present` suffix, with the meaning
that the upper range is omitted.
To fix all issues, this bumps the upper range of the copyright headers
to `-present`.
Further notes:
* Obviously, the yearly 4-line bump commit for the build system (c.f.
b537a2c02a9921235d1ecf8c3c7dc1836ec68131) is fine and will remain.
* For new code, the date range can be fully omitted, as it is done
already by some developers. Obviously, developers are free to pick
whatever style they want. One can list the commits for each style.
* For example, to list all commits that use `-present`:
`git log --format='%an (%ae) [%h: %s]' -S 'present The Bitcoin'`.
* Alternatively, to list all commits that use no range at all:
`git log --format='%an (%ae) [%h: %s]' -S '(c) The Bitcoin'`.
<!--
* The lower range can be wrong as well, so it could be omitted as well,
but this is left for a follow-up. A previous attempt was in
https://github.com/bitcoin/bitcoin/pull/26817.
ACKs for top commit:
l0rinc:
ACK fa4cb13b52030c2e55c6bea170649ab69d75f758
rkrux:
re-ACK fa4cb13b52030c2e55c6bea170649ab69d75f758
janb84:
ACK fa4cb13b52030c2e55c6bea170649ab69d75f758
Tree-SHA512: e5132781bdc4417d1e2922809b27ef4cf0abb37ffb68c65aab8a5391d3c917b61a18928ec2ec2c75ef5184cb79a5b8c8290d63e949220dbeab3bd2c0dfbdc4c5
184 lines
6.8 KiB
C++
184 lines
6.8 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-present The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <merkleblock.h>
|
|
|
|
#include <hash.h>
|
|
#include <consensus/consensus.h>
|
|
|
|
|
|
std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits)
|
|
{
|
|
std::vector<unsigned char> ret((bits.size() + 7) / 8);
|
|
for (unsigned int p = 0; p < bits.size(); p++) {
|
|
ret[p / 8] |= bits[p] << (p % 8);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes)
|
|
{
|
|
std::vector<bool> ret(bytes.size() * 8);
|
|
for (unsigned int p = 0; p < ret.size(); p++) {
|
|
ret[p] = (bytes[p / 8] & (1 << (p % 8))) != 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<Txid>* txids)
|
|
{
|
|
header = block.GetBlockHeader();
|
|
|
|
std::vector<bool> vMatch;
|
|
std::vector<Txid> vHashes;
|
|
|
|
vMatch.reserve(block.vtx.size());
|
|
vHashes.reserve(block.vtx.size());
|
|
|
|
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
|
{
|
|
const Txid& hash{block.vtx[i]->GetHash()};
|
|
if (txids && txids->contains(hash)) {
|
|
vMatch.push_back(true);
|
|
} else if (filter && filter->IsRelevantAndUpdate(*block.vtx[i])) {
|
|
vMatch.push_back(true);
|
|
vMatchedTxn.emplace_back(i, hash);
|
|
} else {
|
|
vMatch.push_back(false);
|
|
}
|
|
vHashes.push_back(hash);
|
|
}
|
|
|
|
txn = CPartialMerkleTree(vHashes, vMatch);
|
|
}
|
|
|
|
// NOLINTNEXTLINE(misc-no-recursion)
|
|
uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::vector<Txid> &vTxid) {
|
|
//we can never have zero txs in a merkle block, we always need the coinbase tx
|
|
//if we do not have this assert, we can hit a memory access violation when indexing into vTxid
|
|
assert(vTxid.size() != 0);
|
|
if (height == 0) {
|
|
// hash at height 0 is the txids themselves
|
|
return vTxid[pos].ToUint256();
|
|
} else {
|
|
// calculate left hash
|
|
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
|
|
// calculate right hash if not beyond the end of the array - copy left hash otherwise
|
|
if (pos*2+1 < CalcTreeWidth(height-1))
|
|
right = CalcHash(height-1, pos*2+1, vTxid);
|
|
else
|
|
right = left;
|
|
// combine subhashes
|
|
return Hash(left, right);
|
|
}
|
|
}
|
|
|
|
// NOLINTNEXTLINE(misc-no-recursion)
|
|
void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const std::vector<Txid> &vTxid, const std::vector<bool> &vMatch) {
|
|
// determine whether this node is the parent of at least one matched txid
|
|
bool fParentOfMatch = false;
|
|
for (unsigned int p = pos << height; p < (pos+1) << height && p < nTransactions; p++)
|
|
fParentOfMatch |= vMatch[p];
|
|
// store as flag bit
|
|
vBits.push_back(fParentOfMatch);
|
|
if (height==0 || !fParentOfMatch) {
|
|
// if at height 0, or nothing interesting below, store hash and stop
|
|
vHash.push_back(CalcHash(height, pos, vTxid));
|
|
} else {
|
|
// otherwise, don't store any hash, but descend into the subtrees
|
|
TraverseAndBuild(height-1, pos*2, vTxid, vMatch);
|
|
if (pos*2+1 < CalcTreeWidth(height-1))
|
|
TraverseAndBuild(height-1, pos*2+1, vTxid, vMatch);
|
|
}
|
|
}
|
|
|
|
// NOLINTNEXTLINE(misc-no-recursion)
|
|
uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<Txid> &vMatch, std::vector<unsigned int> &vnIndex) {
|
|
if (nBitsUsed >= vBits.size()) {
|
|
// overflowed the bits array - failure
|
|
fBad = true;
|
|
return uint256();
|
|
}
|
|
bool fParentOfMatch = vBits[nBitsUsed++];
|
|
if (height==0 || !fParentOfMatch) {
|
|
// if at height 0, or nothing interesting below, use stored hash and do not descend
|
|
if (nHashUsed >= vHash.size()) {
|
|
// overflowed the hash array - failure
|
|
fBad = true;
|
|
return uint256();
|
|
}
|
|
const uint256 &hash = vHash[nHashUsed++];
|
|
if (height==0 && fParentOfMatch) { // in case of height 0, we have a matched txid
|
|
vMatch.push_back(Txid::FromUint256(hash));
|
|
vnIndex.push_back(pos);
|
|
}
|
|
return hash;
|
|
} else {
|
|
// otherwise, descend into the subtrees to extract matched txids and hashes
|
|
uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch, vnIndex), right;
|
|
if (pos*2+1 < CalcTreeWidth(height-1)) {
|
|
right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch, vnIndex);
|
|
if (right == left) {
|
|
// The left and right branches should never be identical, as the transaction
|
|
// hashes covered by them must each be unique.
|
|
fBad = true;
|
|
}
|
|
} else {
|
|
right = left;
|
|
}
|
|
// and combine them before returning
|
|
return Hash(left, right);
|
|
}
|
|
}
|
|
|
|
CPartialMerkleTree::CPartialMerkleTree(const std::vector<Txid> &vTxid, const std::vector<bool> &vMatch) : nTransactions(vTxid.size()), fBad(false) {
|
|
// reset state
|
|
vBits.clear();
|
|
vHash.clear();
|
|
|
|
// calculate height of tree
|
|
int nHeight = 0;
|
|
while (CalcTreeWidth(nHeight) > 1)
|
|
nHeight++;
|
|
|
|
// traverse the partial tree
|
|
TraverseAndBuild(nHeight, 0, vTxid, vMatch);
|
|
}
|
|
|
|
CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
|
|
|
|
uint256 CPartialMerkleTree::ExtractMatches(std::vector<Txid> &vMatch, std::vector<unsigned int> &vnIndex) {
|
|
vMatch.clear();
|
|
// An empty set will not work
|
|
if (nTransactions == 0)
|
|
return uint256();
|
|
// check for excessively high numbers of transactions
|
|
if (nTransactions > MAX_BLOCK_WEIGHT / MIN_TRANSACTION_WEIGHT)
|
|
return uint256();
|
|
// there can never be more hashes provided than one for every txid
|
|
if (vHash.size() > nTransactions)
|
|
return uint256();
|
|
// there must be at least one bit per node in the partial tree, and at least one node per hash
|
|
if (vBits.size() < vHash.size())
|
|
return uint256();
|
|
// calculate height of tree
|
|
int nHeight = 0;
|
|
while (CalcTreeWidth(nHeight) > 1)
|
|
nHeight++;
|
|
// traverse the partial tree
|
|
unsigned int nBitsUsed = 0, nHashUsed = 0;
|
|
uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch, vnIndex);
|
|
// verify that no problems occurred during the tree traversal
|
|
if (fBad)
|
|
return uint256();
|
|
// verify that all bits were consumed (except for the padding caused by serializing it as a byte sequence)
|
|
if ((nBitsUsed+7)/8 != (vBits.size()+7)/8)
|
|
return uint256();
|
|
// verify that all hashes were consumed
|
|
if (nHashUsed != vHash.size())
|
|
return uint256();
|
|
return hashMerkleRoot;
|
|
}
|