Make protobuf support optional.

Protobuf support is now only built if the feature
"serialization-protobuf" is enabled.

Close #19
This commit is contained in:
Andreas Fackler 2018-05-14 17:29:04 +02:00
parent faab03d984
commit e8838f1491
9 changed files with 137 additions and 114 deletions

View File

@ -23,5 +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 check --tests
- cargo test

View File

@ -9,16 +9,23 @@ env_logger = "0.5.10"
itertools = "0.7"
log = "0.4.1"
merkle = { git = "https://github.com/vkomenda/merkle.rs", branch = "public-proof" }
protobuf = "1.6.0"
protobuf = { version = "1.6.0", optional = true }
reed-solomon-erasure = "3.0"
ring = "^0.12"
serde = "1.0.54"
[features]
serialization-protobuf = [ "protobuf", "protoc-rust" ]
[build-dependencies]
protoc-rust = "1.6.0"
protoc-rust = { version = "1.6.0", optional = true }
[dev-dependencies]
crossbeam = "0.3.2"
crossbeam-channel = "0.1"
docopt = "0.8"
rand = "0.3"
[[example]]
name = "consensus-node"
required-features = [ "serialization-protobuf" ]

View File

@ -10,10 +10,12 @@ in Rust. This is a modular library of consensus. There are
# Requirements
To build and run `hbbft`, you must have Google's Protocol Buffer Compiler,
`protoc` binary, located somewhere in your `$PATH`. You must be using
Protocol Buffer Compiler version 3 or greater. Running any of the following
install methods will save a `protoc` binary at `/usr/local/bin/protoc`.
`hbbft` has optional protobuf support. To use protobuf, enable the feature
`serialization-protobuf` in your `Cargo.toml`, and make sure you have
Google's Protocol Buffer Compiler, `protoc` binary, located somewhere in
your `$PATH`. You must be using Protocol Buffer Compiler version 3 or greater.
Running any of the following install methods will save a `protoc` binary at
`/usr/local/bin/protoc`.
*Note:* as of writing this, the latest stable release of `protoc` is
v3.5.1. You can find out what is the latest compiler version is

View File

@ -1,30 +1,28 @@
extern crate protoc_rust;
#[cfg(feature = "serialization-protobuf")]
mod feature_protobuf {
extern crate protoc_rust;
use std::env;
use std::env;
fn protoc_exists() -> bool {
let name = "PATH";
match env::var_os(name) {
Some(paths) => {
for path in env::split_paths(&paths) {
if path.join("protoc").exists() {
return true;
fn protoc_exists() -> bool {
let name = "PATH";
match env::var_os(name) {
Some(paths) => {
for path in env::split_paths(&paths) {
if path.join("protoc").exists() {
return true;
}
}
}
None => println!("PATH environment variable is not defined."),
}
None => println!("PATH environment variable is not defined."),
false
}
false
}
fn main() {
if !protoc_exists() {
panic!(
"
protoc cannot be found. Install the protobuf compiler in the \
system path."
);
} else {
pub fn main() {
if !protoc_exists() {
panic!("protoc cannot be found. Install the protobuf compiler in the system path.");
}
println!("cargo:rerun-if-changed=proto/message.proto");
protoc_rust::run(protoc_rust::Args {
out_dir: "src/proto",
@ -34,3 +32,11 @@ system path."
}).expect("protoc");
}
}
#[cfg(feature = "serialization-protobuf")]
fn main() {
feature_protobuf::main()
}
#[cfg(not(feature = "serialization-protobuf"))]
fn main() {}

13
examples/run-consensus-nodes.sh Normal file → Executable file
View File

@ -2,14 +2,15 @@
export RUST_LOG=hbbft=debug,consensus_node=debug
cargo build --example consensus-node
cargo run --example consensus-node -- --bind-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5003 --remote-address=127.0.0.1:5004 --value=Foo &
cargo build --features=serialization-protobuf --example consensus-node
target/debug/examples/consensus-node --bind-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5003 --remote-address=127.0.0.1:5004 --value=Foo &
sleep 1
cargo run --example consensus-node -- --bind-address=127.0.0.1:5001 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5003 --remote-address=127.0.0.1:5004 &
target/debug/examples/consensus-node --bind-address=127.0.0.1:5001 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5003 --remote-address=127.0.0.1:5004 &
sleep 1
cargo run --example consensus-node -- --bind-address=127.0.0.1:5002 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5003 --remote-address=127.0.0.1:5004 &
target/debug/examples/consensus-node --bind-address=127.0.0.1:5002 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5003 --remote-address=127.0.0.1:5004 &
sleep 1
cargo run --example consensus-node -- --bind-address=127.0.0.1:5003 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5004 &
target/debug/examples/consensus-node --bind-address=127.0.0.1:5003 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5004 &
sleep 1
cargo run --example consensus-node -- --bind-address=127.0.0.1:5004 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5003 &
target/debug/examples/consensus-node --bind-address=127.0.0.1:5004 --remote-address=127.0.0.1:5000 --remote-address=127.0.0.1:5001 --remote-address=127.0.0.1:5002 --remote-address=127.0.0.1:5003 &
wait

View File

@ -1,12 +1,12 @@
use merkle::proof::{Lemma, Positioned, Proof};
use merkle::MerkleTree;
use proto::*;
use reed_solomon_erasure as rse;
use reed_solomon_erasure::ReedSolomon;
use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::fmt::{self, Debug};
use std::hash::Hash;
use std::iter;
use util::{HexBytes, HexList, HexProof};
use messaging::{Target, TargetedMessage};

View File

@ -10,6 +10,7 @@ extern crate bincode;
extern crate log;
extern crate itertools;
extern crate merkle;
#[cfg(feature = "serialization-protobuf")]
extern crate protobuf;
extern crate reed_solomon_erasure;
extern crate ring;
@ -20,5 +21,8 @@ pub mod broadcast;
pub mod common_subset;
pub mod honey_badger;
pub mod messaging;
#[cfg(feature = "serialization-protobuf")]
pub mod proto;
#[cfg(feature = "serialization-protobuf")]
pub mod proto_io;
mod util;

View File

@ -6,55 +6,6 @@ use broadcast::BroadcastMessage;
use merkle::proof::{Lemma, Positioned, Proof};
use proto::message::*;
use ring::digest::Algorithm;
use std::fmt;
/// Wrapper for a byte array, whose `Debug` implementation outputs shortened hexadecimal strings.
pub struct HexBytes<'a>(pub &'a [u8]);
impl<'a> fmt::Debug for HexBytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.0.len() > 6 {
for byte in &self.0[..3] {
write!(f, "{:02x}", byte)?;
}
write!(f, "..")?;
for byte in &self.0[(self.0.len() - 3)..] {
write!(f, "{:02x}", byte)?;
}
} else {
for byte in self.0 {
write!(f, "{:02x}", byte)?;
}
}
Ok(())
}
}
/// Wrapper for a list of byte arrays, whose `Debug` implementation outputs shortened hexadecimal
/// strings.
pub struct HexList<'a, T: 'a>(pub &'a [T]);
impl<'a, T: AsRef<[u8]>> fmt::Debug for HexList<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let v: Vec<_> = self.0.iter().map(|t| HexBytes(t.as_ref())).collect();
write!(f, "{:?}", v)
}
}
pub struct HexProof<'a, T: 'a>(pub &'a Proof<T>);
impl<'a, T: AsRef<[u8]>> fmt::Debug for HexProof<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Proof {{ algorithm: {:?}, root_hash: {:?}, lemma for leaf #{}, value: {:?} }}",
self.0.algorithm,
HexBytes(&self.0.root_hash),
path_of_lemma(&self.0.lemma),
HexBytes(&self.0.value.as_ref())
)
}
}
impl From<message::BroadcastProto> for BroadcastMessage {
fn from(proto: message::BroadcastProto) -> BroadcastMessage {
@ -246,35 +197,3 @@ impl LemmaProto {
}
}
}
/// The path of a lemma in a Merkle tree
struct BinaryPath(Vec<bool>);
/// The path of the lemma, as a binary string
fn path_of_lemma(mut lemma: &Lemma) -> BinaryPath {
let mut result = Vec::new();
loop {
match lemma.sibling_hash {
None => (),
Some(Positioned::Left(_)) => result.push(true),
Some(Positioned::Right(_)) => result.push(false),
}
lemma = match lemma.sub_lemma.as_ref() {
Some(lemma) => lemma,
None => return BinaryPath(result),
}
}
}
impl fmt::Display for BinaryPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for b in &self.0 {
if *b {
write!(f, "1")?;
} else {
write!(f, "0")?;
}
}
Ok(())
}
}

82
src/util.rs Normal file
View File

@ -0,0 +1,82 @@
use merkle::proof::{Lemma, Positioned, Proof};
use std::fmt;
/// Wrapper for a byte array, whose `Debug` implementation outputs shortened hexadecimal strings.
pub struct HexBytes<'a>(pub &'a [u8]);
impl<'a> fmt::Debug for HexBytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.0.len() > 6 {
for byte in &self.0[..3] {
write!(f, "{:02x}", byte)?;
}
write!(f, "..")?;
for byte in &self.0[(self.0.len() - 3)..] {
write!(f, "{:02x}", byte)?;
}
} else {
for byte in self.0 {
write!(f, "{:02x}", byte)?;
}
}
Ok(())
}
}
/// Wrapper for a list of byte arrays, whose `Debug` implementation outputs shortened hexadecimal
/// strings.
pub struct HexList<'a, T: 'a>(pub &'a [T]);
impl<'a, T: AsRef<[u8]>> fmt::Debug for HexList<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let v: Vec<_> = self.0.iter().map(|t| HexBytes(t.as_ref())).collect();
write!(f, "{:?}", v)
}
}
pub struct HexProof<'a, T: 'a>(pub &'a Proof<T>);
impl<'a, T: AsRef<[u8]>> fmt::Debug for HexProof<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Proof {{ algorithm: {:?}, root_hash: {:?}, lemma for leaf #{}, value: {:?} }}",
self.0.algorithm,
HexBytes(&self.0.root_hash),
path_of_lemma(&self.0.lemma),
HexBytes(&self.0.value.as_ref())
)
}
}
/// The path of a lemma in a Merkle tree
struct BinaryPath(Vec<bool>);
/// The path of the lemma, as a binary string
fn path_of_lemma(mut lemma: &Lemma) -> BinaryPath {
let mut result = Vec::new();
loop {
match lemma.sibling_hash {
None => (),
Some(Positioned::Left(_)) => result.push(true),
Some(Positioned::Right(_)) => result.push(false),
}
lemma = match lemma.sub_lemma.as_ref() {
Some(lemma) => lemma,
None => return BinaryPath(result),
}
}
}
impl fmt::Display for BinaryPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for b in &self.0 {
if *b {
write!(f, "1")?;
} else {
write!(f, "0")?;
}
}
Ok(())
}
}