Skip to content

Commit 6f7b4dc

Browse files
authored
Enable 2 round trip receipts (#999)
1 parent cd97024 commit 6f7b4dc

19 files changed

+611
-43
lines changed

src/consensus/pbft/libbyz/nv_info.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ Pre_prepare* NV_info::fetch_request(Seqno n, Digest& d, View& prev_view)
891891
// Null request
892892
Req_queue empty;
893893
size_t requests_in_batch;
894-
pp = new Pre_prepare(v, n, empty, requests_in_batch);
894+
pp = new Pre_prepare(v, n, empty, requests_in_batch, 0);
895895
pp->set_digest();
896896
d = pp->digest();
897897
prev_view = v;

src/consensus/pbft/libbyz/pre_prepare.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Pre_prepare::Pre_prepare(
1919
Seqno s,
2020
Req_queue& reqs,
2121
size_t& requests_in_batch,
22+
uint64_t nonce_,
2223
Prepared_cert* prepared_cert) :
2324
Message(
2425
Pre_prepare_tag,
@@ -29,14 +30,21 @@ Pre_prepare::Pre_prepare(
2930
pbft::GlobalState::get_node().auth_size() + // Merkle root signature
3031
(pbft_max_signature_size + sizeof(uint64_t)) *
3132
pbft::GlobalState::get_node()
32-
.num_of_replicas()) // signatures for the previous pre_prepare
33+
.num_of_replicas()), // signatures for the previous pre_prepare
34+
nonce(nonce_)
3335
{
3436
rep().view = v;
3537
rep().seqno = s;
3638
rep().replicated_state_merkle_root.fill(0);
3739
rep().contains_gov_req = false;
3840
rep().last_gov_req_updated = 0;
3941

42+
Digest dh;
43+
Digest::Context context;
44+
dh.update_last(context, (char*)&nonce_, sizeof(uint64_t));
45+
dh.finalize(context);
46+
rep().hashed_nonce = dh;
47+
4048
START_CC(pp_digest_cycles);
4149
INCR_OP(pp_digest);
4250

@@ -258,6 +266,7 @@ bool Pre_prepare::calculate_digest(Digest& d)
258266
rep().replicated_state_merkle_root.size());
259267
d.update_last(context, (char*)&rep().contains_gov_req, sizeof(uint64_t));
260268
d.update_last(context, (char*)&rep().last_gov_req_updated, sizeof(Seqno));
269+
d.update_last(context, (char*)&rep().hashed_nonce, sizeof(uint64_t));
261270
d.update_last(context, (char*)&rep().ctx, sizeof(rep().ctx));
262271
d.update_last(context, (char*)&rep().rset_size, sizeof(rep().rset_size));
263272
d.update_last(context, (char*)&rep().n_big_reqs, sizeof(rep().n_big_reqs));

src/consensus/pbft/libbyz/pre_prepare.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct Pre_prepare_rep : public Message_rep
3535
View view;
3636
Seqno seqno;
3737
std::array<uint8_t, MERKLE_ROOT_SIZE> replicated_state_merkle_root;
38+
Digest hashed_nonce;
3839
uint64_t contains_gov_req; // should be a bool, but need to use 8 bytes to
3940
// maintain alignment
4041
Seqno last_gov_req_updated;
@@ -67,13 +68,14 @@ class Pre_prepare : public Message
6768
// Pre_prepare messages
6869
//
6970
public:
70-
Pre_prepare(uint32_t msg_size = 0) : Message(msg_size) {}
71+
Pre_prepare(uint32_t msg_size = 0) : Message(msg_size), nonce(0) {}
7172

7273
Pre_prepare(
7374
View v,
7475
Seqno s,
7576
Req_queue& reqs,
7677
size_t& requests_in_batch,
78+
uint64_t nonce,
7779
Prepared_cert* prepared_cert = nullptr);
7880
// Effects: Creates a new signed Pre_prepare message with view
7981
// number "v", sequence number "s", the requests in "reqs" (up to a
@@ -228,12 +230,17 @@ class Pre_prepare : public Message
228230
bool is_signed();
229231
// Effects: checks if there is a signature over the pre_prepare message
230232

233+
uint64_t get_nonce() const;
234+
// Effects: returns the unhashed nonce
235+
231236
static bool convert(Message* m1, Pre_prepare*& m2);
232237
// Effects: If "m1" has the right size and tag, casts "m1" to a
233238
// "Pre_prepare" pointer, returns the pointer in "m2" and returns
234239
// true. Otherwise, it returns false.
235240

236241
private:
242+
uint64_t nonce;
243+
237244
Pre_prepare_rep& rep() const;
238245
// Effects: Casts contents to a Pre_prepare_rep&
239246

@@ -328,3 +335,8 @@ inline bool Pre_prepare::did_exec_gov_req() const
328335
{
329336
return rep().contains_gov_req;
330337
}
338+
339+
inline uint64_t Pre_prepare::get_nonce() const
340+
{
341+
return nonce;
342+
}

src/consensus/pbft/libbyz/prepare.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@
1212
#include "replica.h"
1313

1414
Prepare::Prepare(
15-
View v, Seqno s, Digest& d, Principal* dst, bool is_signed, int id) :
15+
View v,
16+
Seqno s,
17+
Digest& d,
18+
uint64_t nonce_,
19+
Principal* dst,
20+
bool is_signed,
21+
int id) :
1622
Message(
1723
Prepare_tag,
1824
sizeof(Prepare_rep)
1925
#ifndef USE_PKEY
20-
+ ((dst) ? MAC_size : pbft::GlobalState::get_node().auth_size()))
21-
{
26+
+ ((dst) ? MAC_size : pbft::GlobalState::get_node().auth_size())),
2227
#else
23-
+ ((dst) ? MAC_size : pbft_max_signature_size)
24-
{
28+
+ ((dst) ? MAC_size : pbft_max_signature_size)),
2529
#endif
30+
nonce(nonce_)
31+
{
2632
rep().extra = (dst) ? 1 : 0;
2733
rep().view = v;
2834
rep().seqno = s;
@@ -33,6 +39,12 @@ Prepare::Prepare(
3339
rep().id = pbft::GlobalState::get_node().id();
3440
}
3541

42+
Digest dh;
43+
Digest::Context context;
44+
dh.update_last(context, (char*)&nonce, sizeof(uint64_t));
45+
dh.finalize(context);
46+
rep().hashed_nonce = dh;
47+
3648
#ifdef SIGN_BATCH
3749
rep().digest_sig_size = 0;
3850
rep().digest_padding.fill(0);
@@ -43,11 +55,13 @@ Prepare::Prepare(
4355
uint32_t magic = 0xba5eba11;
4456
NodeId id;
4557
Digest d;
58+
Digest n;
4659

47-
signature(Digest d_, NodeId id_) : d(d_), id(id_) {}
60+
signature(Digest d_, NodeId id_, Digest nonce) : d(d_), id(id_), n(nonce)
61+
{}
4862
};
4963

50-
signature s(d, rep().id);
64+
signature s(d, rep().id, rep().hashed_nonce);
5165

5266
rep().digest_sig_size = pbft::GlobalState::get_node().gen_signature(
5367
reinterpret_cast<char*>(&s), sizeof(s), rep().batch_digest_signature);

src/consensus/pbft/libbyz/prepare.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct Prepare_rep : public Message_rep
2323
Seqno seqno;
2424
Digest digest;
2525
int id; // id of the replica that generated the message.
26+
Digest hashed_nonce;
2627
#ifdef SIGN_BATCH
2728
size_t digest_sig_size;
2829
PbftSignature batch_digest_signature;
@@ -50,12 +51,13 @@ class Prepare : public Message
5051
// Prepare messages
5152
//
5253
public:
53-
Prepare(uint32_t msg_size = 0) : Message(msg_size) {}
54+
Prepare(uint32_t msg_size = 0) : Message(msg_size), nonce(0) {}
5455

5556
Prepare(
5657
View v,
5758
Seqno s,
5859
Digest& d,
60+
uint64_t nonce,
5961
Principal* dst = 0,
6062
bool is_signed = false,
6163
int id = -1);
@@ -99,12 +101,17 @@ class Prepare : public Message
99101
bool pre_verify();
100102
// Effects: Performs preliminary verification checks
101103

104+
uint64_t get_nonce() const;
105+
// Effects: returns the unhashed nonce
106+
102107
static bool convert(Message* m1, Prepare*& m2);
103108
// Effects: If "m1" has the right size and tag, casts "m1" to a
104109
// "Prepare" pointer, returns the pointer in "m2" and returns
105110
// true. Otherwise, it returns false.
106111

107112
private:
113+
uint64_t nonce;
114+
108115
Prepare_rep& rep() const;
109116
// Effects: Casts contents to a Prepare_rep&
110117
};
@@ -152,3 +159,8 @@ inline bool Prepare::match(const Prepare* p) const
152159
PBFT_ASSERT(view() == p->view() && seqno() == p->seqno(), "Invalid argument");
153160
return digest() == p->digest();
154161
}
162+
163+
inline uint64_t Prepare::get_nonce() const
164+
{
165+
return nonce;
166+
}

src/consensus/pbft/libbyz/receive_message_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ class IMessageReceiveBase
4848
virtual void playback_pre_prepare(ccf::Store::Tx& tx) = 0;
4949
virtual void playback_request(ccf::Store::Tx& tx) = 0;
5050
virtual char* create_response_message(
51-
int client_id, Request_id rid, uint32_t size) = 0;
51+
int client_id, Request_id rid, uint32_t size, uint64_t nonce) = 0;
5252
virtual bool IsExecutionPending() = 0;
5353
};

src/consensus/pbft/libbyz/rep_info.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ void Rep_info::count_request()
3434
}
3535

3636
char* Rep_info::new_reply(
37-
int pid, Request_id rid, Seqno n, uint32_t message_size)
37+
int pid, Request_id rid, Seqno n, uint64_t nonce, uint32_t message_size)
3838
{
3939
message_size += sizeof(Reply_rep) + MAC_size;
40-
auto r = std::make_unique<Reply>(0, rid, n, 0, message_size);
40+
auto r = std::make_unique<Reply>(0, rid, n, nonce, 0, message_size);
4141
PBFT_ASSERT(r != nullptr, "Out of memory");
4242
r->set_size(message_size);
4343
r->trim();

src/consensus/pbft/libbyz/rep_info.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class Rep_info
4242
// how many individual requests have been processes since the
4343
// replica was initialized. Should be called once for each request.
4444

45-
char* new_reply(int pid, Request_id rid, Seqno n, uint32_t message_size);
45+
char* new_reply(
46+
int pid, Request_id rid, Seqno n, uint64_t nonce, uint32_t message_size);
4647
// Effects: Allocates a new reply for request rid from
4748
// principal pid executed at sequence number n and returns a buffer
4849
// to store the reply to the command. The buffer can store up to

0 commit comments

Comments
 (0)