mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-03 02:06:18 +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
141 lines
5.8 KiB
C++
141 lines
5.8 KiB
C++
// Copyright (c) 2016-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 <policy/rbf.h>
|
|
|
|
#include <consensus/amount.h>
|
|
#include <kernel/mempool_entry.h>
|
|
#include <policy/feerate.h>
|
|
#include <primitives/transaction.h>
|
|
#include <sync.h>
|
|
#include <tinyformat.h>
|
|
#include <txmempool.h>
|
|
#include <uint256.h>
|
|
#include <util/check.h>
|
|
#include <util/moneystr.h>
|
|
#include <util/rbf.h>
|
|
|
|
#include <limits>
|
|
#include <vector>
|
|
|
|
#include <compare>
|
|
|
|
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
|
|
{
|
|
AssertLockHeld(pool.cs);
|
|
|
|
// First check the transaction itself.
|
|
if (SignalsOptInRBF(tx)) {
|
|
return RBFTransactionState::REPLACEABLE_BIP125;
|
|
}
|
|
|
|
// If this transaction is not in our mempool, then we can't be sure
|
|
// we will know about all its inputs.
|
|
if (!pool.exists(tx.GetHash())) {
|
|
return RBFTransactionState::UNKNOWN;
|
|
}
|
|
|
|
// If all the inputs have nSequence >= maxint-1, it still might be
|
|
// signaled for RBF if any unconfirmed parents have signaled.
|
|
const auto& entry{*Assert(pool.GetEntry(tx.GetHash()))};
|
|
auto ancestors{pool.CalculateMemPoolAncestors(entry)};
|
|
|
|
for (CTxMemPool::txiter it : ancestors) {
|
|
if (SignalsOptInRBF(it->GetTx())) {
|
|
return RBFTransactionState::REPLACEABLE_BIP125;
|
|
}
|
|
}
|
|
return RBFTransactionState::FINAL;
|
|
}
|
|
|
|
RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
|
|
{
|
|
// If we don't have a local mempool we can only check the transaction itself.
|
|
return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
|
|
}
|
|
|
|
std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
|
|
CTxMemPool& pool,
|
|
const CTxMemPool::setEntries& iters_conflicting,
|
|
CTxMemPool::setEntries& all_conflicts)
|
|
{
|
|
AssertLockHeld(pool.cs);
|
|
// Rule #5: don't consider replacements that conflict directly with more
|
|
// than MAX_REPLACEMENT_CANDIDATES distinct clusters. This implies a bound
|
|
// on how many mempool clusters might need to be re-sorted in order to
|
|
// process the replacement (though the actual number of clusters we
|
|
// relinearize may be greater than this number, due to cluster splitting).
|
|
auto num_clusters = pool.GetUniqueClusterCount(iters_conflicting);
|
|
if (num_clusters > MAX_REPLACEMENT_CANDIDATES) {
|
|
return strprintf("rejecting replacement %s; too many conflicting clusters (%u > %d)",
|
|
tx.GetHash().ToString(),
|
|
num_clusters,
|
|
MAX_REPLACEMENT_CANDIDATES);
|
|
}
|
|
// Calculate the set of all transactions that would have to be evicted.
|
|
for (CTxMemPool::txiter it : iters_conflicting) {
|
|
// The cluster count limit ensures that we won't do too much work on a
|
|
// single invocation of this function.
|
|
pool.CalculateDescendants(it, all_conflicts);
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries& ancestors,
|
|
const std::set<Txid>& direct_conflicts,
|
|
const Txid& txid)
|
|
{
|
|
for (CTxMemPool::txiter ancestorIt : ancestors) {
|
|
const Txid& hashAncestor = ancestorIt->GetTx().GetHash();
|
|
if (direct_conflicts.contains(hashAncestor)) {
|
|
return strprintf("%s spends conflicting transaction %s",
|
|
txid.ToString(),
|
|
hashAncestor.ToString());
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<std::string> PaysForRBF(CAmount original_fees,
|
|
CAmount replacement_fees,
|
|
size_t replacement_vsize,
|
|
CFeeRate relay_fee,
|
|
const Txid& txid)
|
|
{
|
|
// Rule #3: The replacement fees must be greater than or equal to fees of the
|
|
// transactions it replaces, otherwise the bandwidth used by those conflicting transactions
|
|
// would not be paid for.
|
|
if (replacement_fees < original_fees) {
|
|
return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
|
|
txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
|
|
}
|
|
|
|
// Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
|
|
// vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
|
|
// increasing the fee by tiny amounts.
|
|
CAmount additional_fees = replacement_fees - original_fees;
|
|
if (additional_fees < relay_fee.GetFee(replacement_vsize)) {
|
|
return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
|
|
txid.ToString(),
|
|
FormatMoney(additional_fees),
|
|
FormatMoney(relay_fee.GetFee(replacement_vsize)));
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<std::pair<DiagramCheckError, std::string>> ImprovesFeerateDiagram(CTxMemPool::ChangeSet& changeset)
|
|
{
|
|
// Require that the replacement strictly improves the mempool's feerate diagram.
|
|
const auto chunk_results{changeset.CalculateChunksForRBF()};
|
|
|
|
if (!chunk_results.has_value()) {
|
|
return std::make_pair(DiagramCheckError::UNCALCULABLE, util::ErrorString(chunk_results).original);
|
|
}
|
|
|
|
if (!std::is_gt(CompareChunks(chunk_results.value().second, chunk_results.value().first))) {
|
|
return std::make_pair(DiagramCheckError::FAILURE, "insufficient feerate: does not improve feerate diagram");
|
|
}
|
|
return std::nullopt;
|
|
}
|