diff --git a/src/bytes.rs b/src/bytes.rs index 21d28e87c..8c56d6bf3 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -109,25 +109,25 @@ impl BytesConvertable for Vec { } macro_rules! impl_bytes_convertable_for_array { - ($zero: expr) => (); - ($len: expr, $($idx: expr),*) => { - impl BytesConvertable for [u8; $len] { - fn bytes(&self) -> &[u8] { self } - } - impl_bytes_convertable_for_array! { $($idx),* } - } + ($zero: expr) => (); + ($len: expr, $($idx: expr),*) => { + impl BytesConvertable for [u8; $len] { + fn bytes(&self) -> &[u8] { self } + } + impl_bytes_convertable_for_array! { $($idx),* } + } } // -1 at the end is not expanded impl_bytes_convertable_for_array! { - 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 } #[test] fn bytes_convertable() { assert_eq!(vec![0x12u8, 0x34].bytes(), &[0x12u8, 0x34]); - assert_eq!([0u8; 0].bytes(), &[]); + assert_eq!([0u8; 0].bytes(), &[]); } /// Converts given type to its shortest representation in bytes diff --git a/src/crypto.rs b/src/crypto.rs index d13a53f53..35bb3b7eb 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,4 +1,6 @@ use hash::*; +use bytes::*; +use uint::*; use secp256k1::{key, Secp256k1}; use rand::os::OsRng; @@ -19,6 +21,11 @@ impl Signature { ret[64] = v; ret } + + /// Convert transaction to R, S and V components. + pub fn to_rsv(&self) -> (U256, U256, u8) { + (U256::from(&self.as_slice()[0..32]), U256::from(&self.as_slice()[32..64]), self[64]) + } } #[derive(Debug)] @@ -113,6 +120,8 @@ impl KeyPair { pub mod ec { use hash::*; + use uint::*; + use standard::*; use crypto::*; use crypto::{self}; @@ -129,6 +138,7 @@ pub mod ec { } /// Returns siganture of message hash. pub fn sign(secret: &Secret, message: &H256) -> Result { + // TODO: allow creation of only low-s signatures. use secp256k1::*; let context = Secp256k1::new(); let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) }; @@ -158,6 +168,16 @@ pub mod ec { } } + /// Check if this is a "low" signature. + pub fn is_low(sig: &Signature) -> bool { + H256::from_slice(&sig[32..64]) <= h256_from_hex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0") + } + + /// Check if this is a "low" signature. + pub fn is_low_s(s: &U256) -> bool { + s <= &U256::from_str("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0").unwrap() + } + /// Check if each component of the signature is in range. pub fn is_valid(sig: &Signature) -> bool { sig[64] <= 1 && diff --git a/src/hash.rs b/src/hash.rs index 087454ceb..5eb76a05e 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -224,16 +224,22 @@ macro_rules! impl_hash { } } - impl PartialOrd for $from { - fn partial_cmp(&self, other: &Self) -> Option { + impl Ord for $from { + fn cmp(&self, other: &Self) -> Ordering { for i in 0..$size { if self.0[i] > other.0[i] { - return Some(Ordering::Greater); + return Ordering::Greater; } else if self.0[i] < other.0[i] { - return Some(Ordering::Less); + return Ordering::Less; } } - Some(Ordering::Equal) + Ordering::Equal + } + } + + impl PartialOrd for $from { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } diff --git a/src/json_aid.rs b/src/json_aid.rs new file mode 100644 index 000000000..a382c61ec --- /dev/null +++ b/src/json_aid.rs @@ -0,0 +1,68 @@ +use common::*; + +pub fn clean(s: &str) -> &str { + if s.len() >= 2 && &s[0..2] == "0x" { + &s[2..] + } else { + s + } +} + +pub fn bytes_from_json(json: &Json) -> Bytes { + let s = json.as_string().unwrap_or(""); + if s.len() % 2 == 1 { + FromHex::from_hex(&("0".to_string() + &(clean(s).to_string()))[..]).unwrap_or(vec![]) + } else { + FromHex::from_hex(clean(s)).unwrap_or(vec![]) + } +} + +pub fn address_from_json(json: &Json) -> Address { + let s = json.as_string().unwrap_or("0000000000000000000000000000000000000000"); + if s.len() % 2 == 1 { + address_from_hex(&("0".to_string() + &(clean(s).to_string()))[..]) + } else { + address_from_hex(clean(s)) + } +} + +pub fn h256_from_json(json: &Json) -> H256 { + let s = json.as_string().unwrap_or("0000000000000000000000000000000000000000000000000000000000000000"); + if s.len() % 2 == 1 { + h256_from_hex(&("0".to_string() + &(clean(s).to_string()))[..]) + } else { + h256_from_hex(clean(s)) + } +} + +pub fn u256_from_hex(s: &str) -> U256 { + if s.len() >= 2 && &s[0..2] == "0x" { + U256::from_str(&s[2..]).unwrap_or(U256::from(0)) + } else { + U256::from_dec_str(s).unwrap_or(U256::from(0)) + } +} + +pub fn u256_from_json(json: &Json) -> U256 { + u256_from_hex(json.as_string().unwrap_or("")) +} + +pub fn usize_from_json(json: &Json) -> usize { + u256_from_json(json).low_u64() as usize +} + +pub fn u64_from_json(json: &Json) -> u64 { + u256_from_json(json).low_u64() +} + +pub fn u32_from_json(json: &Json) -> u32 { + u256_from_json(json).low_u32() +} + +pub fn u16_from_json(json: &Json) -> u16 { + u256_from_json(json).low_u32() as u16 +} + +pub fn u8_from_json(json: &Json) -> u8 { + u256_from_json(json).low_u32() as u8 +} diff --git a/src/lib.rs b/src/lib.rs index fdab5e92a..6be02ee6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,7 @@ pub mod hash; pub mod uint; pub mod bytes; pub mod rlp; +pub mod json_aid; pub mod vector; pub mod sha3; pub mod hashdb; @@ -75,6 +76,7 @@ pub mod io; pub mod network; pub use common::*; +pub use json_aid::*; pub use rlp::*; pub use hashdb::*; pub use memorydb::*; diff --git a/src/rlp/rlperrors.rs b/src/rlp/rlperrors.rs index 27b3082b5..9ea470abf 100644 --- a/src/rlp/rlperrors.rs +++ b/src/rlp/rlperrors.rs @@ -9,6 +9,9 @@ pub enum DecoderError { RlpExpectedToBeList, RlpExpectedToBeData, RlpIncorrectListLen, + RlpDataLenWithZeroPrefix, + RlpListLenWithZeroPrefix, + RlpInvalidIndirection, } impl StdError for DecoderError { diff --git a/src/rlp/untrusted_rlp.rs b/src/rlp/untrusted_rlp.rs index 452a198bb..c0e7c4cf7 100644 --- a/src/rlp/untrusted_rlp.rs +++ b/src/rlp/untrusted_rlp.rs @@ -269,6 +269,7 @@ impl<'a> BasicDecoder<'a> { Some(l @ 0xb8...0xbf) => { let len_of_len = l as usize - 0xb7; let header_len = 1 + len_of_len; + if bytes[1] == 0 { return Err(DecoderError::RlpDataLenWithZeroPrefix); } let value_len = try!(usize::from_bytes(&bytes[1..header_len])); PayloadInfo::new(header_len, value_len) } @@ -277,6 +278,7 @@ impl<'a> BasicDecoder<'a> { let len_of_len = l as usize - 0xf7; let header_len = 1 + len_of_len; let value_len = try!(usize::from_bytes(&bytes[1..header_len])); + if bytes[1] == 0 { return Err(DecoderError::RlpListLenWithZeroPrefix); } PayloadInfo::new(header_len, value_len) }, // we cant reach this place, but rust requires _ to be implemented @@ -302,7 +304,13 @@ impl<'a> Decoder for BasicDecoder<'a> { // single byt value Some(l @ 0...0x7f) => Ok(try!(f(&[l]))), // 0-55 bytes - Some(l @ 0x80...0xb7) => Ok(try!(f(&bytes[1..(1 + l as usize - 0x80)]))), + Some(l @ 0x80...0xb7) => { + let d = &bytes[1..(1 + l as usize - 0x80)]; + if l == 0x81 && d[0] < 0x80 { + return Err(DecoderError::RlpInvalidIndirection); + } + Ok(try!(f(d))) + }, // longer than 55 bytes Some(l @ 0xb8...0xbf) => { let len_of_len = l as usize - 0xb7; diff --git a/src/uint.rs b/src/uint.rs index b7411fd30..6fefbd50d 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -462,9 +462,73 @@ macro_rules! construct_uint { ); } +construct_uint!(U512, 8); construct_uint!(U256, 4); construct_uint!(U128, 2); +impl From for U512 { + fn from(value: U256) -> U512 { + let U256(ref arr) = value; + let mut ret = [0; 8]; + ret[0] = arr[0]; + ret[1] = arr[1]; + ret[2] = arr[2]; + ret[3] = arr[3]; + U512(ret) + } +} + +impl From for U256 { + fn from(value: U512) -> U256 { + let U512(ref arr) = value; + if arr[4] | arr[5] | arr[6] | arr[7] != 0 { + panic!("Overflow"); + } + let mut ret = [0; 4]; + ret[0] = arr[0]; + ret[1] = arr[1]; + ret[2] = arr[2]; + ret[3] = arr[3]; + U256(ret) + } +} + +impl From for U128 { + fn from(value: U256) -> U128 { + let U256(ref arr) = value; + if arr[2] | arr[3] != 0 { + panic!("Overflow"); + } + let mut ret = [0; 2]; + ret[0] = arr[0]; + ret[1] = arr[1]; + U128(ret) + } +} + +impl From for U128 { + fn from(value: U512) -> U128 { + let U512(ref arr) = value; + if arr[2] | arr[3] | arr[4] | arr[5] | arr[6] | arr[7] != 0 { + panic!("Overflow"); + } + let mut ret = [0; 2]; + ret[0] = arr[0]; + ret[1] = arr[1]; + U128(ret) + } +} + +impl From for U512 { + fn from(value: U128) -> U512 { + let U128(ref arr) = value; + let mut ret = [0; 8]; + ret[0] = arr[0]; + ret[1] = arr[1]; + U512(ret) + } +} + impl From for U256 { fn from(value: U128) -> U256 { let U128(ref arr) = value;