Bitcoin Core
32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
src
bench
connectblock.cpp
Go to the documentation of this file.
1
// Copyright (c) 2025-present 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 <
addresstype.h
>
6
#include <
bench/bench.h
>
7
#include <chain.h>
8
#include <coins.h>
9
#include <
consensus/amount.h
>
10
#include <
consensus/validation.h
>
11
#include <
key.h
>
12
#include <
node/blockstorage.h
>
13
#include <
policy/feerate.h
>
14
#include <
primitives/block.h
>
15
#include <
primitives/transaction.h
>
16
#include <
pubkey.h
>
17
#include <
script/script.h
>
18
#include <
sync.h
>
19
#include <
test/util/setup_common.h
>
20
#include <
util/check.h
>
21
#include <
validation.h
>
22
23
#include <cstddef>
24
#include <memory>
25
#include <optional>
26
#include <utility>
27
#include <vector>
28
29
/*
30
* Creates a test block containing transactions with the following properties:
31
* - Each transaction has the same number of inputs and outputs
32
* - All Taproot inputs use simple key path spends (no script path spends)
33
* - All signatures use SIGHASH_ALL (default sighash)
34
* - Each transaction spends all outputs from the previous transaction
35
*/
36
CBlock
CreateTestBlock
(
37
TestChain100Setup
&
test_setup
,
38
const
std::vector<CKey>&
keys
,
39
const
std::vector<CTxOut>& outputs,
40
int
num_txs
= 1000)
41
{
42
Chainstate
&
chainstate
{
test_setup
.m_node.chainman->ActiveChainstate()};
43
44
const
WitnessV1Taproot
coinbase_taproot
{
XOnlyPubKey
(
test_setup
.coinbaseKey.GetPubKey())};
45
46
// Create the outputs that will be spent in the first transaction of the test block
47
// Doing this in a separate block excludes the validation of its inputs from the benchmark
48
auto
&
coinbase_to_spend
{
test_setup
.m_coinbase_txns[0]};
49
const
auto
[
first_tx
,
_
]{
test_setup
.CreateValidTransaction(
50
{
coinbase_to_spend
},
51
{
COutPoint
(
coinbase_to_spend
->GetHash(), 0)},
52
chainstate
.m_chain.Height() + 1,
keys
, outputs, {}, {})};
53
const
CScript
coinbase_spk
{
GetScriptForDestination
(
coinbase_taproot
)};
54
test_setup
.CreateAndProcessBlock({
first_tx
},
coinbase_spk
);
55
56
std::vector<CMutableTransaction>
txs
;
57
txs
.
reserve
(
num_txs
);
58
CTransactionRef
tx_to_spend
{
MakeTransactionRef
(
first_tx
)};
59
for
(
int
i{0}; i <
num_txs
; i++) {
60
std::vector<COutPoint> inputs;
61
inputs.reserve(outputs.size());
62
63
for
(
size_t
j
{0};
j
< outputs.size();
j
++) {
64
inputs.emplace_back(
tx_to_spend
->GetHash(),
j
);
65
}
66
67
const
auto
[tx,
_
]{
test_setup
.CreateValidTransaction(
68
{
tx_to_spend
}, inputs,
chainstate
.m_chain.Height() + 1,
keys
, outputs, {}, {})};
69
txs
.emplace_back(tx);
70
tx_to_spend
=
MakeTransactionRef
(tx);
71
}
72
73
// Coinbase output can use any output type as it is not spent and will not change the benchmark
74
return
test_setup
.CreateBlock(
txs
,
coinbase_spk
);
75
}
76
77
/*
78
* Creates key pairs and corresponding outputs for the benchmark transactions.
79
* - For Schnorr signatures: Creates simple key path spendable outputs
80
* - For Ecdsa signatures: Creates P2WPKH (native SegWit v0) outputs
81
* - All outputs have value of 1 BTC
82
*/
83
std::pair<std::vector<CKey>, std::vector<CTxOut>>
CreateKeysAndOutputs
(
const
CKey
& coinbaseKey,
size_t
num_schnorr
,
size_t
num_ecdsa
)
84
{
85
std::vector<CKey>
keys
{coinbaseKey};
86
keys
.reserve(
num_schnorr
+
num_ecdsa
+ 1);
87
88
std::vector<CTxOut> outputs;
89
outputs.reserve(
num_schnorr
+
num_ecdsa
);
90
91
for
(
size_t
i{0}; i <
num_ecdsa
; ++i) {
92
keys
.emplace_back(
GenerateRandomKey
());
93
outputs.emplace_back(
COIN
,
GetScriptForDestination
(
WitnessV0KeyHash
{
keys
.back().
GetPubKey
()}));
94
}
95
96
for
(
size_t
i{0}; i <
num_schnorr
; ++i) {
97
keys
.emplace_back(
GenerateRandomKey
());
98
outputs.emplace_back(
COIN
,
GetScriptForDestination
(
WitnessV1Taproot
{
XOnlyPubKey
(
keys
.back().GetPubKey())}));
99
}
100
101
return
{
keys
, outputs};
102
}
103
104
void
BenchmarkConnectBlock
(
benchmark::Bench
&
bench
, std::vector<CKey>&
keys
, std::vector<CTxOut>& outputs,
TestChain100Setup
&
test_setup
)
105
{
106
const
auto
&
test_block
{
CreateTestBlock
(
test_setup
,
keys
, outputs)};
107
bench
.unit(
"block"
).run([&] {
108
LOCK
(
cs_main
);
109
auto
& chainman{
test_setup
.m_node.chainman};
110
auto
&
chainstate
{chainman->ActiveChainstate()};
111
BlockValidationState
test_block_state
;
112
auto
* pindex{chainman->m_blockman.AddToBlockIndex(
test_block
, chainman->m_best_header)};
// Doing this here doesn't impact the benchmark
113
CCoinsViewCache
viewNew
{&
chainstate
.CoinsTip()};
114
115
assert
(
chainstate
.ConnectBlock(
test_block
,
test_block_state
, pindex,
viewNew
));
116
});
117
}
118
119
static
void
ConnectBlockAllSchnorr
(
benchmark::Bench
&
bench
)
120
{
121
const
auto
test_setup
{
MakeNoLogFileContext<TestChain100Setup>
()};
122
auto
[
keys
, outputs]{
CreateKeysAndOutputs
(
test_setup
->coinbaseKey,
/*num_schnorr=*/
5,
/*num_ecdsa=*/
0)};
123
BenchmarkConnectBlock
(
bench
,
keys
, outputs, *
test_setup
);
124
}
125
126
static
void
ConnectBlockMixedEcdsaSchnorr
(
benchmark::Bench
&
bench
)
127
{
128
const
auto
test_setup
{
MakeNoLogFileContext<TestChain100Setup>
()};
129
// Blocks in range 848000 to 868000 have a roughly 20 to 80 ratio of schnorr to ecdsa inputs
130
auto
[
keys
, outputs]{
CreateKeysAndOutputs
(
test_setup
->coinbaseKey,
/*num_schnorr=*/
1,
/*num_ecdsa=*/
4)};
131
BenchmarkConnectBlock
(
bench
,
keys
, outputs, *
test_setup
);
132
}
133
134
static
void
ConnectBlockAllEcdsa
(
benchmark::Bench
&
bench
)
135
{
136
const
auto
test_setup
{
MakeNoLogFileContext<TestChain100Setup>
()};
137
auto
[
keys
, outputs]{
CreateKeysAndOutputs
(
test_setup
->coinbaseKey,
/*num_schnorr=*/
0,
/*num_ecdsa=*/
5)};
138
BenchmarkConnectBlock
(
bench
,
keys
, outputs, *
test_setup
);
139
}
140
141
BENCHMARK
(
ConnectBlockAllSchnorr
);
142
BENCHMARK
(
ConnectBlockMixedEcdsaSchnorr
);
143
BENCHMARK
(
ConnectBlockAllEcdsa
);
GetScriptForDestination
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition
addresstype.cpp:165
addresstype.h
amount.h
COIN
constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition
amount.h:15
bench.h
BENCHMARK
#define BENCHMARK(n)
Definition
bench.h:69
block.h
blockstorage.h
check.h
BlockValidationState
Definition
validation.h:133
CBlock
Definition
block.h:74
CCoinsViewCache
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition
coins.h:437
CKey
An encapsulated private key.
Definition
key.h:46
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition
transaction.h:30
CScript
Serialized script, used inside transaction inputs and outputs.
Definition
script.h:406
Chainstate
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition
validation.h:550
XOnlyPubKey
Definition
pubkey.h:236
ankerl::nanobench::Bench
Main entry point to nanobench's benchmarking facility.
Definition
nanobench.h:649
prevector::reserve
void reserve(size_type new_capacity)
Definition
prevector.h:293
BenchmarkConnectBlock
void BenchmarkConnectBlock(benchmark::Bench &bench, std::vector< CKey > &keys, std::vector< CTxOut > &outputs, TestChain100Setup &test_setup)
Definition
connectblock.cpp:104
ConnectBlockMixedEcdsaSchnorr
static void ConnectBlockMixedEcdsaSchnorr(benchmark::Bench &bench)
Definition
connectblock.cpp:126
ConnectBlockAllEcdsa
static void ConnectBlockAllEcdsa(benchmark::Bench &bench)
Definition
connectblock.cpp:134
ConnectBlockAllSchnorr
static void ConnectBlockAllSchnorr(benchmark::Bench &bench)
Definition
connectblock.cpp:119
CreateKeysAndOutputs
std::pair< std::vector< CKey >, std::vector< CTxOut > > CreateKeysAndOutputs(const CKey &coinbaseKey, size_t num_schnorr, size_t num_ecdsa)
Definition
connectblock.cpp:83
validation.h
cs_main
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition
cs_main.cpp:8
feerate.h
GenerateRandomKey
CKey GenerateRandomKey(bool compressed) noexcept
Definition
key.cpp:354
key.h
transaction.h
MakeTransactionRef
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition
transaction.h:418
CTransactionRef
std::shared_ptr< const CTransaction > CTransactionRef
Definition
transaction.h:417
pubkey.h
CreateTestBlock
static CBlock CreateTestBlock()
Definition
readwriteblock.cpp:21
script.h
setup_common.h
GetPubKey
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition
sign.cpp:243
TestChain100Setup
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition
setup_common.h:143
WitnessV0KeyHash
Definition
addresstype.h:79
WitnessV1Taproot
Definition
addresstype.h:88
sync.h
LOCK
#define LOCK(cs)
Definition
sync.h:268
keys
std::vector< uint16_t > keys
Definition
dbwrapper.cpp:376
_
consteval auto _(util::TranslatedLiteral str)
Definition
translation.h:79
Ticks
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition
time.h:82
assert
assert(!tx.IsCoinBase())
validation.h
Generated on Thu Oct 22 2026 20:00:28 for Bitcoin Core by
1.9.8