Bitcoin Core 31.99.0
P2P Digital Currency
ipc.cpp
Go to the documentation of this file.
1// Copyright (c) 2026-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
6#include <capnp/capability.h>
7#include <capnp/rpc.h>
8#include <kj/memory.h>
9#include <mp/proxy-io.h>
10#include <mp/proxy.h>
12#include <test/fuzz/fuzz.h>
13#include <ipc/test/fuzz/ipc_fuzz.capnp.h>
14#include <ipc/test/fuzz/ipc_fuzz.capnp.proxy.h>
16#include <test/fuzz/util.h>
18
19#include <future>
20#include <memory>
21#include <stdexcept>
22#include <thread>
23
24namespace {
25class IpcFuzzSetup
26{
27public:
28 IpcFuzzSetup()
29 {
30 std::promise<std::unique_ptr<mp::ProxyClient<test::fuzz::messages::IpcFuzzInterface>>> client_promise;
31 auto client_future{client_promise.get_future()};
33 mp::EventLoop loop("ipc-fuzz", [](mp::LogMessage message) {
34 if (message.level == mp::Log::Raise) throw std::runtime_error(message.message);
35 });
36 auto pipe = loop.m_io_context.provider->newTwoWayPipe();
37
38 auto server_connection = std::make_unique<mp::Connection>(
39 loop,
40 kj::mv(pipe.ends[0]),
41 [&](mp::Connection& connection) {
42 auto server_proxy = kj::heap<mp::ProxyServer<test::fuzz::messages::IpcFuzzInterface>>(
43 std::make_shared<IpcFuzzImplementation>(), connection);
44 return capnp::Capability::Client(kj::mv(server_proxy));
45 });
46 server_connection->onDisconnect([&] { server_connection.reset(); });
47
48 auto client_connection = std::make_unique<mp::Connection>(loop, kj::mv(pipe.ends[1]));
49 auto client_proxy = std::make_unique<mp::ProxyClient<test::fuzz::messages::IpcFuzzInterface>>(
50 client_connection->m_rpc_system->bootstrap(mp::ServerVatId().vat_id)
51 .castAs<test::fuzz::messages::IpcFuzzInterface>(),
52 client_connection.get(),
53 /* destroy_connection= */ true);
54 (void)client_connection.release();
55
56 client_promise.set_value(std::move(client_proxy));
57 loop.loop();
58 });
59 m_client = client_future.get();
60 }
61
62 ~IpcFuzzSetup()
63 {
64 m_client.reset();
65 if (m_loop_thread.joinable()) m_loop_thread.join();
66 }
67
68 std::unique_ptr<mp::ProxyClient<test::fuzz::messages::IpcFuzzInterface>> m_client;
69
70private:
72};
73
74static IpcFuzzSetup* g_ipc;
75
76static void initialize_ipc()
77{
78 static const auto testing_setup = MakeNoLogFileContext<>();
79 (void)testing_setup;
80
81 // Ensure g_thread_context is destroyed after the IPC setup, since C++
82 // destroys thread_local objects in reverse construction order.
84 (void)thread_context;
85
86 thread_local static IpcFuzzSetup ipc; // NOLINT(bitcoin-nontrivial-threadlocal)
87 g_ipc = &ipc;
88}
89
90FUZZ_TARGET(ipc, .init = initialize_ipc)
91{
92 auto& ipc = *g_ipc;
93 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
97 [&] {
98 static constexpr int MIN_ADD{-1'000'000};
99 static constexpr int MAX_ADD{1'000'000};
100 const int a = fuzzed_data_provider.ConsumeIntegralInRange<int>(MIN_ADD, MAX_ADD);
101 const int b = fuzzed_data_provider.ConsumeIntegralInRange<int>(MIN_ADD, MAX_ADD);
102 assert(ipc.m_client->add(a, b) == a + b);
103 },
104 [&] {
107 COutPoint expected{outpoint.hash, outpoint.n ^ 0xFFFFFFFFu};
108 assert(ipc.m_client->passOutPoint(outpoint) == expected);
109 },
110 [&] {
111 std::vector<uint8_t> value = ConsumeRandomLengthByteVector<uint8_t>(fuzzed_data_provider, 512);
112 std::vector<uint8_t> expected{value.rbegin(), value.rend()};
113 assert(ipc.m_client->passVectorUint8(value) == expected);
114 },
115 [&] {
117 CScript expected{script};
118 expected << OP_NOP;
119 assert(ipc.m_client->passScript(script) == expected);
120 },
121 [&] {
122 UniValue value;
123 if (!value.read(fuzzed_data_provider.ConsumeRandomLengthString(512))) return;
124 assert(ipc.m_client->passUniValue(value).write() == value.write());
125 },
126 [&] {
127 const CMutableTransaction mutable_tx = ConsumeTransaction(fuzzed_data_provider, std::nullopt);
128 if (mutable_tx.vin.empty()) return;
129 const CTransactionRef tx = MakeTransactionRef(mutable_tx);
130 assert(*ipc.m_client->passTransaction(tx) == *tx);
131 });
132 }
133}
134} // namespace
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
Txid hash
Definition: transaction.h:31
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
std::string ConsumeRandomLengthString(size_t max_length)
T ConsumeIntegralInRange(T min, T max)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool read(std::string_view raw)
Object holding network & rpc state associated with either an incoming server connection,...
Definition: proxy-io.h:436
Event loop implementation.
Definition: proxy-io.h:242
kj::AsyncIoContext m_io_context
Capnp IO context.
Definition: proxy-io.h:334
static transaction_identifier FromUint256(const uint256 &id)
LIMITED_WHILE(provider.remaining_bytes(), 10000)
#define FUZZ_TARGET(...)
Definition: fuzz.h:35
std::thread m_loop_thread
Definition: protocol.cpp:142
std::promise< std::unique_ptr< ProxyClient< messages::FooInterface > > > client_promise
std::thread thread
Thread variable should be after other struct members so the thread does not start until the other mem...
Definition: basic.cpp:8
Definition: ipc.h:13
thread_local ThreadContext g_thread_context
Definition: proxy.cpp:44
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:404
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:403
@ OP_NOP
Definition: script.h:103
A mutable version of CTransaction.
Definition: transaction.h:358
std::vector< CTxIn > vin
Definition: transaction.h:359
Log level
The severity level of this message.
Definition: proxy-io.h:147
std::string message
Message to be logged.
Definition: proxy-io.h:144
Vat id for server side of connection.
Definition: proxy-io.h:520
The thread_local ThreadContext g_thread_context struct provides information about individual threads ...
Definition: proxy-io.h:706
CScript ConsumeScript(FuzzedDataProvider &fuzzed_data_provider, const bool maybe_p2wsh) noexcept
Definition: util.cpp:93
CMutableTransaction ConsumeTransaction(FuzzedDataProvider &fuzzed_data_provider, const std::optional< std::vector< Txid > > &prevout_txids, const int max_num_in, const int max_num_out) noexcept
Definition: util.cpp:42
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: util.h:195
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
Definition: util.h:37
assert(!tx.IsCoinBase())
FuzzedDataProvider & fuzzed_data_provider
Definition: fees.cpp:39