forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master'
- Loading branch information
Showing
197 changed files
with
32,100 additions
and
15,918 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[main] | ||
host = https://www.transifex.com | ||
|
||
[o:bitcoin:p:bitcoin:r:qt-translation-026x] | ||
[o:bitcoin:p:bitcoin:r:qt-translation-027x] | ||
file_filter = src/qt/locale/bitcoin_<lang>.xlf | ||
source_file = src/qt/locale/bitcoin_en.xlf | ||
source_lang = en |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
QT_TS = \ | ||
qt/locale/bitcoin_af.ts \ | ||
qt/locale/bitcoin_am.ts \ | ||
qt/locale/bitcoin_ar.ts \ | ||
qt/locale/bitcoin_az.ts \ | ||
qt/locale/[email protected] \ | ||
qt/locale/bitcoin_be.ts \ | ||
|
@@ -31,6 +31,7 @@ QT_TS = \ | |
qt/locale/bitcoin_fa.ts \ | ||
qt/locale/bitcoin_fi.ts \ | ||
qt/locale/bitcoin_fil.ts \ | ||
qt/locale/bitcoin_fo.ts \ | ||
qt/locale/bitcoin_fr.ts \ | ||
qt/locale/bitcoin_fr_CM.ts \ | ||
qt/locale/bitcoin_fr_LU.ts \ | ||
|
@@ -52,6 +53,7 @@ QT_TS = \ | |
qt/locale/bitcoin_ja.ts \ | ||
qt/locale/bitcoin_ka.ts \ | ||
qt/locale/bitcoin_kk.ts \ | ||
qt/locale/[email protected] \ | ||
qt/locale/bitcoin_kl.ts \ | ||
qt/locale/bitcoin_km.ts \ | ||
qt/locale/bitcoin_kn.ts \ | ||
|
@@ -60,15 +62,18 @@ QT_TS = \ | |
qt/locale/bitcoin_ku_IQ.ts \ | ||
qt/locale/bitcoin_ky.ts \ | ||
qt/locale/bitcoin_la.ts \ | ||
qt/locale/bitcoin_lb.ts \ | ||
qt/locale/bitcoin_lt.ts \ | ||
qt/locale/bitcoin_lv.ts \ | ||
qt/locale/bitcoin_mg.ts \ | ||
qt/locale/bitcoin_mi.ts \ | ||
qt/locale/bitcoin_mk.ts \ | ||
qt/locale/bitcoin_ml.ts \ | ||
qt/locale/bitcoin_mn.ts \ | ||
qt/locale/bitcoin_mr.ts \ | ||
qt/locale/bitcoin_mr_IN.ts \ | ||
qt/locale/bitcoin_ms.ts \ | ||
qt/locale/bitcoin_mt.ts \ | ||
qt/locale/bitcoin_my.ts \ | ||
qt/locale/bitcoin_nb.ts \ | ||
qt/locale/bitcoin_ne.ts \ | ||
|
@@ -78,11 +83,12 @@ QT_TS = \ | |
qt/locale/bitcoin_pam.ts \ | ||
qt/locale/bitcoin_pl.ts \ | ||
qt/locale/bitcoin_pt.ts \ | ||
qt/locale/[email protected] \ | ||
qt/locale/bitcoin_pt_BR.ts \ | ||
qt/locale/bitcoin_ro.ts \ | ||
qt/locale/bitcoin_ru.ts \ | ||
qt/locale/bitcoin_ru_RU.ts \ | ||
qt/locale/bitcoin_sc.ts \ | ||
qt/locale/bitcoin_sd.ts \ | ||
qt/locale/bitcoin_si.ts \ | ||
qt/locale/bitcoin_sk.ts \ | ||
qt/locale/bitcoin_sl.ts \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
// Copyright (c) 2022 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/v3_policy.h> | ||
|
||
#include <coins.h> | ||
#include <consensus/amount.h> | ||
#include <logging.h> | ||
#include <tinyformat.h> | ||
#include <util/check.h> | ||
|
||
#include <algorithm> | ||
#include <numeric> | ||
#include <vector> | ||
|
||
/** Helper for PackageV3Checks: Returns a vector containing the indices of transactions (within | ||
* package) that are direct parents of ptx. */ | ||
std::vector<size_t> FindInPackageParents(const Package& package, const CTransactionRef& ptx) | ||
{ | ||
std::vector<size_t> in_package_parents; | ||
|
||
std::set<Txid> possible_parents; | ||
for (auto &input : ptx->vin) { | ||
possible_parents.insert(input.prevout.hash); | ||
} | ||
|
||
for (size_t i{0}; i < package.size(); ++i) { | ||
const auto& tx = package.at(i); | ||
// We assume the package is sorted, so that we don't need to continue | ||
// looking past the transaction itself. | ||
if (&(*tx) == &(*ptx)) break; | ||
if (possible_parents.count(tx->GetHash())) { | ||
in_package_parents.push_back(i); | ||
} | ||
} | ||
return in_package_parents; | ||
} | ||
|
||
/** Helper for PackageV3Checks, storing info for a mempool or package parent. */ | ||
struct ParentInfo { | ||
/** Txid used to identify this parent by prevout */ | ||
const Txid& m_txid; | ||
/** Wtxid used for debug string */ | ||
const Wtxid& m_wtxid; | ||
/** nVersion used to check inheritance of v3 and non-v3 */ | ||
decltype(CTransaction::nVersion) m_version; | ||
/** If parent is in mempool, whether it has any descendants in mempool. */ | ||
bool m_has_mempool_descendant; | ||
|
||
ParentInfo() = delete; | ||
ParentInfo(const Txid& txid, const Wtxid& wtxid, decltype(CTransaction::nVersion) version, bool has_mempool_descendant) : | ||
m_txid{txid}, m_wtxid{wtxid}, m_version{version}, | ||
m_has_mempool_descendant{has_mempool_descendant} | ||
{} | ||
}; | ||
|
||
std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t vsize, | ||
const Package& package, | ||
const CTxMemPool::setEntries& mempool_ancestors) | ||
{ | ||
// This function is specialized for these limits, and must be reimplemented if they ever change. | ||
static_assert(V3_ANCESTOR_LIMIT == 2); | ||
static_assert(V3_DESCENDANT_LIMIT == 2); | ||
|
||
const auto in_package_parents{FindInPackageParents(package, ptx)}; | ||
|
||
// Now we have all ancestors, so we can start checking v3 rules. | ||
if (ptx->nVersion == 3) { | ||
if (mempool_ancestors.size() + in_package_parents.size() + 1 > V3_ANCESTOR_LIMIT) { | ||
return strprintf("tx %s (wtxid=%s) would have too many ancestors", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString()); | ||
} | ||
|
||
const bool has_parent{mempool_ancestors.size() + in_package_parents.size() > 0}; | ||
if (has_parent) { | ||
// A v3 child cannot be too large. | ||
if (vsize > V3_CHILD_MAX_VSIZE) { | ||
return strprintf("v3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), | ||
vsize, V3_CHILD_MAX_VSIZE); | ||
} | ||
|
||
// Exactly 1 parent exists, either in mempool or package. Find it. | ||
const auto parent_info = [&] { | ||
if (mempool_ancestors.size() > 0) { | ||
auto& mempool_parent = *mempool_ancestors.begin(); | ||
Assume(mempool_parent->GetCountWithDescendants() == 1); | ||
return ParentInfo{mempool_parent->GetTx().GetHash(), | ||
mempool_parent->GetTx().GetWitnessHash(), | ||
mempool_parent->GetTx().nVersion, | ||
/*has_mempool_descendant=*/mempool_parent->GetCountWithDescendants() > 1}; | ||
} else { | ||
auto& parent_index = in_package_parents.front(); | ||
auto& package_parent = package.at(parent_index); | ||
return ParentInfo{package_parent->GetHash(), | ||
package_parent->GetWitnessHash(), | ||
package_parent->nVersion, | ||
/*has_mempool_descendant=*/false}; | ||
} | ||
}(); | ||
|
||
// If there is a parent, it must have the right version. | ||
if (parent_info.m_version != 3) { | ||
return strprintf("v3 tx %s (wtxid=%s) cannot spend from non-v3 tx %s (wtxid=%s)", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), | ||
parent_info.m_txid.ToString(), parent_info.m_wtxid.ToString()); | ||
} | ||
|
||
for (const auto& package_tx : package) { | ||
// Skip same tx. | ||
if (&(*package_tx) == &(*ptx)) continue; | ||
|
||
for (auto& input : package_tx->vin) { | ||
// Fail if we find another tx with the same parent. We don't check whether the | ||
// sibling is to-be-replaced (done in SingleV3Checks) because these transactions | ||
// are within the same package. | ||
if (input.prevout.hash == parent_info.m_txid) { | ||
return strprintf("tx %s (wtxid=%s) would exceed descendant count limit", | ||
parent_info.m_txid.ToString(), | ||
parent_info.m_wtxid.ToString()); | ||
} | ||
|
||
// This tx can't have both a parent and an in-package child. | ||
if (input.prevout.hash == ptx->GetHash()) { | ||
return strprintf("tx %s (wtxid=%s) would have too many ancestors", | ||
package_tx->GetHash().ToString(), package_tx->GetWitnessHash().ToString()); | ||
} | ||
} | ||
} | ||
|
||
// It shouldn't be possible to have any mempool siblings at this point. SingleV3Checks | ||
// catches mempool siblings. Also, if the package consists of connected transactions, | ||
// any tx having a mempool ancestor would mean the package exceeds ancestor limits. | ||
if (!Assume(!parent_info.m_has_mempool_descendant)) { | ||
return strprintf("tx %u would exceed descendant count limit", parent_info.m_wtxid.ToString()); | ||
} | ||
} | ||
} else { | ||
// Non-v3 transactions cannot have v3 parents. | ||
for (auto it : mempool_ancestors) { | ||
if (it->GetTx().nVersion == 3) { | ||
return strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), | ||
it->GetSharedTx()->GetHash().ToString(), it->GetSharedTx()->GetWitnessHash().ToString()); | ||
} | ||
} | ||
for (const auto& index: in_package_parents) { | ||
if (package.at(index)->nVersion == 3) { | ||
return strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)", | ||
ptx->GetHash().ToString(), | ||
ptx->GetWitnessHash().ToString(), | ||
package.at(index)->GetHash().ToString(), | ||
package.at(index)->GetWitnessHash().ToString()); | ||
} | ||
} | ||
} | ||
return std::nullopt; | ||
} | ||
|
||
std::optional<std::string> SingleV3Checks(const CTransactionRef& ptx, | ||
const CTxMemPool::setEntries& mempool_ancestors, | ||
const std::set<Txid>& direct_conflicts, | ||
int64_t vsize) | ||
{ | ||
// Check v3 and non-v3 inheritance. | ||
for (const auto& entry : mempool_ancestors) { | ||
if (ptx->nVersion != 3 && entry->GetTx().nVersion == 3) { | ||
return strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), | ||
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()); | ||
} else if (ptx->nVersion == 3 && entry->GetTx().nVersion != 3) { | ||
return strprintf("v3 tx %s (wtxid=%s) cannot spend from non-v3 tx %s (wtxid=%s)", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), | ||
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()); | ||
} | ||
} | ||
|
||
// This function is specialized for these limits, and must be reimplemented if they ever change. | ||
static_assert(V3_ANCESTOR_LIMIT == 2); | ||
static_assert(V3_DESCENDANT_LIMIT == 2); | ||
|
||
// The rest of the rules only apply to transactions with nVersion=3. | ||
if (ptx->nVersion != 3) return std::nullopt; | ||
|
||
// Check that V3_ANCESTOR_LIMIT would not be violated. | ||
if (mempool_ancestors.size() + 1 > V3_ANCESTOR_LIMIT) { | ||
return strprintf("tx %s (wtxid=%s) would have too many ancestors", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString()); | ||
} | ||
|
||
// Remaining checks only pertain to transactions with unconfirmed ancestors. | ||
if (mempool_ancestors.size() > 0) { | ||
// If this transaction spends V3 parents, it cannot be too large. | ||
if (vsize > V3_CHILD_MAX_VSIZE) { | ||
return strprintf("v3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes", | ||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, V3_CHILD_MAX_VSIZE); | ||
} | ||
|
||
// Check the descendant counts of in-mempool ancestors. | ||
const auto& parent_entry = *mempool_ancestors.begin(); | ||
// If there are any ancestors, this is the only child allowed. The parent cannot have any | ||
// other descendants. We handle the possibility of multiple children as that case is | ||
// possible through a reorg. | ||
const auto& children = parent_entry->GetMemPoolChildrenConst(); | ||
// Don't double-count a transaction that is going to be replaced. This logic assumes that | ||
// any descendant of the V3 transaction is a direct child, which makes sense because a V3 | ||
// transaction can only have 1 descendant. | ||
const bool child_will_be_replaced = !children.empty() && | ||
std::any_of(children.cbegin(), children.cend(), | ||
[&direct_conflicts](const CTxMemPoolEntry& child){return direct_conflicts.count(child.GetTx().GetHash()) > 0;}); | ||
if (parent_entry->GetCountWithDescendants() + 1 > V3_DESCENDANT_LIMIT && !child_will_be_replaced) { | ||
return strprintf("tx %u (wtxid=%s) would exceed descendant count limit", | ||
parent_entry->GetSharedTx()->GetHash().ToString(), | ||
parent_entry->GetSharedTx()->GetWitnessHash().ToString()); | ||
} | ||
} | ||
return std::nullopt; | ||
} |
Oops, something went wrong.