From 635bf284b4e63552fdc6037b15cdff74fa81fbd5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 12 Jan 2016 23:44:30 +0100 Subject: [PATCH] Fix RLP on consensus. Add JSON helpers. --- src/crypto.rs | 13 ++++++++ src/json_aid.rs | 65 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/rlp/rlperrors.rs | 3 ++ src/rlp/untrusted_rlp.rs | 10 ++++++- 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/json_aid.rs 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/json_aid.rs b/src/json_aid.rs new file mode 100644 index 000000000..ccfdee490 --- /dev/null +++ b/src/json_aid.rs @@ -0,0 +1,65 @@ +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_json(json: &Json) -> U256 { + let s = json.as_string().unwrap_or(""); + 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 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;