fixed U256 and transaction request deserialization, added tests for transaction request

This commit is contained in:
debris 2016-03-11 13:54:52 +01:00
parent d1fa292956
commit ecd33a6093
4 changed files with 55 additions and 21 deletions

View File

@ -20,7 +20,7 @@ use serde::de::Visitor;
use util::common::FromHex; use util::common::FromHex;
/// Wrapper structure around vector of bytes. /// Wrapper structure around vector of bytes.
#[derive(Debug)] #[derive(Debug, PartialEq)]
pub struct Bytes(Vec<u8>); pub struct Bytes(Vec<u8>);
impl Bytes { impl Bytes {

View File

@ -19,7 +19,7 @@ use util::numbers::{Uint, U256};
use ethcore::transaction::{Action, Transaction}; use ethcore::transaction::{Action, Transaction};
use v1::types::Bytes; use v1::types::Bytes;
#[derive(Debug, Default, Deserialize)] #[derive(Debug, Default, PartialEq, Deserialize)]
pub struct TransactionRequest { pub struct TransactionRequest {
pub from: Address, pub from: Address,
pub to: Option<Address>, pub to: Option<Address>,
@ -27,28 +27,26 @@ pub struct TransactionRequest {
pub gas_price: Option<U256>, pub gas_price: Option<U256>,
pub gas: Option<U256>, pub gas: Option<U256>,
pub value: Option<U256>, pub value: Option<U256>,
pub data: Bytes, pub data: Option<Bytes>,
pub nonce: Option<U256>, pub nonce: Option<U256>,
} }
impl Into<Transaction> for TransactionRequest { impl Into<Transaction> for TransactionRequest {
fn into(self) -> Transaction { fn into(self) -> Transaction {
Transaction { Transaction {
nonce: self.nonce.unwrap_or(U256::zero()), nonce: self.nonce.unwrap_or_else(U256::zero),
action: match self.to { action: self.to.map_or(Action::Create, Action::Call),
None => Action::Create, gas: self.gas.unwrap_or_else(U256::zero),
Some(addr) => Action::Call(addr) gas_price: self.gas_price.unwrap_or_else(U256::zero),
}, value: self.value.unwrap_or_else(U256::zero),
gas: self.gas.unwrap_or(U256::zero()), data: self.data.map_or_else(Vec::new, |d| d.to_vec()),
gas_price: self.gas_price.unwrap_or(U256::zero()),
value: self.value.unwrap_or(U256::zero()),
data: self.data.to_vec()
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde_json;
use util::numbers::{Uint, U256}; use util::numbers::{Uint, U256};
use util::hash::Address; use util::hash::Address;
use ethcore::transaction::{Transaction, Action}; use ethcore::transaction::{Transaction, Action};
@ -63,7 +61,7 @@ mod tests {
gas_price: Some(U256::from(20)), gas_price: Some(U256::from(20)),
gas: Some(U256::from(10_000)), gas: Some(U256::from(10_000)),
value: Some(U256::from(1)), value: Some(U256::from(1)),
data: Bytes::new(vec![10, 20]), data: Some(Bytes::new(vec![10, 20])),
nonce: Some(U256::from(12)), nonce: Some(U256::from(12)),
}; };
@ -85,7 +83,7 @@ mod tests {
gas_price: None, gas_price: None,
gas: None, gas: None,
value: None, value: None,
data: Bytes::new(vec![]), data: None,
nonce: None, nonce: None,
}; };
@ -98,4 +96,44 @@ mod tests {
data: vec![], data: vec![],
}, tr.into()); }, 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,
});
}
} }

View File

@ -39,7 +39,6 @@
use std::fmt; use std::fmt;
use std::cmp; use std::cmp;
use std::mem;
use std::str::{FromStr}; use std::str::{FromStr};
use std::convert::From; use std::convert::From;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -788,14 +787,11 @@ macro_rules! construct_uint {
fn visit_str<E>(&mut self, value: &str) -> Result<Self::Value, E> where E: serde::Error { fn visit_str<E>(&mut self, value: &str) -> Result<Self::Value, E> where E: serde::Error {
// 0x + len // 0x + len
if value.len() != 2 + $n_words / 8 { if value.len() > 2 + $n_words * 16 {
return Err(serde::Error::custom("Invalid length.")); return Err(serde::Error::custom("Invalid length."));
} }
match $name::from_str(&value[2..]) { $name::from_str(&value[2..]).map_err(|_| serde::Error::custom("Invalid hex value."))
Ok(val) => Ok(val),
Err(_) => { return Err(serde::Error::custom("Invalid length.")); }
}
} }
fn visit_string<E>(&mut self, value: String) -> Result<Self::Value, E> where E: serde::Error { fn visit_string<E>(&mut self, value: String) -> Result<Self::Value, E> where E: serde::Error {

View File

@ -257,7 +257,7 @@ macro_rules! impl_hash {
return Err(serde::Error::custom("Invalid length.")); 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<E>(&mut self, value: String) -> Result<Self::Value, E> where E: serde::Error { fn visit_string<E>(&mut self, value: String) -> Result<Self::Value, E> where E: serde::Error {