diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index ca54f26bb..2953ff896 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -16,13 +16,21 @@ //! Transaction data structure. -use util::*; +use util::numbers::*; +use std::ops::Deref; +use util::rlp::*; +use util::sha3::*; +use util::{UtilError, CryptoError, Bytes, HeapSizeOf, Signature, Secret, ec}; +use std::cell::*; use error::*; use evm::Schedule; use header::BlockNumber; use ethjson; +use ipc::binary::BinaryConvertError; +use std::mem; +use std::collections::VecDeque; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Binary)] /// Transaction action type. pub enum Action { /// Create creates new contract. @@ -48,7 +56,7 @@ impl Decodable for Action { /// A set of information describing an externally-originating message call /// or contract creation operation. -#[derive(Default, Debug, Clone, PartialEq, Eq)] +#[derive(Default, Debug, Clone, PartialEq, Eq, Binary)] pub struct Transaction { /// Nonce. pub nonce: U256, @@ -183,7 +191,7 @@ impl Transaction { } /// Signed transaction information. -#[derive(Debug, Clone, Eq)] +#[derive(Debug, Clone, Eq, Binary)] pub struct SignedTransaction { /// Plain Transaction. unsigned: Transaction, diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 6a9784790..cf8857325 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -175,6 +175,11 @@ fn binary_expr_struct( ) -> Result { let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { + + if ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)) == "u8" { + return quote_expr!(cx, 1); + } + let field_type_ident = builder.id( &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); @@ -228,23 +233,34 @@ fn binary_expr_struct( }, }; - write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident_qualified::len_params() { - 0 => mem::size_of::<$field_type_ident>(), - _ => { let size = $member_expr .size(); length_stack.push_back(size); size }, - }).unwrap()); - - write_stmts.push(quote_stmt!(cx, - if let Err(e) = $member_expr .to_bytes(&mut buffer[offset..next_line], length_stack) { return Err(e) };).unwrap()); + if ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)) == "u8" { + write_stmts.push(quote_stmt!(cx, let next_line = offset + 1;).unwrap()); + write_stmts.push(quote_stmt!(cx, buffer[offset] = $member_expr; ).unwrap()); + } + else { + write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident_qualified::len_params() { + 0 => mem::size_of::<$field_type_ident>(), + _ => { let size = $member_expr .size(); length_stack.push_back(size); size }, + }).unwrap()); + write_stmts.push(quote_stmt!(cx, + if let Err(e) = $member_expr .to_bytes(&mut buffer[offset..next_line], length_stack) { return Err(e) };).unwrap()); + } write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); let field_index = builder.id(&format!("{}", index)); map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); - map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident_qualified::len_params() { - 0 => mem::size_of::<$field_type_ident>(), - _ => length_stack.pop_front().unwrap(), - }).unwrap()); - map_stmts.push(quote_stmt!(cx, total = total + size;).unwrap()); + + if ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)) == "u8" { + map_stmts.push(quote_stmt!(cx, total = total + 1;).unwrap()); + } + else { + map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident_qualified::len_params() { + 0 => mem::size_of::<$field_type_ident>(), + _ => length_stack.pop_front().unwrap(), + }).unwrap()); + map_stmts.push(quote_stmt!(cx, total = total + size;).unwrap()); + } }; let read_expr = match fields.iter().any(|f| codegen::has_ptr(&f.ty)) { @@ -381,6 +397,21 @@ fn fields_sequence( tt.push(Token(_sp, token::Colon)); } + // special case for u8, it just takes byte form sequence + if ::syntax::print::pprust::ty_to_string(&field.ty) == "u8" { + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); + + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + + tt.push(Token(_sp, token::Comma)); + continue; + } + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!")))); tt.push(Token(_sp, token::OpenDelim(token::Paren))); tt.push( @@ -393,6 +424,7 @@ fn fields_sequence( tt.push(Token(_sp, token::OpenDelim(token::Paren))); tt.push(Token(_sp, token::BinOp(token::And))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); tt.push(Token(_sp, token::OpenDelim(token::Bracket))); @@ -455,6 +487,21 @@ fn named_fields_sequence( tt.push(Token(_sp, token::Ident(field.ident.clone().unwrap()))); tt.push(Token(_sp, token::Colon)); + // special case for u8, it just takes byte form sequence + if ::syntax::print::pprust::ty_to_string(&field.ty) == "u8" { + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); + + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); + tt.push(Token(_sp, token::OpenDelim(token::Bracket))); + tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + tt.push(Token(_sp, token::CloseDelim(token::Bracket))); + + tt.push(Token(_sp, token::Comma)); + continue; + } + tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!")))); tt.push(Token(_sp, token::OpenDelim(token::Paren))); tt.push(Token( diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index 67a3d37e2..2d2bd21b7 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -233,6 +233,29 @@ impl BinaryConvertable for ::std::cell::RefCell where T: BinaryConvertable } } +impl BinaryConvertable for ::std::cell::Cell where T: BinaryConvertable + Copy { + fn size(&self) -> usize { + self.get().size() + } + + fn from_empty_bytes() -> Result { + Ok(::std::cell::Cell::new(try!(T::from_empty_bytes()))) + } + + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { + Ok(::std::cell::Cell::new(try!(T::from_bytes(buffer, length_stack)))) + } + + fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + try!(self.get().to_bytes(buffer, length_stack)); + Ok(()) + } + + fn len_params() -> usize { + T::len_params() + } +} + impl BinaryConvertable for Vec { fn size(&self) -> usize { self.len()