Skip to content

Commit 592d6fc

Browse files
committed
Implement serialization for the blinds cache
1 parent 0188218 commit 592d6fc

File tree

9 files changed

+662
-107
lines changed

9 files changed

+662
-107
lines changed

src/fcmp_pp/blinds_cache.cpp

Lines changed: 174 additions & 75 deletions
Large diffs are not rendered by default.

src/fcmp_pp/blinds_cache.h

Lines changed: 121 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,17 @@
2929
#pragma once
3030

3131
#include "common/threadpool.h"
32+
#include "common/unordered_containers_boost_serialization.h"
3233
#include "curve_trees.h"
3334
#include "fcmp_pp_types.h"
35+
#include "serialization/containers.h"
36+
#include "serialization/crypto.h"
37+
#include "serialization/pair.h"
38+
#include "serialization/serialization.h"
39+
40+
#include <boost/serialization/deque.hpp>
41+
#include <boost/serialization/vector.hpp>
42+
#include <boost/serialization/version.hpp>
3443

3544
#include <deque>
3645
#include <memory>
@@ -43,20 +52,44 @@ namespace fcmp_pp
4352
namespace curve_trees
4453
{
4554
//----------------------------------------------------------------------------------------------------------------------
46-
struct PendingBlind final
55+
static constexpr int BLINDS_CACHE_VERSION = 0;
56+
//----------------------------------------------------------------------------------------------------------------------
57+
struct OutputBlinds final
4758
{
48-
uint8_t *result{nullptr};
49-
PendingBlind() : result{nullptr} {};
59+
FcmpRerandomizedOutputCompressed rerandomized_output;
60+
61+
std::shared_ptr<OutputBlind> blinded_o_blind;
62+
std::shared_ptr<OutputBlind> blinded_i_blind;
63+
std::shared_ptr<OutputBlind> blinded_i_blind_blind;
64+
std::shared_ptr<OutputBlind> blinded_c_blind;
5065
};
5166

52-
struct PendingOutputBlinds final
67+
struct SerializableOutputBlinds final
5368
{
54-
FcmpRerandomizedOutputCompressed rerandomized_output;
55-
56-
std::shared_ptr<PendingBlind> blinded_o_blind;
57-
std::shared_ptr<PendingBlind> blinded_i_blind;
58-
std::shared_ptr<PendingBlind> blinded_i_blind_blind;
59-
std::shared_ptr<PendingBlind> blinded_c_blind;
69+
SerializableRerandomizedOutput rerandomized_output;
70+
71+
OutputBlind blinded_o_blind;
72+
OutputBlind blinded_i_blind;
73+
OutputBlind blinded_i_blind_blind;
74+
OutputBlind blinded_c_blind;
75+
76+
template <class Archive>
77+
inline void serialize(Archive &a, const unsigned int ver)
78+
{
79+
a & rerandomized_output;
80+
a & blinded_o_blind;
81+
a & blinded_i_blind;
82+
a & blinded_i_blind_blind;
83+
a & blinded_c_blind;
84+
}
85+
86+
BEGIN_SERIALIZE_OBJECT()
87+
FIELD(rerandomized_output)
88+
FIELD(blinded_o_blind)
89+
FIELD(blinded_i_blind)
90+
FIELD(blinded_i_blind_blind)
91+
FIELD(blinded_c_blind)
92+
END_SERIALIZE()
6093
};
6194
//----------------------------------------------------------------------------------------------------------------------
6295
template<typename C1, typename C2>
@@ -94,24 +127,32 @@ class BlindsCache final
94127

95128
// Internal helper functions
96129
private:
97-
std::shared_ptr<PendingBlind> get_blinded_o_blind_async(const SeleneScalar o_blind);
98-
std::shared_ptr<PendingBlind> get_blinded_i_blind_async(const SeleneScalar i_blind);
99-
std::shared_ptr<PendingBlind> get_blinded_i_blind_blind_async(const SeleneScalar i_blind_blind);
100-
std::shared_ptr<PendingBlind> get_blinded_c_blind_async(const SeleneScalar c_blind);
130+
std::shared_ptr<OutputBlind> get_blinded_o_blind_async(const SeleneScalar o_blind);
131+
std::shared_ptr<OutputBlind> get_blinded_i_blind_async(const SeleneScalar i_blind);
132+
std::shared_ptr<OutputBlind> get_blinded_i_blind_blind_async(const SeleneScalar i_blind_blind);
133+
std::shared_ptr<OutputBlind> get_blinded_c_blind_async(const SeleneScalar c_blind);
134+
135+
std::shared_ptr<BranchBlind> get_c1_branch_blind_async();
136+
std::shared_ptr<BranchBlind> get_c2_branch_blind_async();
101137

102-
std::shared_ptr<PendingBlind> get_c1_branch_blind_async();
103-
std::shared_ptr<PendingBlind> get_c2_branch_blind_async();
138+
void export_serializable_members(std::unordered_map<OutputPairRef, SerializableOutputBlinds> &output_blinds_out,
139+
std::vector<BranchBlind> &c1_branch_blinds_out,
140+
std::vector<BranchBlind> &c2_branch_blinds_out);
141+
142+
void import_serializable_members(std::unordered_map<OutputPairRef, SerializableOutputBlinds> &&output_blinds,
143+
std::vector<BranchBlind> &&c1_branch_blinds,
144+
std::vector<BranchBlind> &&c2_branch_blinds);
104145

105146
// State held in memory
106147
private:
107148
std::mutex m_mutex;
108149

109150
uint8_t m_n_tree_layers;
110151

111-
std::unordered_map<OutputPairRef, PendingOutputBlinds> m_output_blindings;
152+
std::unordered_map<OutputPairRef, OutputBlinds> m_output_blindings;
112153

113-
std::deque<std::shared_ptr<PendingBlind>> m_pending_c1_branch_blinds;
114-
std::deque<std::shared_ptr<PendingBlind>> m_pending_c2_branch_blinds;
154+
std::deque<std::shared_ptr<BranchBlind>> m_pending_c1_branch_blinds;
155+
std::deque<std::shared_ptr<BranchBlind>> m_pending_c2_branch_blinds;
115156

116157
// Config
117158
private:
@@ -122,18 +163,47 @@ class BlindsCache final
122163
tools::threadpool::waiter m_waiter;
123164

124165
// Serialization
125-
// TODO: serialization: grab the lock and wait for all tasks to finish, read all results from pending objects into serializable data types
126-
// TODO: de-serialization: grab the lock and wait for all tasks to finish, clear all pending objects, initialze pending objects by reading the serializable data types
127-
// public:
128-
// template <class Archive>
129-
// inline void serialize(Archive &a, const unsigned int ver)
130-
// {
131-
132-
// }
133-
134-
// BEGIN_SERIALIZE_OBJECT()
135-
136-
// END_SERIALIZE()
166+
public:
167+
template <class Archive>
168+
inline void serialize(Archive &a, const unsigned int ver)
169+
{
170+
std::unordered_map<OutputPairRef, SerializableOutputBlinds> output_blinds;
171+
std::vector<BranchBlind> c1_branch_blinds;
172+
std::vector<BranchBlind> c2_branch_blinds;
173+
174+
if (typename Archive::is_saving())
175+
this->export_serializable_members(output_blinds, c1_branch_blinds, c2_branch_blinds);
176+
177+
a & output_blinds;
178+
a & c1_branch_blinds;
179+
a & c2_branch_blinds;
180+
181+
if (!typename Archive::is_saving())
182+
this->import_serializable_members(std::move(output_blinds),
183+
std::move(c1_branch_blinds),
184+
std::move(c2_branch_blinds));
185+
}
186+
187+
BEGIN_SERIALIZE_OBJECT()
188+
VERSION_FIELD(BLINDS_CACHE_VERSION)
189+
190+
std::unordered_map<OutputPairRef, SerializableOutputBlinds> output_blinds;
191+
std::vector<BranchBlind> c1_branch_blinds;
192+
std::vector<BranchBlind> c2_branch_blinds;
193+
194+
if (typename Archive<W>::is_saving())
195+
this->export_serializable_members(output_blinds, c1_branch_blinds, c2_branch_blinds);
196+
197+
FIELD(output_blinds)
198+
FIELD(c1_branch_blinds)
199+
FIELD(c2_branch_blinds)
200+
201+
if (!typename Archive<W>::is_saving())
202+
this->import_serializable_members(std::move(output_blinds),
203+
std::move(c1_branch_blinds),
204+
std::move(c2_branch_blinds));
205+
206+
END_SERIALIZE()
137207
};
138208

139209
using BlindsCacheV1 = BlindsCache<Selene, Helios>;
@@ -143,3 +213,23 @@ using BlindsCacheV1 = BlindsCache<Selene, Helios>;
143213
}//namespace curve_trees
144214
}//namespace fcmp_pp
145215

216+
// Since BOOST_CLASS_VERSION does not work for templated class, implement it
217+
namespace boost
218+
{
219+
namespace serialization
220+
{
221+
template<typename C1, typename C2>
222+
struct version<fcmp_pp::curve_trees::BlindsCache<C1, C2>>
223+
{
224+
typedef mpl::int_<fcmp_pp::curve_trees::BLINDS_CACHE_VERSION> type;
225+
typedef mpl::integral_c_tag tag;
226+
static constexpr int value = version::type::value;
227+
BOOST_MPL_ASSERT((
228+
boost::mpl::less<
229+
boost::mpl::int_<fcmp_pp::curve_trees::BLINDS_CACHE_VERSION>,
230+
boost::mpl::int_<256>
231+
>
232+
));
233+
};
234+
}
235+
}

src/fcmp_pp/fcmp_pp_rust/fcmp++.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ struct ObjectSlice
145145
uintptr_t len;
146146
};
147147

148+
struct U8Slice
149+
{
150+
const uint8_t *buf;
151+
uintptr_t len;
152+
};
153+
148154
#ifdef __cplusplus
149155
extern "C" {
150156
#endif
@@ -211,14 +217,33 @@ CResult blind_i_blind(const struct SeleneScalar *i_blind);
211217
CResult blind_i_blind_blind(const struct SeleneScalar *i_blind_blind);
212218
CResult blind_c_blind(const struct SeleneScalar *c_blind);
213219

220+
CResult o_blind_to_buf(const uint8_t *o_blind);
221+
CResult i_blind_to_buf(const uint8_t *i_blind);
222+
CResult i_blind_blind_to_buf(const uint8_t *i_blind_blind);
223+
CResult c_blind_to_buf(const uint8_t *c_blind);
224+
225+
CResult o_blind_from_buf(struct U8Slice o_blind);
226+
CResult i_blind_from_buf(struct U8Slice i_blind);
227+
CResult i_blind_blind_from_buf(struct U8Slice i_blind_blind);
228+
CResult c_blind_from_buf(struct U8Slice c_blind);
229+
214230
CResult output_blinds_new(const uint8_t *o_blind,
215231
const uint8_t *i_blind,
216232
const uint8_t *i_blind_blind,
217233
const uint8_t *c_blind);
218234

235+
CResult output_blinds_to_buf(const uint8_t *output_blinds);
236+
CResult output_blinds_from_buf(struct U8Slice output_blinds);
237+
219238
CResult helios_branch_blind(void);
220239
CResult selene_branch_blind(void);
221240

241+
CResult selene_branch_blind_to_buf(const uint8_t *selene_blind);
242+
CResult helios_branch_blind_to_buf(const uint8_t *helios_blind);
243+
244+
CResult selene_branch_blind_from_buf(struct U8Slice selene_blind);
245+
CResult helios_branch_blind_from_buf(struct U8Slice helios_blind);
246+
222247
CResult fcmp_prove_input_new(const struct FcmpRerandomizedOutputCompressed *rerandomized_output,
223248
const uint8_t *path,
224249
const uint8_t *output_blinds,

src/fcmp_pp/fcmp_pp_rust/src/lib.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ const unsafe fn slice_from_raw_parts_0able<'a, T>(p: *const T, len: usize) -> &'
103103
}
104104
}
105105

106+
fn buf_to_slice(buf: Vec<u8>) -> Slice<u8> {
107+
// Leak the buf into a ptr that the C++ can handle
108+
// TODO: Use Box::leak instead, and then in destructor convert back to box https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak
109+
let len = buf.len();
110+
let ptr = buf.leak().as_ptr();
111+
Slice::<u8>{ buf: ptr, len }
112+
}
113+
106114
fn ed25519_point_from_bytes(ed25519_point: *const u8) -> EdwardsPoint {
107115
let mut ed25519_point = unsafe { core::slice::from_raw_parts(ed25519_point, 32) };
108116
// TODO: Return an error here (instead of unwrapping)
@@ -392,6 +400,37 @@ pub unsafe extern "C" fn blind_o_blind(
392400
}
393401
}
394402

403+
macro_rules! buf_conversion_fns {
404+
($typename:ident, $trait:ty, $to_buf_fn:ident, $from_buf_fn:ident) => {
405+
#[no_mangle]
406+
pub unsafe extern "C" fn $to_buf_fn(
407+
blind: *const $typename<$trait>,
408+
) -> CResult<Slice<u8>, ()> {
409+
let blind = blind.read();
410+
let mut buf = vec![];
411+
let Ok(_) = blind.write(&mut buf) else {
412+
// TODO: no empty err
413+
return CResult::err(());
414+
};
415+
CResult::ok(buf_to_slice(buf))
416+
}
417+
418+
#[no_mangle]
419+
pub unsafe extern "C" fn $from_buf_fn(
420+
blind: Slice<u8>,
421+
) -> CResult<$typename<$trait>, ()> {
422+
let mut buf: &[u8] = blind.into();
423+
let Ok(blind) = $typename::<$trait>::read(&mut buf) else {
424+
// TODO: no empty err
425+
return CResult::err(());
426+
};
427+
CResult::ok(blind)
428+
}
429+
};
430+
}
431+
432+
buf_conversion_fns!(OBlind, EdwardsPoint, o_blind_to_buf, o_blind_from_buf);
433+
395434
//---------------------------------------------- CBlind
396435

397436
/// # Safety
@@ -425,6 +464,8 @@ pub unsafe extern "C" fn blind_c_blind(
425464
}
426465
}
427466

467+
buf_conversion_fns!(CBlind, EdwardsPoint, c_blind_to_buf, c_blind_from_buf);
468+
428469
//---------------------------------------------- IBlind
429470

430471
/// # Safety
@@ -458,6 +499,8 @@ pub unsafe extern "C" fn blind_i_blind(
458499
}
459500
}
460501

502+
buf_conversion_fns!(IBlind, EdwardsPoint, i_blind_to_buf, i_blind_from_buf);
503+
461504
//---------------------------------------------- IBlindBlind
462505

463506
/// # Safety
@@ -491,6 +534,13 @@ pub unsafe extern "C" fn blind_i_blind_blind(
491534
}
492535
}
493536

537+
buf_conversion_fns!(
538+
IBlindBlind,
539+
EdwardsPoint,
540+
i_blind_blind_to_buf,
541+
i_blind_blind_from_buf
542+
);
543+
494544
//---------------------------------------------- OutputBlinds
495545

496546
/// # Safety
@@ -520,6 +570,13 @@ pub unsafe extern "C" fn output_blinds_new(
520570
CResult::ok(ob)
521571
}
522572

573+
buf_conversion_fns!(
574+
OutputBlinds,
575+
EdwardsPoint,
576+
output_blinds_to_buf,
577+
output_blinds_from_buf
578+
);
579+
523580
//---------------------------------------------- BranchBlind
524581

525582
#[no_mangle]
@@ -538,6 +595,19 @@ pub extern "C" fn selene_branch_blind() -> CResult<BranchBlind<<Selene as Cipher
538595
))
539596
}
540597

598+
buf_conversion_fns!(
599+
BranchBlind,
600+
<Helios as Ciphersuite>::G,
601+
helios_branch_blind_to_buf,
602+
helios_branch_blind_from_buf
603+
);
604+
buf_conversion_fns!(
605+
BranchBlind,
606+
<Selene as Ciphersuite>::G,
607+
selene_branch_blind_to_buf,
608+
selene_branch_blind_from_buf
609+
);
610+
541611
//-------------------------------------------------------------------------------------- Fcmp
542612

543613
#[derive(Clone)]

0 commit comments

Comments
 (0)