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:
@@ -438,7 +438,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
|
||||
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
|
||||
// canon chain.
|
||||
@@ -462,7 +462,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
|
||||
impl BlockChain {
|
||||
/// Create new instance of blockchain from given Genesis.
|
||||
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 mut bc = BlockChain {
|
||||
|
||||
@@ -218,15 +218,12 @@ impl Writable for DBTransaction {
|
||||
}
|
||||
|
||||
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]> {
|
||||
let result = self.get(col, &key.key());
|
||||
fn read<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> Option<T>
|
||||
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]> {
|
||||
|
||||
@@ -24,13 +24,12 @@
|
||||
//! decoded object where parts like the hash can be saved.
|
||||
|
||||
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 hash::keccak;
|
||||
use header::{BlockNumber, Header as FullHeader};
|
||||
use heapsize::HeapSizeOf;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use transaction::UnverifiedTransaction;
|
||||
use views::{self, BlockView, HeaderView, BodyView};
|
||||
|
||||
/// Owning header view.
|
||||
@@ -48,7 +47,7 @@ impl Header {
|
||||
pub fn new(encoded: Vec<u8>) -> Self { Header(encoded) }
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
@@ -205,7 +204,7 @@ impl Block {
|
||||
pub fn header_view(&self) -> HeaderView { self.view().header_view() }
|
||||
|
||||
/// 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.
|
||||
pub fn decode_header(&self) -> FullHeader { self.view().rlp().val_at(0) }
|
||||
|
||||
@@ -143,8 +143,10 @@ impl <F> super::EpochVerifier<EthereumMachine> for EpochVerifier<F>
|
||||
}
|
||||
|
||||
fn check_finality_proof(&self, proof: &[u8]) -> Option<Vec<H256>> {
|
||||
let header: Header = ::rlp::decode(proof);
|
||||
self.verify_light(&header).ok().map(|_| vec![header.hash()])
|
||||
match ::rlp::decode(proof) {
|
||||
Ok(header) => self.verify_light(&header).ok().map(|_| vec![header.hash()]),
|
||||
Err(_) => None // REVIEW: log perhaps? Not sure what the policy is.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ mod tests {
|
||||
let nonce = "88ab4e252a7e8c2a23".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();
|
||||
assert_eq!(seal_fields.len(), 2);
|
||||
assert_eq!(seal_fields[0], mix_hash);
|
||||
@@ -415,7 +415,7 @@ mod tests {
|
||||
// that's rlp of block header created with ethash engine.
|
||||
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();
|
||||
|
||||
assert_eq!(header_rlp, encoded_header);
|
||||
|
||||
@@ -236,7 +236,7 @@ mod tests {
|
||||
};
|
||||
|
||||
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_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap();
|
||||
@@ -261,7 +261,7 @@ mod tests {
|
||||
};
|
||||
|
||||
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 = Rlp::new(&fat_rlp[0]).at(1).unwrap();
|
||||
@@ -286,7 +286,7 @@ mod tests {
|
||||
};
|
||||
|
||||
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 mut root = KECCAK_NULL_RLP;
|
||||
|
||||
@@ -281,7 +281,7 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter +
|
||||
// account_key here is the address' hash.
|
||||
for item in account_trie.iter()? {
|
||||
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_db = AccountDB::from_hash(db, account_key_hash);
|
||||
@@ -467,10 +467,10 @@ fn rebuild_accounts(
|
||||
*out = (hash, thin_rlp);
|
||||
}
|
||||
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() {
|
||||
known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp).storage_root);
|
||||
known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp)?.storage_root);
|
||||
}
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ impl StateProducer {
|
||||
|
||||
// sweep once to alter storage tries.
|
||||
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);
|
||||
fill_storage(acct_db, &mut account.storage_root, &mut self.storage_seed);
|
||||
*account_data = DBValue::from_vec(::rlp::encode(&account).into_vec());
|
||||
|
||||
@@ -114,7 +114,7 @@ fn get_code_from_prev_chunk() {
|
||||
// first one will have code inlined,
|
||||
// second will just have its hash.
|
||||
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 db = MemoryDB::new();
|
||||
|
||||
@@ -21,6 +21,7 @@ use std::sync::Arc;
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use error::Error;
|
||||
use hashdb::HashDB;
|
||||
use kvdb::DBValue;
|
||||
use bytes::{Bytes, ToPretty};
|
||||
@@ -144,9 +145,10 @@ impl Account {
|
||||
}
|
||||
|
||||
/// Create a new account from RLP.
|
||||
pub fn from_rlp(rlp: &[u8]) -> Account {
|
||||
let basic: BasicAccount = ::rlp::decode(rlp);
|
||||
basic.into()
|
||||
pub fn from_rlp(rlp: &[u8]) -> Result<Account, Error> {
|
||||
::rlp::decode::<BasicAccount>(rlp)
|
||||
.map(|ba| ba.into())
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
/// Create a new contract account.
|
||||
@@ -202,8 +204,8 @@ impl Account {
|
||||
return Ok(value);
|
||||
}
|
||||
let db = SecTrieDB::new(db, &self.storage_root)?;
|
||||
|
||||
let item: U256 = db.get_with(key, ::rlp::decode)?.unwrap_or_else(U256::zero);
|
||||
let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed");
|
||||
let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero);
|
||||
let value: H256 = item.into();
|
||||
self.storage_cache.borrow_mut().insert(key.clone(), value.clone());
|
||||
Ok(value)
|
||||
@@ -478,7 +480,8 @@ impl Account {
|
||||
|
||||
let trie = TrieDB::new(db, &self.storage_root)?;
|
||||
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)
|
||||
};
|
||||
|
||||
@@ -528,7 +531,7 @@ mod tests {
|
||||
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_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into());
|
||||
assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default());
|
||||
@@ -546,10 +549,10 @@ mod tests {
|
||||
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());
|
||||
|
||||
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(()));
|
||||
}
|
||||
|
||||
@@ -609,7 +612,7 @@ mod tests {
|
||||
#[test]
|
||||
fn rlpio() {
|
||||
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.nonce(), b.nonce());
|
||||
assert_eq!(a.code_hash(), b.code_hash());
|
||||
|
||||
@@ -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
|
||||
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 account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address));
|
||||
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
|
||||
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() {
|
||||
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());
|
||||
@@ -1012,7 +1014,8 @@ impl<B: Backend> State<B> {
|
||||
None => {
|
||||
let maybe_acc = if !self.db.is_known_null(a) {
|
||||
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 {
|
||||
AccountEntry::new_clean(None)
|
||||
};
|
||||
@@ -1064,7 +1067,10 @@ impl<B: Backend> State<B> {
|
||||
let mut recorder = Recorder::new();
|
||||
let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?;
|
||||
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)?
|
||||
};
|
||||
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
|
||||
// address, not keccak(address).
|
||||
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,
|
||||
None => return Ok((Vec::new(), H256::new())),
|
||||
};
|
||||
|
||||
@@ -244,7 +244,7 @@ mod tests {
|
||||
]);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user