Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2021-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <interfaces/init.h>6#include <ipc/capnp/context.h>7#include <ipc/capnp/init.capnp.h>8#include <ipc/capnp/init.capnp.proxy.h>9#include <ipc/capnp/protocol.h>10#include <ipc/exception.h>11#include <ipc/protocol.h>12#include <kj/async.h>13#include <mp/proxy-io.h>14#include <mp/proxy-types.h>15#include <mp/util.h>16#include <util/log.h>17#include <util/threadnames.h>19#include <cassert>20#include <cerrno>21#include <future>22#include <memory>23#include <mutex>24#include <optional>25#include <string>26#include <sys/socket.h>27#include <system_error>28#include <thread>30namespace ipc {31namespace capnp {32namespace {34mp::Log GetRequestedIPCLogLevel()35{36if (util::log::ShouldTraceLog(BCLog::IPC)) return mp::Log::Trace;37if (util::log::ShouldDebugLog(BCLog::IPC)) return mp::Log::Debug;39// Info, Warning, and Error are logged unconditionally40return mp::Log::Info;41}43void IpcLogFn(mp::LogMessage message)44{45switch (message.level) {46case mp::Log::Trace:47LogTrace(BCLog::IPC, "%s", message.message);48return;49case mp::Log::Debug:50LogDebug(BCLog::IPC, "%s", message.message);51return;52case mp::Log::Info:53LogInfo("ipc: %s", message.message);54return;55case mp::Log::Warning:56LogWarning("ipc: %s", message.message);57return;58case mp::Log::Error:59LogError("ipc: %s", message.message);60return;61case mp::Log::Raise:62LogError("ipc: %s", message.message);63throw Exception(message.message);64} // no default case, so the compiler can warn about missing cases66// Be conservative and assume that if MP ever adds a new log level, it67// should only be shown at our most verbose level.68LogTrace(BCLog::IPC, "%s", message.message);69}71class CapnpProtocol : public Protocol72{73public:74CapnpProtocol(const char* exe_name) : m_exe_name{exe_name} {}75~CapnpProtocol() noexcept(true)76{77m_loop_ref.reset();78if (m_loop_thread.joinable()) m_loop_thread.join();79assert(!m_loop);80};81std::unique_ptr<interfaces::Init> connect(mp::Stream stream) override82{83startLoop();84return mp::ConnectStream<messages::Init>(*m_loop, std::move(stream));85}86void listen(mp::SocketId listen_fd, interfaces::Init& init) override87{88startLoop();89if (::listen(listen_fd, /*backlog=*/5) != 0) {90throw std::system_error(errno, std::system_category());91}92mp::ListenConnections<messages::Init>(*m_loop, listen_fd, init);93}94void serve(interfaces::Init& init, const std::function<mp::Stream()>& make_stream) override95{96assert(!m_loop);97mp::CurrentThread().thread_name = mp::ThreadName(m_exe_name);98mp::LogOptions opts = {99.log_fn = IpcLogFn,100.log_level = GetRequestedIPCLogLevel()101};102m_loop.emplace(m_exe_name, std::move(opts), &m_context);103mp::ServeStream<messages::Init>(*m_loop, make_stream(), init);104m_parent_connection = &m_loop->m_incoming_connections.back();105m_loop->loop();106m_loop.reset();107}108void disconnectIncoming() override109{110if (!m_loop) return;111// Delete incoming connections, except the connection to a parent112// process (if there is one), since a parent process should be able to113// monitor and control this process, even during shutdown.114m_loop->sync([&] {115m_loop->m_incoming_connections.remove_if([this](mp::Connection& c) { return &c != m_parent_connection; });116});117}118mp::Stream makeStream(mp::SocketId socket) override119{120startLoop();121return mp::MakeStream(*m_loop, socket);122}123void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) override124{125mp::ProxyTypeRegister::types().at(type)(iface).cleanup_fns.emplace_back(std::move(cleanup));126}127Context& context() override { return m_context; }128void startLoop()129{130if (m_loop) return;131std::promise<void> promise;132m_loop_thread = std::thread([&] {133util::ThreadRename("capnp-loop");134mp::LogOptions opts = {135.log_fn = IpcLogFn,136.log_level = GetRequestedIPCLogLevel()137};138m_loop.emplace(m_exe_name, std::move(opts), &m_context);139m_loop_ref.emplace(*m_loop);140promise.set_value();141m_loop->loop();142m_loop.reset();143});144promise.get_future().wait();145}146const char* m_exe_name;147Context m_context;148//! EventLoop object which manages I/O events for all connections.149std::optional<mp::EventLoop> m_loop;150//! Reference to the same EventLoop. Increments the loop’s refcount on151//! creation, decrements on destruction. The loop thread exits when the152//! refcount reaches 0. Other IPC objects also hold their own EventLoopRef.153std::optional<mp::EventLoopRef> m_loop_ref;154//! Connection to parent, if this is a child process spawned by a parent process.155mp::Connection* m_parent_connection{nullptr};156std::thread m_loop_thread;157};158} // namespace160std::unique_ptr<Protocol> MakeCapnpProtocol(const char* exe_name) { return std::make_unique<CapnpProtocol>(exe_name); }161} // namespace capnp162} // namespace ipc
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.