Skip to content

Commit df14122

Browse files
committed
Merge commit '00a3917ab1d4d59e9d01f951593e37f66874b076' into validation_helpers
2 parents 0eadd82 + 00a3917 commit df14122

56 files changed

Lines changed: 836 additions & 403 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

libbitcoinkernel-sys/bitcoin/CMakeLists.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,8 @@ try_append_cxx_flags("-fno-extended-identifiers" TARGET core_interface SKIP_LINK
488488
# which can cause issues with coverage builds, particularly when using
489489
# Clang in the OSS-Fuzz environment due to its use of other options
490490
# and a third party script, or with GCC.
491-
try_append_cxx_flags("-fdebug-prefix-map=A=B" TARGET core_interface SKIP_LINK
492-
IF_CHECK_PASSED "-fdebug-prefix-map=${PROJECT_SOURCE_DIR}/src=."
493-
)
491+
# Set `-fmacro-prefix-map`, so that source file names are expanded without the
492+
# src prefix.
494493
try_append_cxx_flags("-fmacro-prefix-map=A=B" TARGET core_interface SKIP_LINK
495494
IF_CHECK_PASSED "-fmacro-prefix-map=${PROJECT_SOURCE_DIR}/src=."
496495
)

libbitcoinkernel-sys/bitcoin/CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ The codebase is maintained using the "contributor workflow" where everyone
7878
without exception contributes patch proposals using "pull requests" (PRs). This
7979
facilitates social contribution, easy testing and peer review.
8080

81+
Pull request authors must fully and confidently understand their own changes
82+
and must have tested them. Contributors should mention which tests cover their
83+
changes, or include the manual steps they used to confirm the change.
84+
Contributors are expected to be prepared to clearly motivate and explain their
85+
changes. If there is doubt, the pull request may be closed.
86+
Please refer to the [peer review](#peer-review) section below for more details.
87+
8188
To contribute a patch, the workflow is as follows:
8289

8390
1. Fork repository ([only for the first time](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo))
@@ -338,6 +345,11 @@ reviewers that the changes warrant the review effort, and if reviewers are
338345
"Concept NACK'ing" the PR, the author may need to present arguments and/or do
339346
research backing their suggested changes.
340347

348+
Moreover, if there is reasonable doubt that the pull request author does not
349+
fully understand the changes they are submitting themselves, or if it becomes
350+
clear that they have not tested the changes on a basic level themselves, the
351+
pull request may be closed immediately.
352+
341353
#### Conceptual Review
342354

343355
A review can be a conceptual review, where the reviewer leaves a comment

libbitcoinkernel-sys/bitcoin/contrib/guix/libexec/build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ CONFIGFLAGS="-DREDUCE_EXPORTS=ON -DBUILD_BENCH=OFF -DBUILD_GUI_TESTS=OFF -DBUILD
211211
# CFLAGS
212212
HOST_CFLAGS="-O2 -g"
213213
HOST_CFLAGS+=$(find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;)
214+
HOST_CFLAGS+=" -fdebug-prefix-map=${DISTSRC}/src=."
214215
case "$HOST" in
215216
*mingw*) HOST_CFLAGS+=" -fno-ident" ;;
216217
*darwin*) unset HOST_CFLAGS ;;

libbitcoinkernel-sys/bitcoin/src/bench/connectblock.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <script/interpreter.h>
1010
#include <sync.h>
1111
#include <test/util/setup_common.h>
12+
#include <undo.h>
1213
#include <validation.h>
1314

1415
#include <cassert>
@@ -100,7 +101,9 @@ void BenchmarkConnectBlock(benchmark::Bench& bench, std::vector<CKey>& keys, std
100101
auto* pindex{chainman->m_blockman.AddToBlockIndex(test_block, chainman->m_best_header)}; // Doing this here doesn't impact the benchmark
101102
CCoinsViewCache viewNew{&chainstate.CoinsTip()};
102103

103-
assert(chainstate.ConnectBlock(test_block, test_block_state, pindex, viewNew));
104+
CBlockUndo blockundo;
105+
assert(chainstate.SpendBlock(test_block, pindex, viewNew, test_block_state, blockundo));
106+
assert(chainstate.ConnectBlock(test_block, blockundo, test_block_state, pindex));
104107
});
105108
}
106109

libbitcoinkernel-sys/bitcoin/src/bench/mempool_stress.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static void MemPoolAddTransactions(benchmark::Bench& bench)
106106
std::vector<CTransactionRef> transactions;
107107
// Create 1000 clusters of 100 transactions each
108108
for (int i=0; i<100; i++) {
109-
auto new_txs = CreateCoinCluster(det_rand, childTxs, /*min_ancestors*/ 1);
109+
auto new_txs = CreateCoinCluster(det_rand, childTxs, /*min_ancestors=*/ 1);
110110
transactions.insert(transactions.end(), new_txs.begin(), new_txs.end());
111111
}
112112

@@ -156,7 +156,7 @@ static void ComplexMemPool(benchmark::Bench& bench)
156156
// in the same state at the end of the function, so we benchmark both
157157
// mining a block and reorging the block's contents back into the mempool.
158158
bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
159-
pool.removeForBlock(tx_remove_for_block, /*nBlockHeight*/100);
159+
pool.removeForBlock(tx_remove_for_block, /*nBlockHeight=*/100);
160160
for (auto& tx: tx_remove_for_block) {
161161
AddTx(tx, pool, det_rand);
162162
}

libbitcoinkernel-sys/bitcoin/src/coins.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,29 @@ const Coin& CCoinsViewCache::AccessCoin(const COutPoint &outpoint) const {
167167
}
168168
}
169169

170+
std::vector<std::reference_wrapper<const Coin>> CCoinsViewCache::AccessCoins(const CTransaction& tx) const
171+
{
172+
std::vector<std::reference_wrapper<const Coin>> coins;
173+
coins.reserve(tx.vin.size());
174+
for (const CTxIn& input : tx.vin) {
175+
coins.emplace_back(AccessCoin(input.prevout));
176+
}
177+
return coins;
178+
}
179+
180+
std::vector<CTxOut> CCoinsViewCache::GetUnspentOutputs(const CTransaction& tx) const
181+
{
182+
std::vector<CTxOut> spent_outputs;
183+
spent_outputs.reserve(tx.vin.size());
184+
for (const auto& txin : tx.vin) {
185+
const COutPoint& prevout = txin.prevout;
186+
const Coin& coin = AccessCoin(prevout);
187+
assert(!coin.IsSpent());
188+
spent_outputs.emplace_back(coin.out);
189+
}
190+
return spent_outputs;
191+
}
192+
170193
bool CCoinsViewCache::HaveCoin(const COutPoint &outpoint) const {
171194
CCoinsMap::const_iterator it = FetchCoin(outpoint);
172195
return (it != cacheCoins.end() && !it->second.coin.IsSpent());

libbitcoinkernel-sys/bitcoin/src/coins.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,23 @@ class CCoinsViewCache : public CCoinsViewBacked
413413
*/
414414
const Coin& AccessCoin(const COutPoint &output) const;
415415

416+
/**
417+
* Return a vector of references to Coins in the cache in order they get
418+
* consumed by the tx's inputs, or coinEmpty if the Coin is not
419+
* found.
420+
*
421+
* Generally, this should only be held for a short scope. The coins should
422+
* generally not be held through any other calls to this cache.
423+
*/
424+
std::vector<std::reference_wrapper<const Coin>> AccessCoins(const CTransaction& tx) const;
425+
426+
/**
427+
* Return a vector of unspent outputs of coins in the cache that are spent
428+
* by the provided transaction. The coins they belong to must be unspent in
429+
* the cache.
430+
*/
431+
std::vector<CTxOut> GetUnspentOutputs(const CTransaction& tx) const;
432+
416433
/**
417434
* Add a coin. Set possible_overwrite to true if an unspent version may
418435
* already exist in the cache.

libbitcoinkernel-sys/bitcoin/src/common/system.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@
3737

3838
using util::ReplaceAll;
3939

40-
// Application startup time (used for uptime calculation)
41-
const int64_t nStartupTime = GetTime();
42-
4340
#ifndef WIN32
4441
std::string ShellEscape(const std::string& arg)
4542
{
@@ -130,8 +127,8 @@ std::optional<size_t> GetTotalRAM()
130127
return std::nullopt;
131128
}
132129

133-
// Obtain the application startup time (used for uptime calculation)
134-
int64_t GetStartupTime()
130+
SteadyClock::duration GetUptime()
135131
{
136-
return nStartupTime;
132+
static const auto g_startup_time{SteadyClock::now()};
133+
return SteadyClock::now() - g_startup_time;
137134
}

libbitcoinkernel-sys/bitcoin/src/common/system.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
#define BITCOIN_COMMON_SYSTEM_H
88

99
#include <bitcoin-build-config.h> // IWYU pragma: keep
10+
#include <util/time.h>
1011

12+
#include <chrono>
1113
#include <cstdint>
1214
#include <optional>
1315
#include <string>
1416

15-
// Application startup time (used for uptime calculation)
16-
int64_t GetStartupTime();
17+
/// Monotonic uptime (not affected by system time changes).
18+
SteadyClock::duration GetUptime();
1719

1820
void SetupEnvironment();
1921
[[nodiscard]] bool SetupNetworking();

libbitcoinkernel-sys/bitcoin/src/consensus/tx_verify.cpp

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <util/check.h>
1515
#include <util/moneystr.h>
1616

17+
#include <span>
18+
1719
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
1820
{
1921
if (tx.nLockTime == 0)
@@ -123,62 +125,73 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx)
123125
return nSigOps;
124126
}
125127

126-
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
128+
template <Consensus::CoinRef T>
129+
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const std::span<T> coins)
127130
{
128131
if (tx.IsCoinBase())
129132
return 0;
130133

131134
unsigned int nSigOps = 0;
132-
for (unsigned int i = 0; i < tx.vin.size(); i++)
133-
{
134-
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
135+
Assert(coins.size() == tx.vin.size());
136+
auto input_it = tx.vin.begin();
137+
for (auto it = coins.begin(); it != coins.end(); ++it, ++input_it) {
138+
const Coin& coin = *it;
135139
assert(!coin.IsSpent());
136140
const CTxOut &prevout = coin.out;
137141
if (prevout.scriptPubKey.IsPayToScriptHash())
138-
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
142+
nSigOps += prevout.scriptPubKey.GetSigOpCount(input_it->scriptSig);
139143
}
140144
return nSigOps;
141145
}
142146

143-
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
147+
template unsigned int GetP2SHSigOpCount<const Coin>(
148+
const CTransaction& tx, const std::span<const Coin>);
149+
150+
template unsigned int GetP2SHSigOpCount<std::reference_wrapper<const Coin>>(
151+
const CTransaction& tx, const std::span<std::reference_wrapper<const Coin>>);
152+
153+
template <Consensus::CoinRef T>
154+
int64_t GetTransactionSigOpCost(const CTransaction& tx, const std::span<T> coins, script_verify_flags flags)
144155
{
145156
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
146157

147158
if (tx.IsCoinBase())
148159
return nSigOps;
149160

150161
if (flags & SCRIPT_VERIFY_P2SH) {
151-
nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
162+
nSigOps += GetP2SHSigOpCount(tx, coins) * WITNESS_SCALE_FACTOR;
152163
}
153164

154-
for (unsigned int i = 0; i < tx.vin.size(); i++)
155-
{
156-
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
165+
Assert(coins.size() == tx.vin.size());
166+
auto input_it = tx.vin.begin();
167+
for (auto it = coins.begin(); it != coins.end(); ++it, ++input_it) {
168+
const Coin& coin = *it;
157169
assert(!coin.IsSpent());
158170
const CTxOut &prevout = coin.out;
159-
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, tx.vin[i].scriptWitness, flags);
171+
nSigOps += CountWitnessSigOps(input_it->scriptSig, prevout.scriptPubKey, input_it->scriptWitness, flags);
160172
}
161173
return nSigOps;
162174
}
175+
template int64_t GetTransactionSigOpCost<const Coin>(
176+
const CTransaction& tx, std::span<const Coin> coins, script_verify_flags flags);
163177

164-
bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
165-
{
166-
// are the actual inputs available?
167-
if (!inputs.HaveInputs(tx)) {
168-
return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
169-
strprintf("%s: inputs missing/spent", __func__));
170-
}
178+
template int64_t GetTransactionSigOpCost<std::reference_wrapper<const Coin>>(
179+
const CTransaction& tx, const std::span<std::reference_wrapper<const Coin>> coins, script_verify_flags flags);
171180

181+
template <Consensus::CoinRef T>
182+
bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const std::span<T> coins, int nSpendHeight, CAmount& txfee)
183+
{
172184
CAmount nValueIn = 0;
173-
for (unsigned int i = 0; i < tx.vin.size(); ++i) {
174-
const COutPoint &prevout = tx.vin[i].prevout;
175-
const Coin& coin = inputs.AccessCoin(prevout);
185+
Assert(coins.size() == tx.vin.size());
186+
auto input_it = tx.vin.begin();
187+
for (auto it = coins.begin(); it != coins.end(); ++it, ++input_it) {
188+
const Coin& coin = *it;
176189
assert(!coin.IsSpent());
177190

178191
// If prev is coinbase, check that it's matured
179192
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
180193
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
181-
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
194+
strprintf("tried to spend coinbase at depth %d", static_cast<int>(nSpendHeight - coin.nHeight)));
182195
}
183196

184197
// Check for negative or overflow input values
@@ -203,3 +216,9 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state,
203216
txfee = txfee_aux;
204217
return true;
205218
}
219+
220+
template bool Consensus::CheckTxInputs<const Coin>(
221+
const CTransaction& tx, TxValidationState& state, const std::span<const Coin> coins, int nSpendHeight, CAmount& txfee);
222+
223+
template bool Consensus::CheckTxInputs<std::reference_wrapper<const Coin>>(
224+
const CTransaction& tx, TxValidationState& state, const std::span<std::reference_wrapper<const Coin>> coins, int nSpendHeight, CAmount& txfee);

0 commit comments

Comments
 (0)