Skip to content

Commit

Permalink
WIP serde
Browse files Browse the repository at this point in the history
  • Loading branch information
nyonson committed May 10, 2024
1 parent 351980d commit 9151382
Showing 1 changed file with 231 additions and 59 deletions.
290 changes: 231 additions & 59 deletions protocol/src/v2.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use core::fmt;
//! A subset of commands are represented with a single byte in V2 instead of the 12-byte ASCII encoding like V1.
//!
//! ID mappings defined in [BIP324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki#user-content-v2_Bitcoin_P2P_message_structure).
use alloc::string::String;
use bitcoin::{consensus::Encodable, p2p::message::NetworkMessage};
use core::fmt;

/// A subset of commands are represented with a single byte
/// in V2 instead of the 12-byte ASCII encoding like V1.
use bitcoin::{
consensus::{Decodable, Encodable},
p2p::message::{CommandString, NetworkMessage},
};

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
Expand Down Expand Up @@ -33,69 +36,238 @@ impl std::error::Error for Error {

/// Serialize message in v2 format to buffer.
pub fn serialize(msg: NetworkMessage, buffer: &mut [u8]) -> Result<(), Error> {
let mut b = [0u8; 20];
let mut buf2 = &mut b[1..];
msg.consensus_encode(&mut buffer);
match msg {
NetworkMessage::Version(_) => {}
NetworkMessage::Verack => todo!(),
NetworkMessage::Addr(_) => {
buffer[0] = 1u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Inv(_) => {
buffer[0] = 14u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetData(_) => {
buffer[0] = 11u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::NotFound(_) => {
buffer[0] = 17u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetBlocks(_) => {
buffer[0] = 9u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetHeaders(_) => {
buffer[0] = 12u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::MemPool => {
buffer[0] = 15u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Tx(_) => {
buffer[0] = 21u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Block(_) => {
buffer[0] = 2u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Headers(_) => {
buffer[0] = 13u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Ping(_) => {
buffer[0] = 18u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Pong(_) => {
buffer[0] = 19u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::MerkleBlock(_) => {
buffer[0] = 16u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::FilterLoad(_) => {
buffer[0] = 8u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::FilterAdd(_) => {
buffer[0] = 6u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::FilterClear => {
buffer[0] = 7u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetCFilters(_) => {
buffer[0] = 22u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::CFilter(_) => {
buffer[0] = 23u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetCFHeaders(_) => {
buffer[0] = 24u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::CFHeaders(_) => {
buffer[0] = 25u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetCFCheckpt(_) => {
buffer[0] = 25u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::CFCheckpt(_) => {
buffer[0] = 26u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::SendCmpct(_) => {
buffer[0] = 20u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::CmpctBlock(_) => {
buffer[0] = 4u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::GetBlockTxn(_) => {
buffer[0] = 10u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::BlockTxn(_) => {
buffer[0] = 3u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::FeeFilter(_) => {
buffer[0] = 5u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::AddrV2(_) => {
buffer[0] = 28u8;
let mut payload_buffer = &mut buffer[1..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
// Messages which are not optimized and use the zero-byte + 12 following bytes to encode command in ascii.
NetworkMessage::Version(_)
| NetworkMessage::Verack
| NetworkMessage::SendHeaders
| NetworkMessage::GetAddr
| NetworkMessage::WtxidRelay
| NetworkMessage::SendAddrV2
| NetworkMessage::Alert(_)
| NetworkMessage::Reject(_) => {
buffer[0] = 0u8;
let mut command_buffer = &mut buffer[1..13];
msg.command()
.consensus_encode(&mut command_buffer)
.map_err(|_| Error::Serialize)?;
let mut payload_buffer = &mut buffer[13..];
msg.consensus_encode(&mut payload_buffer)
.map_err(|_| Error::Serialize)?;
}
NetworkMessage::Unknown { command, payload } => {
buffer[0] = 0u8;
let mut command_buffer = &mut buffer[1..13];
command
.consensus_encode(&mut command_buffer)
.map_err(|_| Error::Serialize)?;
buffer[13..].copy_from_slice(&payload[..]);
}
NetworkMessage::Inv(_) => todo!(),
NetworkMessage::GetData(_) => todo!(),
NetworkMessage::NotFound(_) => todo!(),
NetworkMessage::GetBlocks(_) => todo!(),
NetworkMessage::GetHeaders(_) => todo!(),
NetworkMessage::MemPool => todo!(),
NetworkMessage::Tx(_) => todo!(),
NetworkMessage::Block(_) => todo!(),
NetworkMessage::Headers(_) => todo!(),
NetworkMessage::SendHeaders => todo!(),
NetworkMessage::GetAddr => todo!(),
NetworkMessage::Ping(_) => todo!(),
NetworkMessage::Pong(_) => todo!(),
NetworkMessage::MerkleBlock(_) => todo!(),
NetworkMessage::FilterLoad(_) => todo!(),
NetworkMessage::FilterAdd(_) => todo!(),
NetworkMessage::FilterClear => todo!(),
NetworkMessage::GetCFilters(_) => todo!(),
NetworkMessage::CFilter(_) => todo!(),
NetworkMessage::GetCFHeaders(_) => todo!(),
NetworkMessage::CFHeaders(_) => todo!(),
NetworkMessage::GetCFCheckpt(_) => todo!(),
NetworkMessage::CFCheckpt(_) => todo!(),
NetworkMessage::SendCmpct(_) => todo!(),
NetworkMessage::CmpctBlock(_) => todo!(),
NetworkMessage::GetBlockTxn(_) => todo!(),
NetworkMessage::BlockTxn(_) => todo!(),
NetworkMessage::Alert(_) => todo!(),
NetworkMessage::Reject(_) => todo!(),
NetworkMessage::FeeFilter(_) => todo!(),
NetworkMessage::WtxidRelay => todo!(),
NetworkMessage::AddrV2(_) => todo!(),
NetworkMessage::SendAddrV2 => todo!(),
NetworkMessage::Unknown { command, payload } => todo!(),
}

Ok(())
}

/// Deserialize v2 message into NetworkMessage.
pub fn deserialize(buffer: &[u8]) -> Result<NetworkMessage, Error> {
Ok(())
}

fn to_ascii(bytes: [u8; 12]) -> String {
String::from_utf8(bytes.to_vec())
.expect("ascii")
.trim_end_matches("00")
.to_string()
#[cfg(feature = "alloc")]
pub fn serialize_with_alloc(msg: NetworkMessage) -> Result<alloc::vec::Vec<u8>, Error> {
let mut buffer = alloc::vec![];
serialize(msg, &mut buffer)?;
Ok(buffer)
}

fn from_ascii(ascii: String) -> [u8; 12] {
let mut output_bytes = [0u8; 12];
let cmd_bytes = ascii.as_bytes();
output_bytes[0..cmd_bytes.len()].copy_from_slice(cmd_bytes);
output_bytes
/// Deserialize v2 message into NetworkMessage.
#[cfg(feature = "alloc")]
pub fn deserialize(buffer: &[u8]) -> Result<NetworkMessage, Error> {
let short_id = buffer[0];
match short_id {
// zero-byte means the command is encoded in the next 12 bytes.
0u8 => {
let mut command_buffer = &buffer[1..13];
let command = CommandString::consensus_decode(&mut command_buffer)
.map_err(|_| Error::Deserialize)?;
match command {
"verack" => {}
_ => Ok(NetworkMessage::Unknown {
command,
payload: buffer[13..].to_vec(),
}),
}
}
// The following 27 IDs are command short IDs.
1u8 => {
let mut payload_buffer = &buffer[1..];
Ok(NetworkMessage::Addr(
Decodable::consensus_decode(&mut payload_buffer).map_err(|_| Error::Deserialize)?,
))
}
_ => Err(Error::Deserialize),
}
}

0 comments on commit 9151382

Please sign in to comment.