From 857dc2ba47d71f52a541f9399332e6e9c58f9f54 Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Sun, 24 Mar 2019 22:51:56 -0700 Subject: [PATCH] Remove custom serialization --- client/src/thin_client.rs | 8 +- core/src/entry.rs | 8 +- core/src/sigverify.rs | 40 ++-- sdk/src/instruction.rs | 42 +---- sdk/src/lib.rs | 1 - sdk/src/packet.rs | 3 +- sdk/src/shortvec.rs | 373 -------------------------------------- sdk/src/transaction.rs | 197 +++----------------- 8 files changed, 52 insertions(+), 620 deletions(-) delete mode 100644 sdk/src/shortvec.rs diff --git a/client/src/thin_client.rs b/client/src/thin_client.rs index 48d7189cc5..864e773689 100644 --- a/client/src/thin_client.rs +++ b/client/src/thin_client.rs @@ -4,7 +4,7 @@ //! unstable and may change in future releases. use crate::rpc_client::RpcClient; -use bincode::serialize_into; +use bincode::{serialize_into, serialized_size}; use log::*; use solana_sdk::hash::Hash; use solana_sdk::packet::PACKET_DATA_SIZE; @@ -63,7 +63,7 @@ impl ThinClient { /// Send a signed Transaction to the server for processing. This method /// does not wait for a response. pub fn transfer_signed(&self, transaction: &Transaction) -> io::Result { - let mut buf = vec![0; transaction.serialized_size().unwrap() as usize]; + let mut buf = vec![0; serialized_size(&transaction).unwrap() as usize]; let mut wr = std::io::Cursor::new(&mut buf[..]); serialize_into(&mut wr, &transaction) .expect("serialize Transaction in pub fn transfer_signed"); @@ -83,7 +83,7 @@ impl ThinClient { ) -> io::Result { for x in 0..tries { transaction.sign(&[keypair], self.get_recent_blockhash()?); - let mut buf = vec![0; transaction.serialized_size().unwrap() as usize]; + let mut buf = vec![0; serialized_size(&transaction).unwrap() as usize]; let mut wr = std::io::Cursor::new(&mut buf[..]); serialize_into(&mut wr, &transaction) .expect("serialize Transaction in pub fn transfer_signed"); @@ -112,7 +112,7 @@ impl ThinClient { ) -> io::Result { for x in 0..tries { transaction.sign(&[keypair], self.get_recent_blockhash()?); - let mut buf = vec![0; transaction.serialized_size().unwrap() as usize]; + let mut buf = vec![0; serialized_size(&transaction).unwrap() as usize]; let mut wr = std::io::Cursor::new(&mut buf[..]); serialize_into(&mut wr, &transaction) .expect("serialize Transaction in pub fn transfer_signed"); diff --git a/core/src/entry.rs b/core/src/entry.rs index 347cbcb3f6..8c2583394e 100644 --- a/core/src/entry.rs +++ b/core/src/entry.rs @@ -105,7 +105,7 @@ impl Entry { pub fn serialized_size(transactions: &[Transaction]) -> u64 { let txs_size: u64 = transactions .iter() - .map(|tx| tx.serialized_size().unwrap()) + .map(|tx| serialized_size(tx).unwrap()) .sum(); // num_hashes + hash + txs (2 * size_of::() + size_of::()) as u64 + txs_size @@ -402,7 +402,7 @@ pub fn make_large_test_entries(num_entries: usize) -> Vec { let ix = BudgetInstruction::new_apply_timestamp(&pubkey, &pubkey, &pubkey, Utc::now()); let tx = Transaction::new_signed_instructions(&[&keypair], vec![ix], one, 0); - let serialized_size = tx.serialized_size().unwrap(); + let serialized_size = serialized_size(&tx).unwrap(); let num_txs = BLOB_DATA_SIZE / serialized_size as usize; let txs = vec![tx; num_txs]; let entry = next_entries(&one, 1, txs)[0].clone(); @@ -643,8 +643,8 @@ mod tests { let tx_small = create_sample_vote(&vote_account, next_hash); let tx_large = create_sample_payment(&keypair, next_hash); - let tx_small_size = tx_small.serialized_size().unwrap() as usize; - let tx_large_size = tx_large.serialized_size().unwrap() as usize; + let tx_small_size = serialized_size(&tx_small).unwrap() as usize; + let tx_large_size = serialized_size(&tx_large).unwrap() as usize; let entry_size = serialized_size(&Entry { num_hashes: 0, hash: Hash::default(), diff --git a/core/src/sigverify.rs b/core/src/sigverify.rs index e11ef6bf13..ff01b30c4b 100644 --- a/core/src/sigverify.rs +++ b/core/src/sigverify.rs @@ -6,9 +6,9 @@ use crate::packet::{Packet, SharedPackets}; use crate::result::Result; +use byteorder::{LittleEndian, ReadBytesExt}; use solana_metrics::counter::Counter; use solana_sdk::pubkey::Pubkey; -use solana_sdk::shortvec::decode_len; use solana_sdk::signature::Signature; #[cfg(test)] use solana_sdk::transaction::Transaction; @@ -124,25 +124,17 @@ pub fn ed25519_verify(batches: &[SharedPackets]) -> Vec> { } pub fn get_packet_offsets(packet: &Packet, current_offset: u32) -> (u32, u32, u32, u32) { - // Read in the size of signatures array - let start_offset = TX_OFFSET + size_of::(); - let mut rd = Cursor::new(&packet.data[start_offset..]); - let sig_len = decode_len(&mut rd).unwrap(); - let sig_size = rd.position() as usize; - let msg_start_offset = start_offset + sig_size + sig_len * size_of::(); - let mut rd = Cursor::new(&packet.data[msg_start_offset..]); - let _ = decode_len(&mut rd).unwrap(); - let pubkey_size = rd.position() as usize; - let pubkey_offset = current_offset as usize + msg_start_offset + pubkey_size; + // Read in u64 as the size of signatures array + let mut rdr = Cursor::new(&packet.data[TX_OFFSET..size_of::()]); + let sig_len = rdr.read_u64::().unwrap() as u32; - let sig_start = start_offset + current_offset as usize + sig_size; + let msg_start_offset = + current_offset + size_of::() as u32 + sig_len * size_of::() as u32; + let pubkey_offset = msg_start_offset + size_of::() as u32; - ( - sig_len as u32, - sig_start as u32, - current_offset + msg_start_offset as u32, - pubkey_offset as u32, - ) + let sig_start = TX_OFFSET as u32 + size_of::() as u32; + + (sig_len, sig_start, msg_start_offset, pubkey_offset) } pub fn generate_offsets(batches: &[SharedPackets]) -> Result { @@ -157,14 +149,14 @@ pub fn generate_offsets(batches: &[SharedPackets]) -> Result { p.read().unwrap().packets.iter().for_each(|packet| { let current_offset = current_packet as u32 * size_of::() as u32; - let (sig_len, sig_start, msg_start_offset, pubkey_offset) = + let (sig_len, _sig_start, msg_start_offset, pubkey_offset) = get_packet_offsets(packet, current_offset); let mut pubkey_offset = pubkey_offset; sig_lens.push(sig_len); trace!("pubkey_offset: {}", pubkey_offset); - let mut sig_offset = sig_start; + let mut sig_offset = current_offset + size_of::() as u32; for _ in 0..sig_len { signature_offsets.push(sig_offset); sig_offset += size_of::() as u32; @@ -337,7 +329,7 @@ mod tests { use bincode::{deserialize, serialize}; use solana_sdk::transaction::Transaction; - const SIG_OFFSET: usize = std::mem::size_of::() + 1; + const SIG_OFFSET: usize = std::mem::size_of::(); pub fn memfind(a: &[A], b: &[A]) -> Option { assert!(a.len() >= b.len()); @@ -424,11 +416,11 @@ mod tests { #[test] fn test_get_packet_offsets() { - assert_eq!(get_packet_offsets_from_tx(test_tx(), 0), (1, 9, 64, 1)); - assert_eq!(get_packet_offsets_from_tx(test_tx(), 100), (1, 9, 64, 1)); + assert_eq!(get_packet_offsets_from_tx(test_tx(), 0), (1, 8, 64, 8)); + assert_eq!(get_packet_offsets_from_tx(test_tx(), 100), (1, 8, 64, 8)); assert_eq!( get_packet_offsets_from_tx(test_multisig_tx(), 0), - (2, 9, 128, 1) + (2, 8, 128, 8) ); } diff --git a/sdk/src/instruction.rs b/sdk/src/instruction.rs index f999b5c15e..08066615df 100644 --- a/sdk/src/instruction.rs +++ b/sdk/src/instruction.rs @@ -1,12 +1,9 @@ //! Defines a composable Instruction type and a memory-efficient CompiledInstruction. use crate::pubkey::Pubkey; -use crate::shortvec::{deserialize_vec_bytes, encode_len, serialize_vec_bytes}; use crate::system_instruction::SystemError; -use bincode::{serialize, Error}; +use bincode::serialize; use serde::Serialize; -use std::io::{Cursor, Read, Write}; -use std::mem::size_of; /// Reasons the runtime might have rejected an instruction. #[derive(Debug, PartialEq, Eq, Clone)] @@ -129,41 +126,4 @@ impl CompiledInstruction { accounts, } } - - pub fn serialize_with(mut writer: &mut Cursor<&mut [u8]>, ix: &Self) -> Result<(), Error> { - writer.write_all(&[ix.program_ids_index])?; - serialize_vec_bytes(&mut writer, &ix.accounts[..])?; - serialize_vec_bytes(&mut writer, &ix.data[..])?; - Ok(()) - } - - pub fn deserialize_from(mut reader: &mut Cursor<&[u8]>) -> Result { - let mut buf = [0]; - reader.read_exact(&mut buf)?; - let program_ids_index = buf[0]; - let accounts = deserialize_vec_bytes(&mut reader)?; - let data = deserialize_vec_bytes(&mut reader)?; - Ok(CompiledInstruction { - program_ids_index, - accounts, - data, - }) - } - - pub fn serialized_size(&self) -> Result { - let mut buf = [0; size_of::() + 1]; - let mut wr = Cursor::new(&mut buf[..]); - let mut size = size_of::(); - - let len = self.accounts.len(); - encode_len(&mut wr, len)?; - size += wr.position() as usize + (len * size_of::()); - - let len = self.data.len(); - wr.set_position(0); - encode_len(&mut wr, len)?; - size += wr.position() as usize + (len * size_of::()); - - Ok(size as u64) - } } diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 86977cc598..8606d8cf69 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -10,7 +10,6 @@ pub mod native_program; pub mod packet; pub mod pubkey; pub mod rpc_port; -pub mod shortvec; pub mod signature; pub mod system_instruction; pub mod system_program; diff --git a/sdk/src/packet.rs b/sdk/src/packet.rs index a28761155b..6a204dbd6a 100644 --- a/sdk/src/packet.rs +++ b/sdk/src/packet.rs @@ -1,2 +1,3 @@ /// Maximum over-the-wire size of a Transaction -pub const PACKET_DATA_SIZE: usize = 512; +// TODO: Set this back to 512 after shortvec optimization is reinstated. +pub const PACKET_DATA_SIZE: usize = 522; diff --git a/sdk/src/shortvec.rs b/sdk/src/shortvec.rs deleted file mode 100644 index 09b7fb28e6..0000000000 --- a/sdk/src/shortvec.rs +++ /dev/null @@ -1,373 +0,0 @@ -use bincode::{deserialize_from, serialize_into, Error}; -use serde::Serialize; -use std::io::{Cursor, Read, Write}; -use std::mem::size_of; - -pub fn encode_len(writer: &mut W, len: usize) -> Result<(), Error> { - let mut rem_len = len; - loop { - let mut elem = (rem_len & 0x7f) as u8; - rem_len >>= 7; - if rem_len == 0 { - writer.write_all(&[elem])?; - break; - } else { - elem |= 0x80; - writer.write_all(&[elem])?; - } - } - Ok(()) -} - -pub fn decode_len(reader: &mut R) -> Result { - let mut len: usize = 0; - let mut size: usize = 0; - loop { - let mut elem = [0u8; 1]; - reader.read_exact(&mut elem)?; - len |= (elem[0] as usize & 0x7f) << (size * 7); - size += 1; - if elem[0] as usize & 0x80 == 0 { - break; - } - assert!(size <= size_of::() + 1); - } - Ok(len) -} - -pub fn serialize_vec_with( - mut writer: &mut Cursor<&mut [u8]>, - input: &[T], - ser_fn: fn(&mut Cursor<&mut [u8]>, &T) -> Result<(), Error>, -) -> Result<(), Error> { - encode_len(&mut writer, input.len())?; - input.iter().for_each(|e| ser_fn(&mut writer, &e).unwrap()); - Ok(()) -} - -pub fn serialize_vec_bytes(mut writer: W, input: &[u8]) -> Result<(), Error> { - let len = input.len(); - encode_len(&mut writer, len)?; - writer.write_all(input)?; - Ok(()) -} - -pub fn serialize_vec(mut writer: W, input: &[T]) -> Result<(), Error> -where - T: Serialize, -{ - let len = input.len(); - encode_len(&mut writer, len)?; - input - .iter() - .for_each(|e| serialize_into(&mut writer, &e).unwrap()); - Ok(()) -} - -pub fn deserialize_vec_bytes(mut reader: &mut R) -> Result, Error> { - let vec_len = decode_len(&mut reader)?; - let mut buf = vec![0; vec_len]; - reader.read_exact(&mut buf[..])?; - Ok(buf) -} - -pub fn deserialize_vec(mut reader: &mut R) -> Result, Error> -where - T: serde::de::DeserializeOwned, -{ - let vec_len = decode_len(&mut reader)?; - let mut vec: Vec = Vec::with_capacity(vec_len); - for _ in 0..vec_len { - let t: T = deserialize_from(&mut reader)?; - vec.push(t); - } - Ok(vec) -} - -pub fn deserialize_vec_with( - mut reader: &mut Cursor<&[u8]>, - deser_fn: fn(&mut Cursor<&[u8]>) -> Result, -) -> Result, Error> { - let vec_len = decode_len(&mut reader)?; - let mut vec: Vec = Vec::with_capacity(vec_len); - for _ in 0..vec_len { - let t: T = deser_fn(&mut reader)?; - vec.push(t); - } - Ok(vec) -} - -#[cfg(test)] -mod tests { - use super::*; - use bincode::{deserialize, serialize, serialized_size}; - use serde::ser::Serializer; - use serde::Deserialize; - use std::fmt; - use std::io::Cursor; - - #[test] - fn test_shortvec_encode_len() { - let mut buf = vec![0u8; size_of::() + 1]; - let mut wr = Cursor::new(&mut buf[..]); - encode_len(&mut wr, 0x0).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0u8]); - wr.set_position(0); - encode_len(&mut wr, 0x5).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0x5u8]); - wr.set_position(0); - encode_len(&mut wr, 0x7f).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0x7fu8]); - wr.set_position(0); - encode_len(&mut wr, 0x80).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0x80u8, 0x01u8]); - wr.set_position(0); - encode_len(&mut wr, 0xff).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0xffu8, 0x01u8]); - wr.set_position(0); - encode_len(&mut wr, 0x100).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0x80u8, 0x02u8]); - wr.set_position(0); - encode_len(&mut wr, 0x7fff).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0xffu8, 0xffu8, 0x01u8]); - wr.set_position(0); - encode_len(&mut wr, 0x200000).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0x80u8, 0x80u8, 0x80u8, 0x01u8]); - wr.set_position(0); - encode_len(&mut wr, 0x7ffffffff).unwrap(); - let vec = wr.get_ref()[..wr.position() as usize].to_vec(); - assert_eq!(vec, vec![0xffu8, 0xffu8, 0xffu8, 0xffu8, 0x7fu8]); - } - - #[test] - #[should_panic] - fn test_shortvec_decode_zero_len() { - let mut buf = vec![]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0); - assert_eq!(rd.position(), 0); - } - - #[test] - fn test_shortvec_decode_len() { - let mut buf = vec![0u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0); - assert_eq!(rd.position(), 1); - let mut buf = vec![5u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 5); - assert_eq!(rd.position(), 1); - let mut buf = vec![0x7fu8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0x7f); - assert_eq!(rd.position(), 1); - let mut buf = vec![0x80u8, 0x01u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0x80); - assert_eq!(rd.position(), 2); - let mut buf = vec![0xffu8, 0x01u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0xff); - assert_eq!(rd.position(), 2); - let mut buf = vec![0x80u8, 0x02u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0x100); - assert_eq!(rd.position(), 2); - let mut buf = vec![0xffu8, 0xffu8, 0x01u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0x7fff); - assert_eq!(rd.position(), 3); - let mut buf = vec![0x80u8, 0x80u8, 0x80u8, 0x01u8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0x200000); - assert_eq!(rd.position(), 4); - let mut buf = vec![0xffu8, 0xffu8, 0xffu8, 0xffu8, 0x7fu8]; - let mut rd = Cursor::new(&mut buf[..]); - assert_eq!(decode_len(&mut rd).unwrap(), 0x7ffffffff); - assert_eq!(rd.position(), 5); - } - - #[test] - fn test_shortvec_u8() { - let vec: Vec = vec![4; 32]; - let mut buf = vec![0u8; serialized_size(&vec).unwrap() as usize + 1]; - let mut wr = Cursor::new(&mut buf[..]); - serialize_vec_bytes(&mut wr, &vec).unwrap(); - let size = wr.position() as usize; - let ser = &wr.into_inner()[..size]; - assert_eq!(ser.len(), vec.len() + 1); - let mut rd = Cursor::new(&ser[..]); - let deser: Vec = deserialize_vec_bytes(&mut rd).unwrap(); - assert_eq!(vec, deser); - } - - #[derive(Debug, Eq, PartialEq)] - struct TestVec { - vec_u8: Vec, - id: u8, - vec_u32: Vec, - } - - impl TestVec { - pub fn serialize_with( - mut writer: &mut Cursor<&mut [u8]>, - tv: &TestVec, - ) -> Result<(), Error> { - serialize_vec(&mut writer, &tv.vec_u8).unwrap(); - serialize_into(&mut writer, &tv.id).unwrap(); - serialize_vec(&mut writer, &tv.vec_u32).unwrap(); - Ok(()) - } - pub fn from_bytes(mut reader: &mut Cursor<&[u8]>) -> Result { - let vec_u8: Vec = deserialize_vec(&mut reader).unwrap(); - let id: u8 = deserialize_from(&mut reader).unwrap(); - let vec_u32: Vec = deserialize_vec(&mut reader).unwrap(); - Ok(TestVec { - vec_u8, - id, - vec_u32, - }) - } - pub fn serialized_size(&self) -> u64 { - let mut buf = vec![0u8; size_of::() + 1]; - let mut size = size_of::(); - let mut wr = Cursor::new(&mut buf[..]); - encode_len(&mut wr, self.vec_u8.len()).unwrap(); - size += wr.position() as usize + self.vec_u8.len() * size_of::(); - size += size_of::(); - wr.set_position(0); - encode_len(&mut wr, self.vec_u32.len()).unwrap(); - size += wr.position() as usize + self.vec_u32.len() * size_of::(); - size as u64 - } - } - - impl Serialize for TestVec { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - use serde::ser::Error; - let mut buf = vec![0u8; self.serialized_size() as usize]; - let mut wr = Cursor::new(&mut buf[..]); - serialize_vec(&mut wr, &self.vec_u8).map_err(Error::custom)?; - serialize_into(&mut wr, &self.id).map_err(Error::custom)?; - serialize_vec(&mut wr, &self.vec_u32).map_err(Error::custom)?; - let len = wr.position() as usize; - serializer.serialize_bytes(&wr.into_inner()[..len]) - } - } - - struct TestVecVisitor; - impl<'a> serde::de::Visitor<'a> for TestVecVisitor { - type Value = TestVec; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("Expecting TestVec") - } - fn visit_bytes(self, data: &[u8]) -> Result - where - E: serde::de::Error, - { - use serde::de::Error; - let mut rd = Cursor::new(&data[..]); - let v1: Vec = deserialize_vec(&mut rd).map_err(Error::custom)?; - let id: u8 = deserialize_from(&mut rd).map_err(Error::custom)?; - let v2: Vec = deserialize_vec(&mut rd).map_err(Error::custom)?; - Ok(TestVec { - vec_u8: v1, - id, - vec_u32: v2, - }) - } - } - impl<'de> Deserialize<'de> for TestVec { - fn deserialize(deserializer: D) -> Result - where - D: ::serde::Deserializer<'de>, - { - deserializer.deserialize_bytes(TestVecVisitor) - } - } - - #[test] - fn test_shortvec_testvec() { - let tvec: TestVec = TestVec { - vec_u8: vec![4; 32], - id: 5, - vec_u32: vec![6; 32], - }; - let size = tvec.serialized_size() as usize; - assert_eq!( - size, - tvec.vec_u8.len() + 1 + 1 + (tvec.vec_u32.len() * 4) + 1 + 8 - ); - let ser = serialize(&tvec).unwrap(); - assert_eq!( - ser.len(), - tvec.vec_u8.len() + 1 + 1 + (tvec.vec_u32.len() * 4) + 1 + 8 - ); - let deser = deserialize(&ser).unwrap(); - assert_eq!(tvec, deser); - } - - #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] - struct TestVecArr { - data: Vec, - } - impl TestVecArr { - fn new() -> Self { - TestVecArr { data: vec![] } - } - fn serialized_size(tvec: &TestVecArr) -> u64 { - let mut buf = vec![0u8; size_of::() + 1]; - let mut wr = Cursor::new(&mut buf[..]); - encode_len(&mut wr, tvec.data.len()).unwrap(); - let size: u64 = tvec - .data - .iter() - .map(|tv| TestVec::serialized_size(&tv)) - .sum(); - size_of::() as u64 + size + wr.position() - } - } - #[test] - fn test_shortvec_testvec_with() { - let tvec1 = TestVec { - vec_u8: vec![4; 32], - id: 5, - vec_u32: vec![6; 32], - }; - let tvec2 = TestVec { - vec_u8: vec![7; 32], - id: 8, - vec_u32: vec![9; 32], - }; - let tvec3 = TestVec { - vec_u8: vec![], - id: 10, - vec_u32: vec![11; 32], - }; - let mut tvecarr: TestVecArr = TestVecArr::new(); - tvecarr.data.push(tvec1); - tvecarr.data.push(tvec2); - tvecarr.data.push(tvec3); - let mut buf = vec![0u8; TestVecArr::serialized_size(&tvecarr) as usize]; - let mut wr = Cursor::new(&mut buf[..]); - serialize_vec_with(&mut wr, &tvecarr.data, TestVec::serialize_with).unwrap(); - let size = wr.position() as usize; - let ser = &wr.into_inner()[..size]; - let mut rd = Cursor::new(&ser[..]); - let deser = deserialize_vec_with(&mut rd, TestVec::from_bytes).unwrap(); - assert_eq!(tvecarr.data, deser); - } -} diff --git a/sdk/src/transaction.rs b/sdk/src/transaction.rs index f615b5e78c..5dbb0b46fd 100644 --- a/sdk/src/transaction.rs +++ b/sdk/src/transaction.rs @@ -3,16 +3,10 @@ use crate::hash::Hash; use crate::instruction::{CompiledInstruction, Instruction, InstructionError}; use crate::message::Message; -use crate::packet::PACKET_DATA_SIZE; use crate::pubkey::Pubkey; -use crate::shortvec::{deserialize_vec_with, encode_len, serialize_vec_with}; use crate::signature::{KeypairUtil, Signature}; -use bincode::Error; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use serde::{Deserialize, Serialize, Serializer}; -use std::fmt; -use std::io::{Cursor, Read, Write}; -use std::mem::size_of; +use bincode::serialize; +use serde::Serialize; /// Reasons a transaction might be rejected. #[derive(Debug, PartialEq, Eq, Clone)] @@ -53,7 +47,7 @@ pub enum TransactionError { } /// An atomic transaction -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Transaction { /// A set of digital signatures of `account_keys`, `program_ids`, `recent_blockhash`, `fee` and `instructions`, signed by the first /// signatures.len() keys of account_keys @@ -173,24 +167,16 @@ impl Transaction { } /// Get the transaction data to sign. pub fn message(&self) -> Vec { - let mut buf = vec![0u8; PACKET_DATA_SIZE]; - let mut wr = Cursor::new(&mut buf[..]); - serialize_vec_with(&mut wr, &self.account_keys, Transaction::serialize_pubkey) - .expect("serialize account_keys"); - wr.write_all(self.recent_blockhash.as_ref()) - .expect("serialize recent_blockhash"); - wr.write_u64::(self.fee) - .expect("serialize fee"); - serialize_vec_with(&mut wr, &self.program_ids, Transaction::serialize_pubkey) - .expect("serialize program_ids"); - serialize_vec_with( - &mut wr, - &self.instructions, - CompiledInstruction::serialize_with, - ) - .expect("serialize instructions"); - let len = wr.position() as usize; - wr.into_inner()[..len].to_vec() + let mut data = serialize(&self.account_keys).expect("serialize account_keys"); + let blockhash = serialize(&self.recent_blockhash).expect("serialize recent_blockhash"); + data.extend_from_slice(&blockhash); + let fee_data = serialize(&self.fee).expect("serialize fee"); + data.extend_from_slice(&fee_data); + let program_ids = serialize(&self.program_ids).expect("serialize program_ids"); + data.extend_from_slice(&program_ids); + let instructions = serialize(&self.instructions).expect("serialize instructions"); + data.extend_from_slice(&instructions); + data } /// Sign this transaction. @@ -229,141 +215,6 @@ impl Transaction { } true } - - pub fn serialized_size(&self) -> Result { - let mut buf = [0u8; size_of::() + 1]; - let mut wr = Cursor::new(&mut buf[..]); - let mut size = size_of::(); - - let len = self.signatures.len(); - encode_len(&mut wr, len)?; - size += wr.position() as usize + (len * size_of::()); - - let len = self.account_keys.len(); - wr.set_position(0); - encode_len(&mut wr, len)?; - size += wr.position() as usize + (len * size_of::()); - - size += size_of::(); - - size += size_of::(); - - let len = self.program_ids.len(); - wr.set_position(0); - encode_len(&mut wr, len)?; - size += wr.position() as usize + (len * size_of::()); - - let len = self.instructions.len(); - wr.set_position(0); - encode_len(&mut wr, len)?; - size += wr.position() as usize; - let inst_size: u64 = self - .instructions - .iter() - .map(|ix| ix.serialized_size().unwrap()) - .sum(); - Ok(size as u64 + inst_size) - } - - fn serialize_signature(writer: &mut Cursor<&mut [u8]>, sig: &Signature) -> Result<(), Error> { - writer.write_all(sig.as_ref())?; - Ok(()) - } - - fn serialize_pubkey(writer: &mut Cursor<&mut [u8]>, key: &Pubkey) -> Result<(), Error> { - writer.write_all(key.as_ref())?; - Ok(()) - } - - fn deserialize_signature(reader: &mut Cursor<&[u8]>) -> Result { - let mut buf = [0; size_of::()]; - reader.read_exact(&mut buf)?; - Ok(Signature::new(&buf)) - } - - fn deserialize_pubkey(reader: &mut Cursor<&[u8]>) -> Result { - let mut buf = [0; size_of::()]; - reader.read_exact(&mut buf)?; - Ok(Pubkey::new(&buf)) - } -} - -impl Serialize for Transaction { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - use serde::ser::Error; - let mut buf = vec![0u8; self.serialized_size().unwrap() as usize]; - let mut wr = Cursor::new(&mut buf[..]); - serialize_vec_with(&mut wr, &self.signatures, Transaction::serialize_signature) - .map_err(Error::custom)?; - serialize_vec_with(&mut wr, &self.account_keys, Transaction::serialize_pubkey) - .map_err(Error::custom)?; - wr.write_all(self.recent_blockhash.as_ref()) - .map_err(Error::custom)?; - wr.write_u64::(self.fee) - .map_err(Error::custom)?; - serialize_vec_with(&mut wr, &self.program_ids, Transaction::serialize_pubkey) - .map_err(Error::custom)?; - serialize_vec_with( - &mut wr, - &self.instructions, - CompiledInstruction::serialize_with, - ) - .map_err(Error::custom)?; - let size = wr.position() as usize; - serializer.serialize_bytes(&wr.into_inner()[..size]) - } -} - -struct TransactionVisitor; -impl<'a> serde::de::Visitor<'a> for TransactionVisitor { - type Value = Transaction; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("Expecting Instruction") - } - fn visit_bytes(self, data: &[u8]) -> Result - where - E: serde::de::Error, - { - use serde::de::Error; - let mut rd = Cursor::new(&data[..]); - let signatures: Vec = - deserialize_vec_with(&mut rd, Transaction::deserialize_signature) - .map_err(Error::custom)?; - let account_keys: Vec = - deserialize_vec_with(&mut rd, Transaction::deserialize_pubkey) - .map_err(Error::custom)?; - let mut buf = [0; size_of::()]; - rd.read_exact(&mut buf).map_err(Error::custom)?; - let recent_blockhash: Hash = Hash::new(&buf); - let fee = rd.read_u64::().map_err(Error::custom)?; - let program_ids: Vec = - deserialize_vec_with(&mut rd, Transaction::deserialize_pubkey) - .map_err(Error::custom)?; - let instructions: Vec = - deserialize_vec_with(&mut rd, CompiledInstruction::deserialize_from) - .map_err(Error::custom)?; - Ok(Transaction { - signatures, - account_keys, - recent_blockhash, - fee, - program_ids, - instructions, - }) - } -} - -impl<'de> Deserialize<'de> for Transaction { - fn deserialize(deserializer: D) -> Result - where - D: ::serde::Deserializer<'de>, - { - deserializer.deserialize_bytes(TransactionVisitor) - } } #[cfg(test)] @@ -550,16 +401,18 @@ mod tests { assert_eq!( serialize(&create_sample_transaction()).unwrap(), vec![ - 212, 0, 0, 0, 0, 0, 0, 0, 1, 107, 231, 179, 42, 11, 220, 153, 173, 229, 29, 51, - 218, 98, 26, 46, 164, 248, 228, 118, 244, 191, 192, 198, 228, 190, 119, 21, 52, 66, - 25, 124, 247, 192, 73, 48, 231, 2, 70, 34, 82, 133, 137, 148, 66, 73, 231, 72, 195, - 100, 133, 214, 2, 168, 108, 252, 200, 83, 99, 105, 51, 216, 145, 30, 14, 2, 36, - 100, 158, 252, 33, 161, 97, 185, 62, 89, 99, 195, 250, 249, 187, 189, 171, 118, - 241, 90, 248, 14, 68, 219, 231, 62, 157, 5, 142, 27, 210, 117, 1, 1, 1, 4, 5, 6, 7, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 99, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 1, 0, 2, 0, 1, 3, 1, 2, 3 + 1, 0, 0, 0, 0, 0, 0, 0, 60, 2, 97, 229, 100, 48, 42, 208, 222, 192, 129, 29, 142, + 187, 4, 174, 210, 77, 78, 162, 101, 146, 144, 241, 159, 44, 89, 89, 10, 103, 229, + 94, 92, 240, 124, 0, 83, 22, 216, 2, 112, 193, 158, 93, 210, 144, 222, 144, 13, + 138, 209, 246, 89, 156, 195, 234, 186, 215, 92, 250, 125, 210, 24, 10, 2, 0, 0, 0, + 0, 0, 0, 0, 36, 100, 158, 252, 33, 161, 97, 185, 62, 89, 99, 195, 250, 249, 187, + 189, 171, 118, 241, 90, 248, 14, 68, 219, 231, 62, 157, 5, 142, 27, 210, 117, 1, 1, + 1, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 5, + 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 2, 2, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 2, + 3 ] ); }