Add optional serde support.

If the feature "serialization-serde" is specified, protocol messages
implement serde's `Serialize` and `Deserialize` traits.

Close #18
This commit is contained in:
Andreas Fackler 2018-05-14 18:30:07 +02:00
parent e8838f1491
commit e2c66e9a0a
7 changed files with 32 additions and 7 deletions

View File

@ -23,7 +23,7 @@ script:
# - cargo fmt -- --write-mode=diff
- cargo clippy -- -D clippy
- cargo clippy --tests -- -D clippy
- cargo clippy --features=serialization-protobuf -- -D clippy
- cargo clippy --features=serialization-protobuf --tests -- -D clippy
- cargo clippy --features="serialization-protobuf serialization-serde" -- -D clippy
- cargo clippy --features="serialization-protobuf serialization-serde" --tests -- -D clippy
- cargo check --tests
- cargo test

View File

@ -8,14 +8,16 @@ bincode = "1.0.0"
env_logger = "0.5.10"
itertools = "0.7"
log = "0.4.1"
merkle = { git = "https://github.com/vkomenda/merkle.rs", branch = "public-proof" }
merkle = { git = "https://github.com/afck/merkle.rs", branch = "public-proof" }
protobuf = { version = "1.6.0", optional = true }
reed-solomon-erasure = "3.0"
ring = "^0.12"
serde = "1.0.54"
serde = "1.0.55"
serde_derive = { version = "1.0.55", optional = true }
[features]
serialization-protobuf = [ "protobuf", "protoc-rust" ]
serialization-serde = [ "merkle/serialization-serde", "serde_derive" ]
[build-dependencies]
protoc-rust = { version = "1.6.0", optional = true }

View File

@ -11,6 +11,7 @@ use std::hash::Hash;
type AgreementOutput = (Option<bool>, VecDeque<AgreementMessage>);
/// Messages sent during the binary Byzantine agreement stage.
#[cfg_attr(feature = "serialization-serde", derive(Serialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum AgreementMessage {
/// BVAL message with an epoch.

View File

@ -2,6 +2,9 @@ use merkle::proof::{Lemma, Positioned, Proof};
use merkle::MerkleTree;
use reed_solomon_erasure as rse;
use reed_solomon_erasure::ReedSolomon;
use ring::digest;
#[cfg(feature = "serialization-serde")]
use serde::{Deserialize, Deserializer};
use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::fmt::{self, Debug};
use std::hash::Hash;
@ -14,13 +17,26 @@ type MessageQueue<NodeUid> = VecDeque<TargetedMessage<BroadcastMessage, NodeUid>
/// The three kinds of message sent during the reliable broadcast stage of the
/// consensus algorithm.
#[cfg_attr(feature = "serialization-serde", derive(Serialize))]
#[derive(Clone, PartialEq)]
pub enum BroadcastMessage {
#[cfg_attr(feature = "serialization-serde", serde(deserialize_with = "deserialize_proof"))]
Value(Proof<Vec<u8>>),
#[cfg_attr(feature = "serialization-serde", serde(deserialize_with = "deserialize_proof"))]
Echo(Proof<Vec<u8>>),
Ready(Vec<u8>),
}
#[cfg(feature = "serialization-serde")]
#[allow(unused)]
fn deserialize_proof<'de, D>(d: D) -> Result<Proof<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
let data: ::merkle::proof::ProofData<Vec<u8>> = Deserialize::deserialize(d)?;
Ok(data.into_proof(&digest::SHA256))
}
impl fmt::Debug for BroadcastMessage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -199,7 +215,7 @@ impl<NodeUid: Eq + Hash + Debug + Clone + Ord> Broadcast<NodeUid> {
// Convert the Merkle tree into a partial binary tree for later
// deconstruction into compound branches.
let mtree = MerkleTree::from_vec(&::ring::digest::SHA256, shards_t);
let mtree = MerkleTree::from_vec(&digest::SHA256, shards_t);
// Default result in case of `gen_proof` error.
let mut result = Err(Error::ProofConstructionFailed);
@ -458,7 +474,7 @@ where
debug!("Reconstructed shards: {:?}", HexList(&shards));
// Construct the Merkle tree.
let mtree = MerkleTree::from_vec(&::ring::digest::SHA256, shards);
let mtree = MerkleTree::from_vec(&digest::SHA256, shards);
// If the root hash of the reconstructed tree does not match the one
// received with proofs then abort.
if &mtree.root_hash()[..] != root_hash {
@ -504,11 +520,12 @@ pub fn index_of_lemma(lemma: &Lemma, n: usize) -> usize {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_index_of_lemma() {
for &n in &[3, 4, 13, 16, 127, 128, 129, 255] {
let shards: Vec<[u8; 1]> = (0..n).map(|i| [i as u8]).collect();
let mtree = MerkleTree::from_vec(&::ring::digest::SHA256, shards);
let mtree = MerkleTree::from_vec(&digest::SHA256, shards);
for (i, val) in mtree.iter().enumerate() {
let p = mtree.gen_proof(val.clone()).expect("generate proof");
let idx = index_of_lemma(&p.lemma, n);

View File

@ -24,6 +24,7 @@ type CommonSubsetOutput<NodeUid> = (
);
/// Message from Common Subset to remote nodes.
#[cfg_attr(feature = "serialization-serde", derive(Serialize))]
pub enum Message<NodeUid> {
/// A message for the broadcast algorithm concerning the set element proposed by the given node.
Broadcast(NodeUid, BroadcastMessage),

View File

@ -142,6 +142,7 @@ pub struct Batch<T> {
}
/// A message sent to or received from another node's Honey Badger instance.
#[cfg_attr(feature = "serialization-serde", derive(Serialize))]
pub enum Message<N> {
/// A message belonging to the common subset algorithm in the given epoch.
CommonSubset(u64, common_subset::Message<N>),

View File

@ -15,6 +15,9 @@ extern crate protobuf;
extern crate reed_solomon_erasure;
extern crate ring;
extern crate serde;
#[cfg(feature = "serialization-serde")]
#[macro_use]
extern crate serde_derive;
pub mod agreement;
pub mod broadcast;