Rlp decode returns Result (#8527)

rlp::decode returns Result

Make a best effort to handle decoding errors gracefully throughout the code, using `expect` where the value is guaranteed to be valid (and in other places where it makes sense).
This commit is contained in:
David 2018-05-08 11:22:12 +02:00 committed by GitHub
parent a7a46f4253
commit 28c731881f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 108 additions and 91 deletions

View File

@ -228,7 +228,7 @@ impl HeaderChain {
let decoded_header = spec.genesis_header(); let decoded_header = spec.genesis_header();
let chain = if let Some(current) = db.get(col, CURRENT_KEY)? { let chain = if let Some(current) = db.get(col, CURRENT_KEY)? {
let curr : BestAndLatest = ::rlp::decode(&current); let curr : BestAndLatest = ::rlp::decode(&current).expect("decoding db value failed");
let mut cur_number = curr.latest_num; let mut cur_number = curr.latest_num;
let mut candidates = BTreeMap::new(); let mut candidates = BTreeMap::new();
@ -236,7 +236,7 @@ impl HeaderChain {
// load all era entries, referenced headers within them, // load all era entries, referenced headers within them,
// and live epoch proofs. // and live epoch proofs.
while let Some(entry) = db.get(col, era_key(cur_number).as_bytes())? { while let Some(entry) = db.get(col, era_key(cur_number).as_bytes())? {
let entry: Entry = ::rlp::decode(&entry); let entry: Entry = ::rlp::decode(&entry).expect("decoding db value failed");
trace!(target: "chain", "loaded header chain entry for era {} with {} candidates", trace!(target: "chain", "loaded header chain entry for era {} with {} candidates",
cur_number, entry.candidates.len()); cur_number, entry.candidates.len());
@ -524,7 +524,10 @@ impl HeaderChain {
None None
} }
Ok(None) => panic!("stored candidates always have corresponding headers; qed"), Ok(None) => panic!("stored candidates always have corresponding headers; qed"),
Ok(Some(header)) => Some((epoch_transition, ::rlp::decode(&header))), Ok(Some(header)) => Some((
epoch_transition,
::rlp::decode(&header).expect("decoding value from db failed")
)),
}; };
} }
} }
@ -591,7 +594,7 @@ impl HeaderChain {
in an inconsistent state", h_num); in an inconsistent state", h_num);
ErrorKind::Database(msg.into()) ErrorKind::Database(msg.into())
})?; })?;
::rlp::decode(&bytes) ::rlp::decode(&bytes).expect("decoding db value failed")
}; };
let total_difficulty = entry.candidates.iter() let total_difficulty = entry.candidates.iter()
@ -604,9 +607,9 @@ impl HeaderChain {
.total_difficulty; .total_difficulty;
break Ok(Some(SpecHardcodedSync { break Ok(Some(SpecHardcodedSync {
header: header, header,
total_difficulty: total_difficulty, total_difficulty,
chts: chts, chts,
})); }));
}, },
None => { None => {
@ -742,7 +745,7 @@ impl HeaderChain {
/// so including it within a CHT would be redundant. /// so including it within a CHT would be redundant.
pub fn cht_root(&self, n: usize) -> Option<H256> { pub fn cht_root(&self, n: usize) -> Option<H256> {
match self.db.get(self.col, cht_key(n as u64).as_bytes()) { match self.db.get(self.col, cht_key(n as u64).as_bytes()) {
Ok(val) => val.map(|x| ::rlp::decode(&x)), Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")),
Err(e) => { Err(e) => {
warn!(target: "chain", "Error reading from database: {}", e); warn!(target: "chain", "Error reading from database: {}", e);
None None
@ -793,7 +796,7 @@ impl HeaderChain {
pub fn pending_transition(&self, hash: H256) -> Option<PendingEpochTransition> { pub fn pending_transition(&self, hash: H256) -> Option<PendingEpochTransition> {
let key = pending_transition_key(hash); let key = pending_transition_key(hash);
match self.db.get(self.col, &*key) { match self.db.get(self.col, &*key) {
Ok(val) => val.map(|x| ::rlp::decode(&x)), Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")),
Err(e) => { Err(e) => {
warn!(target: "chain", "Error reading from database: {}", e); warn!(target: "chain", "Error reading from database: {}", e);
None None
@ -1192,7 +1195,7 @@ mod tests {
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).expect("failed to instantiate a new HeaderChain");
let mut parent_hash = genesis_header.hash(); let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp(); let mut rolling_timestamp = genesis_header.timestamp();
@ -1211,14 +1214,14 @@ mod tests {
parent_hash = header.hash(); parent_hash = header.hash();
let mut tx = db.transaction(); let mut tx = db.transaction();
let pending = chain.insert(&mut tx, header, None).unwrap(); let pending = chain.insert(&mut tx, header, None).expect("failed inserting a transaction");
db.write(tx).unwrap(); db.write(tx).unwrap();
chain.apply_pending(pending); chain.apply_pending(pending);
rolling_timestamp += 10; rolling_timestamp += 10;
} }
let hardcoded_sync = chain.read_hardcoded_sync().unwrap().unwrap(); let hardcoded_sync = chain.read_hardcoded_sync().expect("failed reading hardcoded sync").expect("failed unwrapping hardcoded sync");
assert_eq!(hardcoded_sync.chts.len(), 3); assert_eq!(hardcoded_sync.chts.len(), 3);
assert_eq!(hardcoded_sync.total_difficulty, total_difficulty); assert_eq!(hardcoded_sync.total_difficulty, total_difficulty);
let decoded: Header = hardcoded_sync.header.decode(); let decoded: Header = hardcoded_sync.header.decode();

View File

@ -407,7 +407,7 @@ mod tests {
let costs = CostTable::default(); let costs = CostTable::default();
let serialized = ::rlp::encode(&costs); let serialized = ::rlp::encode(&costs);
let new_costs: CostTable = ::rlp::decode(&*serialized); let new_costs: CostTable = ::rlp::decode(&*serialized).unwrap();
assert_eq!(costs, new_costs); assert_eq!(costs, new_costs);
} }

View File

@ -1642,7 +1642,7 @@ mod tests {
{ {
// check as single value. // check as single value.
let bytes = ::rlp::encode(&val); let bytes = ::rlp::encode(&val);
let new_val: T = ::rlp::decode(&bytes); let new_val: T = ::rlp::decode(&bytes).unwrap();
assert_eq!(val, new_val); assert_eq!(val, new_val);
// check as list containing single value. // check as list containing single value.

View File

@ -438,7 +438,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
return None return None
} }
let transitions: EpochTransitions = ::rlp::decode(&val[..]); let transitions: EpochTransitions = ::rlp::decode(&val[..]).expect("decode error: the db is corrupted or the data structure has changed");
// if there are multiple candidates, at most one will be on the // if there are multiple candidates, at most one will be on the
// canon chain. // canon chain.
@ -462,7 +462,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
impl BlockChain { impl BlockChain {
/// Create new instance of blockchain from given Genesis. /// Create new instance of blockchain from given Genesis.
pub fn new(config: Config, genesis: &[u8], db: Arc<KeyValueDB>) -> BlockChain { pub fn new(config: Config, genesis: &[u8], db: Arc<KeyValueDB>) -> BlockChain {
// 400 is the avarage size of the key // 400 is the average size of the key
let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400); let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400);
let mut bc = BlockChain { let mut bc = BlockChain {

View File

@ -218,15 +218,12 @@ impl Writable for DBTransaction {
} }
impl<KVDB: KeyValueDB + ?Sized> Readable for KVDB { impl<KVDB: KeyValueDB + ?Sized> Readable for KVDB {
fn read<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> Option<T> where T: rlp::Decodable, R: Deref<Target = [u8]> { fn read<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> Option<T>
let result = self.get(col, &key.key()); where T: rlp::Decodable, R: Deref<Target = [u8]> {
self.get(col, &key.key())
.expect(&format!("db get failed, key: {:?}", &key.key() as &[u8]))
.map(|v| rlp::decode(&v).expect("decode db value failed") )
match result {
Ok(option) => option.map(|v| rlp::decode(&v)),
Err(err) => {
panic!("db get failed, key: {:?}, err: {:?}", &key.key() as &[u8], err);
}
}
} }
fn exists<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> bool where R: Deref<Target = [u8]> { fn exists<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> bool where R: Deref<Target = [u8]> {

View File

@ -24,13 +24,12 @@
//! decoded object where parts like the hash can be saved. //! decoded object where parts like the hash can be saved.
use block::Block as FullBlock; use block::Block as FullBlock;
use header::{BlockNumber, Header as FullHeader};
use transaction::UnverifiedTransaction;
use hash::keccak;
use heapsize::HeapSizeOf;
use ethereum_types::{H256, Bloom, U256, Address}; use ethereum_types::{H256, Bloom, U256, Address};
use hash::keccak;
use header::{BlockNumber, Header as FullHeader};
use heapsize::HeapSizeOf;
use rlp::{Rlp, RlpStream}; use rlp::{Rlp, RlpStream};
use transaction::UnverifiedTransaction;
use views::{self, BlockView, HeaderView, BodyView}; use views::{self, BlockView, HeaderView, BodyView};
/// Owning header view. /// Owning header view.
@ -48,7 +47,7 @@ impl Header {
pub fn new(encoded: Vec<u8>) -> Self { Header(encoded) } pub fn new(encoded: Vec<u8>) -> Self { Header(encoded) }
/// Upgrade this encoded view to a fully owned `Header` object. /// Upgrade this encoded view to a fully owned `Header` object.
pub fn decode(&self) -> FullHeader { ::rlp::decode(&self.0) } pub fn decode(&self) -> FullHeader { ::rlp::decode(&self.0).expect("decoding failure") }
/// Get a borrowed header view onto the data. /// Get a borrowed header view onto the data.
#[inline] #[inline]
@ -205,7 +204,7 @@ impl Block {
pub fn header_view(&self) -> HeaderView { self.view().header_view() } pub fn header_view(&self) -> HeaderView { self.view().header_view() }
/// Decode to a full block. /// Decode to a full block.
pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0) } pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0).expect("decoding failure") }
/// Decode the header. /// Decode the header.
pub fn decode_header(&self) -> FullHeader { self.view().rlp().val_at(0) } pub fn decode_header(&self) -> FullHeader { self.view().rlp().val_at(0) }

View File

@ -143,8 +143,10 @@ impl <F> super::EpochVerifier<EthereumMachine> for EpochVerifier<F>
} }
fn check_finality_proof(&self, proof: &[u8]) -> Option<Vec<H256>> { fn check_finality_proof(&self, proof: &[u8]) -> Option<Vec<H256>> {
let header: Header = ::rlp::decode(proof); match ::rlp::decode(proof) {
self.verify_light(&header).ok().map(|_| vec![header.hash()]) Ok(header) => self.verify_light(&header).ok().map(|_| vec![header.hash()]),
Err(_) => None // REVIEW: log perhaps? Not sure what the policy is.
}
} }
} }

View File

@ -398,7 +398,7 @@ mod tests {
let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap(); let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap();
let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap(); let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap();
let header: Header = rlp::decode(&header_rlp); let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
let seal_fields = header.seal.clone(); let seal_fields = header.seal.clone();
assert_eq!(seal_fields.len(), 2); assert_eq!(seal_fields.len(), 2);
assert_eq!(seal_fields[0], mix_hash); assert_eq!(seal_fields[0], mix_hash);
@ -415,7 +415,7 @@ mod tests {
// that's rlp of block header created with ethash engine. // that's rlp of block header created with ethash engine.
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap(); let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
let header: Header = rlp::decode(&header_rlp); let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
let encoded_header = rlp::encode(&header).into_vec(); let encoded_header = rlp::encode(&header).into_vec();
assert_eq!(header_rlp, encoded_header); assert_eq!(header_rlp, encoded_header);

View File

@ -236,7 +236,7 @@ mod tests {
}; };
let thin_rlp = ::rlp::encode(&account); let thin_rlp = ::rlp::encode(&account);
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), account); assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp).unwrap(), account);
let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap();
let fat_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap(); let fat_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap();
@ -261,7 +261,7 @@ mod tests {
}; };
let thin_rlp = ::rlp::encode(&account); let thin_rlp = ::rlp::encode(&account);
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), account); assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp).unwrap(), account);
let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap();
let fat_rlp = Rlp::new(&fat_rlp[0]).at(1).unwrap(); let fat_rlp = Rlp::new(&fat_rlp[0]).at(1).unwrap();
@ -286,7 +286,7 @@ mod tests {
}; };
let thin_rlp = ::rlp::encode(&account); let thin_rlp = ::rlp::encode(&account);
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), account); assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp).unwrap(), account);
let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap(); let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap();
let mut root = KECCAK_NULL_RLP; let mut root = KECCAK_NULL_RLP;

View File

@ -281,7 +281,7 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter +
// account_key here is the address' hash. // account_key here is the address' hash.
for item in account_trie.iter()? { for item in account_trie.iter()? {
let (account_key, account_data) = item?; let (account_key, account_data) = item?;
let account = ::rlp::decode(&*account_data); let account = ::rlp::decode(&*account_data)?;
let account_key_hash = H256::from_slice(&account_key); let account_key_hash = H256::from_slice(&account_key);
let account_db = AccountDB::from_hash(db, account_key_hash); let account_db = AccountDB::from_hash(db, account_key_hash);
@ -467,10 +467,10 @@ fn rebuild_accounts(
*out = (hash, thin_rlp); *out = (hash, thin_rlp);
} }
if let Some(&(ref hash, ref rlp)) = out_chunk.iter().last() { if let Some(&(ref hash, ref rlp)) = out_chunk.iter().last() {
known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp).storage_root); known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp)?.storage_root);
} }
if let Some(&(ref hash, ref rlp)) = out_chunk.iter().next() { if let Some(&(ref hash, ref rlp)) = out_chunk.iter().next() {
known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp).storage_root); known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp)?.storage_root);
} }
Ok(status) Ok(status)
} }

View File

@ -75,7 +75,7 @@ impl StateProducer {
// sweep once to alter storage tries. // sweep once to alter storage tries.
for &mut (ref mut address_hash, ref mut account_data) in &mut accounts_to_modify { for &mut (ref mut address_hash, ref mut account_data) in &mut accounts_to_modify {
let mut account: BasicAccount = ::rlp::decode(&*account_data); let mut account: BasicAccount = ::rlp::decode(&*account_data).expect("error decoding basic account");
let acct_db = AccountDBMut::from_hash(db, *address_hash); let acct_db = AccountDBMut::from_hash(db, *address_hash);
fill_storage(acct_db, &mut account.storage_root, &mut self.storage_seed); fill_storage(acct_db, &mut account.storage_root, &mut self.storage_seed);
*account_data = DBValue::from_vec(::rlp::encode(&account).into_vec()); *account_data = DBValue::from_vec(::rlp::encode(&account).into_vec());

View File

@ -114,7 +114,7 @@ fn get_code_from_prev_chunk() {
// first one will have code inlined, // first one will have code inlined,
// second will just have its hash. // second will just have its hash.
let thin_rlp = acc_stream.out(); let thin_rlp = acc_stream.out();
let acc: BasicAccount = ::rlp::decode(&thin_rlp); let acc: BasicAccount = ::rlp::decode(&thin_rlp).expect("error decoding basic account");
let mut make_chunk = |acc, hash| { let mut make_chunk = |acc, hash| {
let mut db = MemoryDB::new(); let mut db = MemoryDB::new();

View File

@ -21,6 +21,7 @@ use std::sync::Arc;
use std::collections::{HashMap, BTreeMap}; use std::collections::{HashMap, BTreeMap};
use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak};
use ethereum_types::{H256, U256, Address}; use ethereum_types::{H256, U256, Address};
use error::Error;
use hashdb::HashDB; use hashdb::HashDB;
use kvdb::DBValue; use kvdb::DBValue;
use bytes::{Bytes, ToPretty}; use bytes::{Bytes, ToPretty};
@ -144,9 +145,10 @@ impl Account {
} }
/// Create a new account from RLP. /// Create a new account from RLP.
pub fn from_rlp(rlp: &[u8]) -> Account { pub fn from_rlp(rlp: &[u8]) -> Result<Account, Error> {
let basic: BasicAccount = ::rlp::decode(rlp); ::rlp::decode::<BasicAccount>(rlp)
basic.into() .map(|ba| ba.into())
.map_err(|e| e.into())
} }
/// Create a new contract account. /// Create a new contract account.
@ -202,8 +204,8 @@ impl Account {
return Ok(value); return Ok(value);
} }
let db = SecTrieDB::new(db, &self.storage_root)?; let db = SecTrieDB::new(db, &self.storage_root)?;
let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed");
let item: U256 = db.get_with(key, ::rlp::decode)?.unwrap_or_else(U256::zero); let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero);
let value: H256 = item.into(); let value: H256 = item.into();
self.storage_cache.borrow_mut().insert(key.clone(), value.clone()); self.storage_cache.borrow_mut().insert(key.clone(), value.clone());
Ok(value) Ok(value)
@ -478,7 +480,8 @@ impl Account {
let trie = TrieDB::new(db, &self.storage_root)?; let trie = TrieDB::new(db, &self.storage_root)?;
let item: U256 = { let item: U256 = {
let query = (&mut recorder, ::rlp::decode); let panicky_decoder = |bytes:&[u8]| ::rlp::decode(bytes).expect("decoding db value failed");
let query = (&mut recorder, panicky_decoder);
trie.get_with(&storage_key, query)?.unwrap_or_else(U256::zero) trie.get_with(&storage_key, query)?.unwrap_or_else(U256::zero)
}; };
@ -528,7 +531,7 @@ mod tests {
a.rlp() a.rlp()
}; };
let a = Account::from_rlp(&rlp); let a = Account::from_rlp(&rlp).expect("decoding db value failed");
assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into()); assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into());
assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default()); assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default());
@ -546,10 +549,10 @@ mod tests {
a.rlp() a.rlp()
}; };
let mut a = Account::from_rlp(&rlp); let mut a = Account::from_rlp(&rlp).expect("decoding db value failed");
assert!(a.cache_code(&db.immutable()).is_some()); assert!(a.cache_code(&db.immutable()).is_some());
let mut a = Account::from_rlp(&rlp); let mut a = Account::from_rlp(&rlp).expect("decoding db value failed");
assert_eq!(a.note_code(vec![0x55, 0x44, 0xffu8]), Ok(())); assert_eq!(a.note_code(vec![0x55, 0x44, 0xffu8]), Ok(()));
} }
@ -609,7 +612,7 @@ mod tests {
#[test] #[test]
fn rlpio() { fn rlpio() {
let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new()); let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new());
let b = Account::from_rlp(&a.rlp()); let b = Account::from_rlp(&a.rlp()).unwrap();
assert_eq!(a.balance(), b.balance()); assert_eq!(a.balance(), b.balance());
assert_eq!(a.nonce(), b.nonce()); assert_eq!(a.nonce(), b.nonce());
assert_eq!(a.code_hash(), b.code_hash()); assert_eq!(a.code_hash(), b.code_hash());

View File

@ -605,7 +605,8 @@ impl<B: Backend> State<B> {
// account is not found in the global cache, get from the DB and insert into local // account is not found in the global cache, get from the DB and insert into local
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
let maybe_acc = db.get_with(address, Account::from_rlp)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed");
let maybe_acc = db.get_with(address, from_rlp)?;
let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| {
let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address));
a.storage_at(account_db.as_hashdb(), key) a.storage_at(account_db.as_hashdb(), key)
@ -983,7 +984,8 @@ impl<B: Backend> State<B> {
// not found in the global cache, get from the DB and insert into local // not found in the global cache, get from the DB and insert into local
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?;
let mut maybe_acc = db.get_with(a, Account::from_rlp)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed");
let mut maybe_acc = db.get_with(a, from_rlp)?;
if let Some(ref mut account) = maybe_acc.as_mut() { if let Some(ref mut account) = maybe_acc.as_mut() {
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a));
Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb());
@ -1012,7 +1014,8 @@ impl<B: Backend> State<B> {
None => { None => {
let maybe_acc = if !self.db.is_known_null(a) { let maybe_acc = if !self.db.is_known_null(a) {
let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?;
AccountEntry::new_clean(db.get_with(a, Account::from_rlp)?) let from_rlp = |b:&[u8]| { Account::from_rlp(b).expect("decoding db value failed") };
AccountEntry::new_clean(db.get_with(a, from_rlp)?)
} else { } else {
AccountEntry::new_clean(None) AccountEntry::new_clean(None)
}; };
@ -1064,7 +1067,10 @@ impl<B: Backend> State<B> {
let mut recorder = Recorder::new(); let mut recorder = Recorder::new();
let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?;
let maybe_account: Option<BasicAccount> = { let maybe_account: Option<BasicAccount> = {
let query = (&mut recorder, ::rlp::decode); let panicky_decoder = |bytes: &[u8]| {
::rlp::decode(bytes).expect(&format!("prove_account, could not query trie for account key={}", &account_key))
};
let query = (&mut recorder, panicky_decoder);
trie.get_with(&account_key, query)? trie.get_with(&account_key, query)?
}; };
let account = maybe_account.unwrap_or_else(|| BasicAccount { let account = maybe_account.unwrap_or_else(|| BasicAccount {
@ -1086,7 +1092,8 @@ impl<B: Backend> State<B> {
// TODO: probably could look into cache somehow but it's keyed by // TODO: probably could look into cache somehow but it's keyed by
// address, not keccak(address). // address, not keccak(address).
let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?;
let acc = match trie.get_with(&account_key, Account::from_rlp)? { let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed");
let acc = match trie.get_with(&account_key, from_rlp)? {
Some(acc) => acc, Some(acc) => acc,
None => return Ok((Vec::new(), H256::new())), None => return Ok((Vec::new(), H256::new())),
}; };

View File

@ -244,7 +244,7 @@ mod tests {
]); ]);
let encoded = ::rlp::encode(&block_traces); let encoded = ::rlp::encode(&block_traces);
let decoded = ::rlp::decode(&encoded); let decoded = ::rlp::decode(&encoded).expect("error decoding block traces");
assert_eq!(block_traces, decoded); assert_eq!(block_traces, decoded);
} }
} }

View File

@ -576,7 +576,8 @@ mod tests {
#[test] #[test]
fn sender_test() { fn sender_test() {
let t: UnverifiedTransaction = rlp::decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); let bytes = ::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap();
let t: UnverifiedTransaction = rlp::decode(&bytes).expect("decoding UnverifiedTransaction failed");
assert_eq!(t.data, b""); assert_eq!(t.data, b"");
assert_eq!(t.gas, U256::from(0x5208u64)); assert_eq!(t.gas, U256::from(0x5208u64));
assert_eq!(t.gas_price, U256::from(0x01u64)); assert_eq!(t.gas_price, U256::from(0x01u64));
@ -645,7 +646,7 @@ mod tests {
use rustc_hex::FromHex; use rustc_hex::FromHex;
let test_vector = |tx_data: &str, address: &'static str| { let test_vector = |tx_data: &str, address: &'static str| {
let signed = rlp::decode(&FromHex::from_hex(tx_data).unwrap()); let signed = rlp::decode(&FromHex::from_hex(tx_data).unwrap()).expect("decoding tx data failed");
let signed = SignedTransaction::new(signed).unwrap(); let signed = SignedTransaction::new(signed).unwrap();
assert_eq!(signed.sender(), address.into()); assert_eq!(signed.sender(), address.into());
println!("chainid: {:?}", signed.chain_id()); println!("chainid: {:?}", signed.chain_id());

View File

@ -193,7 +193,7 @@ mod tests {
); );
let encoded = ::rlp::encode(&r); let encoded = ::rlp::encode(&r);
assert_eq!(&encoded[..], &expected[..]); assert_eq!(&encoded[..], &expected[..]);
let decoded: Receipt = ::rlp::decode(&encoded); let decoded: Receipt = ::rlp::decode(&encoded).expect("decoding receipt failed");
assert_eq!(decoded, r); assert_eq!(decoded, r);
} }
@ -211,7 +211,7 @@ mod tests {
); );
let encoded = ::rlp::encode(&r); let encoded = ::rlp::encode(&r);
assert_eq!(&encoded[..], &expected[..]); assert_eq!(&encoded[..], &expected[..]);
let decoded: Receipt = ::rlp::decode(&encoded); let decoded: Receipt = ::rlp::decode(&encoded).expect("decoding receipt failed");
assert_eq!(decoded, r); assert_eq!(decoded, r);
} }
} }

View File

@ -64,7 +64,7 @@ mod tests {
fn should_encode_and_decode_call_type() { fn should_encode_and_decode_call_type() {
let original = CallType::Call; let original = CallType::Call;
let encoded = encode(&original); let encoded = encode(&original);
let decoded = decode(&encoded); let decoded = decode(&encoded).expect("failure decoding CallType");
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }
} }

View File

@ -566,7 +566,8 @@ fn rpc_eth_pending_transaction_by_hash() {
let tester = EthTester::default(); let tester = EthTester::default();
{ {
let tx = rlp::decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); let bytes = FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap();
let tx = rlp::decode(&bytes).expect("decoding failure");
let tx = SignedTransaction::new(tx).unwrap(); let tx = SignedTransaction::new(tx).unwrap();
tester.miner.pending_transactions.lock().insert(H256::zero(), tx); tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
} }

View File

@ -45,14 +45,15 @@ pub struct ArchiveDB {
impl ArchiveDB { impl ArchiveDB {
/// Create a new instance from a key-value db. /// Create a new instance from a key-value db.
pub fn new(backing: Arc<KeyValueDB>, col: Option<u32>) -> ArchiveDB { pub fn new(backing: Arc<KeyValueDB>, column: Option<u32>) -> ArchiveDB {
let latest_era = backing.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") let latest_era = backing.get(column, &LATEST_ERA_KEY)
.map(|val| decode::<u64>(&val)); .expect("Low-level database error.")
.map(|val| decode::<u64>(&val).expect("decoding db value failed"));
ArchiveDB { ArchiveDB {
overlay: MemoryDB::new(), overlay: MemoryDB::new(),
backing: backing, backing,
latest_era: latest_era, latest_era,
column: col, column,
} }
} }

View File

@ -263,7 +263,7 @@ impl EarlyMergeDB {
let mut refs = HashMap::new(); let mut refs = HashMap::new();
let mut latest_era = None; let mut latest_era = None;
if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") { if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") {
let mut era = decode::<u64>(&val); let mut era = decode::<u64>(&val).expect("decoding db value failed");
latest_era = Some(era); latest_era = Some(era);
loop { loop {
let mut db_key = DatabaseKey { let mut db_key = DatabaseKey {

View File

@ -137,7 +137,7 @@ impl OverlayDB {
fn payload(&self, key: &H256) -> Option<Payload> { fn payload(&self, key: &H256) -> Option<Payload> {
self.backing.get(self.column, key) self.backing.get(self.column, key)
.expect("Low-level database error. Some issue with your hard disk?") .expect("Low-level database error. Some issue with your hard disk?")
.map(|d| decode(&d)) .map(|d| decode(&d).expect("decoding db value failed"))
} }
/// Put the refs and value of the given key, possibly deleting it from the db. /// Put the refs and value of the given key, possibly deleting it from the db.

View File

@ -186,7 +186,7 @@ impl OverlayRecentDB {
let mut earliest_era = None; let mut earliest_era = None;
let mut cumulative_size = 0; let mut cumulative_size = 0;
if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") { if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") {
let mut era = decode::<u64>(&val); let mut era = decode::<u64>(&val).expect("decoding db value failed");
latest_era = Some(era); latest_era = Some(era);
loop { loop {
let mut db_key = DatabaseKey { let mut db_key = DatabaseKey {
@ -195,7 +195,7 @@ impl OverlayRecentDB {
}; };
while let Some(rlp_data) = db.get(col, &encode(&db_key)).expect("Low-level database error.") { while let Some(rlp_data) = db.get(col, &encode(&db_key)).expect("Low-level database error.") {
trace!("read_overlay: era={}, index={}", era, db_key.index); trace!("read_overlay: era={}, index={}", era, db_key.index);
let value = decode::<DatabaseValue>(&rlp_data); let value = decode::<DatabaseValue>(&rlp_data).expect(&format!("read_overlay: Error decoding DatabaseValue era={}, index{}", era, db_key.index));
count += value.inserts.len(); count += value.inserts.len();
let mut inserted_keys = Vec::new(); let mut inserted_keys = Vec::new();
for (k, v) in value.inserts { for (k, v) in value.inserts {

View File

@ -62,17 +62,18 @@ pub struct RefCountedDB {
impl RefCountedDB { impl RefCountedDB {
/// Create a new instance given a `backing` database. /// Create a new instance given a `backing` database.
pub fn new(backing: Arc<KeyValueDB>, col: Option<u32>) -> RefCountedDB { pub fn new(backing: Arc<KeyValueDB>, column: Option<u32>) -> RefCountedDB {
let latest_era = backing.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") let latest_era = backing.get(column, &LATEST_ERA_KEY)
.map(|val| decode::<u64>(&val)); .expect("Low-level database error.")
.map(|v| decode::<u64>(&v).expect("decoding db value failed"));
RefCountedDB { RefCountedDB {
forward: OverlayDB::new(backing.clone(), col), forward: OverlayDB::new(backing.clone(), column),
backing: backing, backing,
inserts: vec![], inserts: vec![],
removes: vec![], removes: vec![],
latest_era: latest_era, latest_era,
column: col, column,
} }
} }
} }

View File

@ -63,13 +63,13 @@ pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1];
/// ///
/// fn main () { /// fn main () {
/// let data = vec![0x83, b'c', b'a', b't']; /// let data = vec![0x83, b'c', b'a', b't'];
/// let animal: String = rlp::decode(&data); /// let animal: String = rlp::decode(&data).expect("could not decode");
/// assert_eq!(animal, "cat".to_owned()); /// assert_eq!(animal, "cat".to_owned());
/// } /// }
/// ``` /// ```
pub fn decode<T>(bytes: &[u8]) -> T where T: Decodable { pub fn decode<T>(bytes: &[u8]) -> Result<T, DecoderError> where T: Decodable {
let rlp = Rlp::new(bytes); let rlp = Rlp::new(bytes);
rlp.as_val().expect("trusted rlp should be valid") rlp.as_val()
} }
pub fn decode_list<T>(bytes: &[u8]) -> Vec<T> where T: Decodable { pub fn decode_list<T>(bytes: &[u8]) -> Vec<T> where T: Decodable {

View File

@ -209,8 +209,10 @@ 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 { fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: Decodable + fmt::Debug + cmp::Eq {
for t in &tests { for t in &tests {
let res: T = rlp::decode(&t.1); let res : Result<T, DecoderError> = rlp::decode(&t.1);
assert_eq!(res, t.0); assert!(res.is_ok());
let res = res.unwrap();
assert_eq!(&res, &t.0);
} }
} }

View File

@ -24,7 +24,7 @@ fn test_encode_foo() {
let out = encode(&foo).into_vec(); let out = encode(&foo).into_vec();
assert_eq!(out, expected); assert_eq!(out, expected);
let decoded = decode(&expected); let decoded = decode(&expected).expect("decode failure");
assert_eq!(foo, decoded); assert_eq!(foo, decoded);
} }
@ -38,7 +38,7 @@ fn test_encode_foo_wrapper() {
let out = encode(&foo).into_vec(); let out = encode(&foo).into_vec();
assert_eq!(out, expected); assert_eq!(out, expected);
let decoded = decode(&expected); let decoded = decode(&expected).expect("decode failure");
assert_eq!(foo, decoded); assert_eq!(foo, decoded);
} }

View File

@ -446,7 +446,7 @@ mod tests {
}; };
let encoded = ::rlp::encode(&envelope); let encoded = ::rlp::encode(&envelope);
let decoded = ::rlp::decode(&encoded); let decoded = ::rlp::decode(&encoded).expect("failure decoding Envelope");
assert_eq!(envelope, decoded) assert_eq!(envelope, decoded)
} }
@ -462,7 +462,7 @@ mod tests {
}; };
let encoded = ::rlp::encode(&envelope); let encoded = ::rlp::encode(&envelope);
let decoded = ::rlp::decode(&encoded); let decoded = ::rlp::decode(&encoded).expect("failure decoding Envelope");
assert_eq!(envelope, decoded) assert_eq!(envelope, decoded)
} }