From ecd33a60931be9616245984149a46aba12457f36 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 11 Mar 2016 13:54:52 +0100 Subject: [PATCH] fixed U256 and transaction request deserialization, added tests for transaction request --- rpc/src/v1/types/bytes.rs | 2 +- rpc/src/v1/types/transaction_request.rs | 64 ++++++++++++++++++++----- util/bigint/src/uint.rs | 8 +--- util/src/hash.rs | 2 +- 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 466fbebde..0b14c30e8 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -20,7 +20,7 @@ use serde::de::Visitor; use util::common::FromHex; /// Wrapper structure around vector of bytes. -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct Bytes(Vec); impl Bytes { diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index a61b11c25..d40402ab5 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -19,7 +19,7 @@ use util::numbers::{Uint, U256}; use ethcore::transaction::{Action, Transaction}; use v1::types::Bytes; -#[derive(Debug, Default, Deserialize)] +#[derive(Debug, Default, PartialEq, Deserialize)] pub struct TransactionRequest { pub from: Address, pub to: Option
, @@ -27,28 +27,26 @@ pub struct TransactionRequest { pub gas_price: Option, pub gas: Option, pub value: Option, - pub data: Bytes, + pub data: Option, pub nonce: Option, } impl Into for TransactionRequest { fn into(self) -> Transaction { Transaction { - nonce: self.nonce.unwrap_or(U256::zero()), - action: match self.to { - None => Action::Create, - Some(addr) => Action::Call(addr) - }, - gas: self.gas.unwrap_or(U256::zero()), - gas_price: self.gas_price.unwrap_or(U256::zero()), - value: self.value.unwrap_or(U256::zero()), - data: self.data.to_vec() + nonce: self.nonce.unwrap_or_else(U256::zero), + action: self.to.map_or(Action::Create, Action::Call), + gas: self.gas.unwrap_or_else(U256::zero), + gas_price: self.gas_price.unwrap_or_else(U256::zero), + value: self.value.unwrap_or_else(U256::zero), + data: self.data.map_or_else(Vec::new, |d| d.to_vec()), } } } #[cfg(test)] mod tests { + use serde_json; use util::numbers::{Uint, U256}; use util::hash::Address; use ethcore::transaction::{Transaction, Action}; @@ -63,7 +61,7 @@ mod tests { gas_price: Some(U256::from(20)), gas: Some(U256::from(10_000)), value: Some(U256::from(1)), - data: Bytes::new(vec![10, 20]), + data: Some(Bytes::new(vec![10, 20])), nonce: Some(U256::from(12)), }; @@ -85,7 +83,7 @@ mod tests { gas_price: None, gas: None, value: None, - data: Bytes::new(vec![]), + data: None, nonce: None, }; @@ -98,4 +96,44 @@ mod tests { data: vec![], }, tr.into()); } + + #[test] + fn transaction_request_deserialize() { + let s = r#"{ + "from":"0x0000000000000000000000000000000000000001", + "to":"0x0000000000000000000000000000000000000002", + "gasPrice":"0x1", + "gas":"0x2", + "value":"0x3", + "data":"0x123456", + "nonce":"0x4" + }"#; + let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); + + assert_eq!(deserialized, TransactionRequest { + from: Address::from(1), + to: Some(Address::from(2)), + gas_price: Some(U256::from(1)), + gas: Some(U256::from(2)), + value: Some(U256::from(3)), + data: Some(Bytes::new(vec![0x12, 0x34, 0x56])), + nonce: Some(U256::from(4)), + }); + } + + #[test] + fn transaction_request_deserialize_empty() { + let s = r#"{"from":"0x0000000000000000000000000000000000000001"}"#; + let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); + + assert_eq!(deserialized, TransactionRequest { + from: Address::from(1), + to: None, + gas_price: None, + gas: None, + value: None, + data: None, + nonce: None, + }); + } } diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index 959df0944..47888fd88 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -39,7 +39,6 @@ use std::fmt; use std::cmp; -use std::mem; use std::str::{FromStr}; use std::convert::From; use std::hash::{Hash, Hasher}; @@ -788,14 +787,11 @@ macro_rules! construct_uint { fn visit_str(&mut self, value: &str) -> Result where E: serde::Error { // 0x + len - if value.len() != 2 + $n_words / 8 { + if value.len() > 2 + $n_words * 16 { return Err(serde::Error::custom("Invalid length.")); } - match $name::from_str(&value[2..]) { - Ok(val) => Ok(val), - Err(_) => { return Err(serde::Error::custom("Invalid length.")); } - } + $name::from_str(&value[2..]).map_err(|_| serde::Error::custom("Invalid hex value.")) } fn visit_string(&mut self, value: String) -> Result where E: serde::Error { diff --git a/util/src/hash.rs b/util/src/hash.rs index 4eb96b53e..3dc15116d 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -257,7 +257,7 @@ macro_rules! impl_hash { return Err(serde::Error::custom("Invalid length.")); } - value[2..].from_hex().map(|ref v| $from::from_slice(v)).map_err(|_| serde::Error::custom("Invalid valid hex.")) + value[2..].from_hex().map(|ref v| $from::from_slice(v)).map_err(|_| serde::Error::custom("Invalid hex value.")) } fn visit_string(&mut self, value: String) -> Result where E: serde::Error {