diff --git a/src/crypto.rs b/src/crypto.rs index 9a27c68ae..35bb3b7eb 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -120,6 +120,8 @@ impl KeyPair { pub mod ec { use hash::*; + use uint::*; + use standard::*; use crypto::*; use crypto::{self}; @@ -136,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) }; @@ -165,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 b856431cd..7bfe147f9 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; @@ -74,6 +75,7 @@ pub mod semantic_version; 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;