1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::fmt::{self, Debug};

use hex_fmt::HexFmt;
use rand::distributions::{Distribution, Standard};
use rand::{self, seq::SliceRandom, Rng};
use serde::{Deserialize, Serialize};

use super::merkle::{Digest, MerkleTree, Proof};

/// The three kinds of message sent during the reliable broadcast stage of the
/// consensus algorithm.
#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub enum Message {
    /// A share of the value, sent from the sender to another validator.
    Value(Proof<Vec<u8>>),
    /// A copy of the value received from the sender, multicast by a validator.
    Echo(Proof<Vec<u8>>),
    /// Indicates that the sender knows that every node will eventually be able to decode.
    Ready(Digest),
}

// A random generation impl is provided for test cases. Unfortunately `#[cfg(test)]` does not work
// for integration tests.
impl Distribution<Message> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Message {
        let message_type = *["value", "echo", "ready"].choose(rng).unwrap();

        // Create a random buffer for our proof.
        let mut buffer: [u8; 32] = [0; 32];
        rng.fill_bytes(&mut buffer);

        // Generate a dummy proof to fill broadcast messages with.
        let tree = MerkleTree::from_vec(vec![buffer.to_vec()]);
        let proof = tree.proof(0).unwrap();

        match message_type {
            "value" => Message::Value(proof),
            "echo" => Message::Echo(proof),
            "ready" => Message::Ready([b'r'; 32]),
            _ => unreachable!(),
        }
    }
}

impl Debug for Message {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Message::Value(ref v) => f.debug_tuple("Value").field(&HexProof(v)).finish(),
            Message::Echo(ref v) => f.debug_tuple("Echo").field(&HexProof(v)).finish(),
            Message::Ready(ref b) => write!(f, "Ready({:0.10})", HexFmt(b)),
        }
    }
}
/// Wrapper for a `Proof`, to print the bytes as a shortened hexadecimal number.
pub struct HexProof<'a, T>(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 {{ #{}, root_hash: {:0.10}, value: {:0.10}, .. }}",
            &self.0.index(),
            HexFmt(self.0.root_hash()),
            HexFmt(self.0.value())
        )
    }
}