pub use self::{
protocol::*,
raw::{
Message, MessageBuffer, MessageWriter, RawMessage, ServiceMessage, HEADER_LENGTH,
PROTOCOL_MAJOR_VERSION,
},
};
use bit_vec::BitVec;
use std::fmt;
use crypto::PublicKey;
use encoding::Error;
use helpers::{Height, Round, ValidatorId};
#[macro_use]
mod spec;
mod protocol;
mod raw;
#[cfg(test)]
mod tests;
pub type RawTransaction = RawMessage;
impl fmt::Debug for RawTransaction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Transaction")
.field("version", &self.version())
.field("service_id", &self.service_id())
.field("message_type", &self.message_type())
.field("length", &self.len())
.field("hash", &self.hash())
.finish()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Any {
Connect(Connect),
Status(Status),
Block(BlockResponse),
Consensus(ConsensusMessage),
Request(RequestMessage),
Transaction(RawTransaction),
TransactionsBatch(TransactionsResponse),
}
#[derive(Clone, PartialEq)]
pub enum ConsensusMessage {
Propose(Propose),
Prevote(Prevote),
Precommit(Precommit),
}
#[derive(Clone, PartialEq)]
pub enum RequestMessage {
Propose(ProposeRequest),
Transactions(TransactionsRequest),
Prevotes(PrevotesRequest),
Peers(PeersRequest),
Block(BlockRequest),
}
impl RequestMessage {
pub fn from(&self) -> &PublicKey {
match *self {
RequestMessage::Propose(ref msg) => msg.from(),
RequestMessage::Transactions(ref msg) => msg.from(),
RequestMessage::Prevotes(ref msg) => msg.from(),
RequestMessage::Peers(ref msg) => msg.from(),
RequestMessage::Block(ref msg) => msg.from(),
}
}
pub fn to(&self) -> &PublicKey {
match *self {
RequestMessage::Propose(ref msg) => msg.to(),
RequestMessage::Transactions(ref msg) => msg.to(),
RequestMessage::Prevotes(ref msg) => msg.to(),
RequestMessage::Peers(ref msg) => msg.to(),
RequestMessage::Block(ref msg) => msg.to(),
}
}
pub fn verify(&self, public_key: &PublicKey) -> bool {
match *self {
RequestMessage::Propose(ref msg) => msg.verify_signature(public_key),
RequestMessage::Transactions(ref msg) => msg.verify_signature(public_key),
RequestMessage::Prevotes(ref msg) => msg.verify_signature(public_key),
RequestMessage::Peers(ref msg) => msg.verify_signature(public_key),
RequestMessage::Block(ref msg) => msg.verify_signature(public_key),
}
}
pub fn raw(&self) -> &RawMessage {
match *self {
RequestMessage::Propose(ref msg) => msg.raw(),
RequestMessage::Transactions(ref msg) => msg.raw(),
RequestMessage::Prevotes(ref msg) => msg.raw(),
RequestMessage::Peers(ref msg) => msg.raw(),
RequestMessage::Block(ref msg) => msg.raw(),
}
}
}
impl fmt::Debug for RequestMessage {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
RequestMessage::Propose(ref msg) => write!(fmt, "{:?}", msg),
RequestMessage::Transactions(ref msg) => write!(fmt, "{:?}", msg),
RequestMessage::Prevotes(ref msg) => write!(fmt, "{:?}", msg),
RequestMessage::Peers(ref msg) => write!(fmt, "{:?}", msg),
RequestMessage::Block(ref msg) => write!(fmt, "{:?}", msg),
}
}
}
impl ConsensusMessage {
pub fn validator(&self) -> ValidatorId {
match *self {
ConsensusMessage::Propose(ref msg) => msg.validator(),
ConsensusMessage::Prevote(ref msg) => msg.validator(),
ConsensusMessage::Precommit(ref msg) => msg.validator(),
}
}
pub fn height(&self) -> Height {
match *self {
ConsensusMessage::Propose(ref msg) => msg.height(),
ConsensusMessage::Prevote(ref msg) => msg.height(),
ConsensusMessage::Precommit(ref msg) => msg.height(),
}
}
pub fn round(&self) -> Round {
match *self {
ConsensusMessage::Propose(ref msg) => msg.round(),
ConsensusMessage::Prevote(ref msg) => msg.round(),
ConsensusMessage::Precommit(ref msg) => msg.round(),
}
}
pub fn raw(&self) -> &RawMessage {
match *self {
ConsensusMessage::Propose(ref msg) => msg.raw(),
ConsensusMessage::Prevote(ref msg) => msg.raw(),
ConsensusMessage::Precommit(ref msg) => msg.raw(),
}
}
pub fn verify(&self, public_key: &PublicKey) -> bool {
match *self {
ConsensusMessage::Propose(ref msg) => msg.verify_signature(public_key),
ConsensusMessage::Prevote(ref msg) => msg.verify_signature(public_key),
ConsensusMessage::Precommit(ref msg) => msg.verify_signature(public_key),
}
}
}
impl fmt::Debug for ConsensusMessage {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
ConsensusMessage::Propose(ref msg) => write!(fmt, "{:?}", msg),
ConsensusMessage::Prevote(ref msg) => write!(fmt, "{:?}", msg),
ConsensusMessage::Precommit(ref msg) => write!(fmt, "{:?}", msg),
}
}
}
impl Any {
pub fn from_raw(raw: RawMessage) -> Result<Self, Error> {
let msg = if raw.service_id() == CONSENSUS {
match raw.message_type() {
CONNECT_MESSAGE_ID => Any::Connect(Connect::from_raw(raw)?),
STATUS_MESSAGE_ID => Any::Status(Status::from_raw(raw)?),
BLOCK_RESPONSE_MESSAGE_ID => Any::Block(BlockResponse::from_raw(raw)?),
TRANSACTIONS_RESPONSE_MESSAGE_ID => {
Any::TransactionsBatch(TransactionsResponse::from_raw(raw)?)
}
PROPOSE_MESSAGE_ID => {
Any::Consensus(ConsensusMessage::Propose(Propose::from_raw(raw)?))
}
PREVOTE_MESSAGE_ID => {
Any::Consensus(ConsensusMessage::Prevote(Prevote::from_raw(raw)?))
}
PRECOMMIT_MESSAGE_ID => {
Any::Consensus(ConsensusMessage::Precommit(Precommit::from_raw(raw)?))
}
PROPOSE_REQUEST_MESSAGE_ID => {
Any::Request(RequestMessage::Propose(ProposeRequest::from_raw(raw)?))
}
TRANSACTIONS_REQUEST_MESSAGE_ID => Any::Request(RequestMessage::Transactions(
TransactionsRequest::from_raw(raw)?,
)),
PREVOTES_REQUEST_MESSAGE_ID => {
Any::Request(RequestMessage::Prevotes(PrevotesRequest::from_raw(raw)?))
}
PEERS_REQUEST_MESSAGE_ID => {
Any::Request(RequestMessage::Peers(PeersRequest::from_raw(raw)?))
}
BLOCK_REQUEST_MESSAGE_ID => {
Any::Request(RequestMessage::Block(BlockRequest::from_raw(raw)?))
}
message_type => {
return Err(Error::IncorrectMessageType { message_type });
}
}
} else {
Any::Transaction(raw)
};
Ok(msg)
}
}