Bitcoin ABC  0.26.3
P2P Digital Currency
packages.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <consensus/validation.h>
6 #include <policy/packages.h>
8 #include <primitives/txid.h>
9 #include <util/hasher.h>
10 
11 #include <numeric>
12 #include <unordered_set>
13 
14 bool CheckPackage(const Package &txns, PackageValidationState &state) {
15  const size_t package_count = txns.size();
16 
17  // These context-free package limits can be checked before taking the
18  // mempool lock.
19  if (package_count > MAX_PACKAGE_COUNT) {
21  "package-too-many-transactions");
22  }
23 
24  const int64_t total_size = std::accumulate(
25  txns.cbegin(), txns.cend(), 0, [](int64_t sum, const auto &tx) {
26  return sum + GetVirtualTransactionSize(*tx);
27  });
28  // If the package only contains 1 tx, it's better to report the policy
29  // violation on individual tx size.
30  if (package_count > 1 && total_size > MAX_PACKAGE_SIZE * 1000) {
32  "package-too-large");
33  }
34 
35  // Require the package to be sorted in order of dependency, i.e. parents
36  // appear before children.
37  // An unsorted package will fail anyway on missing-inputs, but it's better
38  // to quit earlier and fail on something less ambiguous (missing-inputs
39  // could also be an orphan or trying to spend nonexistent coins).
40  std::unordered_set<TxId, SaltedTxIdHasher> later_txids;
41  std::transform(txns.cbegin(), txns.cend(),
42  std::inserter(later_txids, later_txids.end()),
43  [](const auto &tx) { return tx->GetId(); });
44 
45  // Package must not contain any duplicate transactions, which is checked by
46  // txid.
47  if (later_txids.size() != txns.size()) {
49  "package-contains-duplicates");
50  }
51 
52  for (const auto &tx : txns) {
53  for (const auto &input : tx->vin) {
54  if (later_txids.find(input.prevout.GetTxId()) !=
55  later_txids.end()) {
56  // The parent is a subsequent transaction in the package.
58  "package-not-sorted");
59  }
60  }
61  later_txids.erase(tx->GetId());
62  }
63 
64  // Don't allow any conflicting transactions, i.e. spending the same
65  // inputs, in a package.
66  std::unordered_set<COutPoint, SaltedOutpointHasher> inputs_seen;
67  for (const auto &tx : txns) {
68  for (const auto &input : tx->vin) {
69  if (inputs_seen.find(input.prevout) != inputs_seen.end()) {
70  // This input is also present in another tx in the package.
72  "conflict-in-package");
73  }
74  }
75  // Batch-add all the inputs for a tx at a time. If we added them 1
76  // at a time, we could catch duplicate inputs within a single tx.
77  // This is a more severe, consensus error, and we want to report
78  // that from CheckTransaction instead.
79  std::transform(tx->vin.cbegin(), tx->vin.cend(),
80  std::inserter(inputs_seen, inputs_seen.end()),
81  [](const auto &input) { return input.prevout; });
82  }
83  return true;
84 }
85 
86 bool IsChildWithParents(const Package &package) {
87  assert(std::all_of(package.cbegin(), package.cend(),
88  [](const auto &tx) { return tx != nullptr; }));
89  if (package.size() < 2) {
90  return false;
91  }
92 
93  // The package is expected to be sorted, so the last transaction is the
94  // child.
95  const auto &child = package.back();
96  std::unordered_set<TxId, SaltedTxIdHasher> input_txids;
97  std::transform(child->vin.cbegin(), child->vin.cend(),
98  std::inserter(input_txids, input_txids.end()),
99  [](const auto &input) { return input.prevout.GetTxId(); });
100 
101  // Every transaction must be a parent of the last transaction in the
102  // package.
103  return std::all_of(package.cbegin(), package.cend() - 1,
104  [&input_txids](const auto &ptx) {
105  return input_txids.count(ptx->GetId()) > 0;
106  });
107 }
108 
109 bool IsChildWithParentsTree(const Package &package) {
110  if (!IsChildWithParents(package)) {
111  return false;
112  }
113  std::unordered_set<TxId, SaltedTxIdHasher> parent_txids;
114  std::transform(package.cbegin(), package.cend() - 1,
115  std::inserter(parent_txids, parent_txids.end()),
116  [](const auto &ptx) { return ptx->GetId(); });
117  // Each parent must not have an input who is one of the other parents.
118  return std::all_of(
119  package.cbegin(), package.cend() - 1, [&](const auto &ptx) {
120  for (const auto &input : ptx->vin) {
121  if (parent_txids.count(input.prevout.GetTxId()) > 0) {
122  return false;
123  }
124  }
125  return true;
126  });
127 }
128 
129 uint256 GetPackageHash(const Package &package) {
130  // Create a vector of the txids.
131  std::vector<TxId> txids_copy;
132  std::transform(package.cbegin(), package.cend(),
133  std::back_inserter(txids_copy),
134  [](const auto &tx) { return tx->GetId(); });
135 
136  // Sort in ascending order
137  std::sort(txids_copy.begin(), txids_copy.end(),
138  [](const auto &lhs, const auto &rhs) { return lhs < rhs; });
139 
140  // Get (single) sha256 hash of the txids concatenated in this order
141  HashWriter hashwriter;
142  for (const auto &txid : txids_copy) {
143  hashwriter << txid;
144  }
145  return hashwriter.GetSHA256();
146 }
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:99
uint256 GetSHA256()
Compute the SHA256 hash of all data written to this object.
Definition: hash.h:127
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
Definition: validation.h:99
256-bit opaque blob.
Definition: uint256.h:129
volatile double sum
Definition: examples.cpp:10
bool IsChildWithParents(const Package &package)
Context-free check that a package is exactly one child and its parents; not all parents need to be pr...
Definition: packages.cpp:86
bool IsChildWithParentsTree(const Package &package)
Context-free check that a package IsChildWithParents() and none of the parents depend on each other (...
Definition: packages.cpp:109
bool CheckPackage(const Package &txns, PackageValidationState &state)
Context-free package policy checks:
Definition: packages.cpp:14
uint256 GetPackageHash(const Package &package)
Definition: packages.cpp:129
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
Definition: packages.h:40
static constexpr uint32_t MAX_PACKAGE_COUNT
Default maximum number of transactions in a package.
Definition: packages.h:15
static constexpr uint32_t MAX_PACKAGE_SIZE
Default maximum total size of transactions in a package in KB.
Definition: packages.h:17
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).
assert(!tx.IsCoinBase())