Remove protoc dep, use new MerkleTree methods.

This commit is contained in:
Andreas Fackler 2018-05-17 16:50:47 +02:00
parent 01e89a7c48
commit 50d007b954
5 changed files with 11 additions and 152 deletions

View File

@ -17,11 +17,11 @@ serde = "1.0.55"
serde_derive = { version = "1.0.55", optional = true }
[features]
serialization-protobuf = [ "protobuf", "protoc-rust" ]
serialization-protobuf = [ "protobuf", "protobuf-codegen-pure" ]
serialization-serde = [ "merkle/serialization-serde", "serde_derive" ]
[build-dependencies]
protoc-rust = { version = "1.6.0", optional = true }
protobuf-codegen-pure = { version = "1.6.0", optional = true }
[dev-dependencies]
colored = "1.6"

View File

@ -15,46 +15,8 @@ An example is included to run a simulation of a network:
$ cargo run --example simulation -- --nodes 10 --faulty 1 --txs 1000 --batch 100
# Requirements
`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
[here](https://github.com/google/protobuf/releases), if you are not
installing `protoc` on Debian 9 or Ubuntu 17, change your cURL URL and zip
file names accordingly.
## Installing `protoc` on Debian 9 (Strech) and Ubuntu 17 (Artful)
$ sudo apt-get update
$ sudo apt-get install -y protobuf-compiler
## Installing `protoc` on other versions of Debian and Ubuntu
$ sudo apt-get update
$ sudo apt-get install -y unzip
$ cd <some temporary working directory>
$ curl -OL https://github.com/google/protobuf/releases/download/v3.5.1/protoc-3.5.1-linux-x86_64.zip
$ sudo unzip protoc-3.5.1-linux-x86_64.zip -d /usr/local bin/protoc
$ sudo chown $(whoami) /usr/local/bin/protoc
$ rm protoc-3.5.1-linux-x86_64.zip
## Installing `protoc` on OSX
$ cd <some temporary working directory>
$ curl -OL https://github.com/google/protobuf/releases/download/v3.5.1/protoc-3.5.1-osx-x86_64.zip
$ sudo unzip protoc-3.5.1-osx-x86_64.zip -d /usr/local bin/protoc
$ rm protoc-3.5.1-osx-x86_64.zip
# Building
Once you have verified that the `protoc` binary is in your `$PATH`, you can
build `hbbft` using cargo:
You can build `hbbft` using cargo:
$ cargo build [--release]

View File

@ -1,30 +1,10 @@
#[cfg(feature = "serialization-protobuf")]
mod feature_protobuf {
extern crate protoc_rust;
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;
}
}
}
None => println!("PATH environment variable is not defined."),
}
false
}
extern crate protobuf_codegen_pure;
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 {
protobuf_codegen_pure::run(protobuf_codegen_pure::Args {
out_dir: "src/proto",
input: &["proto/message.proto"],
includes: &["proto"],

View File

@ -1,11 +1,8 @@
use fmt::{HexBytes, HexList, HexProof};
use merkle::proof::{Lemma, Positioned, Proof};
use merkle::MerkleTree;
use merkle::{MerkleTree, Proof};
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::iter;
@ -14,27 +11,15 @@ use messaging::{DistAlgorithm, Target, TargetedMessage};
/// The three kinds of message sent during the reliable broadcast stage of the
/// consensus algorithm.
#[cfg_attr(feature = "serialization-serde", derive(Serialize))]
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[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 {
impl Debug for BroadcastMessage {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BroadcastMessage::Value(ref v) => write!(f, "Value({:?})", HexProof(&v)),
@ -381,11 +366,6 @@ impl<N: Eq + Debug + Clone + Ord> Broadcast<N> {
self.all_uids.iter().position(|id| id == node_id)
}
/// Returns the index of this proof's leave in the Merkle tree.
fn index_of_proof(&self, proof: &Proof<Vec<u8>>) -> usize {
index_of_lemma(&proof.lemma, self.num_nodes)
}
/// Returns `true` if the proof is valid and has the same index as the node ID. Otherwise
/// logs an info message.
fn validate_proof(&self, p: &Proof<Vec<u8>>, id: &N) -> bool {
@ -397,7 +377,7 @@ impl<N: Eq + Debug + Clone + Ord> Broadcast<N> {
);
false
} else if self.index_of_node(id) != Some(p.value[0] as usize)
|| self.index_of_proof(&p) != p.value[0] as usize
|| p.index(self.num_nodes) != p.value[0] as usize
{
info!(
"Node {:?} received proof for wrong position: {:?}.",
@ -556,33 +536,3 @@ where
t[1..(payload_len + 1)].to_vec().into()
}
/// Computes the Merkle tree leaf index of a value in a given lemma.
pub fn index_of_lemma(lemma: &Lemma, n: usize) -> usize {
let m = n.next_power_of_two();
match (lemma.sub_lemma.as_ref(), lemma.sibling_hash.as_ref()) {
(None, Some(&Positioned::Right(_))) | (None, None) => 0,
(None, Some(&Positioned::Left(_))) => 1,
(Some(l), None) => index_of_lemma(l, n),
(Some(l), Some(&Positioned::Left(_))) => (m >> 1) + index_of_lemma(l, n - (m >> 1)),
(Some(l), Some(&Positioned::Right(_))) => index_of_lemma(l, m >> 1),
}
}
#[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(&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);
assert_eq!(i, idx, "Wrong index {} for leaf {}/{}.", idx, i, n);
}
}
}
}

View File

@ -1,4 +1,4 @@
use merkle::proof::{Lemma, Positioned, Proof};
use merkle::Proof;
use std::fmt;
/// Wrapper for a byte array, whose `Debug` implementation outputs shortened hexadecimal strings.
@ -40,43 +40,10 @@ 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: {:?} }}",
"Proof {{ algorithm: {:?}, root_hash: {:?}, 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(())
}
}