From b14e740d2d5de718e224c16f4b382b2d2b860f7e Mon Sep 17 00:00:00 2001 From: Boog900 <54e72d8a-345f-4599-bd90-c6b9bc7d0ec5@aleeas.com> Date: Wed, 17 Jan 2024 16:31:57 +0000 Subject: [PATCH] monero-wire: fix some message decoding --- Cargo.lock | 14 +++++- net/monero-wire/Cargo.toml | 2 +- net/monero-wire/src/p2p/common.rs | 26 +++++++++-- net/monero-wire/src/p2p/protocol.rs | 68 ++++++++++++---------------- net/monero-wire/src/serde_helpers.rs | 22 +++++++++ 5 files changed, 84 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dc645a4..1139d858 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -463,7 +463,7 @@ dependencies = [ "futures", "hex", "monero-consensus", - "monero-epee-bin-serde", + "monero-epee-bin-serde 1.0.1 (git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=e4a585a)", "monero-serai", "monero-wire", "multiexp", @@ -1163,6 +1163,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "monero-epee-bin-serde" +version = "1.0.1" +source = "git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=aafe4ba#aafe4ba1b9912b03cf616db7403628fc2bd82eb1" +dependencies = [ + "byteorder", + "serde", + "serde_bytes", +] + [[package]] name = "monero-epee-bin-serde" version = "1.0.1" @@ -1245,7 +1255,7 @@ version = "0.1.0" dependencies = [ "hex", "levin-cuprate", - "monero-epee-bin-serde", + "monero-epee-bin-serde 1.0.1 (git+https://github.com/monero-rs/monero-epee-bin-serde.git?rev=aafe4ba)", "serde", "serde_bytes", "thiserror", diff --git a/net/monero-wire/Cargo.toml b/net/monero-wire/Cargo.toml index 7ad6e5bc..3413b927 100644 --- a/net/monero-wire/Cargo.toml +++ b/net/monero-wire/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/SyntheticBird45/cuprate/tree/main/net/monero-wi [dependencies] levin-cuprate = {path="../levin"} -monero-epee-bin-serde = {git = "https://github.com/monero-rs/monero-epee-bin-serde.git", rev="e4a585a"} +monero-epee-bin-serde = {git = "https://github.com/monero-rs/monero-epee-bin-serde.git", rev="aafe4ba"} serde = {version = "1", features = ["derive"]} serde_bytes = "0.11" thiserror = "1" diff --git a/net/monero-wire/src/p2p/common.rs b/net/monero-wire/src/p2p/common.rs index e08e5ff9..adfa8e46 100644 --- a/net/monero-wire/src/p2p/common.rs +++ b/net/monero-wire/src/p2p/common.rs @@ -16,10 +16,9 @@ //! Common types that are used across multiple messages. use serde::{Deserialize, Serialize}; -use serde_bytes::ByteBuf; use crate::{ - serde_helpers::{default_false, default_zero}, + serde_helpers::{default_false, default_zero, serde_vec_bytes}, NetworkAddress, }; @@ -159,7 +158,8 @@ impl std::hash::Hash for PeerListEntryBase { #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct PrunedTxBlobEntry { /// The Tx - pub tx: ByteBuf, + #[serde(with = "serde_bytes")] + pub tx: Vec, /// The Prunable Tx Hash pub prunable_hash: [u8; 32], } @@ -168,12 +168,29 @@ pub struct PrunedTxBlobEntry { #[serde(untagged)] pub enum TransactionBlobs { Pruned(Vec), - Normal(Vec), + #[serde(with = "serde_vec_bytes")] + Normal(Vec>), #[serde(skip_serializing)] None, } impl TransactionBlobs { + pub fn take_pruned(self) -> Option> { + match self { + TransactionBlobs::Normal(_) => None, + TransactionBlobs::Pruned(txs) => Some(txs), + TransactionBlobs::None => Some(vec![]), + } + } + + pub fn take_normal(self) -> Option>> { + match self { + TransactionBlobs::Normal(txs) => Some(txs), + TransactionBlobs::Pruned(_) => None, + TransactionBlobs::None => Some(vec![]), + } + } + pub fn len(&self) -> usize { match self { TransactionBlobs::Normal(txs) => txs.len(), @@ -198,7 +215,6 @@ pub struct BlockCompleteEntry { #[serde(default = "default_false")] pub pruned: bool, /// The Block - //#[serde_as(as = "Bytes")] #[serde(with = "serde_bytes")] pub block: Vec, /// The Block Weight/Size diff --git a/net/monero-wire/src/p2p/protocol.rs b/net/monero-wire/src/p2p/protocol.rs index 1e547ad0..f2810a2e 100644 --- a/net/monero-wire/src/p2p/protocol.rs +++ b/net/monero-wire/src/p2p/protocol.rs @@ -21,6 +21,8 @@ use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; +use monero_epee_bin_serde::container_as_blob; + use super::common::BlockCompleteEntry; use crate::serde_helpers::*; @@ -43,13 +45,17 @@ pub struct NewTransactions { pub dandelionpp_fluff: bool, /// Padding #[serde(rename = "_")] - pub padding: ByteBuf, + #[serde(with = "serde_bytes")] + pub padding: Vec, } /// A Request For Blocks #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct GetObjectsRequest { /// Block hashes we want + #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] pub blocks: Vec<[u8; 32]>, /// Pruned #[serde(default = "default_false")] @@ -64,6 +70,8 @@ pub struct GetObjectsResponse { pub blocks: Vec, /// Missed IDs #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] pub missed_ids: Vec<[u8; 32]>, /// The height of the peers blockchain pub current_blockchain_height: u64, @@ -73,6 +81,9 @@ pub struct GetObjectsResponse { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ChainRequest { /// Block IDs + #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] pub block_ids: Vec<[u8; 32]>, /// Prune #[serde(default = "default_false")] @@ -80,7 +91,6 @@ pub struct ChainRequest { } /// A Chain Response -// TODO: Fix the fields on this: m_block_ids, m_block_weights #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ChainResponse { /// Start Height @@ -93,46 +103,19 @@ pub struct ChainResponse { #[serde(default = "default_zero")] pub cumulative_difficulty_top64: u64, /// Block IDs - #[serde(default = "ByteBuf::new")] - pub m_block_ids: ByteBuf, + #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] + pub m_block_ids: Vec<[u8; 32]>, /// Block Weights - #[serde(default = "ByteBuf::new")] - pub m_block_weights: ByteBuf, + #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] + pub m_block_weights: Vec, /// The first Block in the response - #[serde(default = "ByteBuf::new")] - pub first_block: ByteBuf, -} - -impl ChainResponse { - /* - pub fn new( - start_height: u64, - total_height: u64, - cumulative_difficulty_128: u128, - m_block_ids: ByteBuf, - m_block_weights: Vec, - first_block: ByteBuf, - ) -> Self { - let cumulative_difficulty_low = cumulative_difficulty_128 as u64; - let cumulative_difficulty_high = (cumulative_difficulty_128 >> 64) as u64; - Self { - // start_height, - // total_height, - // cumulative_difficulty_low, - // cumulative_difficulty_high, - m_block_ids, - // m_block_weights, - // first_block, - } - } - pub fn cumulative_difficulty(&self) -> u128 { - let mut ret: u128 = self.cumulative_difficulty_high as u128; - ret <<= 64; - ret | self.cumulative_difficulty_low as u128 - } - - - */ + #[serde(default = "Vec::new")] + #[serde(with = "serde_bytes")] + pub first_block: Vec, } /// A Block that doesn't have transactions unless requested @@ -152,6 +135,9 @@ pub struct FluffyMissingTransactionsRequest { /// The current blockchain height pub current_blockchain_height: u64, /// The Tx Indices + #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] pub missing_tx_indices: Vec, } @@ -160,6 +146,8 @@ pub struct FluffyMissingTransactionsRequest { pub struct GetTxPoolCompliment { /// Tx Hashes #[serde(default = "Vec::new")] + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(with = "container_as_blob")] pub hashes: Vec<[u8; 32]>, } diff --git a/net/monero-wire/src/serde_helpers.rs b/net/monero-wire/src/serde_helpers.rs index efc8844d..5b61876e 100644 --- a/net/monero-wire/src/serde_helpers.rs +++ b/net/monero-wire/src/serde_helpers.rs @@ -11,3 +11,25 @@ pub(crate) fn default_zero>() -> T { .map_err(|_| "Couldn't fit 0 into integer type!") .unwrap() } + +pub(crate) mod serde_vec_bytes { + use serde::{Deserialize, Deserializer, Serializer}; + use serde_bytes::ByteBuf; + + pub fn deserialize<'de, D>(d: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + Ok(Vec::::deserialize(d)? + .into_iter() + .map(ByteBuf::into_vec) + .collect()) + } + + pub fn serialize(t: &[Vec], s: S) -> Result + where + S: Serializer, + { + s.collect_seq(t.iter()) + } +}