mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-13 19:37:04 +01:00
Add capnp serialization code for bitcoin types
- Add capnp ToBlob, ToArray, Wrap, Serialize, and Unserialize helper functions - Add support for std::chrono::seconds capnp serialization - Add support for util::Result capnp serialization
This commit is contained in:
parent
1d813e4bf5
commit
516f8637b8
2 changed files with 118 additions and 2 deletions
|
@ -8,9 +8,12 @@
|
|||
#include <clientversion.h>
|
||||
#include <interfaces/types.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <protocol.h>
|
||||
#include <serialize.h>
|
||||
#include <streams.h>
|
||||
#include <univalue.h>
|
||||
#include <util/result.h>
|
||||
#include <util/translation.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <mp/proxy-types.h>
|
||||
|
@ -28,12 +31,27 @@
|
|||
#include <mp/type-threadmap.h>
|
||||
#include <mp/type-vector.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
namespace ipc {
|
||||
namespace capnp {
|
||||
//! Convert kj::ArrayPtr to base_blob.
|
||||
template <typename T>
|
||||
inline T ToBlob(const kj::ArrayPtr<const kj::byte>& array)
|
||||
{
|
||||
return T({array.begin(), array.begin() + array.size()});
|
||||
}
|
||||
|
||||
//! Convert base_blob to kj::ArrayPtr.
|
||||
template <typename T>
|
||||
inline kj::ArrayPtr<const kj::byte> ToArray(const T& blob)
|
||||
{
|
||||
return {reinterpret_cast<const kj::byte*>(blob.data()), blob.size()};
|
||||
}
|
||||
|
||||
//! Construct a ParamStream wrapping a data stream with serialization parameters
|
||||
//! needed to pass transaction objects between bitcoin processes.
|
||||
//! needed to pass transaction and address objects between bitcoin processes.
|
||||
//! In the future, more params may be added here to serialize other objects that
|
||||
//! require serialization parameters. Params should just be chosen to serialize
|
||||
//! objects completely and ensure that serializing and deserializing objects
|
||||
|
@ -42,7 +60,28 @@ namespace capnp {
|
|||
template <typename S>
|
||||
auto Wrap(S& s)
|
||||
{
|
||||
return ParamsStream{s, TX_WITH_WITNESS};
|
||||
return ParamsStream{s, TX_WITH_WITNESS, CAddress::V2_NETWORK};
|
||||
}
|
||||
|
||||
//! Serialize bitcoin value.
|
||||
template <typename T>
|
||||
DataStream Serialize(const T& value)
|
||||
{
|
||||
DataStream stream;
|
||||
auto wrapper{Wrap(stream)};
|
||||
value.Serialize(wrapper);
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Deserialize bitcoin value.
|
||||
template <typename T>
|
||||
T Unserialize(const kj::ArrayPtr<const kj::byte>& data)
|
||||
{
|
||||
SpanReader stream{{data.begin(), data.end()}};
|
||||
T value;
|
||||
auto wrapper{Wrap(stream)};
|
||||
value.Unserialize(wrapper);
|
||||
return value;
|
||||
}
|
||||
|
||||
//! Detect if type has a deserialize_type constructor, which is
|
||||
|
@ -127,6 +166,63 @@ decltype(auto) CustomReadField(TypeList<UniValue>, Priority<1>, InvokeContext& i
|
|||
});
|
||||
}
|
||||
|
||||
//! Overload CustomBuildField and CustomReadField to serialize
|
||||
//! UniValue::type_error exceptions as text strings.
|
||||
template <typename Value, typename Output>
|
||||
void CustomBuildField(TypeList<UniValue::type_error>, Priority<1>, InvokeContext& invoke_context,
|
||||
Value&& value, Output&& output)
|
||||
{
|
||||
BuildField(TypeList<std::string>(), invoke_context, output, std::string(value.what()));
|
||||
}
|
||||
|
||||
template <typename Input, typename ReadDest>
|
||||
decltype(auto) CustomReadField(TypeList<UniValue::type_error>, Priority<1>, InvokeContext& invoke_context,
|
||||
Input&& input, ReadDest&& read_dest)
|
||||
{
|
||||
read_dest.construct(ReadField(TypeList<std::string>(), invoke_context, input, mp::ReadDestTemp<std::string>()));
|
||||
}
|
||||
|
||||
//! Overload CustomBuildField and CustomReadField to serialize util::Result
|
||||
//! return values as common.capnp Result and ResultVoid structs
|
||||
template <typename LocalType, typename Value, typename Output>
|
||||
void CustomBuildField(TypeList<util::Result<LocalType>>, Priority<1>, InvokeContext& invoke_context, Value&& value,
|
||||
Output&& output)
|
||||
{
|
||||
auto result = output.init();
|
||||
if (value) {
|
||||
if constexpr (!std::is_same_v<LocalType, void>) {
|
||||
using ValueAccessor = typename ProxyStruct<typename decltype(result)::Builds>::ValueAccessor;
|
||||
BuildField(TypeList<LocalType>(), invoke_context, Make<StructField, ValueAccessor>(result), *value);
|
||||
}
|
||||
} else {
|
||||
BuildField(TypeList<bilingual_str>(), invoke_context, Make<ValueField>(result.initError()),
|
||||
util::ErrorString(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LocalType, typename Input, typename ReadDest>
|
||||
decltype(auto) CustomReadField(TypeList<util::Result<LocalType>>, Priority<1>, InvokeContext& invoke_context,
|
||||
Input&& input, ReadDest&& read_dest)
|
||||
{
|
||||
auto result = input.get();
|
||||
if (result.hasError()) {
|
||||
bilingual_str error;
|
||||
ReadField(mp::TypeList<bilingual_str>(), invoke_context, mp::Make<mp::ValueField>(result.getError()),
|
||||
mp::ReadDestUpdate(error));
|
||||
read_dest.construct(util::Error{std::move(error)});
|
||||
} else {
|
||||
if constexpr (!std::is_same_v<LocalType, void>) {
|
||||
assert (result.hasValue());
|
||||
ReadField(mp::TypeList<LocalType>(), invoke_context, mp::Make<mp::ValueField>(result.getValue()),
|
||||
mp::ReadDestEmplace(
|
||||
mp::TypeList<LocalType>(), [&](auto&&... args) -> auto& {
|
||||
return *read_dest.construct(LocalType{std::forward<decltype(args)>(args)...});
|
||||
}));
|
||||
} else {
|
||||
read_dest.construct();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace mp
|
||||
|
||||
#endif // BITCOIN_IPC_CAPNP_COMMON_TYPES_H
|
||||
|
|
|
@ -14,3 +14,23 @@ struct BlockRef $Proxy.wrap("interfaces::BlockRef") {
|
|||
hash @0 :Data;
|
||||
height @1 :Int32;
|
||||
}
|
||||
|
||||
struct BilingualStr $Proxy.wrap("bilingual_str") {
|
||||
original @0 :Text;
|
||||
translated @1 :Text;
|
||||
}
|
||||
|
||||
struct Result(Value) {
|
||||
value @0 :Value;
|
||||
error @1: BilingualStr;
|
||||
}
|
||||
|
||||
# Wrapper for util::Result<void>
|
||||
struct ResultVoid(Value) {
|
||||
error @0: BilingualStr;
|
||||
}
|
||||
|
||||
struct Pair(Key, Value) {
|
||||
key @0 :Key;
|
||||
value @1 :Value;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue