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) 2023-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#ifndef BITCOIN_IPC_CAPNP_COMMON_TYPES_H6#define BITCOIN_IPC_CAPNP_COMMON_TYPES_H8#include <clientversion.h>9#include <interfaces/types.h>10#include <primitives/transaction.h>11#include <serialize.h>12#include <streams.h>13#include <univalue.h>15#include <cstddef>16#include <mp/proxy-types.h>17#include <mp/type-chrono.h>18#include <mp/type-context.h>19#include <mp/type-data.h>20#include <mp/type-decay.h>21#include <mp/type-interface.h>22#include <mp/type-message.h>23#include <mp/type-number.h>24#include <mp/type-optional.h>25#include <mp/type-pointer.h>26#include <mp/type-string.h>27#include <mp/type-struct.h>28#include <mp/type-threadmap.h>29#include <mp/type-vector.h>30#include <stdexcept>31#include <type_traits>32#include <utility>34namespace ipc {35namespace capnp {36//! Construct a ParamStream wrapping a data stream with serialization parameters37//! needed to pass transaction objects between bitcoin processes.38//! In the future, more params may be added here to serialize other objects that39//! require serialization parameters. Params should just be chosen to serialize40//! objects completely and ensure that serializing and deserializing objects41//! with the specified parameters produces equivalent objects. It's also42//! harmless to specify serialization parameters here that are not used.43template <typename S>44auto Wrap(S& s)45{46return ParamsStream{s, TX_WITH_WITNESS};47}49//! Detect if type has a deserialize_type constructor, which is50//! used to deserialize types like CTransaction that can't be unserialized into51//! existing objects because they are immutable.52template <typename T>53concept Deserializable = std::is_constructible_v<T, ::deserialize_type, ::DataStream&>;54} // namespace capnp55} // namespace ipc57//! Functions to serialize / deserialize common bitcoin types.58namespace mp {59//! Overload multiprocess library's CustomBuildField hook to allow any60//! serializable object to be stored in a capnproto Data field or passed to a61//! capnproto interface. Use Priority<1> so this hook has medium priority, and62//! higher priority hooks could take precedence over this one.63template <typename LocalType, typename Value, typename Output>64void CustomBuildField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output)65// Enable if serializeable and if LocalType is not cv or reference qualified. If66// LocalType is cv or reference qualified, it is important to fall back to67// lower-priority Priority<0> implementation of this function that strips cv68// references, to prevent this CustomBuildField overload from taking precedence69// over more narrow overloads for specific LocalTypes.70requires Serializable<LocalType, DataStream> && std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>71{72DataStream stream;73auto wrapper{ipc::capnp::Wrap(stream)};74value.Serialize(wrapper);75auto result = output.init(stream.size());76memcpy(result.begin(), stream.data(), stream.size());77}79//! Overload multiprocess library's CustomReadField hook to allow any object80//! with an Unserialize method to be read from a capnproto Data field or81//! returned from capnproto interface. Use Priority<1> so this hook has medium82//! priority, and higher priority hooks could take precedence over this one.83template <typename LocalType, typename Input, typename ReadDest>84decltype(auto) CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest)85requires Unserializable<LocalType, DataStream> && (!ipc::capnp::Deserializable<LocalType>)86{87return read_dest.update([&](auto& value) {88if (!input.has()) return;89auto data = input.get();90SpanReader stream({data.begin(), data.end()});91auto wrapper{ipc::capnp::Wrap(stream)};92value.Unserialize(wrapper);93});94}96//! Overload multiprocess library's CustomReadField hook to allow any object97//! with a deserialize constructor to be read from a capnproto Data field or98//! returned from capnproto interface. Use Priority<1> so this hook has medium99//! priority, and higher priority hooks could take precedence over this one.100template <typename LocalType, typename Input, typename ReadDest>101decltype(auto) CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest)102requires ipc::capnp::Deserializable<LocalType>103{104assert(input.has());105auto data = input.get();106SpanReader stream({data.begin(), data.end()});107auto wrapper{ipc::capnp::Wrap(stream)};108return read_dest.construct(::deserialize, wrapper);109}111//! Overload CustomBuildField and CustomReadField to serialize UniValue112//! parameters and return values as JSON strings.113template <typename Value, typename Output>114void CustomBuildField(TypeList<UniValue>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output)115{116std::string str = value.write();117auto result = output.init(str.size());118memcpy(result.begin(), str.data(), str.size());119}121template <typename Input, typename ReadDest>122decltype(auto) CustomReadField(TypeList<UniValue>, Priority<1>, InvokeContext& invoke_context, Input&& input,123ReadDest&& read_dest)124{125return read_dest.update([&](auto& value) {126auto data = input.get();127if (!value.read(std::string_view{data.begin(), data.size()})) {128throw std::runtime_error{"invalid JSON received over IPC"};129}130});131}133//! Interpret empty Data fields as null CTransactionRef values. This is safe to134//! do because no CTransaction is ever serialized as empty Data, and it is135//! convenient because this allows std::vector<CTransactionRef> to be passed as136//! List(Data) even if the vector contains null values, and even though Cap'n137//! Proto does not (currently) allow distinguishing between null and empty Data138//! values in a List. Interpreting empty Data values as null CTransactionRef139//! values works well for this purpose.140template <typename Input>141bool CustomHasField(TypeList<CTransaction>, InvokeContext& invoke_context, const Input& input)142{143return input.get().size() > 0;144}145} // namespace mp147#endif // BITCOIN_IPC_CAPNP_COMMON_TYPES_H
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.