diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index 4c023fbe4..5488e2715 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -778,7 +778,7 @@ impl Body { pub fn check_response(&self, cache: &Mutex<::cache::Cache>, body: &encoded::Body) -> Result { // check the integrity of the the body against the header let header = self.0.as_ref()?; - let tx_root = ::triehash::ordered_trie_root(body.rlp().at(0).iter().map(|r| r.as_raw().to_vec())); + let tx_root = ::triehash::ordered_trie_root(body.rlp().at(0).iter().map(|r| r.as_raw())); if tx_root != header.transactions_root() { return Err(Error::WrongTrieRoot(header.transactions_root(), tx_root)); } @@ -808,7 +808,7 @@ impl BlockReceipts { /// Check a response with receipts against the stored header. pub fn check_response(&self, cache: &Mutex<::cache::Cache>, receipts: &[Receipt]) -> Result, Error> { let receipts_root = self.0.as_ref()?.receipts_root(); - let found_root = ::triehash::ordered_trie_root(receipts.iter().map(|r| ::rlp::encode(r).into_vec())); + let found_root = ::triehash::ordered_trie_root(receipts.iter().map(|r| ::rlp::encode(r))); match receipts_root == found_root { true => { @@ -1028,7 +1028,7 @@ mod tests { let mut header = Header::new(); let receipts_root = ::triehash::ordered_trie_root( - receipts.iter().map(|x| ::rlp::encode(x).into_vec()) + receipts.iter().map(|x| ::rlp::encode(x)) ); header.set_receipts_root(receipts_root); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 329a1c328..cd78230b5 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -447,11 +447,11 @@ impl<'x> OpenBlock<'x> { if let Err(e) = s.block.state.commit() { warn!("Encountered error on state commit: {}", e); } - s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); + s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes()))); let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); s.block.header.set_uncles_hash(keccak(&uncle_bytes)); s.block.header.set_state_root(s.block.state.root().clone()); - s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().into_vec()))); + s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes()))); s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator s.block.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used)); @@ -474,14 +474,14 @@ impl<'x> OpenBlock<'x> { warn!("Encountered error on state commit: {}", e); } if s.block.header.transactions_root().is_zero() || s.block.header.transactions_root() == &KECCAK_NULL_RLP { - s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); + s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes()))); } let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); if s.block.header.uncles_hash().is_zero() || s.block.header.uncles_hash() == &KECCAK_EMPTY_LIST_RLP { s.block.header.set_uncles_hash(keccak(&uncle_bytes)); } if s.block.header.receipts_root().is_zero() || s.block.header.receipts_root() == &KECCAK_NULL_RLP { - s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().into_vec()))); + s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes()))); } s.block.header.set_state_root(s.block.state.root().clone()); @@ -577,7 +577,7 @@ impl LockedBlock { for receipt in &mut block.block.receipts { receipt.outcome = TransactionOutcome::Unknown; } - block.block.header.set_receipts_root(ordered_trie_root(block.block.receipts.iter().map(|r| r.rlp_bytes().into_vec()))); + block.block.header.set_receipts_root(ordered_trie_root(block.block.receipts.iter().map(|r| r.rlp_bytes()))); block } } diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index 07edf5f88..7093ab896 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -378,7 +378,7 @@ impl ValidatorSet for ValidatorSafeContract { // ensure receipts match header. // TODO: optimize? these were just decoded. let found_root = ::triehash::ordered_trie_root( - receipts.iter().map(::rlp::encode).map(|x| x.to_vec()) + receipts.iter().map(::rlp::encode) ); if found_root != *old_header.receipts_root() { return Err(::error::BlockError::InvalidReceiptsRoot( diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 0f3819407..7af9fbc06 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -65,7 +65,7 @@ impl PodAccount { let mut stream = RlpStream::new_list(4); stream.append(&self.nonce); stream.append(&self.balance); - stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), rlp::encode(&U256::from(&**v)).to_vec())).collect())); + stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k, rlp::encode(&U256::from(&**v)))))); stream.append(&keccak(&self.code.as_ref().unwrap_or(&vec![]))); stream.out() } diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index 9c468ebe0..f626c72d7 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -41,7 +41,7 @@ impl PodState { /// Get the root hash of the trie of the RLP of this. pub fn root(&self) -> H256 { - sec_trie_root(self.0.iter().map(|(k, v)| (k.to_vec(), v.rlp())).collect()) + sec_trie_root(self.0.iter().map(|(k, v)| (k, v.rlp()))) } /// Drain object to get the underlying map. diff --git a/ethcore/src/snapshot/block.rs b/ethcore/src/snapshot/block.rs index d503a57bb..98215b324 100644 --- a/ethcore/src/snapshot/block.rs +++ b/ethcore/src/snapshot/block.rs @@ -107,7 +107,7 @@ impl AbridgedBlock { let uncles: Vec
= rlp.list_at(9)?; header.set_transactions_root(ordered_trie_root( - rlp.at(8)?.iter().map(|r| r.as_raw().to_owned()) + rlp.at(8)?.iter().map(|r| r.as_raw()) )); header.set_receipts_root(receipts_root); @@ -194,7 +194,7 @@ mod tests { let receipts_root = b.header.receipts_root().clone(); b.header.set_transactions_root(::triehash::ordered_trie_root( - b.transactions.iter().map(::rlp::encode).map(|out| out.into_vec()) + b.transactions.iter().map(::rlp::encode) )); let encoded = encode_block(&b); diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index 2c3b89d98..bfb213091 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -249,7 +249,7 @@ impl Rebuilder for PowRebuilder { let abridged_block = AbridgedBlock::from_raw(abridged_rlp); let receipts: Vec<::receipt::Receipt> = pair.list_at(1)?; let receipts_root = ordered_trie_root( - pair.at(1)?.iter().map(|r| r.as_raw().to_owned()) + pair.at(1)?.iter().map(|r| r.as_raw()) ); let block = abridged_block.to_block(parent_hash, cur_number, receipts_root)?; diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 6a7c2c788..10cd3f6cb 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -320,7 +320,7 @@ fn verify_parent(header: &Header, parent: &Header, gas_limit_divisor: U256) -> R fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: &H256) -> Result<(), Error> { let block = UntrustedRlp::new(block); let tx = block.at(1)?; - let expected_root = &ordered_trie_root(tx.iter().map(|r| r.as_raw().to_vec())); //TODO: get rid of vectors here + let expected_root = &ordered_trie_root(tx.iter().map(|r| r.as_raw())); if expected_root != transactions_root { return Err(From::from(BlockError::InvalidTransactionsRoot(Mismatch { expected: expected_root.clone(), found: transactions_root.clone() }))) } @@ -570,7 +570,7 @@ mod tests { let mut uncles_rlp = RlpStream::new(); uncles_rlp.append_list(&good_uncles); let good_uncles_hash = keccak(uncles_rlp.as_raw()); - let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| ::rlp::encode::(t).into_vec())); + let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| ::rlp::encode::(t))); let mut parent = good.clone(); parent.set_number(9); diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index 7ce426f59..65244a4e7 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -345,7 +345,7 @@ impl BlockCollection { let header_id = { let body = UntrustedRlp::new(&b); let tx = body.at(0)?; - let tx_root = ordered_trie_root(tx.iter().map(|r| r.as_raw().to_vec())); //TODO: get rid of vectors here + let tx_root = ordered_trie_root(tx.iter().map(|r| r.as_raw())); let uncles = keccak(body.at(1)?.as_raw()); HeaderId { transactions_root: tx_root, @@ -379,7 +379,7 @@ impl BlockCollection { fn insert_receipt(&mut self, r: Bytes) -> Result<(), network::Error> { let receipt_root = { let receipts = UntrustedRlp::new(&r); - ordered_trie_root(receipts.iter().map(|r| r.as_raw().to_vec())) //TODO: get rid of vectors here + ordered_trie_root(receipts.iter().map(|r| r.as_raw())) }; self.downloading_receipts.remove(&receipt_root); match self.receipt_ids.entry(receipt_root) { diff --git a/util/triehash/src/lib.rs b/util/triehash/src/lib.rs index 13ed4919c..e958e82b1 100644 --- a/util/triehash/src/lib.rs +++ b/util/triehash/src/lib.rs @@ -40,27 +40,28 @@ fn shared_prefix_len(first: &[T], second: &[T]) -> usize { /// use triehash::ordered_trie_root; /// /// fn main() { -/// let v = vec![From::from("doe"), From::from("reindeer")]; +/// let v = &["doe", "reindeer"]; /// let root = "e766d5d51b89dc39d981b41bda63248d7abce4f0225eefd023792a540bcffee3"; -/// assert_eq!(ordered_trie_root(v), root.parse().unwrap()); +/// assert_eq!(ordered_trie_root(v), root.into()); /// } /// ``` -pub fn ordered_trie_root(input: I) -> H256 - where I: IntoIterator> +pub fn ordered_trie_root(input: I) -> H256 + where I: IntoIterator, + A: AsRef<[u8]>, { - let gen_input = input + let gen_input: Vec<_> = input // first put elements into btree to sort them by nibbles // optimize it later .into_iter() .enumerate() - .map(|(i, vec)| (rlp::encode(&i).into_vec(), vec)) + .map(|(i, slice)| (rlp::encode(&i), slice)) .collect::>() // then move them to a vector .into_iter() .map(|(k, v)| (as_nibbles(&k), v) ) .collect(); - gen_trie_root(gen_input) + gen_trie_root(&gen_input) } /// Generates a trie root hash for a vector of key-values @@ -71,28 +72,30 @@ pub fn ordered_trie_root(input: I) -> H256 /// /// fn main() { /// let v = vec![ -/// (From::from("doe"), From::from("reindeer")), -/// (From::from("dog"), From::from("puppy")), -/// (From::from("dogglesworth"), From::from("cat")), +/// ("doe", "reindeer"), +/// ("dog", "puppy"), +/// ("dogglesworth", "cat"), /// ]; /// /// let root = "8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3"; -/// assert_eq!(trie_root(v), root.parse().unwrap()); +/// assert_eq!(trie_root(v), root.into()); /// } /// ``` -pub fn trie_root(input: I) -> H256 - where I: IntoIterator, Vec)> +pub fn trie_root(input: I) -> H256 + where I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, { - let gen_input = input + let gen_input: Vec<_> = input // first put elements into btree to sort them and to remove duplicates .into_iter() .collect::>() // then move them to a vector .into_iter() - .map(|(k, v)| (as_nibbles(&k), v) ) + .map(|(k, v)| (as_nibbles(k.as_ref()), v) ) .collect(); - gen_trie_root(gen_input) + gen_trie_root(&gen_input) } /// Generates a key-hashed (secure) trie root hash for a vector of key-values. @@ -103,17 +106,21 @@ pub fn trie_root(input: I) -> H256 /// /// fn main() { /// let v = vec![ -/// (From::from("doe"), From::from("reindeer")), -/// (From::from("dog"), From::from("puppy")), -/// (From::from("dogglesworth"), From::from("cat")), +/// ("doe", "reindeer"), +/// ("dog", "puppy"), +/// ("dogglesworth", "cat"), /// ]; /// /// let root = "d4cd937e4a4368d7931a9cf51686b7e10abb3dce38a39000fd7902a092b64585"; -/// assert_eq!(sec_trie_root(v), root.parse().unwrap()); +/// assert_eq!(sec_trie_root(v), root.into()); /// } /// ``` -pub fn sec_trie_root(input: Vec<(Vec, Vec)>) -> H256 { - let gen_input = input +pub fn sec_trie_root(input: I) -> H256 + where I: IntoIterator, + A: AsRef<[u8]>, + B: AsRef<[u8]>, +{ + let gen_input: Vec<_> = input // first put elements into btree to sort them and to remove duplicates .into_iter() .map(|(k, v)| (keccak(k), v)) @@ -123,12 +130,12 @@ pub fn sec_trie_root(input: Vec<(Vec, Vec)>) -> H256 { .map(|(k, v)| (as_nibbles(&k), v) ) .collect(); - gen_trie_root(gen_input) + gen_trie_root(&gen_input) } -fn gen_trie_root(input: Vec<(Vec, Vec)>) -> H256 { +fn gen_trie_root, B: AsRef<[u8]>>(input: &[(A, B)]) -> H256 { let mut stream = RlpStream::new(); - hash256rlp(&input, 0, &mut stream); + hash256rlp(input, 0, &mut stream); keccak(stream.out()) } @@ -189,7 +196,7 @@ fn as_nibbles(bytes: &[u8]) -> Vec { res } -fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStream) { +fn hash256rlp, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) { let inlen = input.len(); // in case of empty slice, just append empty data @@ -199,8 +206,8 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre } // take slices - let key: &[u8] = &input[0].0; - let value: &[u8] = &input[0].1; + let key: &[u8] = &input[0].0.as_ref(); + let value: &[u8] = &input[0].1.as_ref(); // if the slice contains just one item, append the suffix of the key // and then append value @@ -217,7 +224,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre .skip(1) // get minimum number of shared nibbles between first and each successive .fold(key.len(), | acc, &(ref k, _) | { - cmp::min(shared_prefix_len(key, k), acc) + cmp::min(shared_prefix_len(key, k.as_ref()), acc) }); // if shared prefix is higher than current prefix append its @@ -245,7 +252,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // cout how many successive elements have same next nibble let len = match begin < input.len() { true => input[begin..].iter() - .take_while(| pair | pair.0[pre_len] == i ) + .take_while(| pair | pair.0.as_ref()[pre_len] == i ) .count(), false => 0 }; @@ -266,7 +273,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre }; } -fn hash256aux(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStream) { +fn hash256aux, B: AsRef<[u8]>>(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) { let mut s = RlpStream::new(); hash256rlp(input, pre_len, &mut s); let out = s.out(); @@ -330,8 +337,8 @@ mod tests { #[test] fn simple_test() { assert_eq!(trie_root(vec![ - (b"A".to_vec(), b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_vec()) - ]), "d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab".parse().unwrap()); + (b"A", b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" as &[u8]) + ]), "d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab".into()); } #[test]