mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-11-16 15:58:14 +00:00
add new LevinCommand
enum and clean up monero-wire message de/encoding
This commit is contained in:
parent
6a75b90fe7
commit
19f19fdb16
1 changed files with 210 additions and 94 deletions
|
@ -16,7 +16,9 @@
|
|||
//! This module defines a Monero `Message` enum which contains
|
||||
//! every possible Monero network message (levin body)
|
||||
|
||||
use levin_cuprate::{BucketBuilder, BucketError, LevinBody, MessageType};
|
||||
use levin_cuprate::{
|
||||
BucketBuilder, BucketError, LevinBody, LevinCommand as LevinCommandTrait, MessageType,
|
||||
};
|
||||
|
||||
pub mod admin;
|
||||
pub mod common;
|
||||
|
@ -32,6 +34,100 @@ pub use protocol::{
|
|||
GetObjectsResponse, GetTxPoolCompliment, NewBlock, NewFluffyBlock, NewTransactions,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum LevinCommand {
|
||||
Handshake,
|
||||
TimedSync,
|
||||
Ping,
|
||||
SupportFlags,
|
||||
|
||||
NewBlock,
|
||||
NewTransactions,
|
||||
GetObjectsRequest,
|
||||
GetObjectsResponse,
|
||||
ChainRequest,
|
||||
ChainResponse,
|
||||
NewFluffyBlock,
|
||||
FluffyMissingTxsRequest,
|
||||
GetTxPoolCompliment,
|
||||
|
||||
Unknown(u32),
|
||||
}
|
||||
|
||||
impl LevinCommandTrait for LevinCommand {
|
||||
fn bucket_size_limit(&self) -> u64 {
|
||||
// https://github.com/monero-project/monero/blob/00fd416a99686f0956361d1cd0337fe56e58d4a7/src/cryptonote_basic/connection_context.cpp#L37
|
||||
match self {
|
||||
LevinCommand::Handshake => 65536,
|
||||
LevinCommand::TimedSync => 65536,
|
||||
LevinCommand::Ping => 4096,
|
||||
LevinCommand::SupportFlags => 4096,
|
||||
|
||||
LevinCommand::NewBlock => 1024 * 1024 * 128, // 128 MB (max packet is a bit less than 100 MB though)
|
||||
LevinCommand::NewTransactions => 1024 * 1024 * 128, // 128 MB (max packet is a bit less than 100 MB though)
|
||||
LevinCommand::GetObjectsRequest => 1024 * 1024 * 2, // 2 MB
|
||||
LevinCommand::GetObjectsResponse => 1024 * 1024 * 128, // 128 MB (max packet is a bit less than 100 MB though)
|
||||
LevinCommand::ChainRequest => 512 * 1024, // 512 kB
|
||||
LevinCommand::ChainResponse => 1024 * 1024 * 4, // 4 MB
|
||||
LevinCommand::NewFluffyBlock => 1024 * 1024 * 4, // 4 MB
|
||||
LevinCommand::FluffyMissingTxsRequest => 1024 * 1024, // 1 MB
|
||||
LevinCommand::GetTxPoolCompliment => 1024 * 1024 * 4, // 4 MB
|
||||
|
||||
LevinCommand::Unknown(_) => usize::MAX.try_into().unwrap_or(u64::MAX),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_handshake(&self) -> bool {
|
||||
matches!(self, LevinCommand::Handshake)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for LevinCommand {
|
||||
fn from(value: u32) -> Self {
|
||||
match value {
|
||||
1001 => LevinCommand::Handshake,
|
||||
1002 => LevinCommand::TimedSync,
|
||||
1003 => LevinCommand::Ping,
|
||||
1007 => LevinCommand::SupportFlags,
|
||||
|
||||
2001 => LevinCommand::NewBlock,
|
||||
2002 => LevinCommand::NewTransactions,
|
||||
2003 => LevinCommand::GetObjectsRequest,
|
||||
2004 => LevinCommand::GetObjectsResponse,
|
||||
2006 => LevinCommand::ChainRequest,
|
||||
2007 => LevinCommand::ChainResponse,
|
||||
2008 => LevinCommand::NewFluffyBlock,
|
||||
2009 => LevinCommand::FluffyMissingTxsRequest,
|
||||
2010 => LevinCommand::NewBlock,
|
||||
|
||||
x => LevinCommand::Unknown(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LevinCommand> for u32 {
|
||||
fn from(value: LevinCommand) -> Self {
|
||||
match value {
|
||||
LevinCommand::Handshake => 1001,
|
||||
LevinCommand::TimedSync => 1002,
|
||||
LevinCommand::Ping => 1003,
|
||||
LevinCommand::SupportFlags => 1007,
|
||||
|
||||
LevinCommand::NewBlock => 2001,
|
||||
LevinCommand::NewTransactions => 2002,
|
||||
LevinCommand::GetObjectsRequest => 2003,
|
||||
LevinCommand::GetObjectsResponse => 2004,
|
||||
LevinCommand::ChainRequest => 2006,
|
||||
LevinCommand::ChainResponse => 2007,
|
||||
LevinCommand::NewFluffyBlock => 2008,
|
||||
LevinCommand::FluffyMissingTxsRequest => 2009,
|
||||
LevinCommand::GetTxPoolCompliment => 2010,
|
||||
|
||||
LevinCommand::Unknown(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ProtocolMessage {
|
||||
NewBlock(NewBlock),
|
||||
NewFluffyBlock(NewFluffyBlock),
|
||||
|
@ -45,19 +141,33 @@ pub enum ProtocolMessage {
|
|||
}
|
||||
|
||||
impl ProtocolMessage {
|
||||
fn decode(buf: &[u8], command: u32) -> Result<Self, epee_encoding::Error> {
|
||||
fn decode(buf: &[u8], command: LevinCommand) -> Result<Self, epee_encoding::Error> {
|
||||
Ok(match command {
|
||||
2001 => ProtocolMessage::NewBlock(epee_encoding::from_bytes(buf)?),
|
||||
2002 => ProtocolMessage::NewTransactions(epee_encoding::from_bytes(buf)?),
|
||||
2003 => ProtocolMessage::GetObjectsRequest(epee_encoding::from_bytes(buf)?),
|
||||
2004 => ProtocolMessage::GetObjectsResponse(epee_encoding::from_bytes(buf)?),
|
||||
2006 => ProtocolMessage::ChainRequest(epee_encoding::from_bytes(buf)?),
|
||||
2007 => ProtocolMessage::ChainEntryResponse(epee_encoding::from_bytes(buf)?),
|
||||
2008 => ProtocolMessage::NewFluffyBlock(epee_encoding::from_bytes(buf)?),
|
||||
2009 => {
|
||||
LevinCommand::NewBlock => ProtocolMessage::NewBlock(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::NewTransactions => {
|
||||
ProtocolMessage::NewTransactions(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
LevinCommand::GetObjectsRequest => {
|
||||
ProtocolMessage::GetObjectsRequest(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
LevinCommand::GetObjectsResponse => {
|
||||
ProtocolMessage::GetObjectsResponse(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
LevinCommand::ChainRequest => {
|
||||
ProtocolMessage::ChainRequest(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
LevinCommand::ChainResponse => {
|
||||
ProtocolMessage::ChainEntryResponse(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
LevinCommand::NewFluffyBlock => {
|
||||
ProtocolMessage::NewFluffyBlock(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
LevinCommand::FluffyMissingTxsRequest => {
|
||||
ProtocolMessage::FluffyMissingTransactionsRequest(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
2010 => ProtocolMessage::GetTxPoolCompliment(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::GetTxPoolCompliment => {
|
||||
ProtocolMessage::GetTxPoolCompliment(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
_ => {
|
||||
return Err(epee_encoding::Error::Value(
|
||||
"Failed to decode message, unknown command",
|
||||
|
@ -66,45 +176,39 @@ impl ProtocolMessage {
|
|||
})
|
||||
}
|
||||
|
||||
fn build(&self, builder: &mut BucketBuilder) -> Result<(), epee_encoding::Error> {
|
||||
fn encode(&self) -> Result<Vec<u8>, epee_encoding::Error> {
|
||||
match self {
|
||||
ProtocolMessage::NewBlock(nb) => {
|
||||
builder.set_command(2001);
|
||||
builder.set_body(epee_encoding::to_bytes(nb)?);
|
||||
}
|
||||
ProtocolMessage::NewTransactions(nt) => {
|
||||
builder.set_command(2002);
|
||||
builder.set_body(epee_encoding::to_bytes(nt)?);
|
||||
}
|
||||
ProtocolMessage::GetObjectsRequest(gt) => {
|
||||
builder.set_command(2003);
|
||||
builder.set_body(epee_encoding::to_bytes(gt)?);
|
||||
}
|
||||
ProtocolMessage::GetObjectsResponse(ge) => {
|
||||
builder.set_command(2004);
|
||||
builder.set_body(epee_encoding::to_bytes(ge)?);
|
||||
}
|
||||
ProtocolMessage::ChainRequest(ct) => {
|
||||
builder.set_command(2006);
|
||||
builder.set_body(epee_encoding::to_bytes(ct)?);
|
||||
}
|
||||
ProtocolMessage::ChainEntryResponse(ce) => {
|
||||
builder.set_command(2007);
|
||||
builder.set_body(epee_encoding::to_bytes(ce)?);
|
||||
}
|
||||
ProtocolMessage::NewFluffyBlock(fb) => {
|
||||
builder.set_command(2008);
|
||||
builder.set_body(epee_encoding::to_bytes(fb)?);
|
||||
}
|
||||
ProtocolMessage::FluffyMissingTransactionsRequest(ft) => {
|
||||
builder.set_command(2009);
|
||||
builder.set_body(epee_encoding::to_bytes(ft)?);
|
||||
}
|
||||
ProtocolMessage::GetTxPoolCompliment(tp) => {
|
||||
builder.set_command(2010);
|
||||
builder.set_body(epee_encoding::to_bytes(tp)?);
|
||||
ProtocolMessage::NewBlock(nb) => epee_encoding::to_bytes(nb),
|
||||
ProtocolMessage::NewTransactions(nt) => epee_encoding::to_bytes(nt),
|
||||
ProtocolMessage::GetObjectsRequest(gt) => epee_encoding::to_bytes(gt),
|
||||
ProtocolMessage::GetObjectsResponse(ge) => epee_encoding::to_bytes(ge),
|
||||
ProtocolMessage::ChainRequest(ct) => epee_encoding::to_bytes(ct),
|
||||
ProtocolMessage::ChainEntryResponse(ce) => epee_encoding::to_bytes(ce),
|
||||
ProtocolMessage::NewFluffyBlock(fb) => epee_encoding::to_bytes(fb),
|
||||
ProtocolMessage::FluffyMissingTransactionsRequest(ft) => epee_encoding::to_bytes(ft),
|
||||
ProtocolMessage::GetTxPoolCompliment(tp) => epee_encoding::to_bytes(tp),
|
||||
}
|
||||
}
|
||||
|
||||
fn command(&self) -> LevinCommand {
|
||||
match self {
|
||||
ProtocolMessage::NewBlock(_) => LevinCommand::NewBlock,
|
||||
ProtocolMessage::NewTransactions(_) => LevinCommand::NewTransactions,
|
||||
ProtocolMessage::GetObjectsRequest(_) => LevinCommand::GetObjectsRequest,
|
||||
ProtocolMessage::GetObjectsResponse(_) => LevinCommand::GetObjectsResponse,
|
||||
ProtocolMessage::ChainRequest(_) => LevinCommand::ChainRequest,
|
||||
ProtocolMessage::ChainEntryResponse(_) => LevinCommand::ChainResponse,
|
||||
ProtocolMessage::NewFluffyBlock(_) => LevinCommand::NewFluffyBlock,
|
||||
ProtocolMessage::FluffyMissingTransactionsRequest(_) => {
|
||||
LevinCommand::FluffyMissingTxsRequest
|
||||
}
|
||||
ProtocolMessage::GetTxPoolCompliment(_) => LevinCommand::GetTxPoolCompliment,
|
||||
}
|
||||
}
|
||||
|
||||
fn build(&self, builder: &mut BucketBuilder<LevinCommand>) -> Result<(), epee_encoding::Error> {
|
||||
builder.set_command(self.command());
|
||||
builder.set_body(self.encode()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -117,12 +221,12 @@ pub enum RequestMessage {
|
|||
}
|
||||
|
||||
impl RequestMessage {
|
||||
fn decode(buf: &[u8], command: u32) -> Result<Self, epee_encoding::Error> {
|
||||
fn decode(buf: &[u8], command: LevinCommand) -> Result<Self, epee_encoding::Error> {
|
||||
Ok(match command {
|
||||
1001 => RequestMessage::Handshake(epee_encoding::from_bytes(buf)?),
|
||||
1002 => RequestMessage::TimedSync(epee_encoding::from_bytes(buf)?),
|
||||
1003 => RequestMessage::Ping,
|
||||
1007 => RequestMessage::SupportFlags,
|
||||
LevinCommand::Handshake => RequestMessage::Handshake(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::TimedSync => RequestMessage::TimedSync(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::Ping => RequestMessage::Ping,
|
||||
LevinCommand::SupportFlags => RequestMessage::SupportFlags,
|
||||
_ => {
|
||||
return Err(epee_encoding::Error::Value(
|
||||
"Failed to decode message, unknown command",
|
||||
|
@ -131,25 +235,27 @@ impl RequestMessage {
|
|||
})
|
||||
}
|
||||
|
||||
fn build(&self, builder: &mut BucketBuilder) -> Result<(), epee_encoding::Error> {
|
||||
fn command(&self) -> LevinCommand {
|
||||
match self {
|
||||
RequestMessage::Handshake(hs) => {
|
||||
builder.set_command(1001);
|
||||
builder.set_body(epee_encoding::to_bytes(hs)?);
|
||||
}
|
||||
RequestMessage::TimedSync(ts) => {
|
||||
builder.set_command(1002);
|
||||
builder.set_body(epee_encoding::to_bytes(ts)?);
|
||||
}
|
||||
RequestMessage::Ping => {
|
||||
builder.set_command(1003);
|
||||
builder.set_body(Vec::new());
|
||||
}
|
||||
RequestMessage::SupportFlags => {
|
||||
builder.set_command(1007);
|
||||
builder.set_body(Vec::new());
|
||||
RequestMessage::Handshake(_) => LevinCommand::Handshake,
|
||||
RequestMessage::TimedSync(_) => LevinCommand::TimedSync,
|
||||
RequestMessage::Ping => LevinCommand::Ping,
|
||||
RequestMessage::SupportFlags => LevinCommand::SupportFlags,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode(&self) -> Result<Vec<u8>, epee_encoding::Error> {
|
||||
match self {
|
||||
RequestMessage::Handshake(x) => epee_encoding::to_bytes(x),
|
||||
RequestMessage::TimedSync(x) => epee_encoding::to_bytes(x),
|
||||
RequestMessage::Ping => Ok(vec![]),
|
||||
RequestMessage::SupportFlags => Ok(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
fn build(&self, builder: &mut BucketBuilder<LevinCommand>) -> Result<(), epee_encoding::Error> {
|
||||
builder.set_command(self.command());
|
||||
builder.set_body(self.encode()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -162,12 +268,14 @@ pub enum ResponseMessage {
|
|||
}
|
||||
|
||||
impl ResponseMessage {
|
||||
fn decode(buf: &[u8], command: u32) -> Result<Self, epee_encoding::Error> {
|
||||
fn decode(buf: &[u8], command: LevinCommand) -> Result<Self, epee_encoding::Error> {
|
||||
Ok(match command {
|
||||
1001 => ResponseMessage::Handshake(epee_encoding::from_bytes(buf)?),
|
||||
1002 => ResponseMessage::TimedSync(epee_encoding::from_bytes(buf)?),
|
||||
1003 => ResponseMessage::Ping(epee_encoding::from_bytes(buf)?),
|
||||
1007 => ResponseMessage::SupportFlags(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::Handshake => ResponseMessage::Handshake(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::TimedSync => ResponseMessage::TimedSync(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::Ping => ResponseMessage::Ping(epee_encoding::from_bytes(buf)?),
|
||||
LevinCommand::SupportFlags => {
|
||||
ResponseMessage::SupportFlags(epee_encoding::from_bytes(buf)?)
|
||||
}
|
||||
_ => {
|
||||
return Err(epee_encoding::Error::Value(
|
||||
"Failed to decode message, unknown command",
|
||||
|
@ -176,25 +284,27 @@ impl ResponseMessage {
|
|||
})
|
||||
}
|
||||
|
||||
fn build(&self, builder: &mut BucketBuilder) -> Result<(), epee_encoding::Error> {
|
||||
fn command(&self) -> LevinCommand {
|
||||
match self {
|
||||
ResponseMessage::Handshake(hs) => {
|
||||
builder.set_command(1001);
|
||||
builder.set_body(epee_encoding::to_bytes(hs)?);
|
||||
}
|
||||
ResponseMessage::TimedSync(ts) => {
|
||||
builder.set_command(1002);
|
||||
builder.set_body(epee_encoding::to_bytes(ts)?);
|
||||
}
|
||||
ResponseMessage::Ping(pg) => {
|
||||
builder.set_command(1003);
|
||||
builder.set_body(epee_encoding::to_bytes(pg)?);
|
||||
}
|
||||
ResponseMessage::SupportFlags(sf) => {
|
||||
builder.set_command(1007);
|
||||
builder.set_body(epee_encoding::to_bytes(sf)?);
|
||||
ResponseMessage::Handshake(_) => LevinCommand::Handshake,
|
||||
ResponseMessage::TimedSync(_) => LevinCommand::TimedSync,
|
||||
ResponseMessage::Ping(_) => LevinCommand::Ping,
|
||||
ResponseMessage::SupportFlags(_) => LevinCommand::SupportFlags,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode(&self) -> Result<Vec<u8>, epee_encoding::Error> {
|
||||
match self {
|
||||
ResponseMessage::Handshake(x) => epee_encoding::to_bytes(x),
|
||||
ResponseMessage::TimedSync(x) => epee_encoding::to_bytes(x),
|
||||
ResponseMessage::Ping(x) => epee_encoding::to_bytes(x),
|
||||
ResponseMessage::SupportFlags(x) => epee_encoding::to_bytes(x),
|
||||
}
|
||||
}
|
||||
|
||||
fn build(&self, builder: &mut BucketBuilder<LevinCommand>) -> Result<(), epee_encoding::Error> {
|
||||
builder.set_command(self.command());
|
||||
builder.set_body(self.encode()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +316,13 @@ pub enum Message {
|
|||
}
|
||||
|
||||
impl LevinBody for Message {
|
||||
fn decode_message(body: &[u8], typ: MessageType, command: u32) -> Result<Self, BucketError> {
|
||||
type Command = LevinCommand;
|
||||
|
||||
fn decode_message(
|
||||
body: &[u8],
|
||||
typ: MessageType,
|
||||
command: LevinCommand,
|
||||
) -> Result<Self, BucketError> {
|
||||
Ok(match typ {
|
||||
MessageType::Request => Message::Request(
|
||||
RequestMessage::decode(body, command)
|
||||
|
@ -223,7 +339,7 @@ impl LevinBody for Message {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, builder: &mut BucketBuilder) -> Result<(), BucketError> {
|
||||
fn encode(&self, builder: &mut BucketBuilder<LevinCommand>) -> Result<(), BucketError> {
|
||||
match self {
|
||||
Message::Protocol(pro) => {
|
||||
builder.set_message_type(MessageType::Notification);
|
||||
|
|
Loading…
Reference in a new issue