openethereum/crates/ethcore/sync/src/chain/sync_packet.rs

156 lines
5.0 KiB
Rust

// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! When sending packets over p2p we specify both which subprotocol
//! to use and what kind of packet we are sending (through a packet id).
//! Likewise when receiving packets from other peers we decode the
//! subprotocol and the packet id. This module helps coupling both
//! pieces of information together and provides an easy mechanism
//! to convert to/from the packet id values transmitted over the
//! wire.
#![allow(unused_doc_comments)]
use api::{ETH_PROTOCOL, PAR_PROTOCOL};
use network::{PacketId, ProtocolId};
// An enum that defines all known packet ids in the context of
// synchronization and provides a mechanism to convert from
// packet ids (of type PacketId or u8) directly read from the network
// to enum variants. This implicitly provides a mechanism to
// check whether a given packet id is known, and to prevent
// packet id clashes when defining new ids.
enum_from_primitive! {
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SyncPacket {
StatusPacket = 0x00,
NewBlockHashesPacket = 0x01,
TransactionsPacket = 0x02,
GetBlockHeadersPacket = 0x03,
BlockHeadersPacket = 0x04,
GetBlockBodiesPacket = 0x05,
BlockBodiesPacket = 0x06,
NewBlockPacket = 0x07,
NewPooledTransactionHashesPacket = 0x08,
GetPooledTransactionsPacket = 0x09,
PooledTransactionsPacket = 0x0a,
//GetNodeDataPacket = 0x0d,
//NodeDataPacket = 0x0e,
GetReceiptsPacket = 0x0f,
ReceiptsPacket = 0x10,
GetSnapshotManifestPacket = 0x11,
SnapshotManifestPacket = 0x12,
GetSnapshotDataPacket = 0x13,
SnapshotDataPacket = 0x14,
ConsensusDataPacket = 0x15,
}
}
use self::SyncPacket::*;
/// Provide both subprotocol and packet id information within the
/// same object.
pub trait PacketInfo {
fn id(&self) -> PacketId;
fn protocol(&self) -> ProtocolId;
fn has_request_id_in_eth_66(&self) -> bool;
}
// The mechanism to match packet ids and protocol may be improved
// through some macro magic, but for now this works.
impl PacketInfo for SyncPacket {
fn protocol(&self) -> ProtocolId {
match self {
StatusPacket
| NewBlockHashesPacket
| TransactionsPacket
| GetBlockHeadersPacket
| BlockHeadersPacket
| GetBlockBodiesPacket
| BlockBodiesPacket
| NewBlockPacket
| NewPooledTransactionHashesPacket
| GetPooledTransactionsPacket
| PooledTransactionsPacket
//| GetNodeDataPacket
//| NodeDataPacket
| GetReceiptsPacket
| ReceiptsPacket => ETH_PROTOCOL,
GetSnapshotManifestPacket
| SnapshotManifestPacket
| GetSnapshotDataPacket
| SnapshotDataPacket
| ConsensusDataPacket => PAR_PROTOCOL,
}
}
fn id(&self) -> PacketId {
(*self) as PacketId
}
fn has_request_id_in_eth_66(&self) -> bool {
// Note: NodeDataPacket and GetNodeDataPacket also get a request id in eth-66.
match self {
GetBlockHeadersPacket
| BlockHeadersPacket
| GetBlockBodiesPacket
| BlockBodiesPacket
| GetPooledTransactionsPacket
| PooledTransactionsPacket
| GetReceiptsPacket
| ReceiptsPacket => true,
_ => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use enum_primitive::FromPrimitive;
#[test]
fn packet_ids_from_u8_when_from_primitive_zero_then_equals_status_packet() {
assert_eq!(SyncPacket::from_u8(0x00), Some(StatusPacket));
}
#[test]
fn packet_ids_from_u8_when_from_primitive_eleven_then_equals_get_snapshot_manifest_packet() {
assert_eq!(SyncPacket::from_u8(0x11), Some(GetSnapshotManifestPacket));
}
#[test]
fn packet_ids_from_u8_when_invalid_packet_id_then_none() {
assert!(SyncPacket::from_u8(0x99).is_none());
}
#[test]
fn when_status_packet_then_id_and_protocol_match() {
assert_eq!(StatusPacket.id(), StatusPacket as PacketId);
assert_eq!(StatusPacket.protocol(), ETH_PROTOCOL);
}
#[test]
fn when_consensus_data_packet_then_id_and_protocol_match() {
assert_eq!(ConsensusDataPacket.id(), ConsensusDataPacket as PacketId);
assert_eq!(ConsensusDataPacket.protocol(), PAR_PROTOCOL);
}
}