Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
bitcoin-chainstate.cpp
Go to the documentation of this file.
1
// Copyright (c) 2022-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
// The bitcoin-chainstate executable serves to surface the dependencies required
6
// by a program wishing to use Bitcoin Core's consensus engine as it is right
7
// now.
8
//
9
// DEVELOPER NOTE: Since this is a "demo-only", experimental, etc. executable,
10
// it may diverge from Bitcoin Core's coding style.
11
//
12
// It is part of the libbitcoinkernel project.
13
14
#include <
kernel/bitcoinkernel_wrapper.h
>
15
16
#include <cassert>
17
#include <charconv>
18
#include <filesystem>
19
#include <iostream>
20
#include <optional>
21
#include <string>
22
#include <string_view>
23
#include <vector>
24
25
using namespace
btck
;
26
27
std::vector<std::byte>
hex_string_to_byte_vec
(std::string_view hex)
28
{
29
std::vector<std::byte> bytes;
30
bytes.reserve(hex.length() / 2);
31
32
for
(
size_t
i{0}; i < hex.length(); i += 2) {
33
uint8_t byte_value;
34
auto
[ptr, ec] = std::from_chars(hex.data() + i, hex.data() + i + 2, byte_value, 16);
35
36
if
(ec != std::errc{} || ptr != hex.data() + i + 2) {
37
throw
std::invalid_argument(
"Invalid hex character"
);
38
}
39
bytes.push_back(
static_cast<
std::byte
>
(byte_value));
40
}
41
return
bytes;
42
}
43
44
class
KernelLog
45
{
46
public
:
47
void
LogMessage
(std::string_view message)
48
{
49
std::cout <<
"kernel: "
<< message;
50
}
51
};
52
53
class
TestValidationInterface
:
public
ValidationInterface
54
{
55
public
:
56
TestValidationInterface
() =
default
;
57
58
std::optional<std::string>
m_expected_valid_block
= std::nullopt;
59
60
void
BlockChecked
(
Block
block,
BlockValidationStateView
state)
override
61
{
62
auto
mode{state.
GetValidationMode
()};
63
switch
(mode) {
64
case
ValidationMode::VALID
: {
65
std::cout <<
"Valid block"
<< std::endl;
66
return
;
67
}
68
case
ValidationMode::INVALID
: {
69
std::cout <<
"Invalid block: "
;
70
auto
result{state.
GetBlockValidationResult
()};
71
switch
(result) {
72
case
BlockValidationResult::UNSET
:
73
std::cout <<
"initial value. Block has not yet been rejected"
<< std::endl;
74
break
;
75
case
BlockValidationResult::HEADER_LOW_WORK
:
76
std::cout <<
"the block header may be on a too-little-work chain"
<< std::endl;
77
break
;
78
case
BlockValidationResult::CONSENSUS
:
79
std::cout <<
"invalid by consensus rules"
<< std::endl;
80
break
;
81
case
BlockValidationResult::CACHED_INVALID
:
82
std::cout <<
"this block was cached as being invalid and we didn't store the reason why"
<< std::endl;
83
break
;
84
case
BlockValidationResult::INVALID_HEADER
:
85
std::cout <<
"invalid proof of work or time too old"
<< std::endl;
86
break
;
87
case
BlockValidationResult::MUTATED
:
88
std::cout <<
"the block's data didn't match the data committed to by the PoW"
<< std::endl;
89
break
;
90
case
BlockValidationResult::MISSING_PREV
:
91
std::cout <<
"We don't have the previous block the checked one is built on"
<< std::endl;
92
break
;
93
case
BlockValidationResult::INVALID_PREV
:
94
std::cout <<
"A block this one builds on is invalid"
<< std::endl;
95
break
;
96
case
BlockValidationResult::TIME_FUTURE
:
97
std::cout <<
"block timestamp was > 2 hours in the future (or our clock is bad)"
<< std::endl;
98
break
;
99
}
100
return
;
101
}
102
case
ValidationMode::INTERNAL_ERROR
: {
103
std::cout <<
"Internal error"
<< std::endl;
104
return
;
105
}
106
}
107
}
108
};
109
110
class
TestKernelNotifications
:
public
KernelNotifications
111
{
112
public
:
113
void
BlockTipHandler
(
SynchronizationState
,
const
BlockTreeEntry
,
double
)
override
114
{
115
std::cout <<
"Block tip changed"
<< std::endl;
116
}
117
118
void
ProgressHandler
(std::string_view title,
int
progress_percent,
bool
resume_possible)
override
119
{
120
std::cout <<
"Made progress: "
<< title <<
" "
<< progress_percent <<
"%"
<< std::endl;
121
}
122
123
void
WarningSetHandler
(
Warning
warning, std::string_view message)
override
124
{
125
std::cout << message << std::endl;
126
}
127
128
void
WarningUnsetHandler
(
Warning
warning)
override
129
{
130
std::cout <<
"Warning unset: "
<<
static_cast<
std::underlying_type_t<Warning>
>
(warning) << std::endl;
131
}
132
133
void
FlushErrorHandler
(std::string_view error)
override
134
{
135
std::cout << error << std::endl;
136
}
137
138
void
FatalErrorHandler
(std::string_view error)
override
139
{
140
std::cout << error << std::endl;
141
}
142
};
143
144
int
main
(
int
argc,
char
* argv[])
145
{
146
// SETUP: Argument parsing and handling
147
const
bool
has_regtest_flag{argc == 3 && std::string(argv[1]) ==
"-regtest"
};
148
if
(argc < 2 || argc > 3 || (argc == 3 && !has_regtest_flag)) {
149
std::cerr
150
<<
"Usage: "
<< argv[0] <<
" [-regtest] DATADIR"
<< std::endl
151
<<
"Display DATADIR information, and process hex-encoded blocks on standard input."
<< std::endl
152
<<
"Uses mainnet parameters by default, regtest with -regtest flag"
<< std::endl
153
<< std::endl
154
<<
"IMPORTANT: THIS EXECUTABLE IS EXPERIMENTAL, FOR TESTING ONLY, AND EXPECTED TO"
<< std::endl
155
<<
" BREAK IN FUTURE VERSIONS. DO NOT USE ON YOUR ACTUAL DATADIR."
<< std::endl;
156
return
1;
157
}
158
std::filesystem::path abs_datadir{std::filesystem::absolute(argv[argc-1])};
159
std::filesystem::create_directories(abs_datadir);
160
161
btck_LoggingOptions
logging_options = {
162
.log_timestamps =
true
,
163
.log_time_micros =
false
,
164
.log_threadnames =
false
,
165
.log_sourcelocations =
false
,
166
.always_print_category_levels =
true
,
167
};
168
169
logging_set_options
(logging_options);
170
171
Logger
logger{std::make_unique<KernelLog>()};
172
173
ContextOptions options{};
174
ChainParams
params{has_regtest_flag ?
ChainType::REGTEST
:
ChainType::MAINNET
};
175
options.SetChainParams(params);
176
177
options.SetNotifications(std::make_shared<TestKernelNotifications>());
178
options.SetValidationInterface(std::make_shared<TestValidationInterface>());
179
180
Context context{options};
181
182
ChainstateManagerOptions chainman_opts{context, abs_datadir.string(), (abs_datadir /
"blocks"
).
string
()};
183
chainman_opts.SetWorkerThreads(4);
184
185
std::unique_ptr<ChainMan> chainman;
186
try
{
187
chainman = std::make_unique<ChainMan>(context, chainman_opts);
188
}
catch
(std::exception&) {
189
std::cerr <<
"Failed to instantiate ChainMan, exiting"
<< std::endl;
190
return
1;
191
}
192
193
std::cout <<
"Enter the block you want to validate on the next line:"
<< std::endl;
194
195
for
(std::string line; std::getline(std::cin, line);) {
196
if
(line.empty()) {
197
std::cerr <<
"Empty line found, try again:"
<< std::endl;
198
continue
;
199
}
200
201
auto
raw_block{
hex_string_to_byte_vec
(line)};
202
std::unique_ptr<Block> block;
203
try
{
204
block = std::make_unique<Block>(raw_block);
205
}
catch
(std::exception&) {
206
std::cerr <<
"Block decode failed, try again:"
<< std::endl;
207
continue
;
208
}
209
210
bool
new_block =
false
;
211
bool
accepted = chainman->ProcessBlock(*block, &new_block);
212
if
(accepted) {
213
std::cerr <<
"Block has not yet been rejected"
<< std::endl;
214
}
else
{
215
std::cerr <<
"Block was not accepted"
<< std::endl;
216
}
217
if
(!new_block) {
218
std::cerr <<
"Block is a duplicate"
<< std::endl;
219
}
220
}
221
}
hex_string_to_byte_vec
std::vector< std::byte > hex_string_to_byte_vec(std::string_view hex)
Definition
bitcoin-chainstate.cpp:27
bitcoinkernel_wrapper.h
ChainType::REGTEST
@ REGTEST
Definition
chaintype.h:15
KernelLog
Definition
bitcoin-chainstate.cpp:45
KernelLog::LogMessage
void LogMessage(std::string_view message)
Definition
bitcoin-chainstate.cpp:47
TestKernelNotifications
Definition
bitcoin-chainstate.cpp:111
TestKernelNotifications::FlushErrorHandler
void FlushErrorHandler(std::string_view error) override
Definition
bitcoin-chainstate.cpp:133
TestKernelNotifications::FatalErrorHandler
void FatalErrorHandler(std::string_view error) override
Definition
bitcoin-chainstate.cpp:138
TestKernelNotifications::WarningUnsetHandler
void WarningUnsetHandler(Warning warning) override
Definition
bitcoin-chainstate.cpp:128
TestKernelNotifications::WarningSetHandler
void WarningSetHandler(Warning warning, std::string_view message) override
Definition
bitcoin-chainstate.cpp:123
TestKernelNotifications::ProgressHandler
void ProgressHandler(std::string_view title, int progress_percent, bool resume_possible) override
Definition
bitcoin-chainstate.cpp:118
TestKernelNotifications::BlockTipHandler
void BlockTipHandler(SynchronizationState, const BlockTreeEntry, double) override
Definition
bitcoin-chainstate.cpp:113
TestValidationInterface::TestValidationInterface
TestValidationInterface()=default
TestValidationInterface::m_expected_valid_block
std::optional< std::string > m_expected_valid_block
Definition
bitcoin-chainstate.cpp:58
TestValidationInterface::BlockChecked
void BlockChecked(Block block, BlockValidationStateView state) override
Definition
bitcoin-chainstate.cpp:60
btck::Block
Definition
bitcoinkernel_wrapper.h:771
btck::BlockTreeEntry
Definition
bitcoinkernel_wrapper.h:852
btck::BlockValidationStateApi::GetValidationMode
ValidationMode GetValidationMode() const
Definition
bitcoinkernel_wrapper.h:920
btck::BlockValidationStateApi::GetBlockValidationResult
BlockValidationResult GetBlockValidationResult() const
Definition
bitcoinkernel_wrapper.h:925
btck::BlockValidationStateView
Definition
bitcoinkernel_wrapper.h:932
btck::ChainParams
Definition
bitcoinkernel_wrapper.h:960
btck::KernelNotifications
Definition
bitcoinkernel_wrapper.h:888
btck::Logger
Definition
bitcoinkernel_wrapper.h:840
btck::ValidationInterface
Definition
bitcoinkernel_wrapper.h:946
main
int main(void)
Definition
bench.c:156
btck
Definition
bitcoinkernel_wrapper.h:23
btck::ChainType::MAINNET
@ MAINNET
Definition
bitcoinkernel_wrapper.h:46
btck::BlockValidationResult::TIME_FUTURE
@ TIME_FUTURE
Definition
bitcoinkernel_wrapper.h:78
btck::BlockValidationResult::HEADER_LOW_WORK
@ HEADER_LOW_WORK
Definition
bitcoinkernel_wrapper.h:79
btck::BlockValidationResult::INVALID_HEADER
@ INVALID_HEADER
Definition
bitcoinkernel_wrapper.h:74
btck::BlockValidationResult::UNSET
@ UNSET
Definition
bitcoinkernel_wrapper.h:71
btck::BlockValidationResult::CONSENSUS
@ CONSENSUS
Definition
bitcoinkernel_wrapper.h:72
btck::BlockValidationResult::MUTATED
@ MUTATED
Definition
bitcoinkernel_wrapper.h:75
btck::BlockValidationResult::CACHED_INVALID
@ CACHED_INVALID
Definition
bitcoinkernel_wrapper.h:73
btck::BlockValidationResult::MISSING_PREV
@ MISSING_PREV
Definition
bitcoinkernel_wrapper.h:76
btck::BlockValidationResult::INVALID_PREV
@ INVALID_PREV
Definition
bitcoinkernel_wrapper.h:77
btck::logging_set_options
void logging_set_options(const btck_LoggingOptions &logging_options)
Definition
bitcoinkernel_wrapper.h:813
btck::ValidationMode::VALID
@ VALID
Definition
bitcoinkernel_wrapper.h:65
btck::ValidationMode::INVALID
@ INVALID
Definition
bitcoinkernel_wrapper.h:66
btck::ValidationMode::INTERNAL_ERROR
@ INTERNAL_ERROR
Definition
bitcoinkernel_wrapper.h:67
btck::SynchronizationState
SynchronizationState
Definition
bitcoinkernel_wrapper.h:53
btck::Warning
Warning
Definition
bitcoinkernel_wrapper.h:59
btck_LoggingOptions
Options controlling the format of log messages.
Definition
bitcoinkernel.h:452
Generated on
for Bitcoin Core by
1.17.0