Skip to content

Commit d043950

Browse files
multiprocess: Add serialization code for BlockValidationState
Co-authored-by: TheCharlatan <seb.kung@gmail.com>
1 parent 33c2eee commit d043950

File tree

8 files changed

+104
-3
lines changed

8 files changed

+104
-3
lines changed

src/ipc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# file COPYING or https://opensource.org/license/mit/.
44

55
add_library(bitcoin_ipc STATIC EXCLUDE_FROM_ALL
6+
capnp/mining.cpp
67
capnp/protocol.cpp
78
interfaces.cpp
89
process.cpp

src/ipc/capnp/mining-types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,14 @@
1313
#include <node/types.h>
1414
#include <validation.h>
1515

16+
namespace mp {
17+
// Custom serialization for BlockValidationState.
18+
void CustomBuildMessage(InvokeContext& invoke_context,
19+
const BlockValidationState& src,
20+
ipc::capnp::messages::BlockValidationState::Builder&& builder);
21+
void CustomReadMessage(InvokeContext& invoke_context,
22+
const ipc::capnp::messages::BlockValidationState::Reader& reader,
23+
BlockValidationState& dest);
24+
} // namespace mp
25+
1626
#endif // BITCOIN_IPC_CAPNP_MINING_TYPES_H

src/ipc/capnp/mining.capnp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") {
3939
coinbaseOutputMaxAdditionalSigops @2 :UInt64 $Proxy.name("coinbase_output_max_additional_sigops");
4040
}
4141

42-
# TODO add fields to this struct
43-
struct BlockValidationState $Proxy.wrap("BlockValidationState") {
42+
# Note: serialization of the BlockValidationState C++ type is somewhat fragile
43+
# and using the struct can be awkward. It would be good if testBlockValidity
44+
# method were changed to return validity information in a simpler format.
45+
struct BlockValidationState {
46+
mode @0 :Int32;
47+
result @1 :Int32;
48+
rejectReason @2 :Text;
49+
debugMessage @3 :Text;
4450
}

src/ipc/capnp/mining.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2024 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+
#include <ipc/capnp/mining-types.h>
6+
#include <ipc/capnp/mining.capnp.proxy-types.h>
7+
8+
#include <mp/proxy-types.h>
9+
10+
namespace mp {
11+
void CustomBuildMessage(InvokeContext& invoke_context,
12+
const BlockValidationState& src,
13+
ipc::capnp::messages::BlockValidationState::Builder&& builder)
14+
{
15+
if (src.IsValid()) {
16+
builder.setMode(0);
17+
} else if (src.IsInvalid()) {
18+
builder.setMode(1);
19+
} else if (src.IsError()) {
20+
builder.setMode(2);
21+
} else {
22+
assert(false);
23+
}
24+
builder.setResult(static_cast<int>(src.GetResult()));
25+
builder.setRejectReason(src.GetRejectReason());
26+
builder.setDebugMessage(src.GetDebugMessage());
27+
}
28+
29+
void CustomReadMessage(InvokeContext& invoke_context,
30+
const ipc::capnp::messages::BlockValidationState::Reader& reader,
31+
BlockValidationState& dest)
32+
{
33+
if (reader.getMode() == 0) {
34+
assert(reader.getResult() == 0);
35+
assert(reader.getRejectReason().size() == 0);
36+
assert(reader.getDebugMessage().size() == 0);
37+
} else if (reader.getMode() == 1) {
38+
dest.Invalid(static_cast<BlockValidationResult>(reader.getResult()), reader.getRejectReason(), reader.getDebugMessage());
39+
} else if (reader.getMode() == 2) {
40+
assert(reader.getResult() == 0);
41+
dest.Error(reader.getRejectReason());
42+
assert(reader.getDebugMessage().size() == 0);
43+
} else {
44+
assert(false);
45+
}
46+
}
47+
} // namespace mp

src/test/ipc_test.capnp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ $Cxx.namespace("gen");
99

1010
using Proxy = import "/mp/proxy.capnp";
1111
$Proxy.include("test/ipc_test.h");
12-
$Proxy.includeTypes("ipc/capnp/common-types.h");
12+
$Proxy.includeTypes("test/ipc_test_types.h");
13+
14+
using Mining = import "../ipc/capnp/mining.capnp";
1315

1416
interface FooInterface $Proxy.wrap("FooImplementation") {
1517
add @0 (a :Int32, b :Int32) -> (result :Int32);
1618
passOutPoint @1 (arg :Data) -> (result :Data);
1719
passUniValue @2 (arg :Text) -> (result :Text);
1820
passTransaction @3 (arg :Data) -> (result :Data);
1921
passVectorChar @4 (arg :Data) -> (result :Data);
22+
passBlockState @5 (arg :Mining.BlockValidationState) -> (result :Mining.BlockValidationState);
2023
}

src/test/ipc_test.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <test/ipc_test.capnp.proxy.h>
1313
#include <test/ipc_test.h>
1414
#include <tinyformat.h>
15+
#include <validation.h>
1516

1617
#include <future>
1718
#include <thread>
@@ -101,6 +102,25 @@ void IpcPipeTest()
101102
std::vector<char> vec2{foo->passVectorChar(vec1)};
102103
BOOST_CHECK_EQUAL(std::string_view(vec1.begin(), vec1.end()), std::string_view(vec2.begin(), vec2.end()));
103104

105+
BlockValidationState bs1;
106+
bs1.Invalid(BlockValidationResult::BLOCK_CHECKPOINT, "reject reason", "debug message");
107+
BlockValidationState bs2{foo->passBlockState(bs1)};
108+
BOOST_CHECK_EQUAL(bs1.IsValid(), bs2.IsValid());
109+
BOOST_CHECK_EQUAL(bs1.IsError(), bs2.IsError());
110+
BOOST_CHECK_EQUAL(bs1.IsInvalid(), bs2.IsInvalid());
111+
BOOST_CHECK_EQUAL(static_cast<int>(bs1.GetResult()), static_cast<int>(bs2.GetResult()));
112+
BOOST_CHECK_EQUAL(bs1.GetRejectReason(), bs2.GetRejectReason());
113+
BOOST_CHECK_EQUAL(bs1.GetDebugMessage(), bs2.GetDebugMessage());
114+
115+
BlockValidationState bs3;
116+
BlockValidationState bs4{foo->passBlockState(bs3)};
117+
BOOST_CHECK_EQUAL(bs3.IsValid(), bs4.IsValid());
118+
BOOST_CHECK_EQUAL(bs3.IsError(), bs4.IsError());
119+
BOOST_CHECK_EQUAL(bs3.IsInvalid(), bs4.IsInvalid());
120+
BOOST_CHECK_EQUAL(static_cast<int>(bs3.GetResult()), static_cast<int>(bs4.GetResult()));
121+
BOOST_CHECK_EQUAL(bs3.GetRejectReason(), bs4.GetRejectReason());
122+
BOOST_CHECK_EQUAL(bs3.GetDebugMessage(), bs4.GetDebugMessage());
123+
104124
// Test cleanup: disconnect pipe and join thread
105125
disconnect_client();
106126
thread.join();

src/test/ipc_test.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <primitives/transaction.h>
99
#include <univalue.h>
1010
#include <util/fs.h>
11+
#include <validation.h>
1112

1213
class FooImplementation
1314
{
@@ -17,6 +18,7 @@ class FooImplementation
1718
UniValue passUniValue(UniValue v) { return v; }
1819
CTransactionRef passTransaction(CTransactionRef t) { return t; }
1920
std::vector<char> passVectorChar(std::vector<char> v) { return v; }
21+
BlockValidationState passBlockState(BlockValidationState s) { return s; }
2022
};
2123

2224
void IpcPipeTest();

src/test/ipc_test_types.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2024 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+
#ifndef BITCOIN_TEST_IPC_TEST_TYPES_H
6+
#define BITCOIN_TEST_IPC_TEST_TYPES_H
7+
8+
#include <ipc/capnp/common-types.h>
9+
#include <ipc/capnp/mining-types.h>
10+
#include <test/ipc_test.capnp.h>
11+
12+
#endif // BITCOIN_TEST_IPC_TEST_TYPES_H

0 commit comments

Comments
 (0)