Skip to content

Commit d0daf3e

Browse files
committed
kernel: Move sanity check to context constructor
This ensures that it is impossible to construct a context that does not pass the sanity checks. Also de-duplicate the init error messages in case of a kernel context initialization error.
1 parent 9d3b216 commit d0daf3e

File tree

7 files changed

+44
-22
lines changed

7 files changed

+44
-22
lines changed

src/bitcoind.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,12 @@ static bool AppInit(NodeContext& node)
184184
return false;
185185
}
186186

187-
node.kernel = std::make_unique<kernel::Context>();
188-
if (!AppInitSanityChecks(*node.kernel))
189-
{
187+
if (!InitKernel(node)) {
188+
// InitError will have been called with detailed error, which ends up on console
189+
return false;
190+
}
191+
192+
if (!AppInitSanityChecks()) {
190193
// InitError will have been called with detailed error, which ends up on console
191194
return false;
192195
}

src/init.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#include <init.h>
1111

12-
#include <kernel/checks.h>
1312
#include <kernel/mempool_persist.h>
1413
#include <kernel/validation_cache_sizes.h>
1514

@@ -680,6 +679,17 @@ static bool AppInitServers(NodeContext& node)
680679
return true;
681680
}
682681

682+
bool InitKernel(NodeContext& node)
683+
{
684+
auto result{kernel::Context::MakeContext()};
685+
if (!result) {
686+
return InitError(strprintf(_("Initialization kernel sanity check failed: %s. %s is shutting down."),
687+
util::ErrorString(result), PACKAGE_NAME));
688+
}
689+
node.kernel = std::move(result.value());
690+
return true;
691+
}
692+
683693
// Parameter interaction based on rules
684694
void InitParameterInteraction(ArgsManager& args)
685695
{
@@ -1026,14 +1036,9 @@ static bool LockDataDirectory(bool probeOnly)
10261036
return true;
10271037
}
10281038

1029-
bool AppInitSanityChecks(const kernel::Context& kernel)
1039+
bool AppInitSanityChecks()
10301040
{
10311041
// ********************************************************* Step 4: sanity checks
1032-
auto result{kernel::SanityChecks(kernel)};
1033-
if (!result) {
1034-
InitError(util::ErrorString(result));
1035-
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), PACKAGE_NAME));
1036-
}
10371042

10381043
// Probe the data directory lock to give an early error message, if possible
10391044
// We cannot hold the data directory lock here, as the forking for daemon() hasn't yet happened,

src/init.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ class ArgsManager;
1919
namespace interfaces {
2020
struct BlockAndHeaderTipInfo;
2121
}
22-
namespace kernel {
23-
struct Context;
24-
}
2522
namespace node {
2623
struct NodeContext;
2724
} // namespace node
@@ -34,6 +31,8 @@ void InitLogging(const ArgsManager& args);
3431
//!Parameter interaction: change current parameters depending on various rules
3532
void InitParameterInteraction(ArgsManager& args);
3633

34+
bool InitKernel(node::NodeContext& node);
35+
3736
/** Initialize bitcoin core: Basic context setup.
3837
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
3938
* @pre Parameters should be parsed and config file should be read.
@@ -50,7 +49,7 @@ bool AppInitParameterInteraction(const ArgsManager& args);
5049
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
5150
* @pre Parameters should be parsed and config file should be read, AppInitParameterInteraction should have been called.
5251
*/
53-
bool AppInitSanityChecks(const kernel::Context& kernel);
52+
bool AppInitSanityChecks();
5453
/**
5554
* Lock bitcoin core data directory.
5655
* @note This should only be done after daemonization. Do not call Shutdown() if this function fails.

src/kernel/context.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,35 @@
55
#include <kernel/context.h>
66

77
#include <crypto/sha256.h>
8+
#include <kernel/checks.h>
89
#include <key.h>
910
#include <logging.h>
10-
#include <pubkey.h>
1111
#include <random.h>
12+
#include <util/result.h>
1213

14+
#include <cassert>
15+
#include <memory>
1316
#include <string>
14-
17+
#include <utility>
1518

1619
namespace kernel {
1720
Context* g_context;
1821

19-
Context::Context()
22+
util::Result<std::unique_ptr<Context>> Context::MakeContext()
2023
{
2124
assert(!g_context);
22-
g_context = this;
25+
auto context{std::unique_ptr<Context>(new Context())};
26+
g_context = context.get();
2327
std::string sha256_algo = SHA256AutoDetect();
2428
LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo);
2529
RandomInit();
2630
ECC_Start();
31+
32+
if (auto res{SanityChecks(*context)}; !res) {
33+
return util::Error{ErrorString(res)};
34+
}
35+
36+
return {std::move(context)};
2737
}
2838

2939
Context::~Context()

src/kernel/context.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef BITCOIN_KERNEL_CONTEXT_H
66
#define BITCOIN_KERNEL_CONTEXT_H
77

8+
#include <util/result.h>
89
#include <util/signalinterrupt.h>
910

1011
#include <memory>
@@ -24,8 +25,11 @@ struct Context {
2425
//! Declare default constructor and destructor that are not inline, so code
2526
//! instantiating the kernel::Context struct doesn't need to #include class
2627
//! definitions for all the unique_ptr members.
27-
Context();
28+
static util::Result<std::unique_ptr<Context>> MakeContext();
2829
~Context();
30+
31+
private:
32+
Context() = default;
2933
};
3034

3135
//! Global pointer to kernel::Context for legacy code. New code should avoid

src/node/interfaces.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ class NodeImpl : public Node
9797
if (!AppInitBasicSetup(args(), Assert(context())->exit_status)) return false;
9898
if (!AppInitParameterInteraction(args())) return false;
9999

100-
m_context->kernel = std::make_unique<kernel::Context>();
101-
if (!AppInitSanityChecks(*m_context->kernel)) return false;
100+
if (!InitKernel(*m_context)) return false;
101+
102+
if (!AppInitSanityChecks()) return false;
102103

103104
if (!AppInitLockDataDirectory()) return false;
104105
if (!AppInitInterfaces(*m_context)) return false;

src/test/util/setup_common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ BasicTestingSetup::BasicTestingSetup(const ChainType chainType, const std::vecto
127127
InitLogging(*m_node.args);
128128
AppInitParameterInteraction(*m_node.args);
129129
LogInstance().StartLogging();
130-
m_node.kernel = std::make_unique<kernel::Context>();
130+
m_node.kernel = std::move(Assert(kernel::Context::MakeContext()).value());
131131
SetupEnvironment();
132132
SetupNetworking();
133133

0 commit comments

Comments
 (0)