Bitcoin Core 22.99.0
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
6#include <policy/packages.h>
8#include <uint256.h>
9#include <util/hasher.h>
10
11#include <numeric>
12#include <unordered_set>
13
15{
16 const unsigned int package_count = txns.size();
17
18 if (package_count > MAX_PACKAGE_COUNT) {
19 return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-too-many-transactions");
20 }
21
22 const int64_t total_size = std::accumulate(txns.cbegin(), txns.cend(), 0,
23 [](int64_t sum, const auto& tx) { return sum + GetVirtualTransactionSize(*tx); });
24 // If the package only contains 1 tx, it's better to report the policy violation on individual tx size.
25 if (package_count > 1 && total_size > MAX_PACKAGE_SIZE * 1000) {
26 return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-too-large");
27 }
28
29 // Require the package to be sorted in order of dependency, i.e. parents appear before children.
30 // An unsorted package will fail anyway on missing-inputs, but it's better to quit earlier and
31 // fail on something less ambiguous (missing-inputs could also be an orphan or trying to
32 // spend nonexistent coins).
33 std::unordered_set<uint256, SaltedTxidHasher> later_txids;
34 std::transform(txns.cbegin(), txns.cend(), std::inserter(later_txids, later_txids.end()),
35 [](const auto& tx) { return tx->GetHash(); });
36 for (const auto& tx : txns) {
37 for (const auto& input : tx->vin) {
38 if (later_txids.find(input.prevout.hash) != later_txids.end()) {
39 // The parent is a subsequent transaction in the package.
40 return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-sorted");
41 }
42 }
43 later_txids.erase(tx->GetHash());
44 }
45
46 // Don't allow any conflicting transactions, i.e. spending the same inputs, in a package.
47 std::unordered_set<COutPoint, SaltedOutpointHasher> inputs_seen;
48 for (const auto& tx : txns) {
49 for (const auto& input : tx->vin) {
50 if (inputs_seen.find(input.prevout) != inputs_seen.end()) {
51 // This input is also present in another tx in the package.
52 return state.Invalid(PackageValidationResult::PCKG_POLICY, "conflict-in-package");
53 }
54 }
55 // Batch-add all the inputs for a tx at a time. If we added them 1 at a time, we could
56 // catch duplicate inputs within a single tx. This is a more severe, consensus error,
57 // and we want to report that from CheckTransaction instead.
58 std::transform(tx->vin.cbegin(), tx->vin.cend(), std::inserter(inputs_seen, inputs_seen.end()),
59 [](const auto& input) { return input.prevout; });
60 }
61 return true;
62}
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
Definition: validation.h:102
volatile double sum
Definition: examples.cpp:10
bool CheckPackage(const Package &txns, PackageValidationState &state)
Context-free package policy checks:
Definition: packages.cpp:14
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
Definition: packages.h:32
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 virtual size of transactions in a package in KvB.
Definition: packages.h:17
@ PCKG_POLICY
The package itself is invalid (e.g. too many transactions).