rlp deserialization refactor, 30% faster (#4901)
* fixed naming of rlp modules * RlpStream cleanup * appending short rlp lists (0...55 bytes) is 25% faster * RlpStream does not use bytes module, nor trait Stream * removed unused code from rlp module * compiling ethcore-util with new rlp serialization * compiling parity with new rlp serialization * fixed compiling ethcore-light with new rlp serialization * fixed compiling ethsync with new rlp serialization * moved rlp benches and rlp tests * rlp deserialization refactor, 30% faster * removed redundant comment, print * fixed compiling parity with new rlp deserialization * removed redundant double-space * fixed failing test * updated rlp docs, removed unused traits * fixed rlp benchmarks * replace usage of WriteBytesExt with ByteOrder * removed unused, commented out code * fixed merge conflict
This commit is contained in:
parent
b6f9cf4ba7
commit
044d070667
@ -23,7 +23,7 @@
|
||||
use ethcore::ids::BlockId;
|
||||
use util::{Bytes, H256, U256, HashDB, MemoryDB};
|
||||
use util::trie::{self, TrieMut, TrieDBMut, Trie, TrieDB, Recorder};
|
||||
use rlp::{RlpStream, UntrustedRlp, View};
|
||||
use rlp::{RlpStream, UntrustedRlp};
|
||||
|
||||
// encode a key.
|
||||
macro_rules! key {
|
||||
|
@ -24,7 +24,7 @@ use ethcore::receipt::Receipt;
|
||||
|
||||
use io::TimerToken;
|
||||
use network::{NetworkProtocolHandler, NetworkContext, PeerId};
|
||||
use rlp::{RlpStream, UntrustedRlp, View};
|
||||
use rlp::{RlpStream, UntrustedRlp};
|
||||
use util::hash::H256;
|
||||
use util::{Bytes, DBValue, Mutex, RwLock, U256};
|
||||
use time::{Duration, SteadyTime};
|
||||
@ -953,7 +953,7 @@ impl LightProtocol {
|
||||
let id_guard = self.pre_verify_response(peer, request::Kind::Receipts, &raw)?;
|
||||
let raw_receipts: Vec<Vec<Receipt>> = raw.at(2)?
|
||||
.iter()
|
||||
.map(|x| x.as_val())
|
||||
.map(|x| x.as_list())
|
||||
.collect::<Result<_,_>>()?;
|
||||
|
||||
let req_id = id_guard.defuse();
|
||||
|
@ -126,10 +126,8 @@ impl Encodable for CostTable {
|
||||
}
|
||||
}
|
||||
|
||||
impl RlpDecodable for CostTable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let rlp = decoder.as_rlp();
|
||||
|
||||
impl Decodable for CostTable {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let mut headers = None;
|
||||
let mut bodies = None;
|
||||
let mut receipts = None;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! Peer status and capabilities.
|
||||
|
||||
use rlp::{DecoderError, RlpDecodable, Encodable, RlpStream, UntrustedRlp, View};
|
||||
use rlp::{DecoderError, Encodable, Decodable, RlpStream, UntrustedRlp};
|
||||
use util::{H256, U256};
|
||||
|
||||
use super::request_credits::FlowParams;
|
||||
@ -91,7 +91,7 @@ struct Parser<'a> {
|
||||
impl<'a> Parser<'a> {
|
||||
// expect a specific next key, and decode the value.
|
||||
// error on unexpected key or invalid value.
|
||||
fn expect<T: RlpDecodable>(&mut self, key: Key) -> Result<T, DecoderError> {
|
||||
fn expect<T: Decodable>(&mut self, key: Key) -> Result<T, DecoderError> {
|
||||
self.expect_raw(key).and_then(|item| item.as_val())
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
// get the next key and value RLP.
|
||||
fn get_next(&mut self) -> Result<Option<(Key, UntrustedRlp<'a>)>, DecoderError> {
|
||||
while self.pos < self.rlp.item_count() {
|
||||
while self.pos < self.rlp.item_count()? {
|
||||
let pair = self.rlp.at(self.pos)?;
|
||||
let k: String = pair.val_at(0)?;
|
||||
|
||||
@ -374,7 +374,7 @@ mod tests {
|
||||
use super::*;
|
||||
use super::super::request_credits::FlowParams;
|
||||
use util::{U256, H256};
|
||||
use rlp::{RlpStream, UntrustedRlp, View};
|
||||
use rlp::{RlpStream, UntrustedRlp};
|
||||
|
||||
#[test]
|
||||
fn full_handshake() {
|
||||
@ -474,7 +474,7 @@ mod tests {
|
||||
let handshake = write_handshake(&status, &capabilities, Some(&flow_params));
|
||||
let interleaved = {
|
||||
let handshake = UntrustedRlp::new(&handshake);
|
||||
let mut stream = RlpStream::new_list(handshake.item_count() * 3);
|
||||
let mut stream = RlpStream::new_list(handshake.item_count().unwrap_or(0) * 3);
|
||||
|
||||
for item in handshake.iter() {
|
||||
stream.append_raw(item.as_raw(), 1);
|
||||
|
@ -26,7 +26,7 @@ use ethcore::receipt::Receipt;
|
||||
use ethcore::state::{self, ProvedExecution};
|
||||
use ethcore::transaction::SignedTransaction;
|
||||
|
||||
use rlp::{RlpStream, UntrustedRlp, View};
|
||||
use rlp::{RlpStream, UntrustedRlp};
|
||||
use util::{Address, Bytes, DBValue, HashDB, H256, U256};
|
||||
use util::memorydb::MemoryDB;
|
||||
use util::sha3::Hashable;
|
||||
|
@ -20,7 +20,7 @@ use std::cmp;
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, Decoder, DecoderError, View};
|
||||
use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError};
|
||||
use util::{Bytes, Address, Uint, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RLP};
|
||||
use util::error::{Mismatch, OutOfBounds};
|
||||
|
||||
@ -67,18 +67,17 @@ impl Block {
|
||||
|
||||
|
||||
impl Decodable for Block {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
if decoder.as_raw().len() != decoder.as_rlp().payload_info()?.total() {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
if rlp.as_raw().len() != rlp.payload_info()?.total() {
|
||||
return Err(DecoderError::RlpIsTooBig);
|
||||
}
|
||||
let d = decoder.as_rlp();
|
||||
if d.item_count() != 3 {
|
||||
if rlp.item_count()? != 3 {
|
||||
return Err(DecoderError::RlpIncorrectListLen);
|
||||
}
|
||||
Ok(Block {
|
||||
header: d.val_at(0)?,
|
||||
transactions: d.val_at(1)?,
|
||||
uncles: d.val_at(2)?,
|
||||
header: rlp.val_at(0)?,
|
||||
transactions: rlp.list_at(1)?,
|
||||
uncles: rlp.list_at(2)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -154,13 +154,12 @@ impl HeapSizeOf for BlockDetails {
|
||||
}
|
||||
|
||||
impl Decodable for BlockDetails {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let details = BlockDetails {
|
||||
number: d.val_at(0)?,
|
||||
total_difficulty: d.val_at(1)?,
|
||||
parent: d.val_at(2)?,
|
||||
children: d.val_at(3)?,
|
||||
number: rlp.val_at(0)?,
|
||||
total_difficulty: rlp.val_at(1)?,
|
||||
parent: rlp.val_at(2)?,
|
||||
children: rlp.list_at(3)?,
|
||||
};
|
||||
Ok(details)
|
||||
}
|
||||
@ -190,11 +189,10 @@ impl HeapSizeOf for TransactionAddress {
|
||||
}
|
||||
|
||||
impl Decodable for TransactionAddress {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let tx_address = TransactionAddress {
|
||||
block_hash: d.val_at(0)?,
|
||||
index: d.val_at(1)?,
|
||||
block_hash: rlp.val_at(0)?,
|
||||
index: rlp.val_at(1)?,
|
||||
};
|
||||
|
||||
Ok(tx_address)
|
||||
@ -224,9 +222,9 @@ impl BlockReceipts {
|
||||
}
|
||||
|
||||
impl Decodable for BlockReceipts {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(BlockReceipts {
|
||||
receipts: Decodable::decode(decoder)?
|
||||
receipts: rlp.as_list()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ impl Into<bc::Bloom> for Bloom {
|
||||
}
|
||||
|
||||
impl Decodable for Bloom {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
Decodable::decode(decoder).map(Bloom)
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
LogBloom::decode(rlp).map(Bloom)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,8 @@ impl Into<bc::BloomGroup> for BloomGroup {
|
||||
}
|
||||
|
||||
impl Decodable for BloomGroup {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let blooms = Decodable::decode(decoder)?;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let blooms = rlp.as_list()?;
|
||||
let group = BloomGroup {
|
||||
blooms: blooms
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ use evm::{Factory as EvmFactory, Schedule};
|
||||
use miner::{Miner, MinerService, TransactionImportResult};
|
||||
use snapshot::{self, io as snapshot_io};
|
||||
use factory::Factories;
|
||||
use rlp::{View, UntrustedRlp};
|
||||
use rlp::UntrustedRlp;
|
||||
use state_db::StateDB;
|
||||
use rand::OsRng;
|
||||
use client::registry::Registry;
|
||||
@ -539,7 +539,7 @@ impl Client {
|
||||
)?;
|
||||
|
||||
// Commit results
|
||||
let receipts = ::rlp::decode(&receipts_bytes);
|
||||
let receipts = ::rlp::decode_list(&receipts_bytes);
|
||||
let mut batch = DBTransaction::new();
|
||||
chain.insert_unordered_block(&mut batch, &block_bytes, receipts, None, false, true);
|
||||
// Final commit to the DB
|
||||
|
@ -21,7 +21,7 @@ use std::sync::Weak;
|
||||
use std::time::{UNIX_EPOCH, Duration};
|
||||
use util::*;
|
||||
use ethkey::{verify_address, Signature};
|
||||
use rlp::{UntrustedRlp, View, encode};
|
||||
use rlp::{UntrustedRlp, encode};
|
||||
use account_provider::AccountProvider;
|
||||
use block::*;
|
||||
use spec::CommonParams;
|
||||
|
@ -138,7 +138,7 @@ impl Engine for BasicAuthority {
|
||||
}
|
||||
|
||||
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
// Check if the signature belongs to a validator, can depend on parent state.
|
||||
let sig = UntrustedRlp::new(&header.seal()[0]).as_val::<H520>()?;
|
||||
let signer = public_to_address(&recover(&sig.into(), &header.bare_hash())?);
|
||||
|
@ -20,7 +20,7 @@ use util::*;
|
||||
use super::{Height, View, BlockHash, Step};
|
||||
use error::Error;
|
||||
use header::Header;
|
||||
use rlp::{Rlp, UntrustedRlp, RlpStream, Encodable, Decodable, Decoder, DecoderError, View as RlpView};
|
||||
use rlp::{Rlp, UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError};
|
||||
use ethkey::{recover, public_to_address};
|
||||
use super::super::vote_collector::Message;
|
||||
|
||||
@ -150,8 +150,8 @@ impl Step {
|
||||
}
|
||||
|
||||
impl Decodable for Step {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
match decoder.as_rlp().as_val()? {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
match rlp.as_val()? {
|
||||
0u8 => Ok(Step::Propose),
|
||||
1 => Ok(Step::Prevote),
|
||||
2 => Ok(Step::Precommit),
|
||||
@ -168,8 +168,7 @@ impl Encodable for Step {
|
||||
|
||||
/// (signature, (height, view, step, block_hash))
|
||||
impl Decodable for ConsensusMessage {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let rlp = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let m = rlp.at(1)?;
|
||||
let block_message: H256 = m.val_at(3)?;
|
||||
Ok(ConsensusMessage {
|
||||
|
@ -33,7 +33,7 @@ use error::{Error, BlockError};
|
||||
use header::Header;
|
||||
use builtin::Builtin;
|
||||
use env_info::EnvInfo;
|
||||
use rlp::{UntrustedRlp, View as RlpView};
|
||||
use rlp::UntrustedRlp;
|
||||
use ethkey::{recover, public_to_address, Signature};
|
||||
use account_provider::AccountProvider;
|
||||
use block::*;
|
||||
|
@ -27,7 +27,7 @@ use transaction::UnverifiedTransaction;
|
||||
use engines::Engine;
|
||||
use evm::Schedule;
|
||||
use ethjson;
|
||||
use rlp::{self, UntrustedRlp, View};
|
||||
use rlp::{self, UntrustedRlp};
|
||||
|
||||
/// Parity tries to round block.gas_limit to multiple of this constant
|
||||
pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
|
||||
|
@ -261,9 +261,7 @@ impl Header {
|
||||
}
|
||||
|
||||
impl Decodable for Header {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let r = decoder.as_rlp();
|
||||
|
||||
fn decode(r: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let mut blockheader = Header {
|
||||
parent_hash: r.val_at(0)?,
|
||||
uncles_hash: r.val_at(1)?,
|
||||
@ -283,7 +281,7 @@ impl Decodable for Header {
|
||||
bare_hash: RefCell::new(None),
|
||||
};
|
||||
|
||||
for i in 13..r.item_count() {
|
||||
for i in 13..r.item_count()? {
|
||||
blockheader.seal.push(r.at(i)?.as_raw().to_vec())
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
use super::test_common::*;
|
||||
use evm;
|
||||
use ethjson;
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
use transaction::{Action, UnverifiedTransaction};
|
||||
use ethstore::ethkey::public_to_address;
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! This migration compresses the state db.
|
||||
|
||||
use util::migration::{SimpleMigration, Progress};
|
||||
use rlp::{Compressible, UntrustedRlp, View, RlpType};
|
||||
use rlp::{Compressible, UntrustedRlp, RlpType};
|
||||
|
||||
/// Compressing migration.
|
||||
#[derive(Default)]
|
||||
|
@ -26,8 +26,7 @@ use util::migration::{Batch, Config, Error, Migration, SimpleMigration, Progress
|
||||
use util::sha3::Hashable;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rlp::{decode, Rlp, RlpStream, View};
|
||||
|
||||
use rlp::{decode, Rlp, RlpStream};
|
||||
|
||||
// attempt to migrate a key, value pair. None if migration not possible.
|
||||
fn attempt_migrate(mut key_h: H256, val: &[u8]) -> Option<H256> {
|
||||
@ -184,7 +183,7 @@ impl OverlayRecentV7 {
|
||||
}
|
||||
|
||||
// migrate all deleted keys.
|
||||
let mut deleted_keys: Vec<H256> = rlp.val_at(2);
|
||||
let mut deleted_keys: Vec<H256> = rlp.list_at(2);
|
||||
for old_key in &mut deleted_keys {
|
||||
if let Some(new) = self.migrated_keys.get(&*old_key) {
|
||||
*old_key = new.clone();
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
//! This migration consolidates all databases into single one using Column Families.
|
||||
|
||||
use rlp::{Rlp, RlpStream, View};
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use util::kvdb::Database;
|
||||
use util::migration::{Batch, Config, Error, Migration, Progress};
|
||||
use std::sync::Arc;
|
||||
|
@ -22,7 +22,7 @@ use snapshot::Error;
|
||||
|
||||
use util::{U256, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP};
|
||||
use util::trie::{TrieDB, Trie};
|
||||
use rlp::{RlpStream, UntrustedRlp, View};
|
||||
use rlp::{RlpStream, UntrustedRlp};
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
@ -180,7 +180,7 @@ mod tests {
|
||||
|
||||
use util::sha3::{SHA3_EMPTY, SHA3_NULL_RLP};
|
||||
use util::{Address, H256, HashDB, DBValue};
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
@ -20,7 +20,7 @@ use block::Block;
|
||||
use header::Header;
|
||||
|
||||
use views::BlockView;
|
||||
use rlp::{DecoderError, RlpStream, UntrustedRlp, View};
|
||||
use rlp::{DecoderError, RlpStream, UntrustedRlp};
|
||||
use util::{Bytes, Hashable, H256};
|
||||
use util::triehash::ordered_trie_root;
|
||||
|
||||
@ -101,8 +101,8 @@ impl AbridgedBlock {
|
||||
header.set_timestamp(rlp.val_at(6)?);
|
||||
header.set_extra_data(rlp.val_at(7)?);
|
||||
|
||||
let transactions = rlp.val_at(8)?;
|
||||
let uncles: Vec<Header> = rlp.val_at(9)?;
|
||||
let transactions = rlp.list_at(8)?;
|
||||
let uncles: Vec<Header> = rlp.list_at(9)?;
|
||||
|
||||
header.set_transactions_root(ordered_trie_root(
|
||||
rlp.at(8)?.iter().map(|r| r.as_raw().to_owned())
|
||||
@ -114,7 +114,7 @@ impl AbridgedBlock {
|
||||
header.set_uncles_hash(uncles_rlp.as_raw().sha3());
|
||||
|
||||
let mut seal_fields = Vec::new();
|
||||
for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count() {
|
||||
for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count()? {
|
||||
let seal_rlp = rlp.at(i)?;
|
||||
seal_fields.push(seal_rlp.as_raw().to_owned());
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use util::Bytes;
|
||||
use util::hash::H256;
|
||||
use rlp::{self, Encodable, RlpStream, UntrustedRlp, View};
|
||||
use rlp::{self, Encodable, RlpStream, UntrustedRlp};
|
||||
|
||||
use super::ManifestData;
|
||||
|
||||
@ -57,12 +57,10 @@ impl Encodable for ChunkInfo {
|
||||
}
|
||||
|
||||
impl rlp::Decodable for ChunkInfo {
|
||||
fn decode<D: rlp::Decoder>(decoder: &D) -> Result<Self, rlp::DecoderError> {
|
||||
let d = decoder.as_rlp();
|
||||
|
||||
let hash = d.val_at(0)?;
|
||||
let len = d.val_at(1)?;
|
||||
let off = d.val_at(2)?;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, rlp::DecoderError> {
|
||||
let hash = rlp.val_at(0)?;
|
||||
let len = rlp.val_at(1)?;
|
||||
let off = rlp.val_at(2)?;
|
||||
Ok(ChunkInfo(hash, len, off))
|
||||
}
|
||||
}
|
||||
@ -257,8 +255,8 @@ impl PackedReader {
|
||||
|
||||
let rlp = UntrustedRlp::new(&manifest_buf);
|
||||
|
||||
let state: Vec<ChunkInfo> = rlp.val_at(0)?;
|
||||
let blocks: Vec<ChunkInfo> = rlp.val_at(1)?;
|
||||
let state: Vec<ChunkInfo> = rlp.list_at(0)?;
|
||||
let blocks: Vec<ChunkInfo> = rlp.list_at(1)?;
|
||||
|
||||
let manifest = ManifestData {
|
||||
state_hashes: state.iter().map(|c| c.0).collect(),
|
||||
|
@ -37,7 +37,7 @@ use util::journaldb::{self, Algorithm, JournalDB};
|
||||
use util::kvdb::Database;
|
||||
use util::trie::{TrieDB, TrieDBMut, Trie, TrieMut};
|
||||
use util::sha3::SHA3_NULL_RLP;
|
||||
use rlp::{RlpStream, UntrustedRlp, View};
|
||||
use rlp::{RlpStream, UntrustedRlp};
|
||||
use bloom_journal::Bloom;
|
||||
|
||||
use self::block::AbridgedBlock;
|
||||
@ -408,10 +408,10 @@ impl StateRebuilder {
|
||||
pub fn feed(&mut self, chunk: &[u8], flag: &AtomicBool) -> Result<(), ::error::Error> {
|
||||
let rlp = UntrustedRlp::new(chunk);
|
||||
let empty_rlp = StateAccount::new_basic(U256::zero(), U256::zero()).rlp();
|
||||
let mut pairs = Vec::with_capacity(rlp.item_count());
|
||||
let mut pairs = Vec::with_capacity(rlp.item_count()?);
|
||||
|
||||
// initialize the pairs vector with empty values so we have slots to write into.
|
||||
pairs.resize(rlp.item_count(), (H256::new(), Vec::new()));
|
||||
pairs.resize(rlp.item_count()?, (H256::new(), Vec::new()));
|
||||
|
||||
let status = rebuild_accounts(
|
||||
self.db.as_hashdb_mut(),
|
||||
@ -601,7 +601,7 @@ impl BlockRebuilder {
|
||||
use util::triehash::ordered_trie_root;
|
||||
|
||||
let rlp = UntrustedRlp::new(chunk);
|
||||
let item_count = rlp.item_count();
|
||||
let item_count = rlp.item_count()?;
|
||||
let num_blocks = (item_count - 3) as u64;
|
||||
|
||||
trace!(target: "snapshot", "restoring block chunk with {} blocks.", item_count - 3);
|
||||
@ -621,7 +621,7 @@ impl BlockRebuilder {
|
||||
let pair = rlp.at(idx)?;
|
||||
let abridged_rlp = pair.at(0)?.as_raw().to_owned();
|
||||
let abridged_block = AbridgedBlock::from_raw(abridged_rlp);
|
||||
let receipts: Vec<::receipt::Receipt> = pair.val_at(1)?;
|
||||
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())
|
||||
);
|
||||
|
@ -34,7 +34,7 @@ use super::genesis::Genesis;
|
||||
use super::seal::Generic as GenericSeal;
|
||||
use ethereum;
|
||||
use ethjson;
|
||||
use rlp::{Rlp, RlpStream, View};
|
||||
use rlp::{Rlp, RlpStream};
|
||||
|
||||
/// Parameters common to all engines.
|
||||
#[derive(Debug, PartialEq, Clone, Default)]
|
||||
|
@ -461,7 +461,7 @@ impl fmt::Debug for Account {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rlp::{UntrustedRlp, RlpType, View, Compressible};
|
||||
use rlp::{UntrustedRlp, RlpType, Compressible};
|
||||
use util::*;
|
||||
use super::*;
|
||||
use account_db::*;
|
||||
|
@ -25,7 +25,6 @@ use types::filter::Filter;
|
||||
use util::*;
|
||||
use devtools::*;
|
||||
use miner::Miner;
|
||||
use rlp::View;
|
||||
use spec::Spec;
|
||||
use views::BlockView;
|
||||
use ethkey::{KeyPair, Secret};
|
||||
|
@ -60,8 +60,8 @@ impl Into<BloomGroup> for BlockTracesBloomGroup {
|
||||
}
|
||||
|
||||
impl Decodable for BlockTracesBloom {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
Decodable::decode(decoder).map(BlockTracesBloom)
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
LogBloom::decode(rlp).map(BlockTracesBloom)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,8 +72,8 @@ impl Encodable for BlockTracesBloom {
|
||||
}
|
||||
|
||||
impl Decodable for BlockTracesBloomGroup {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let blooms = Decodable::decode(decoder)?;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let blooms = rlp.as_list()?;
|
||||
let group = BlockTracesBloomGroup {
|
||||
blooms: blooms
|
||||
};
|
||||
|
@ -43,8 +43,7 @@ impl Encodable for BasicAccount {
|
||||
}
|
||||
|
||||
impl Decodable for BasicAccount {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let rlp = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(BasicAccount {
|
||||
nonce: rlp.val_at(0)?,
|
||||
balance: rlp.val_at(1)?,
|
||||
|
@ -29,7 +29,7 @@ use transaction::UnverifiedTransaction;
|
||||
use views;
|
||||
|
||||
use util::{Address, Hashable, H256, H2048, U256, HeapSizeOf};
|
||||
use rlp::{Rlp, View};
|
||||
use rlp::Rlp;
|
||||
|
||||
/// Owning header view.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -51,8 +51,8 @@ impl Encodable for CallType {
|
||||
}
|
||||
|
||||
impl Decodable for CallType {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
decoder.as_rlp().as_val().and_then(|v| Ok(match v {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.as_val().and_then(|v| Ok(match v {
|
||||
0u32 => CallType::None,
|
||||
1 => CallType::Call,
|
||||
2 => CallType::CallCode,
|
||||
|
@ -47,12 +47,11 @@ impl Encodable for LogEntry {
|
||||
}
|
||||
|
||||
impl Decodable for LogEntry {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let entry = LogEntry {
|
||||
address: d.val_at(0)?,
|
||||
topics: d.val_at(1)?,
|
||||
data: d.val_at(2)?,
|
||||
address: rlp.val_at(0)?,
|
||||
topics: rlp.list_at(1)?,
|
||||
data: rlp.val_at(2)?,
|
||||
};
|
||||
Ok(entry)
|
||||
}
|
||||
|
@ -65,21 +65,20 @@ impl Encodable for Receipt {
|
||||
}
|
||||
|
||||
impl Decodable for Receipt {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
if d.item_count() == 3 {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
if rlp.item_count()? == 3 {
|
||||
Ok(Receipt {
|
||||
state_root: None,
|
||||
gas_used: d.val_at(0)?,
|
||||
log_bloom: d.val_at(1)?,
|
||||
logs: d.val_at(2)?,
|
||||
gas_used: rlp.val_at(0)?,
|
||||
log_bloom: rlp.val_at(1)?,
|
||||
logs: rlp.list_at(2)?,
|
||||
})
|
||||
} else {
|
||||
Ok(Receipt {
|
||||
state_root: Some(d.val_at(0)?),
|
||||
gas_used: d.val_at(1)?,
|
||||
log_bloom: d.val_at(2)?,
|
||||
logs: d.val_at(3)?,
|
||||
state_root: Some(rlp.val_at(0)?),
|
||||
gas_used: rlp.val_at(1)?,
|
||||
log_bloom: rlp.val_at(2)?,
|
||||
logs: rlp.list_at(3)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ impl ManifestData {
|
||||
pub fn from_rlp(raw: &[u8]) -> Result<Self, DecoderError> {
|
||||
let decoder = UntrustedRlp::new(raw);
|
||||
|
||||
let state_hashes: Vec<H256> = decoder.val_at(0)?;
|
||||
let block_hashes: Vec<H256> = decoder.val_at(1)?;
|
||||
let state_hashes: Vec<H256> = decoder.list_at(0)?;
|
||||
let block_hashes: Vec<H256> = decoder.list_at(1)?;
|
||||
let state_root: H256 = decoder.val_at(2)?;
|
||||
let block_number: u64 = decoder.val_at(3)?;
|
||||
let block_hash: H256 = decoder.val_at(4)?;
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! Trace errors.
|
||||
|
||||
use std::fmt;
|
||||
use rlp::{Encodable, RlpStream, Decodable, Decoder, DecoderError, View};
|
||||
use rlp::{Encodable, RlpStream, Decodable, DecoderError, UntrustedRlp};
|
||||
use evm::Error as EvmError;
|
||||
|
||||
/// Trace evm errors.
|
||||
@ -91,9 +91,9 @@ impl Encodable for Error {
|
||||
}
|
||||
|
||||
impl Decodable for Error {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
use self::Error::*;
|
||||
let value: u8 = decoder.as_rlp().as_val()?;
|
||||
let value: u8 = rlp.as_val()?;
|
||||
match value {
|
||||
0 => Ok(OutOfGas),
|
||||
1 => Ok(BadJumpDestination),
|
||||
|
@ -64,9 +64,8 @@ impl Encodable for FlatTrace {
|
||||
}
|
||||
|
||||
impl Decodable for FlatTrace {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
let v: Vec<usize> = d.val_at(3)?;
|
||||
fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let v: Vec<usize> = d.list_at(3)?;
|
||||
let res = FlatTrace {
|
||||
action: d.val_at(0)?,
|
||||
result: d.val_at(1)?,
|
||||
@ -108,8 +107,8 @@ impl Encodable for FlatTransactionTraces {
|
||||
}
|
||||
|
||||
impl Decodable for FlatTransactionTraces {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
Ok(FlatTransactionTraces(Decodable::decode(decoder)?))
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(FlatTransactionTraces(rlp.as_list()?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,8 +148,8 @@ impl Encodable for FlatBlockTraces {
|
||||
}
|
||||
|
||||
impl Decodable for FlatBlockTraces {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
Ok(FlatBlockTraces(Decodable::decode(decoder)?))
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(FlatBlockTraces(rlp.as_list()?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,11 +45,10 @@ impl Encodable for CallResult {
|
||||
}
|
||||
|
||||
impl Decodable for CallResult {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = CallResult {
|
||||
gas_used: d.val_at(0)?,
|
||||
output: d.val_at(1)?,
|
||||
gas_used: rlp.val_at(0)?,
|
||||
output: rlp.val_at(1)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -78,12 +77,11 @@ impl Encodable for CreateResult {
|
||||
}
|
||||
|
||||
impl Decodable for CreateResult {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = CreateResult {
|
||||
gas_used: d.val_at(0)?,
|
||||
code: d.val_at(1)?,
|
||||
address: d.val_at(2)?,
|
||||
gas_used: rlp.val_at(0)?,
|
||||
code: rlp.val_at(1)?,
|
||||
address: rlp.val_at(2)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -141,15 +139,14 @@ impl Encodable for Call {
|
||||
}
|
||||
|
||||
impl Decodable for Call {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = Call {
|
||||
from: d.val_at(0)?,
|
||||
to: d.val_at(1)?,
|
||||
value: d.val_at(2)?,
|
||||
gas: d.val_at(3)?,
|
||||
input: d.val_at(4)?,
|
||||
call_type: d.val_at(5)?,
|
||||
from: rlp.val_at(0)?,
|
||||
to: rlp.val_at(1)?,
|
||||
value: rlp.val_at(2)?,
|
||||
gas: rlp.val_at(3)?,
|
||||
input: rlp.val_at(4)?,
|
||||
call_type: rlp.val_at(5)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -201,13 +198,12 @@ impl Encodable for Create {
|
||||
}
|
||||
|
||||
impl Decodable for Create {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = Create {
|
||||
from: d.val_at(0)?,
|
||||
value: d.val_at(1)?,
|
||||
gas: d.val_at(2)?,
|
||||
init: d.val_at(3)?,
|
||||
from: rlp.val_at(0)?,
|
||||
value: rlp.val_at(1)?,
|
||||
gas: rlp.val_at(2)?,
|
||||
init: rlp.val_at(3)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -252,12 +248,11 @@ impl Encodable for Suicide {
|
||||
}
|
||||
|
||||
impl Decodable for Suicide {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = Suicide {
|
||||
address: d.val_at(0)?,
|
||||
refund_address: d.val_at(1)?,
|
||||
balance: d.val_at(2)?,
|
||||
address: rlp.val_at(0)?,
|
||||
refund_address: rlp.val_at(1)?,
|
||||
balance: rlp.val_at(2)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -298,13 +293,12 @@ impl Encodable for Action {
|
||||
}
|
||||
|
||||
impl Decodable for Action {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
let action_type: u8 = d.val_at(0)?;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let action_type: u8 = rlp.val_at(0)?;
|
||||
match action_type {
|
||||
0 => d.val_at(1).map(Action::Call),
|
||||
1 => d.val_at(1).map(Action::Create),
|
||||
2 => d.val_at(1).map(Action::Suicide),
|
||||
0 => rlp.val_at(1).map(Action::Call),
|
||||
1 => rlp.val_at(1).map(Action::Create),
|
||||
2 => rlp.val_at(1).map(Action::Suicide),
|
||||
_ => Err(DecoderError::Custom("Invalid action type.")),
|
||||
}
|
||||
}
|
||||
@ -369,14 +363,13 @@ impl Encodable for Res {
|
||||
}
|
||||
|
||||
impl Decodable for Res {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
let action_type: u8 = d.val_at(0)?;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let action_type: u8 = rlp.val_at(0)?;
|
||||
match action_type {
|
||||
0 => d.val_at(1).map(Res::Call),
|
||||
1 => d.val_at(1).map(Res::Create),
|
||||
2 => d.val_at(1).map(Res::FailedCall),
|
||||
3 => d.val_at(1).map(Res::FailedCreate),
|
||||
0 => rlp.val_at(1).map(Res::Call),
|
||||
1 => rlp.val_at(1).map(Res::Create),
|
||||
2 => rlp.val_at(1).map(Res::FailedCall),
|
||||
3 => rlp.val_at(1).map(Res::FailedCreate),
|
||||
4 => Ok(Res::None),
|
||||
_ => Err(DecoderError::Custom("Invalid result type.")),
|
||||
}
|
||||
@ -420,11 +413,10 @@ impl Encodable for MemoryDiff {
|
||||
}
|
||||
|
||||
impl Decodable for MemoryDiff {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(MemoryDiff {
|
||||
offset: d.val_at(0)?,
|
||||
data: d.val_at(1)?,
|
||||
offset: rlp.val_at(0)?,
|
||||
data: rlp.val_at(1)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -448,11 +440,10 @@ impl Encodable for StorageDiff {
|
||||
}
|
||||
|
||||
impl Decodable for StorageDiff {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(StorageDiff {
|
||||
location: d.val_at(0)?,
|
||||
value: d.val_at(1)?,
|
||||
location: rlp.val_at(0)?,
|
||||
value: rlp.val_at(1)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -482,13 +473,12 @@ impl Encodable for VMExecutedOperation {
|
||||
}
|
||||
|
||||
impl Decodable for VMExecutedOperation {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(VMExecutedOperation {
|
||||
gas_used: d.val_at(0)?,
|
||||
stack_push: d.val_at(1)?,
|
||||
mem_diff: d.val_at(2)?,
|
||||
store_diff: d.val_at(3)?,
|
||||
gas_used: rlp.val_at(0)?,
|
||||
stack_push: rlp.list_at(1)?,
|
||||
mem_diff: rlp.val_at(2)?,
|
||||
store_diff: rlp.val_at(3)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -518,13 +508,12 @@ impl Encodable for VMOperation {
|
||||
}
|
||||
|
||||
impl Decodable for VMOperation {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = VMOperation {
|
||||
pc: d.val_at(0)?,
|
||||
instruction: d.val_at(1)?,
|
||||
gas_cost: d.val_at(2)?,
|
||||
executed: d.val_at(3)?,
|
||||
pc: rlp.val_at(0)?,
|
||||
instruction: rlp.val_at(1)?,
|
||||
gas_cost: rlp.val_at(2)?,
|
||||
executed: rlp.val_at(3)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -557,13 +546,12 @@ impl Encodable for VMTrace {
|
||||
}
|
||||
|
||||
impl Decodable for VMTrace {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = VMTrace {
|
||||
parent_step: d.val_at(0)?,
|
||||
code: d.val_at(1)?,
|
||||
operations: d.val_at(2)?,
|
||||
subs: d.val_at(3)?,
|
||||
parent_step: rlp.val_at(0)?,
|
||||
code: rlp.val_at(1)?,
|
||||
operations: rlp.list_at(2)?,
|
||||
subs: rlp.list_at(3)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
|
@ -42,8 +42,7 @@ impl Default for Action {
|
||||
}
|
||||
|
||||
impl Decodable for Action {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let rlp = decoder.as_rlp();
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
if rlp.is_empty() {
|
||||
Ok(Action::Create)
|
||||
} else {
|
||||
@ -243,12 +242,11 @@ impl Deref for UnverifiedTransaction {
|
||||
}
|
||||
|
||||
impl Decodable for UnverifiedTransaction {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = decoder.as_rlp();
|
||||
if d.item_count() != 9 {
|
||||
fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
if d.item_count()? != 9 {
|
||||
return Err(DecoderError::RlpIncorrectListLen);
|
||||
}
|
||||
let hash = decoder.as_raw().sha3();
|
||||
let hash = d.as_raw().sha3();
|
||||
Ok(UnverifiedTransaction {
|
||||
unsigned: Transaction {
|
||||
nonce: d.val_at(0)?,
|
||||
|
@ -26,7 +26,7 @@ use engines::Engine;
|
||||
use error::{BlockError, Error};
|
||||
use blockchain::*;
|
||||
use header::{BlockNumber, Header};
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
use transaction::SignedTransaction;
|
||||
use views::BlockView;
|
||||
use time::get_time;
|
||||
@ -101,7 +101,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
|
||||
verify_parent(&header, &parent)?;
|
||||
engine.verify_block_family(&header, &parent, Some(bytes))?;
|
||||
|
||||
let num_uncles = UntrustedRlp::new(bytes).at(2)?.item_count();
|
||||
let num_uncles = UntrustedRlp::new(bytes).at(2)?.item_count()?;
|
||||
if num_uncles != 0 {
|
||||
if num_uncles > engine.maximum_uncle_count() {
|
||||
return Err(From::from(BlockError::TooManyUncles(OutOfBounds { min: None, max: Some(engine.maximum_uncle_count()), found: num_uncles })));
|
||||
@ -264,7 +264,6 @@ mod tests {
|
||||
use transaction::*;
|
||||
use tests::helpers::*;
|
||||
use types::log_entry::{LogEntry, LocalizedLogEntry};
|
||||
use rlp::View;
|
||||
use time::get_time;
|
||||
use encoded;
|
||||
|
||||
|
@ -20,7 +20,7 @@ use util::*;
|
||||
use header::*;
|
||||
use transaction::*;
|
||||
use super::{TransactionView, HeaderView};
|
||||
use rlp::{Rlp, View};
|
||||
use rlp::Rlp;
|
||||
|
||||
/// View onto block rlp.
|
||||
pub struct BlockView<'a> {
|
||||
@ -69,7 +69,7 @@ impl<'a> BlockView<'a> {
|
||||
|
||||
/// Return List of transactions in given block.
|
||||
pub fn transactions(&self) -> Vec<UnverifiedTransaction> {
|
||||
self.rlp.val_at(1)
|
||||
self.rlp.list_at(1)
|
||||
}
|
||||
|
||||
/// Return List of transactions with additional localization info.
|
||||
@ -125,7 +125,7 @@ impl<'a> BlockView<'a> {
|
||||
|
||||
/// Return list of uncles of given block.
|
||||
pub fn uncles(&self) -> Vec<Header> {
|
||||
self.rlp.val_at(2)
|
||||
self.rlp.list_at(2)
|
||||
}
|
||||
|
||||
/// Return number of uncles in given block, without deserializing them.
|
||||
|
@ -20,7 +20,7 @@ use util::*;
|
||||
use header::*;
|
||||
use transaction::*;
|
||||
use super::{TransactionView, HeaderView};
|
||||
use rlp::{Rlp, View};
|
||||
use rlp::Rlp;
|
||||
|
||||
/// View onto block rlp.
|
||||
pub struct BodyView<'a> {
|
||||
@ -49,7 +49,7 @@ impl<'a> BodyView<'a> {
|
||||
|
||||
/// Return List of transactions in given block.
|
||||
pub fn transactions(&self) -> Vec<UnverifiedTransaction> {
|
||||
self.rlp.val_at(0)
|
||||
self.rlp.list_at(0)
|
||||
}
|
||||
|
||||
/// Return List of transactions with additional localization info.
|
||||
@ -99,7 +99,7 @@ impl<'a> BodyView<'a> {
|
||||
|
||||
/// Return list of uncles of given block.
|
||||
pub fn uncles(&self) -> Vec<Header> {
|
||||
self.rlp.val_at(1)
|
||||
self.rlp.list_at(1)
|
||||
}
|
||||
|
||||
/// Return number of uncles in given block, without deserializing them.
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! View onto block header rlp
|
||||
|
||||
use util::{U256, Bytes, Hashable, H256, Address, H2048};
|
||||
use rlp::{Rlp, View};
|
||||
use rlp::Rlp;
|
||||
use header::BlockNumber;
|
||||
|
||||
/// View onto block header rlp.
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! View onto transaction rlp
|
||||
use util::{U256, Bytes, Hashable, H256};
|
||||
use rlp::{Rlp, View};
|
||||
use rlp::Rlp;
|
||||
|
||||
/// View onto transaction rlp.
|
||||
pub struct TransactionView<'a> {
|
||||
|
@ -25,7 +25,7 @@ use ethcore::transaction::{
|
||||
};
|
||||
use ethcore::service::ClientIoMessage;
|
||||
use io::IoHandler;
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
use util::kvdb::KeyValueDB;
|
||||
|
||||
extern crate ethcore;
|
||||
|
@ -32,7 +32,6 @@ use ethcore::snapshot::{RestorationStatus, SnapshotService as SS};
|
||||
use number_prefix::{binary_prefix, Standalone, Prefixed};
|
||||
use ethcore_rpc::{is_major_importing};
|
||||
use ethcore_rpc::informant::RpcStats;
|
||||
use rlp::View;
|
||||
|
||||
pub struct Informant {
|
||||
report: RwLock<Option<ClientReport>>,
|
||||
|
@ -21,7 +21,7 @@ use std::time::{Instant, Duration};
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use futures::{self, future, BoxFuture, Future};
|
||||
use rlp::{self, UntrustedRlp, View};
|
||||
use rlp::{self, UntrustedRlp};
|
||||
use time::get_time;
|
||||
use util::{H160, H256, Address, U256, H64};
|
||||
use util::sha3::Hashable;
|
||||
|
@ -36,7 +36,7 @@ use ethcore::executed::{Executed, ExecutionError};
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::transaction::{Action, SignedTransaction, Transaction as EthTransaction};
|
||||
use ethsync::LightSync;
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
use util::sha3::{SHA3_NULL_RLP, SHA3_EMPTY_LIST_RLP};
|
||||
use util::{RwLock, Mutex, Uint, U256};
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::transaction::{SignedTransaction, PendingTransaction};
|
||||
use futures::{future, BoxFuture, Future, IntoFuture};
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
use std::sync::{Weak, Arc};
|
||||
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use rlp::UntrustedRlp;
|
||||
use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId};
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::transaction::SignedTransaction;
|
||||
|
@ -940,7 +940,7 @@ fn rpc_eth_send_raw_transaction_error() {
|
||||
],
|
||||
"id": 1
|
||||
}"#;
|
||||
let res = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid RLP.","data":"RlpIncorrectListLen"},"id":1}"#.into();
|
||||
let res = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid RLP.","data":"RlpExpectedToBeList"},"id":1}"#.into();
|
||||
|
||||
assert_eq!(tester.io.handle_request_sync(&req), Some(res));
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ impl BlockDownloader {
|
||||
|
||||
/// Add new block headers.
|
||||
pub fn import_headers(&mut self, io: &mut SyncIo, r: &UntrustedRlp, expected_hash: Option<H256>) -> Result<DownloadAction, BlockDownloaderImportError> {
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count().unwrap_or(0);
|
||||
if self.state == State::Idle {
|
||||
trace!(target: "sync", "Ignored unexpected block headers");
|
||||
return Ok(DownloadAction::None)
|
||||
@ -314,7 +314,7 @@ impl BlockDownloader {
|
||||
|
||||
/// Called by peer once it has new block bodies
|
||||
pub fn import_bodies(&mut self, _io: &mut SyncIo, r: &UntrustedRlp) -> Result<(), BlockDownloaderImportError> {
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count().unwrap_or(0);
|
||||
if item_count == 0 {
|
||||
return Err(BlockDownloaderImportError::Useless);
|
||||
}
|
||||
@ -340,7 +340,7 @@ impl BlockDownloader {
|
||||
|
||||
/// Called by peer once it has new block bodies
|
||||
pub fn import_receipts(&mut self, _io: &mut SyncIo, r: &UntrustedRlp) -> Result<(), BlockDownloaderImportError> {
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count().unwrap_or(0);
|
||||
if item_count == 0 {
|
||||
return Err(BlockDownloaderImportError::Useless);
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ impl ChainSync {
|
||||
let confirmed = match self.peers.get_mut(&peer_id) {
|
||||
Some(ref mut peer) if peer.asking == PeerAsking::ForkHeader => {
|
||||
peer.asking = PeerAsking::Nothing;
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count()?;
|
||||
let (fork_number, fork_hash) = self.fork_block.expect("ForkHeader request is sent only fork block is Some; qed").clone();
|
||||
if item_count == 0 || item_count != 1 {
|
||||
trace!(target: "sync", "{}: Chain is too short to confirm the block", peer_id);
|
||||
@ -696,7 +696,7 @@ impl ChainSync {
|
||||
self.continue_sync(io);
|
||||
return Ok(());
|
||||
}
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}, set = {:?}", peer_id, item_count, self.state, block_set);
|
||||
if (self.state == SyncState::Idle || self.state == SyncState::WaitingPeers) && self.old_blocks.is_none() {
|
||||
trace!(target: "sync", "Ignored unexpected block headers");
|
||||
@ -764,7 +764,7 @@ impl ChainSync {
|
||||
self.continue_sync(io);
|
||||
return Ok(());
|
||||
}
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{} -> BlockBodies ({} entries), set = {:?}", peer_id, item_count, block_set);
|
||||
if item_count == 0 {
|
||||
self.deactivate_peer(io, peer_id);
|
||||
@ -818,7 +818,7 @@ impl ChainSync {
|
||||
self.continue_sync(io);
|
||||
return Ok(());
|
||||
}
|
||||
let item_count = r.item_count();
|
||||
let item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{} -> BlockReceipts ({} entries)", peer_id, item_count);
|
||||
if item_count == 0 {
|
||||
self.deactivate_peer(io, peer_id);
|
||||
@ -954,7 +954,7 @@ impl ChainSync {
|
||||
self.continue_sync(io);
|
||||
return Ok(());
|
||||
}
|
||||
trace!(target: "sync", "{} -> NewHashes ({} entries)", peer_id, r.item_count());
|
||||
trace!(target: "sync", "{} -> NewHashes ({} entries)", peer_id, r.item_count()?);
|
||||
let mut max_height: BlockNumber = 0;
|
||||
let mut new_hashes = Vec::new();
|
||||
let last_imported_number = self.new_blocks.last_imported_block_number();
|
||||
@ -1439,7 +1439,7 @@ impl ChainSync {
|
||||
trace!(target: "sync", "{} Ignoring transactions from unconfirmed/unknown peer", peer_id);
|
||||
}
|
||||
|
||||
let mut item_count = r.item_count();
|
||||
let mut item_count = r.item_count()?;
|
||||
trace!(target: "sync", "{:02} -> Transactions ({} entries)", peer_id, item_count);
|
||||
item_count = min(item_count, MAX_TX_TO_IMPORT);
|
||||
let mut transactions = Vec::with_capacity(item_count);
|
||||
@ -1557,7 +1557,7 @@ impl ChainSync {
|
||||
|
||||
/// Respond to GetBlockBodies request
|
||||
fn return_block_bodies(io: &SyncIo, r: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult {
|
||||
let mut count = r.item_count();
|
||||
let mut count = r.item_count().unwrap_or(0);
|
||||
if count == 0 {
|
||||
debug!(target: "sync", "Empty GetBlockBodies request, ignoring.");
|
||||
return Ok(None);
|
||||
@ -1579,7 +1579,7 @@ impl ChainSync {
|
||||
|
||||
/// Respond to GetNodeData request
|
||||
fn return_node_data(io: &SyncIo, r: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult {
|
||||
let mut count = r.item_count();
|
||||
let mut count = r.item_count().unwrap_or(0);
|
||||
trace!(target: "sync", "{} -> GetNodeData: {} entries", peer_id, count);
|
||||
if count == 0 {
|
||||
debug!(target: "sync", "Empty GetNodeData request, ignoring.");
|
||||
@ -1603,7 +1603,7 @@ impl ChainSync {
|
||||
}
|
||||
|
||||
fn return_receipts(io: &SyncIo, rlp: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult {
|
||||
let mut count = rlp.item_count();
|
||||
let mut count = rlp.item_count().unwrap_or(0);
|
||||
trace!(target: "sync", "{} -> GetReceipts: {} entries", peer_id, count);
|
||||
if count == 0 {
|
||||
debug!(target: "sync", "Empty GetReceipts request, ignoring.");
|
||||
@ -1628,7 +1628,7 @@ impl ChainSync {
|
||||
|
||||
/// Respond to GetSnapshotManifest request
|
||||
fn return_snapshot_manifest(io: &SyncIo, r: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult {
|
||||
let count = r.item_count();
|
||||
let count = r.item_count().unwrap_or(0);
|
||||
trace!(target: "sync", "{} -> GetSnapshotManifest", peer_id);
|
||||
if count != 0 {
|
||||
debug!(target: "sync", "Invalid GetSnapshotManifest request, ignoring.");
|
||||
@ -2177,7 +2177,7 @@ mod tests {
|
||||
use util::sha3::Hashable;
|
||||
use util::hash::H256;
|
||||
use util::bytes::Bytes;
|
||||
use rlp::{Rlp, RlpStream, UntrustedRlp, View};
|
||||
use rlp::{Rlp, RlpStream, UntrustedRlp};
|
||||
use super::*;
|
||||
use ::SyncConfig;
|
||||
use super::{PeerInfo, PeerAsking};
|
||||
@ -2746,7 +2746,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let rlp = UntrustedRlp::new(&*p.data);
|
||||
let item_count = rlp.item_count();
|
||||
let item_count = rlp.item_count().unwrap_or(0);
|
||||
if item_count != 1 {
|
||||
return None;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ use std::fmt;
|
||||
|
||||
use ethcore::header::Header;
|
||||
use light::request::{HashOrNumber, Headers as HeadersRequest};
|
||||
use rlp::{DecoderError, UntrustedRlp, View};
|
||||
use rlp::{DecoderError, UntrustedRlp};
|
||||
use util::{Bytes, H256};
|
||||
|
||||
/// Errors found when decoding headers and verifying with basic constraints.
|
||||
|
@ -481,7 +481,7 @@ impl Discovery {
|
||||
fn on_neighbours(&mut self, rlp: &UntrustedRlp, _node: &NodeId, from: &SocketAddr) -> Result<Option<TableUpdates>, NetworkError> {
|
||||
// TODO: validate packet
|
||||
let mut added = HashMap::new();
|
||||
trace!(target: "discovery", "Got {} Neighbours from {:?}", rlp.at(0)?.item_count(), &from);
|
||||
trace!(target: "discovery", "Got {} Neighbours from {:?}", rlp.at(0)?.item_count()?, &from);
|
||||
for r in rlp.at(0)?.iter() {
|
||||
let endpoint = NodeEndpoint::from_rlp(&r)?;
|
||||
if !endpoint.is_valid() {
|
||||
|
@ -116,9 +116,8 @@ pub struct PeerCapabilityInfo {
|
||||
}
|
||||
|
||||
impl Decodable for PeerCapabilityInfo {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let c = decoder.as_rlp();
|
||||
let p: Vec<u8> = c.val_at(0)?;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let p: Vec<u8> = rlp.val_at(0)?;
|
||||
if p.len() != 3 {
|
||||
return Err(DecoderError::Custom("Invalid subprotocol string length. Should be 3"));
|
||||
}
|
||||
@ -126,7 +125,7 @@ impl Decodable for PeerCapabilityInfo {
|
||||
p2.clone_from_slice(&p);
|
||||
Ok(PeerCapabilityInfo {
|
||||
protocol: p2,
|
||||
version: c.val_at(1)?
|
||||
version: rlp.val_at(1)?
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -473,7 +472,7 @@ impl Session {
|
||||
where Message: Send + Sync + Clone {
|
||||
let protocol = rlp.val_at::<u32>(0)?;
|
||||
let client_version = rlp.val_at::<String>(1)?;
|
||||
let peer_caps = rlp.val_at::<Vec<PeerCapabilityInfo>>(2)?;
|
||||
let peer_caps: Vec<PeerCapabilityInfo> = rlp.list_at(2)?;
|
||||
let id = rlp.val_at::<NodeId>(4)?;
|
||||
|
||||
// Intersect with host capabilities
|
||||
|
@ -23,13 +23,12 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
extern crate ethcore_bigint as bigint;
|
||||
extern crate rlp;
|
||||
extern crate ethcore_util as util;
|
||||
|
||||
use test::Bencher;
|
||||
use std::str::FromStr;
|
||||
use rlp::*;
|
||||
use util::U256;
|
||||
use bigint::prelude::U256;
|
||||
use rlp::{RlpStream, Rlp};
|
||||
|
||||
#[bench]
|
||||
fn bench_stream_u64_value(b: &mut Bencher) {
|
||||
@ -56,9 +55,8 @@ fn bench_stream_u256_value(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
// u256
|
||||
let mut stream = RlpStream::new();
|
||||
stream.append(&U256::from_str("8090a0b0c0d0e0f009102030405060770000000000000001000000000\
|
||||
00012f0")
|
||||
.unwrap());
|
||||
let uint: U256 = "8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0".into();
|
||||
stream.append(&uint);
|
||||
let _ = stream.out();
|
||||
});
|
||||
}
|
||||
@ -93,11 +91,11 @@ fn bench_decode_nested_empty_lists(b: &mut Bencher) {
|
||||
// [ [], [[]], [ [], [[]] ] ]
|
||||
let data = vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0];
|
||||
let rlp = Rlp::new(&data);
|
||||
let _v0: Vec<u16> = rlp.val_at(0);
|
||||
let _v1: Vec<Vec<u16>> = rlp.val_at(1);
|
||||
let _v0: Vec<u16> = rlp.at(0).as_list();
|
||||
let _v1: Vec<u16> = rlp.at(1).at(0).as_list();
|
||||
let nested_rlp = rlp.at(2);
|
||||
let _v2a: Vec<u16> = nested_rlp.val_at(0);
|
||||
let _v2b: Vec<Vec<u16>> = nested_rlp.val_at(1);
|
||||
let _v2a: Vec<u16> = nested_rlp.at(0).as_list();
|
||||
let _v2b: Vec<u16> = nested_rlp.at(1).at(0).as_list();
|
||||
});
|
||||
}
|
||||
|
@ -1,148 +0,0 @@
|
||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Unified interfaces for RLP bytes operations on basic types
|
||||
//!
|
||||
|
||||
use std::{mem, fmt, cmp};
|
||||
use std::error::Error as StdError;
|
||||
use bigint::prelude::{U128, U256, H64, H128, H160, H256, H512, H520, H2048};
|
||||
|
||||
/// Error returned when `FromBytes` conversation goes wrong
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FromBytesError {
|
||||
/// Expected more RLP data
|
||||
DataIsTooShort,
|
||||
/// Extra bytes after the end of the last item
|
||||
DataIsTooLong,
|
||||
/// Integer-representation is non-canonically prefixed with zero byte(s).
|
||||
ZeroPrefixedInt,
|
||||
/// String representation is not utf-8
|
||||
InvalidUtf8,
|
||||
}
|
||||
|
||||
impl StdError for FromBytesError {
|
||||
fn description(&self) -> &str { "from_bytes error" }
|
||||
}
|
||||
|
||||
impl fmt::Display for FromBytesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Alias for the result of `FromBytes` trait
|
||||
pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
||||
|
||||
/// Converts to given type from its bytes representation
|
||||
///
|
||||
/// TODO: check size of bytes before conversation and return appropriate error
|
||||
pub trait FromBytes: Sized {
|
||||
/// Create a value from bytes
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
||||
}
|
||||
|
||||
impl FromBytes for String {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
|
||||
::std::str::from_utf8(bytes).map(|s| s.to_owned()).map_err(|_| FromBytesError::InvalidUtf8)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_uint_from_bytes {
|
||||
($to: ident) => {
|
||||
impl FromBytes for $to {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> {
|
||||
match bytes.len() {
|
||||
0 => Ok(0),
|
||||
l if l <= mem::size_of::<$to>() => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(FromBytesError::ZeroPrefixedInt)
|
||||
}
|
||||
let mut res = 0 as $to;
|
||||
for i in 0..l {
|
||||
let shift = (l - 1 - i) * 8;
|
||||
res = res + ((bytes[i] as $to) << shift);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
_ => Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBytes for bool {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<bool> {
|
||||
match bytes.len() {
|
||||
0 => Ok(false),
|
||||
1 => Ok(bytes[0] != 0),
|
||||
_ => Err(FromBytesError::DataIsTooLong),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//impl_uint_from_bytes!(u8);
|
||||
impl_uint_from_bytes!(u16);
|
||||
impl_uint_from_bytes!(u32);
|
||||
impl_uint_from_bytes!(u64);
|
||||
impl_uint_from_bytes!(usize);
|
||||
|
||||
macro_rules! impl_uint_from_bytes {
|
||||
($name: ident, $size: expr) => {
|
||||
impl FromBytes for $name {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
||||
if !bytes.is_empty() && bytes[0] == 0 {
|
||||
Err(FromBytesError::ZeroPrefixedInt)
|
||||
} else if bytes.len() <= $size {
|
||||
Ok($name::from(bytes))
|
||||
} else {
|
||||
Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_uint_from_bytes!(U256, 32);
|
||||
impl_uint_from_bytes!(U128, 16);
|
||||
|
||||
macro_rules! impl_hash_from_bytes {
|
||||
($name: ident, $size: expr) => {
|
||||
impl FromBytes for $name {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
||||
match bytes.len().cmp(&$size) {
|
||||
cmp::Ordering::Less => Err(FromBytesError::DataIsTooShort),
|
||||
cmp::Ordering::Greater => Err(FromBytesError::DataIsTooLong),
|
||||
cmp::Ordering::Equal => {
|
||||
let mut t = [0u8; $size];
|
||||
t.copy_from_slice(bytes);
|
||||
Ok($name(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_hash_from_bytes!(H64, 8);
|
||||
impl_hash_from_bytes!(H128, 16);
|
||||
impl_hash_from_bytes!(H160, 20);
|
||||
impl_hash_from_bytes!(H256, 32);
|
||||
impl_hash_from_bytes!(H512, 64);
|
||||
impl_hash_from_bytes!(H520, 65);
|
||||
impl_hash_from_bytes!(H2048, 256);
|
||||
|
@ -17,7 +17,7 @@
|
||||
use std::collections::HashMap;
|
||||
use elastic_array::ElasticArray1024;
|
||||
use common::{BLOCKS_RLP_SWAPPER, SNAPSHOT_RLP_SWAPPER};
|
||||
use {UntrustedRlp, View, Compressible, encode, RlpStream};
|
||||
use {UntrustedRlp, Compressible, encode, RlpStream};
|
||||
|
||||
/// Stores RLPs used for compression
|
||||
pub struct InvalidRlpSwapper<'a> {
|
||||
@ -69,7 +69,7 @@ fn to_elastic(slice: &[u8]) -> ElasticArray1024<u8> {
|
||||
fn map_rlp<F>(rlp: &UntrustedRlp, f: F) -> Option<ElasticArray1024<u8>> where
|
||||
F: Fn(&UntrustedRlp) -> Option<ElasticArray1024<u8>> {
|
||||
match rlp.iter()
|
||||
.fold((false, RlpStream::new_list(rlp.item_count())),
|
||||
.fold((false, RlpStream::new_list(rlp.item_count().unwrap_or(0))),
|
||||
|(is_some, mut acc), subrlp| {
|
||||
let new = f(&subrlp);
|
||||
if let Some(ref insert) = new {
|
||||
@ -138,7 +138,7 @@ fn deep_decompress(rlp: &UntrustedRlp, swapper: &InvalidRlpSwapper) -> Option<El
|
||||
swapper.get_valid(rlp.as_raw()).map(to_elastic);
|
||||
// Simply decompress data.
|
||||
if rlp.is_data() { return simple_swap(); }
|
||||
match rlp.item_count() {
|
||||
match rlp.item_count().unwrap_or(0) {
|
||||
// Look for special compressed list, which contains nested data.
|
||||
2 if rlp.at(0).map(|r| r.as_raw() == &[0x81, 0x7f]).unwrap_or(false) =>
|
||||
rlp.at(1).ok().map_or(simple_swap(),
|
||||
@ -169,7 +169,7 @@ impl<'a> Compressible for UntrustedRlp<'a> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use compression::InvalidRlpSwapper;
|
||||
use {UntrustedRlp, Compressible, View, RlpType};
|
||||
use {UntrustedRlp, Compressible, RlpType};
|
||||
|
||||
#[test]
|
||||
fn invalid_rlp_swapper() {
|
||||
|
@ -16,13 +16,10 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::error::Error as StdError;
|
||||
use bytes::FromBytesError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// Error concerning the RLP decoder.
|
||||
pub enum DecoderError {
|
||||
/// Couldn't convert given bytes to an instance of required type.
|
||||
FromBytesError(FromBytesError),
|
||||
/// Data has additional bytes at the end of the valid RLP fragment.
|
||||
RlpIsTooBig,
|
||||
/// Data has too few bytes for valid RLP.
|
||||
@ -56,9 +53,3 @@ impl fmt::Display for DecoderError {
|
||||
fmt::Debug::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FromBytesError> for DecoderError {
|
||||
fn from(err: FromBytesError) -> DecoderError {
|
||||
DecoderError::FromBytesError(err)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,26 @@
|
||||
use std::{cmp, mem, str};
|
||||
use byteorder::{ByteOrder, BigEndian};
|
||||
use bigint::prelude::{Uint, U128, U256, H64, H128, H160, H256, H512, H520, H2048};
|
||||
use traits::Encodable;
|
||||
use traits::{Encodable, Decodable};
|
||||
use stream::RlpStream;
|
||||
use {UntrustedRlp, DecoderError};
|
||||
|
||||
pub fn decode_usize(bytes: &[u8]) -> Result<usize, DecoderError> {
|
||||
match bytes.len() {
|
||||
l if l <= mem::size_of::<usize>() => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(DecoderError::RlpInvalidIndirection);
|
||||
}
|
||||
let mut res = 0usize;
|
||||
for i in 0..l {
|
||||
let shift = (l - 1 - i) * 8;
|
||||
res = res + ((bytes[i] as usize) << shift);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
_ => Err(DecoderError::RlpIsTooBig),
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for bool {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
@ -13,6 +32,18 @@ impl Encodable for bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for bool {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| {
|
||||
match bytes.len() {
|
||||
0 => Ok(false),
|
||||
1 => Ok(bytes[0] != 0),
|
||||
_ => Err(DecoderError::RlpIsTooBig),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encodable for &'a [u8] {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.encoder().encode_value(self);
|
||||
@ -25,6 +56,14 @@ impl Encodable for Vec<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Vec<u8> {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| {
|
||||
Ok(bytes.to_vec())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Encodable for Option<T> where T: Encodable {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
match *self {
|
||||
@ -39,6 +78,17 @@ impl<T> Encodable for Option<T> where T: Encodable {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Decodable for Option<T> where T: Decodable {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let items = rlp.item_count()?;
|
||||
match items {
|
||||
1 => rlp.val_at(0).map(Some),
|
||||
0 => Ok(None),
|
||||
_ => Err(DecoderError::RlpIncorrectListLen),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for u8 {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
if *self != 0 {
|
||||
@ -49,6 +99,19 @@ impl Encodable for u8 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for u8 {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| {
|
||||
match bytes.len() {
|
||||
1 if bytes[0] != 0 => Ok(bytes[0]),
|
||||
0 => Ok(0),
|
||||
1 => Err(DecoderError::RlpInvalidIndirection),
|
||||
_ => Err(DecoderError::RlpIsTooBig),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_encodable_for_u {
|
||||
($name: ident, $func: ident, $size: expr) => {
|
||||
impl Encodable for $name {
|
||||
@ -62,16 +125,52 @@ macro_rules! impl_encodable_for_u {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_decodable_for_u {
|
||||
($name: ident) => {
|
||||
impl Decodable for $name {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| {
|
||||
match bytes.len() {
|
||||
0 | 1 => u8::decode(rlp).map(|v| v as $name),
|
||||
l if l <= mem::size_of::<$name>() => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(DecoderError::RlpInvalidIndirection);
|
||||
}
|
||||
let mut res = 0 as $name;
|
||||
for i in 0..l {
|
||||
let shift = (l - 1 - i) * 8;
|
||||
res = res + ((bytes[i] as $name) << shift);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
_ => Err(DecoderError::RlpIsTooBig),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_encodable_for_u!(u16, write_u16, 2);
|
||||
impl_encodable_for_u!(u32, write_u32, 4);
|
||||
impl_encodable_for_u!(u64, write_u64, 8);
|
||||
|
||||
impl_decodable_for_u!(u16);
|
||||
impl_decodable_for_u!(u32);
|
||||
impl_decodable_for_u!(u64);
|
||||
|
||||
impl Encodable for usize {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
(*self as u64).rlp_append(s);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for usize {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
u64::decode(rlp).map(|value| value as usize)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_encodable_for_hash {
|
||||
($name: ident) => {
|
||||
impl Encodable for $name {
|
||||
@ -82,6 +181,24 @@ macro_rules! impl_encodable_for_hash {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_decodable_for_hash {
|
||||
($name: ident, $size: expr) => {
|
||||
impl Decodable for $name {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) {
|
||||
cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort),
|
||||
cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig),
|
||||
cmp::Ordering::Equal => {
|
||||
let mut t = [0u8; $size];
|
||||
t.copy_from_slice(bytes);
|
||||
Ok($name(t))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_encodable_for_hash!(H64);
|
||||
impl_encodable_for_hash!(H128);
|
||||
impl_encodable_for_hash!(H160);
|
||||
@ -90,6 +207,14 @@ impl_encodable_for_hash!(H512);
|
||||
impl_encodable_for_hash!(H520);
|
||||
impl_encodable_for_hash!(H2048);
|
||||
|
||||
impl_decodable_for_hash!(H64, 8);
|
||||
impl_decodable_for_hash!(H128, 16);
|
||||
impl_decodable_for_hash!(H160, 20);
|
||||
impl_decodable_for_hash!(H256, 32);
|
||||
impl_decodable_for_hash!(H512, 64);
|
||||
impl_decodable_for_hash!(H520, 65);
|
||||
impl_decodable_for_hash!(H2048, 256);
|
||||
|
||||
macro_rules! impl_encodable_for_uint {
|
||||
($name: ident, $size: expr) => {
|
||||
impl Encodable for $name {
|
||||
@ -103,9 +228,30 @@ macro_rules! impl_encodable_for_uint {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_decodable_for_uint {
|
||||
($name: ident, $size: expr) => {
|
||||
impl Decodable for $name {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| {
|
||||
if !bytes.is_empty() && bytes[0] == 0 {
|
||||
Err(DecoderError::RlpInvalidIndirection)
|
||||
} else if bytes.len() <= $size {
|
||||
Ok($name::from(bytes))
|
||||
} else {
|
||||
Err(DecoderError::RlpIsTooBig)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_encodable_for_uint!(U256, 32);
|
||||
impl_encodable_for_uint!(U128, 16);
|
||||
|
||||
impl_decodable_for_uint!(U256, 32);
|
||||
impl_decodable_for_uint!(U128, 16);
|
||||
|
||||
impl<'a> Encodable for &'a str {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.encoder().encode_value(self.as_bytes());
|
||||
@ -118,3 +264,14 @@ impl Encodable for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for String {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| {
|
||||
match str::from_utf8(bytes) {
|
||||
Ok(s) => Ok(s.to_owned()),
|
||||
// consider better error type here
|
||||
Err(_err) => Err(DecoderError::RlpExpectedToBeData),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -61,17 +61,13 @@ mod untrusted_rlp;
|
||||
mod stream;
|
||||
mod compression;
|
||||
mod common;
|
||||
mod bytes;
|
||||
mod impls;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use elastic_array::ElasticArray1024;
|
||||
|
||||
pub use error::DecoderError;
|
||||
pub use traits::{Decoder, Decodable, View, Encodable, RlpDecodable, Compressible};
|
||||
pub use traits::{Decodable, Encodable, Compressible};
|
||||
pub use untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype};
|
||||
pub use rlpin::{Rlp, RlpIterator};
|
||||
pub use stream::RlpStream;
|
||||
@ -88,16 +84,21 @@ pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1];
|
||||
/// extern crate rlp;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let animals: Vec<String> = rlp::decode(&data);
|
||||
/// assert_eq!(animals, vec!["cat".to_string(), "dog".to_string()]);
|
||||
/// let data = vec![0x83, b'c', b'a', b't'];
|
||||
/// let animal: String = rlp::decode(&data);
|
||||
/// assert_eq!(animal, "cat".to_owned());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn decode<T>(bytes: &[u8]) -> T where T: RlpDecodable {
|
||||
pub fn decode<T>(bytes: &[u8]) -> T where T: Decodable {
|
||||
let rlp = Rlp::new(bytes);
|
||||
rlp.as_val()
|
||||
}
|
||||
|
||||
pub fn decode_list<T>(bytes: &[u8]) -> Vec<T> where T: Decodable {
|
||||
let rlp = Rlp::new(bytes);
|
||||
rlp.as_list()
|
||||
}
|
||||
|
||||
/// Shortcut function to encode structure into rlp.
|
||||
///
|
||||
/// ```rust
|
||||
|
@ -15,8 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
use {View, DecoderError, UntrustedRlp, PayloadInfo, Prototype, RlpDecodable};
|
||||
use {UntrustedRlp, PayloadInfo, Prototype, Decodable};
|
||||
|
||||
impl<'a> From<UntrustedRlp<'a>> for Rlp<'a> {
|
||||
fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> {
|
||||
@ -39,95 +38,215 @@ impl<'a> fmt::Display for Rlp<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'view> View<'a, 'view> for Rlp<'a> where 'a: 'view {
|
||||
type Prototype = Prototype;
|
||||
type PayloadInfo = PayloadInfo;
|
||||
type Data = &'a [u8];
|
||||
type Item = Rlp<'a>;
|
||||
type Iter = RlpIterator<'a, 'view>;
|
||||
|
||||
impl<'a, 'view> Rlp<'a> where 'a: 'view {
|
||||
/// Create a new instance of `Rlp`
|
||||
fn new(bytes: &'a [u8]) -> Rlp<'a> {
|
||||
pub fn new(bytes: &'a [u8]) -> Rlp<'a> {
|
||||
Rlp {
|
||||
rlp: UntrustedRlp::new(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_raw(&'view self) -> &'a [u8] {
|
||||
/// The raw data of the RLP as slice.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let dog = rlp.at(1).as_raw();
|
||||
/// assert_eq!(dog, &[0x83, b'd', b'o', b'g']);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn as_raw(&'view self) -> &'a [u8] {
|
||||
self.rlp.as_raw()
|
||||
}
|
||||
|
||||
fn prototype(&self) -> Self::Prototype {
|
||||
/// Get the prototype of the RLP.
|
||||
pub fn prototype(&self) -> Prototype {
|
||||
self.rlp.prototype().unwrap()
|
||||
}
|
||||
|
||||
fn payload_info(&self) -> Self::PayloadInfo {
|
||||
/// Get payload info.
|
||||
pub fn payload_info(&self) -> PayloadInfo {
|
||||
self.rlp.payload_info().unwrap()
|
||||
}
|
||||
|
||||
fn data(&'view self) -> Self::Data {
|
||||
/// Get underlieing data.
|
||||
pub fn data(&'view self) -> &'a [u8] {
|
||||
self.rlp.data().unwrap()
|
||||
}
|
||||
|
||||
fn item_count(&self) -> usize {
|
||||
self.rlp.item_count()
|
||||
/// Returns number of RLP items.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.item_count(), 2);
|
||||
/// let view = rlp.at(1);
|
||||
/// assert_eq!(view.item_count(), 0);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn item_count(&self) -> usize {
|
||||
self.rlp.item_count().unwrap_or(0)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
/// Returns the number of bytes in the data, or zero if it isn't data.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.size(), 0);
|
||||
/// let view = rlp.at(1);
|
||||
/// assert_eq!(view.size(), 3);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn size(&self) -> usize {
|
||||
self.rlp.size()
|
||||
}
|
||||
|
||||
fn at(&'view self, index: usize) -> Self::Item {
|
||||
/// Get view onto RLP-slice at index.
|
||||
///
|
||||
/// Caches offset to given index, so access to successive
|
||||
/// slices is faster.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let dog: String = rlp.at(1).as_val();
|
||||
/// assert_eq!(dog, "dog".to_string());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn at(&'view self, index: usize) -> Rlp<'a> {
|
||||
From::from(self.rlp.at(index).unwrap())
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
/// No value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_null());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.rlp.is_null()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
/// Contains a zero-length string or zero-length list.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc0];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_empty());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.rlp.is_empty()
|
||||
}
|
||||
|
||||
fn is_list(&self) -> bool {
|
||||
/// List value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_list());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn is_list(&self) -> bool {
|
||||
self.rlp.is_list()
|
||||
}
|
||||
|
||||
fn is_data(&self) -> bool {
|
||||
/// String value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.at(1).is_data());
|
||||
/// }
|
||||
/// ```
|
||||
pub fn is_data(&self) -> bool {
|
||||
self.rlp.is_data()
|
||||
}
|
||||
|
||||
fn is_int(&self) -> bool {
|
||||
/// Int value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc1, 0x10];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.is_int(), false);
|
||||
/// assert_eq!(rlp.at(0).is_int(), true);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn is_int(&self) -> bool {
|
||||
self.rlp.is_int()
|
||||
}
|
||||
|
||||
fn iter(&'view self) -> Self::Iter {
|
||||
/// Get iterator over rlp-slices
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let strings: Vec<String> = rlp.iter().map(| i | i.as_val()).collect();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn iter(&'view self) -> RlpIterator<'a, 'view> {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
self.rlp.as_val()
|
||||
/// Decode data into an object
|
||||
pub fn as_val<T>(&self) -> T where T: Decodable {
|
||||
self.rlp.as_val().expect("Unexpected rlp error")
|
||||
}
|
||||
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
self.at(index).rlp.as_val()
|
||||
}
|
||||
pub fn as_list<T>(&self) -> Vec<T> where T: Decodable {
|
||||
self.iter().map(|rlp| rlp.as_val()).collect()
|
||||
}
|
||||
|
||||
impl <'a, 'view> Rlp<'a> where 'a: 'view {
|
||||
fn view_as_val<T, R>(r: &'view R) -> T where R: View<'a, 'view>, T: RlpDecodable {
|
||||
let res: Result<T, DecoderError> = r.as_val();
|
||||
res.unwrap_or_else(|e| panic!("DecodeError: {}, {}", e, r.as_raw().to_hex()))
|
||||
/// Decode data at given list index into an object
|
||||
pub fn val_at<T>(&self, index: usize) -> T where T: Decodable {
|
||||
self.at(index).as_val()
|
||||
}
|
||||
|
||||
/// Decode into an object
|
||||
pub fn as_val<T>(&self) -> T where T: RlpDecodable {
|
||||
Self::view_as_val(self)
|
||||
}
|
||||
|
||||
/// Decode list item at given index into an object
|
||||
pub fn val_at<T>(&self, index: usize) -> T where T: RlpDecodable {
|
||||
Self::view_as_val(&self.at(index))
|
||||
pub fn list_at<T>(&self, index: usize) -> Vec<T> where T: Decodable {
|
||||
self.at(index).as_list()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,212 +16,12 @@
|
||||
|
||||
//! Common RLP traits
|
||||
use elastic_array::ElasticArray1024;
|
||||
use stream::RlpStream;
|
||||
use {DecoderError, UntrustedRlp};
|
||||
|
||||
/// Type is able to decode RLP.
|
||||
pub trait Decoder: Sized {
|
||||
/// Read a value from the RLP into a given type.
|
||||
fn read_value<T, F>(&self, f: &F) -> Result<T, DecoderError>
|
||||
where F: Fn(&[u8]) -> Result<T, DecoderError>;
|
||||
|
||||
/// Get underlying `UntrustedRLP` object.
|
||||
fn as_rlp(&self) -> &UntrustedRlp;
|
||||
/// Get underlying raw bytes slice.
|
||||
fn as_raw(&self) -> &[u8];
|
||||
}
|
||||
use {DecoderError, UntrustedRlp, RlpStream};
|
||||
|
||||
/// RLP decodable trait
|
||||
pub trait Decodable: Sized {
|
||||
/// Decode a value from RLP bytes
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder;
|
||||
}
|
||||
|
||||
/// Internal helper trait. Implement `Decodable` for custom types.
|
||||
pub trait RlpDecodable: Sized {
|
||||
/// Decode a value from RLP bytes
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder;
|
||||
}
|
||||
|
||||
/// A view into RLP encoded data
|
||||
pub trait View<'a, 'view>: Sized {
|
||||
/// RLP prototype type
|
||||
type Prototype;
|
||||
/// Payload info type
|
||||
type PayloadInfo;
|
||||
/// Data type
|
||||
type Data;
|
||||
/// Item type
|
||||
type Item;
|
||||
/// Iterator type
|
||||
type Iter;
|
||||
|
||||
/// Creates a new instance of `Rlp` reader
|
||||
fn new(bytes: &'a [u8]) -> Self;
|
||||
|
||||
/// The raw data of the RLP as slice.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let dog = rlp.at(1).as_raw();
|
||||
/// assert_eq!(dog, &[0x83, b'd', b'o', b'g']);
|
||||
/// }
|
||||
/// ```
|
||||
fn as_raw(&'view self) -> &'a [u8];
|
||||
|
||||
/// Get the prototype of the RLP.
|
||||
fn prototype(&self) -> Self::Prototype;
|
||||
|
||||
/// Get payload info.
|
||||
fn payload_info(&self) -> Self::PayloadInfo;
|
||||
|
||||
/// Get underlieing data.
|
||||
fn data(&'view self) -> Self::Data;
|
||||
|
||||
/// Returns number of RLP items.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.item_count(), 2);
|
||||
/// let view = rlp.at(1);
|
||||
/// assert_eq!(view.item_count(), 0);
|
||||
/// }
|
||||
/// ```
|
||||
fn item_count(&self) -> usize;
|
||||
|
||||
/// Returns the number of bytes in the data, or zero if it isn't data.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.size(), 0);
|
||||
/// let view = rlp.at(1);
|
||||
/// assert_eq!(view.size(), 3);
|
||||
/// }
|
||||
/// ```
|
||||
fn size(&self) -> usize;
|
||||
|
||||
/// Get view onto RLP-slice at index.
|
||||
///
|
||||
/// Caches offset to given index, so access to successive
|
||||
/// slices is faster.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let dog: String = rlp.at(1).as_val();
|
||||
/// assert_eq!(dog, "dog".to_string());
|
||||
/// }
|
||||
fn at(&'view self, index: usize) -> Self::Item;
|
||||
|
||||
/// No value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_null());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_null(&self) -> bool;
|
||||
|
||||
/// Contains a zero-length string or zero-length list.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc0];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_empty());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_empty(&self) -> bool;
|
||||
|
||||
/// List value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_list());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_list(&self) -> bool;
|
||||
|
||||
/// String value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.at(1).is_data());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_data(&self) -> bool;
|
||||
|
||||
/// Int value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc1, 0x10];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.is_int(), false);
|
||||
/// assert_eq!(rlp.at(0).is_int(), true);
|
||||
/// }
|
||||
/// ```
|
||||
fn is_int(&self) -> bool;
|
||||
|
||||
/// Get iterator over rlp-slices
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rlp;
|
||||
/// use rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let strings: Vec<String> = rlp.iter().map(| i | i.as_val()).collect();
|
||||
/// }
|
||||
/// ```
|
||||
fn iter(&'view self) -> Self::Iter;
|
||||
|
||||
/// Decode data into an object
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable;
|
||||
|
||||
/// Decode data at given list index into an object
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable;
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError>;
|
||||
}
|
||||
|
||||
/// Structure encodable to RLP
|
||||
|
@ -17,9 +17,8 @@
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
|
||||
use bytes::{FromBytes, FromBytesResult, FromBytesError};
|
||||
use ::{View, Decoder, Decodable, DecoderError, RlpDecodable};
|
||||
use impls::decode_usize;
|
||||
use {Decodable, DecoderError};
|
||||
|
||||
/// rlp offset
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -64,7 +63,7 @@ fn calculate_payload_info(header_bytes: &[u8], len_of_len: usize) -> Result<Payl
|
||||
_ => (),
|
||||
}
|
||||
if header_bytes.len() < header_len { return Err(DecoderError::RlpIsTooShort); }
|
||||
let value_len = usize::from_bytes(&header_bytes[1..header_len])?;
|
||||
let value_len = decode_usize(&header_bytes[1..header_len])?;
|
||||
Ok(PayloadInfo::new(header_len, value_len))
|
||||
}
|
||||
|
||||
@ -141,15 +140,8 @@ impl<'a> fmt::Display for UntrustedRlp<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
type Prototype = Result<Prototype, DecoderError>;
|
||||
type PayloadInfo = Result<PayloadInfo, DecoderError>;
|
||||
type Data = Result<&'a [u8], DecoderError>;
|
||||
type Item = Result<UntrustedRlp<'a>, DecoderError>;
|
||||
type Iter = UntrustedRlpIterator<'a, 'view>;
|
||||
|
||||
//returns new instance of `UntrustedRlp`
|
||||
fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> {
|
||||
impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
|
||||
pub fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> {
|
||||
UntrustedRlp {
|
||||
bytes: bytes,
|
||||
offset_cache: Cell::new(OffsetCache::new(usize::max_value(), 0)),
|
||||
@ -157,45 +149,45 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
}
|
||||
}
|
||||
|
||||
fn as_raw(&'view self) -> &'a [u8] {
|
||||
pub fn as_raw(&'view self) -> &'a [u8] {
|
||||
self.bytes
|
||||
}
|
||||
|
||||
fn prototype(&self) -> Self::Prototype {
|
||||
pub fn prototype(&self) -> Result<Prototype, DecoderError> {
|
||||
// optimize? && return appropriate errors
|
||||
if self.is_data() {
|
||||
Ok(Prototype::Data(self.size()))
|
||||
} else if self.is_list() {
|
||||
Ok(Prototype::List(self.item_count()))
|
||||
self.item_count().map(Prototype::List)
|
||||
} else {
|
||||
Ok(Prototype::Null)
|
||||
}
|
||||
}
|
||||
|
||||
fn payload_info(&self) -> Self::PayloadInfo {
|
||||
pub fn payload_info(&self) -> Result<PayloadInfo, DecoderError> {
|
||||
BasicDecoder::payload_info(self.bytes)
|
||||
}
|
||||
|
||||
fn data(&'view self) -> Self::Data {
|
||||
pub fn data(&'view self) -> Result<&'a [u8], DecoderError> {
|
||||
let pi = BasicDecoder::payload_info(self.bytes)?;
|
||||
Ok(&self.bytes[pi.header_len..(pi.header_len + pi.value_len)])
|
||||
}
|
||||
|
||||
fn item_count(&self) -> usize {
|
||||
pub fn item_count(&self) -> Result<usize, DecoderError> {
|
||||
match self.is_list() {
|
||||
true => match self.count_cache.get() {
|
||||
Some(c) => c,
|
||||
Some(c) => Ok(c),
|
||||
None => {
|
||||
let c = self.iter().count();
|
||||
self.count_cache.set(Some(c));
|
||||
c
|
||||
Ok(c)
|
||||
}
|
||||
},
|
||||
false => 0
|
||||
false => Err(DecoderError::RlpExpectedToBeList),
|
||||
}
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
pub fn size(&self) -> usize {
|
||||
match self.is_data() {
|
||||
// TODO: No panic on malformed data, but ideally would Err on no PayloadInfo.
|
||||
true => BasicDecoder::payload_info(self.bytes).map(|b| b.value_len).unwrap_or(0),
|
||||
@ -203,7 +195,7 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
}
|
||||
}
|
||||
|
||||
fn at(&'view self, index: usize) -> Self::Item {
|
||||
pub fn at(&'view self, index: usize) -> Result<UntrustedRlp<'a>, DecoderError> {
|
||||
if !self.is_list() {
|
||||
return Err(DecoderError::RlpExpectedToBeList);
|
||||
}
|
||||
@ -213,7 +205,7 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
let c = self.offset_cache.get();
|
||||
let (mut bytes, to_skip) = match c.index <= index {
|
||||
true => (UntrustedRlp::consume(self.bytes, c.offset)?, index - c.index),
|
||||
false => (self.consume_list_prefix()?, index),
|
||||
false => (self.consume_list_payload()?, index),
|
||||
};
|
||||
|
||||
// skip up to x items
|
||||
@ -227,23 +219,23 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
Ok(UntrustedRlp::new(&bytes[0..found.header_len + found.value_len]))
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.bytes.len() == 0
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
!self.is_null() && (self.bytes[0] == 0xc0 || self.bytes[0] == 0x80)
|
||||
}
|
||||
|
||||
fn is_list(&self) -> bool {
|
||||
pub fn is_list(&self) -> bool {
|
||||
!self.is_null() && self.bytes[0] >= 0xc0
|
||||
}
|
||||
|
||||
fn is_data(&self) -> bool {
|
||||
pub fn is_data(&self) -> bool {
|
||||
!self.is_null() && self.bytes[0] < 0xc0
|
||||
}
|
||||
|
||||
fn is_int(&self) -> bool {
|
||||
pub fn is_int(&self) -> bool {
|
||||
if self.is_null() {
|
||||
return false;
|
||||
}
|
||||
@ -256,23 +248,32 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
}
|
||||
}
|
||||
|
||||
fn iter(&'view self) -> Self::Iter {
|
||||
pub fn iter(&'view self) -> UntrustedRlpIterator<'a, 'view> {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
// optimize, so it doesn't use clone (although This clone is cheap)
|
||||
T::decode(&BasicDecoder::new(self.clone()))
|
||||
pub fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
|
||||
T::decode(self)
|
||||
}
|
||||
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
pub fn as_list<T>(&self) -> Result<Vec<T>, DecoderError> where T: Decodable {
|
||||
self.iter().map(|rlp| rlp.as_val()).collect()
|
||||
}
|
||||
|
||||
pub fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
|
||||
self.at(index)?.as_val()
|
||||
}
|
||||
|
||||
pub fn list_at<T>(&self, index: usize) -> Result<Vec<T>, DecoderError> where T: Decodable {
|
||||
self.at(index)?.as_list()
|
||||
}
|
||||
|
||||
pub fn decoder(&self) -> BasicDecoder {
|
||||
BasicDecoder::new(self.clone())
|
||||
}
|
||||
|
||||
impl<'a> UntrustedRlp<'a> {
|
||||
/// consumes first found prefix
|
||||
fn consume_list_prefix(&self) -> Result<&'a [u8], DecoderError> {
|
||||
fn consume_list_payload(&self) -> Result<&'a [u8], DecoderError> {
|
||||
let item = BasicDecoder::payload_info(self.bytes)?;
|
||||
let bytes = UntrustedRlp::consume(self.bytes, item.header_len)?;
|
||||
Ok(bytes)
|
||||
@ -327,7 +328,7 @@ impl<'a, 'view> Iterator for UntrustedRlpIterator<'a, 'view> {
|
||||
}
|
||||
}
|
||||
|
||||
struct BasicDecoder<'a> {
|
||||
pub struct BasicDecoder<'a> {
|
||||
rlp: UntrustedRlp<'a>
|
||||
}
|
||||
|
||||
@ -346,10 +347,8 @@ impl<'a> BasicDecoder<'a> {
|
||||
_ => Err(DecoderError::RlpIsTooShort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decoder for BasicDecoder<'a> {
|
||||
fn read_value<T, F>(&self, f: &F) -> Result<T, DecoderError>
|
||||
pub fn decode_value<T, F>(&self, f: F) -> Result<T, DecoderError>
|
||||
where F: Fn(&[u8]) -> Result<T, DecoderError> {
|
||||
|
||||
let bytes = self.rlp.as_raw();
|
||||
@ -378,7 +377,7 @@ impl<'a> Decoder for BasicDecoder<'a> {
|
||||
if bytes.len() < begin_of_value {
|
||||
return Err(DecoderError::RlpInconsistentLengthAndData);
|
||||
}
|
||||
let len = usize::from_bytes(&bytes[1..begin_of_value])?;
|
||||
let len = decode_usize(&bytes[1..begin_of_value])?;
|
||||
|
||||
let last_index_of_value = begin_of_value + len;
|
||||
if bytes.len() < last_index_of_value {
|
||||
@ -390,108 +389,12 @@ impl<'a> Decoder for BasicDecoder<'a> {
|
||||
_ => Err(DecoderError::RlpExpectedToBeData)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_raw(&self) -> &[u8] {
|
||||
self.rlp.as_raw()
|
||||
}
|
||||
|
||||
fn as_rlp(&self) -> &UntrustedRlp {
|
||||
&self.rlp
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Decodable for T where T: FromBytes {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
decoder.read_value(&|bytes: &[u8]| Ok(T::from_bytes(bytes)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Decodable for Vec<T> where T: Decodable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
decoder.as_rlp().iter().map(|d| T::decode(&BasicDecoder::new(d))).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Decodable for Option<T> where T: Decodable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
decoder.as_rlp().iter().map(|d| T::decode(&BasicDecoder::new(d))).collect::<Result<Vec<_>, DecoderError>>().map(|mut a| a.pop())
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Vec<u8> {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
decoder.read_value(&|bytes: &[u8]| Ok(bytes.to_vec()))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_array_decodable {
|
||||
($index_type:ty, $len:expr ) => (
|
||||
impl<T> Decodable for [T; $len] where T: Decodable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let decoders = decoder.as_rlp();
|
||||
|
||||
let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() };
|
||||
if decoders.item_count() != $len {
|
||||
return Err(DecoderError::RlpIncorrectListLen);
|
||||
}
|
||||
|
||||
for i in 0..decoders.item_count() {
|
||||
result[i] = T::decode(&BasicDecoder::new(decoders.at(i)?))?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! impl_array_decodable_recursive {
|
||||
($index_type:ty, ) => ();
|
||||
($index_type:ty, $len:expr, $($more:expr,)*) => (
|
||||
impl_array_decodable!($index_type, $len);
|
||||
impl_array_decodable_recursive!($index_type, $($more,)*);
|
||||
);
|
||||
}
|
||||
|
||||
impl_array_decodable_recursive!(
|
||||
u8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,
|
||||
);
|
||||
|
||||
impl<T> RlpDecodable for T where T: Decodable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
Decodable::decode(decoder)
|
||||
}
|
||||
}
|
||||
|
||||
struct DecodableU8 (u8);
|
||||
|
||||
impl FromBytes for DecodableU8 {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<DecodableU8> {
|
||||
match bytes.len() {
|
||||
0 => Ok(DecodableU8(0u8)),
|
||||
1 => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(FromBytesError::ZeroPrefixedInt)
|
||||
}
|
||||
Ok(DecodableU8(bytes[0]))
|
||||
}
|
||||
_ => Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RlpDecodable for u8 {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let u: DecodableU8 = Decodable::decode(decoder)?;
|
||||
Ok(u.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ::{UntrustedRlp, View};
|
||||
use UntrustedRlp;
|
||||
|
||||
#[test]
|
||||
fn test_rlp_display() {
|
||||
use rustc_serialize::hex::FromHex;
|
||||
|
@ -14,9 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate ethcore_bigint as bigint;
|
||||
extern crate rlp;
|
||||
|
||||
use std::{fmt, cmp};
|
||||
use bigint::prelude::U256;
|
||||
use {Encodable, RlpDecodable, UntrustedRlp, RlpStream, View, DecoderError};
|
||||
use rlp::{Encodable, Decodable, UntrustedRlp, RlpStream, DecoderError};
|
||||
|
||||
#[test]
|
||||
fn rlp_at() {
|
||||
@ -24,7 +27,7 @@ fn rlp_at() {
|
||||
{
|
||||
let rlp = UntrustedRlp::new(&data);
|
||||
assert!(rlp.is_list());
|
||||
let animals: Vec<String> = rlp.as_val().unwrap();
|
||||
let animals: Vec<String> = rlp.as_list().unwrap();
|
||||
assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]);
|
||||
|
||||
let cat = rlp.at(0).unwrap();
|
||||
@ -89,7 +92,7 @@ fn run_encode_tests<T>(tests: Vec<ETestPair<T>>)
|
||||
where T: Encodable
|
||||
{
|
||||
for t in &tests {
|
||||
let res = super::encode(&t.0);
|
||||
let res = rlp::encode(&t.0);
|
||||
assert_eq!(&res[..], &t.1[..]);
|
||||
}
|
||||
}
|
||||
@ -100,7 +103,7 @@ fn run_encode_tests_list<T>(tests: Vec<VETestPair<T>>)
|
||||
where T: Encodable
|
||||
{
|
||||
for t in &tests {
|
||||
let res = super::encode_list(&t.0);
|
||||
let res = rlp::encode_list(&t.0);
|
||||
assert_eq!(&res[..], &t.1[..]);
|
||||
}
|
||||
}
|
||||
@ -210,11 +213,20 @@ fn encode_vector_str() {
|
||||
run_encode_tests_list(tests);
|
||||
}
|
||||
|
||||
struct DTestPair<T>(T, Vec<u8>) where T: RlpDecodable + fmt::Debug + cmp::Eq;
|
||||
struct DTestPair<T>(T, Vec<u8>) where T: Decodable + fmt::Debug + cmp::Eq;
|
||||
|
||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: RlpDecodable + fmt::Debug + cmp::Eq {
|
||||
struct VDTestPair<T>(Vec<T>, Vec<u8>) where T: Decodable + fmt::Debug + cmp::Eq;
|
||||
|
||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: Decodable + fmt::Debug + cmp::Eq {
|
||||
for t in &tests {
|
||||
let res: T = super::decode(&t.1);
|
||||
let res: T = rlp::decode(&t.1);
|
||||
assert_eq!(res, t.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_decode_tests_list<T>(tests: Vec<VDTestPair<T>>) where T: Decodable + fmt::Debug + cmp::Eq {
|
||||
for t in &tests {
|
||||
let res: Vec<T> = rlp::decode_list(&t.1);
|
||||
assert_eq!(res, t.0);
|
||||
}
|
||||
}
|
||||
@ -318,35 +330,19 @@ fn decode_untrusted_address() {
|
||||
#[test]
|
||||
fn decode_untrusted_vector_u64() {
|
||||
let tests = vec![
|
||||
DTestPair(vec![], vec![0xc0]),
|
||||
DTestPair(vec![15u64], vec![0xc1, 0x0f]),
|
||||
DTestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]),
|
||||
DTestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]),
|
||||
VDTestPair(vec![], vec![0xc0]),
|
||||
VDTestPair(vec![15u64], vec![0xc1, 0x0f]),
|
||||
VDTestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]),
|
||||
VDTestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]),
|
||||
];
|
||||
run_decode_tests(tests);
|
||||
run_decode_tests_list(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_untrusted_vector_str() {
|
||||
let tests = vec![DTestPair(vec!["cat".to_owned(), "dog".to_owned()],
|
||||
let tests = vec![VDTestPair(vec!["cat".to_owned(), "dog".to_owned()],
|
||||
vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])];
|
||||
run_decode_tests(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_untrusted_vector_of_vectors_str() {
|
||||
let tests = vec![DTestPair(vec![vec!["cat".to_owned()]],
|
||||
vec![0xc5, 0xc4, 0x83, b'c', b'a', b't'])];
|
||||
run_decode_tests(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decoding_array() {
|
||||
let v = vec![5u16, 2u16];
|
||||
let res = super::encode_list(&v);
|
||||
let arr: [u16; 2] = super::decode(&res);
|
||||
assert_eq!(arr[0], 5);
|
||||
assert_eq!(arr[1], 2);
|
||||
run_decode_tests_list(tests);
|
||||
}
|
||||
|
||||
#[test]
|
@ -290,7 +290,7 @@ impl EarlyMergeDB {
|
||||
&r.drain()
|
||||
}).expect("Low-level database error.") {
|
||||
let rlp = Rlp::new(&rlp_data);
|
||||
let inserts: Vec<H256> = rlp.val_at(1);
|
||||
let inserts: Vec<H256> = rlp.list_at(1);
|
||||
Self::replay_keys(&inserts, db, col, &mut refs);
|
||||
index += 1;
|
||||
};
|
||||
@ -466,11 +466,11 @@ impl JournalDB for EarlyMergeDB {
|
||||
&last
|
||||
})? {
|
||||
let rlp = Rlp::new(&rlp_data);
|
||||
let inserts: Vec<H256> = rlp.val_at(1);
|
||||
let inserts: Vec<H256> = rlp.list_at(1);
|
||||
|
||||
if canon_id == &rlp.val_at::<H256>(0) {
|
||||
// Collect keys to be removed. Canon block - remove the (enacted) deletes.
|
||||
let deletes: Vec<H256> = rlp.val_at(2);
|
||||
let deletes: Vec<H256> = rlp.list_at(2);
|
||||
trace!(target: "jdb.ops", " Expunging: {:?}", deletes);
|
||||
Self::remove_keys(&deletes, &mut refs, batch, self.column, RemoveFrom::Archive, trace);
|
||||
|
||||
|
@ -155,7 +155,7 @@ impl OverlayRecentDB {
|
||||
let rlp = Rlp::new(&rlp_data);
|
||||
let id: H256 = rlp.val_at(0);
|
||||
let insertions = rlp.at(1);
|
||||
let deletions: Vec<H256> = rlp.val_at(2);
|
||||
let deletions: Vec<H256> = rlp.list_at(2);
|
||||
let mut inserted_keys = Vec::new();
|
||||
for r in insertions.iter() {
|
||||
let k: H256 = r.val_at(0);
|
||||
|
@ -171,7 +171,7 @@ impl JournalDB for RefCountedDB {
|
||||
} {
|
||||
let rlp = Rlp::new(&rlp_data);
|
||||
let our_id: H256 = rlp.val_at(0);
|
||||
let to_remove: Vec<H256> = rlp.val_at(if *canon_id == our_id {2} else {1});
|
||||
let to_remove: Vec<H256> = rlp.list_at(if *canon_id == our_id {2} else {1});
|
||||
trace!(target: "rcdb", "delete journal for time #{}.{}=>{}, (canon was {}): deleting {:?}", end_era, index, our_id, canon_id, to_remove);
|
||||
for i in &to_remove {
|
||||
self.forward.remove(i);
|
||||
|
@ -23,7 +23,7 @@ use std::path::PathBuf;
|
||||
use common::*;
|
||||
use elastic_array::*;
|
||||
use hashdb::DBValue;
|
||||
use rlp::{UntrustedRlp, RlpType, View, Compressible};
|
||||
use rlp::{UntrustedRlp, RlpType, Compressible};
|
||||
use rocksdb::{DB, Writable, WriteBatch, WriteOptions, IteratorMode, DBIterator,
|
||||
Options, DBCompactionStyle, BlockBasedOptions, Direction, Cache, Column, ReadOptions};
|
||||
#[cfg(target_os = "linux")]
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
use hashdb::HashDB;
|
||||
use nibbleslice::NibbleSlice;
|
||||
use rlp::{Rlp, View};
|
||||
use rlp::Rlp;
|
||||
use ::{H256};
|
||||
|
||||
use super::{TrieError, Query};
|
||||
|
@ -24,7 +24,7 @@ use super::node::NodeKey;
|
||||
use ::{HashDB, H256};
|
||||
use ::bytes::ToPretty;
|
||||
use ::nibbleslice::NibbleSlice;
|
||||
use ::rlp::{Rlp, RlpStream, View};
|
||||
use ::rlp::{Rlp, RlpStream};
|
||||
use ::sha3::SHA3_NULL_RLP;
|
||||
use hashdb::DBValue;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user