Merge branch 'master' into jsonsertests
This commit is contained in:
commit
becf1d7b28
@ -116,7 +116,12 @@ impl Account {
|
|||||||
/// Get (and cache) the contents of the trie's storage at `key`.
|
/// Get (and cache) the contents of the trie's storage at `key`.
|
||||||
pub fn storage_at(&self, db: &AccountDB, key: &H256) -> H256 {
|
pub fn storage_at(&self, db: &AccountDB, key: &H256) -> H256 {
|
||||||
self.storage_overlay.borrow_mut().entry(key.clone()).or_insert_with(||{
|
self.storage_overlay.borrow_mut().entry(key.clone()).or_insert_with(||{
|
||||||
(Filth::Clean, H256::from(SecTrieDB::new(db, &self.storage_root).get(key.bytes()).map_or(U256::zero(), |v| -> U256 {decode(v)})))
|
let db = SecTrieDB::new(db, &self.storage_root)
|
||||||
|
.expect("Account storage_root initially set to zero (valid) and only altered by SecTrieDBMut. \
|
||||||
|
SecTrieDBMut would not set it to an invalid state root. Therefore the root is valid and DB creation \
|
||||||
|
using it will not fail.");
|
||||||
|
|
||||||
|
(Filth::Clean, H256::from(db.get(key.bytes()).map_or(U256::zero(), |v| -> U256 {decode(v)})))
|
||||||
}).1.clone()
|
}).1.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +209,10 @@ impl Account {
|
|||||||
|
|
||||||
/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
|
/// Commit the `storage_overlay` to the backing DB and update `storage_root`.
|
||||||
pub fn commit_storage(&mut self, db: &mut AccountDBMut) {
|
pub fn commit_storage(&mut self, db: &mut AccountDBMut) {
|
||||||
let mut t = SecTrieDBMut::from_existing(db, &mut self.storage_root);
|
let mut t = SecTrieDBMut::from_existing(db, &mut self.storage_root)
|
||||||
|
.expect("Account storage_root initially set to zero (valid) and only altered by SecTrieDBMut. \
|
||||||
|
SecTrieDBMut would not set it to an invalid state root. Therefore the root is valid and DB creation \
|
||||||
|
using it will not fail.");
|
||||||
for (k, &mut (ref mut f, ref mut v)) in self.storage_overlay.borrow_mut().iter_mut() {
|
for (k, &mut (ref mut f, ref mut v)) in self.storage_overlay.borrow_mut().iter_mut() {
|
||||||
if f == &Filth::Dirty {
|
if f == &Filth::Dirty {
|
||||||
// cast key and value to trait type,
|
// cast key and value to trait type,
|
||||||
|
@ -278,7 +278,7 @@ mod tests {
|
|||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let vm_factory = Default::default();
|
let vm_factory = Default::default();
|
||||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), 3141562.into(), vec![]);
|
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), 3141562.into(), vec![]).unwrap();
|
||||||
let b = b.close_and_lock();
|
let b = b.close_and_lock();
|
||||||
let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap();
|
let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap();
|
||||||
|
|
||||||
|
@ -212,9 +212,20 @@ pub struct SealedBlock {
|
|||||||
impl<'x> OpenBlock<'x> {
|
impl<'x> OpenBlock<'x> {
|
||||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||||
/// Create a new `OpenBlock` ready for transaction pushing.
|
/// Create a new `OpenBlock` ready for transaction pushing.
|
||||||
pub fn new(engine: &'x Engine, vm_factory: &'x EvmFactory, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self {
|
pub fn new(
|
||||||
|
engine: &'x Engine,
|
||||||
|
vm_factory: &'x EvmFactory,
|
||||||
|
tracing: bool,
|
||||||
|
db: Box<JournalDB>,
|
||||||
|
parent: &Header,
|
||||||
|
last_hashes: LastHashes,
|
||||||
|
author: Address,
|
||||||
|
gas_floor_target: U256,
|
||||||
|
extra_data: Bytes
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let state = try!(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce()));
|
||||||
let mut r = OpenBlock {
|
let mut r = OpenBlock {
|
||||||
block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce()), tracing),
|
block: ExecutedBlock::new(state, tracing),
|
||||||
engine: engine,
|
engine: engine,
|
||||||
vm_factory: vm_factory,
|
vm_factory: vm_factory,
|
||||||
last_hashes: last_hashes,
|
last_hashes: last_hashes,
|
||||||
@ -229,7 +240,7 @@ impl<'x> OpenBlock<'x> {
|
|||||||
|
|
||||||
engine.populate_from_parent(&mut r.block.base.header, parent, gas_floor_target);
|
engine.populate_from_parent(&mut r.block.base.header, parent, gas_floor_target);
|
||||||
engine.on_new_block(&mut r.block);
|
engine.on_new_block(&mut r.block);
|
||||||
r
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alter the author for the block.
|
/// Alter the author for the block.
|
||||||
@ -448,12 +459,12 @@ impl IsBlock for SealedBlock {
|
|||||||
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result<LockedBlock, Error> {
|
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result<LockedBlock, Error> {
|
||||||
{
|
{
|
||||||
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
||||||
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce());
|
let s = try!(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce()));
|
||||||
trace!("enact(): root={}, author={}, author_balance={}\n", s.root(), header.author(), s.balance(&header.author()));
|
trace!("enact(): root={}, author={}, author_balance={}\n", s.root(), header.author(), s.balance(&header.author()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut b = OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), 3141562.into(), header.extra_data().clone());
|
let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), 3141562.into(), header.extra_data().clone()));
|
||||||
b.set_difficulty(*header.difficulty());
|
b.set_difficulty(*header.difficulty());
|
||||||
b.set_gas_limit(*header.gas_limit());
|
b.set_gas_limit(*header.gas_limit());
|
||||||
b.set_timestamp(header.timestamp());
|
b.set_timestamp(header.timestamp());
|
||||||
@ -498,7 +509,7 @@ mod tests {
|
|||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let vm_factory = Default::default();
|
let vm_factory = Default::default();
|
||||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]);
|
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]).unwrap();
|
||||||
let b = b.close_and_lock();
|
let b = b.close_and_lock();
|
||||||
let _ = b.seal(engine.deref(), vec![]);
|
let _ = b.seal(engine.deref(), vec![]);
|
||||||
}
|
}
|
||||||
@ -514,7 +525,8 @@ mod tests {
|
|||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let vm_factory = Default::default();
|
let vm_factory = Default::default();
|
||||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]).close_and_lock().seal(engine.deref(), vec![]).unwrap();
|
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]).unwrap()
|
||||||
|
.close_and_lock().seal(engine.deref(), vec![]).unwrap();
|
||||||
let orig_bytes = b.rlp_bytes();
|
let orig_bytes = b.rlp_bytes();
|
||||||
let orig_db = b.drain();
|
let orig_db = b.drain();
|
||||||
|
|
||||||
@ -541,7 +553,7 @@ mod tests {
|
|||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let vm_factory = Default::default();
|
let vm_factory = Default::default();
|
||||||
let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]);
|
let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]).unwrap();
|
||||||
let mut uncle1_header = Header::new();
|
let mut uncle1_header = Header::new();
|
||||||
uncle1_header.extra_data = b"uncle1".to_vec();
|
uncle1_header.extra_data = b"uncle1".to_vec();
|
||||||
let mut uncle2_header = Header::new();
|
let mut uncle2_header = Header::new();
|
||||||
|
@ -386,18 +386,14 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
|
|
||||||
let root = HeaderView::new(&header).state_root();
|
let root = HeaderView::new(&header).state_root();
|
||||||
|
|
||||||
// TODO [rob]: refactor State::from_existing so we avoid doing redundant lookups.
|
State::from_existing(db, root, self.engine.account_start_nonce()).ok()
|
||||||
if !db.contains(&root) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(State::from_existing(db, root, self.engine.account_start_nonce()))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a copy of the best block's state.
|
/// Get a copy of the best block's state.
|
||||||
pub fn state(&self) -> State {
|
pub fn state(&self) -> State {
|
||||||
State::from_existing(self.state_db.lock().unwrap().boxed_clone(), HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce())
|
State::from_existing(self.state_db.lock().unwrap().boxed_clone(), HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce())
|
||||||
|
.expect("State root of best block header always valid.")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get info on the cache.
|
/// Get info on the cache.
|
||||||
@ -776,7 +772,8 @@ impl<V> MiningBlockChainClient for Client<V> where V: Verifier {
|
|||||||
author,
|
author,
|
||||||
gas_floor_target,
|
gas_floor_target,
|
||||||
extra_data,
|
extra_data,
|
||||||
);
|
).expect("OpenBlock::new only fails if parent state root invalid. State root of best block's header is never invalid. \
|
||||||
|
Therefore creating an OpenBlock with the best block's header will not fail.");
|
||||||
|
|
||||||
// Add uncles
|
// Add uncles
|
||||||
self.chain
|
self.chain
|
||||||
|
@ -224,6 +224,8 @@ pub enum Error {
|
|||||||
PowHashInvalid,
|
PowHashInvalid,
|
||||||
/// The value of the nonce or mishash is invalid.
|
/// The value of the nonce or mishash is invalid.
|
||||||
PowInvalid,
|
PowInvalid,
|
||||||
|
/// Error concerning TrieDBs
|
||||||
|
TrieError(TrieError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -239,6 +241,7 @@ impl fmt::Display for Error {
|
|||||||
f.write_fmt(format_args!("Unknown engine name ({})", name)),
|
f.write_fmt(format_args!("Unknown engine name ({})", name)),
|
||||||
Error::PowHashInvalid => f.write_str("Invalid or out of date PoW hash."),
|
Error::PowHashInvalid => f.write_str("Invalid or out of date PoW hash."),
|
||||||
Error::PowInvalid => f.write_str("Invalid nonce or mishash"),
|
Error::PowInvalid => f.write_str("Invalid nonce or mishash"),
|
||||||
|
Error::TrieError(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,6 +303,12 @@ impl From<IoError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TrieError> for Error {
|
||||||
|
fn from(err: TrieError) -> Error {
|
||||||
|
Error::TrieError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted.
|
// TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted.
|
||||||
/*#![feature(concat_idents)]
|
/*#![feature(concat_idents)]
|
||||||
macro_rules! assimilate {
|
macro_rules! assimilate {
|
||||||
|
@ -308,7 +308,7 @@ mod tests {
|
|||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let vm_factory = Default::default();
|
let vm_factory = Default::default();
|
||||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]);
|
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]).unwrap();
|
||||||
let b = b.close();
|
let b = b.close();
|
||||||
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
|
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ mod tests {
|
|||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let vm_factory = Default::default();
|
let vm_factory = Default::default();
|
||||||
let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]);
|
let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]).unwrap();
|
||||||
let mut uncle = Header::new();
|
let mut uncle = Header::new();
|
||||||
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
||||||
uncle.author = uncle_author.clone();
|
uncle.author = uncle_author.clone();
|
||||||
|
@ -62,7 +62,7 @@ mod tests {
|
|||||||
let mut db_result = get_temp_journal_db();
|
let mut db_result = get_temp_journal_db();
|
||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
spec.ensure_db_good(db.as_hashdb_mut());
|
spec.ensure_db_good(db.as_hashdb_mut());
|
||||||
let s = State::from_existing(db, genesis_header.state_root.clone(), engine.account_start_nonce());
|
let s = State::from_existing(db, genesis_header.state_root.clone(), engine.account_start_nonce()).unwrap();
|
||||||
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000001")), U256::from(1u64));
|
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000001")), U256::from(1u64));
|
||||||
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000002")), U256::from(1u64));
|
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000002")), U256::from(1u64));
|
||||||
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000003")), U256::from(1u64));
|
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000003")), U256::from(1u64));
|
||||||
|
@ -44,6 +44,9 @@ pub struct State {
|
|||||||
account_start_nonce: U256,
|
account_start_nonce: U256,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with valid root. Creating a SecTrieDB with a valid root will not fail. \
|
||||||
|
Therefore creating a SecTrieDB with this state's root will not fail.";
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
/// Creates new state with empty state root
|
/// Creates new state with empty state root
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -64,18 +67,17 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates new state with existing state root
|
/// Creates new state with existing state root
|
||||||
pub fn from_existing(db: Box<JournalDB>, root: H256, account_start_nonce: U256) -> State {
|
pub fn from_existing(db: Box<JournalDB>, root: H256, account_start_nonce: U256) -> Result<State, TrieError> {
|
||||||
{
|
if !db.as_hashdb().contains(&root) {
|
||||||
// trie should panic! if root does not exist
|
Err(TrieError::InvalidStateRoot)
|
||||||
let _ = SecTrieDB::new(db.as_hashdb(), &root);
|
} else {
|
||||||
}
|
Ok(State {
|
||||||
|
db: db,
|
||||||
State {
|
root: root,
|
||||||
db: db,
|
cache: RefCell::new(HashMap::new()),
|
||||||
root: root,
|
snapshots: RefCell::new(Vec::new()),
|
||||||
cache: RefCell::new(HashMap::new()),
|
account_start_nonce: account_start_nonce,
|
||||||
snapshots: RefCell::new(Vec::new()),
|
})
|
||||||
account_start_nonce: account_start_nonce,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +156,8 @@ impl State {
|
|||||||
|
|
||||||
/// Determine whether an account exists.
|
/// Determine whether an account exists.
|
||||||
pub fn exists(&self, a: &Address) -> bool {
|
pub fn exists(&self, a: &Address) -> bool {
|
||||||
self.cache.borrow().get(&a).unwrap_or(&None).is_some() || SecTrieDB::new(self.db.as_hashdb(), &self.root).contains(&a)
|
let db = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
||||||
|
self.cache.borrow().get(&a).unwrap_or(&None).is_some() || db.contains(&a)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the balance of account `a`.
|
/// Get the balance of account `a`.
|
||||||
@ -245,7 +248,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut trie = SecTrieDBMut::from_existing(db, root);
|
let mut trie = SecTrieDBMut::from_existing(db, root).unwrap();
|
||||||
for (address, ref a) in accounts.iter() {
|
for (address, ref a) in accounts.iter() {
|
||||||
match **a {
|
match **a {
|
||||||
Some(ref account) => trie.insert(address, &account.rlp()),
|
Some(ref account) => trie.insert(address, &account.rlp()),
|
||||||
@ -308,7 +311,8 @@ impl State {
|
|||||||
fn get<'a>(&'a self, a: &Address, require_code: bool) -> &'a Option<Account> {
|
fn get<'a>(&'a self, a: &Address, require_code: bool) -> &'a Option<Account> {
|
||||||
let have_key = self.cache.borrow().contains_key(a);
|
let have_key = self.cache.borrow().contains_key(a);
|
||||||
if !have_key {
|
if !have_key {
|
||||||
self.insert_cache(a, SecTrieDB::new(self.db.as_hashdb(), &self.root).get(&a).map(Account::from_rlp))
|
let db = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
||||||
|
self.insert_cache(a, db.get(&a).map(Account::from_rlp))
|
||||||
}
|
}
|
||||||
if require_code {
|
if require_code {
|
||||||
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
|
if let Some(ref mut account) = self.cache.borrow_mut().get_mut(a).unwrap().as_mut() {
|
||||||
@ -328,7 +332,8 @@ impl State {
|
|||||||
fn require_or_from<'a, F: FnOnce() -> Account, G: FnOnce(&mut Account)>(&self, a: &Address, require_code: bool, default: F, not_default: G) -> &'a mut Account {
|
fn require_or_from<'a, F: FnOnce() -> Account, G: FnOnce(&mut Account)>(&self, a: &Address, require_code: bool, default: F, not_default: G) -> &'a mut Account {
|
||||||
let have_key = self.cache.borrow().contains_key(a);
|
let have_key = self.cache.borrow().contains_key(a);
|
||||||
if !have_key {
|
if !have_key {
|
||||||
self.insert_cache(a, SecTrieDB::new(self.db.as_hashdb(), &self.root).get(&a).map(Account::from_rlp))
|
let db = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR);
|
||||||
|
self.insert_cache(a, db.get(&a).map(Account::from_rlp))
|
||||||
} else {
|
} else {
|
||||||
self.note_cache(a);
|
self.note_cache(a);
|
||||||
}
|
}
|
||||||
@ -1145,7 +1150,7 @@ fn code_from_database() {
|
|||||||
state.drop()
|
state.drop()
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = State::from_existing(db, root, U256::from(0u8));
|
let state = State::from_existing(db, root, U256::from(0u8)).unwrap();
|
||||||
assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec()));
|
assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1160,7 +1165,7 @@ fn storage_at_from_database() {
|
|||||||
state.drop()
|
state.drop()
|
||||||
};
|
};
|
||||||
|
|
||||||
let s = State::from_existing(db, root, U256::from(0u8));
|
let s = State::from_existing(db, root, U256::from(0u8)).unwrap();
|
||||||
assert_eq!(s.storage_at(&a, &H256::from(&U256::from(01u64))), H256::from(&U256::from(69u64)));
|
assert_eq!(s.storage_at(&a, &H256::from(&U256::from(01u64))), H256::from(&U256::from(69u64)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,7 +1182,7 @@ fn get_from_database() {
|
|||||||
state.drop()
|
state.drop()
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = State::from_existing(db, root, U256::from(0u8));
|
let state = State::from_existing(db, root, U256::from(0u8)).unwrap();
|
||||||
assert_eq!(state.balance(&a), U256::from(69u64));
|
assert_eq!(state.balance(&a), U256::from(69u64));
|
||||||
assert_eq!(state.nonce(&a), U256::from(1u64));
|
assert_eq!(state.nonce(&a), U256::from(1u64));
|
||||||
}
|
}
|
||||||
@ -1210,7 +1215,7 @@ fn remove_from_database() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (root, db) = {
|
let (root, db) = {
|
||||||
let mut state = State::from_existing(db, root, U256::from(0u8));
|
let mut state = State::from_existing(db, root, U256::from(0u8)).unwrap();
|
||||||
assert_eq!(state.exists(&a), true);
|
assert_eq!(state.exists(&a), true);
|
||||||
assert_eq!(state.nonce(&a), U256::from(1u64));
|
assert_eq!(state.nonce(&a), U256::from(1u64));
|
||||||
state.kill_account(&a);
|
state.kill_account(&a);
|
||||||
@ -1220,7 +1225,7 @@ fn remove_from_database() {
|
|||||||
state.drop()
|
state.drop()
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = State::from_existing(db, root, U256::from(0u8));
|
let state = State::from_existing(db, root, U256::from(0u8)).unwrap();
|
||||||
assert_eq!(state.exists(&a), false);
|
assert_eq!(state.exists(&a), false);
|
||||||
assert_eq!(state.nonce(&a), U256::from(0u64));
|
assert_eq!(state.nonce(&a), U256::from(0u64));
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ Parity. Ethereum Client.
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
parity daemon <pid-file> [options]
|
parity daemon <pid-file> [options]
|
||||||
parity account (new | list) [options]
|
parity account (new | list ) [options]
|
||||||
|
parity account import <path>... [options]
|
||||||
parity import [ <file> ] [options]
|
parity import [ <file> ] [options]
|
||||||
parity export [ <file> ] [options]
|
parity export [ <file> ] [options]
|
||||||
parity signer new-token [options]
|
parity signer new-token [options]
|
||||||
@ -212,6 +213,7 @@ pub struct Args {
|
|||||||
pub cmd_new_token: bool,
|
pub cmd_new_token: bool,
|
||||||
pub arg_pid_file: String,
|
pub arg_pid_file: String,
|
||||||
pub arg_file: Option<String>,
|
pub arg_file: Option<String>,
|
||||||
|
pub arg_path: Vec<String>,
|
||||||
pub flag_chain: String,
|
pub flag_chain: String,
|
||||||
pub flag_db_path: String,
|
pub flag_db_path: String,
|
||||||
pub flag_identity: String,
|
pub flag_identity: String,
|
||||||
|
@ -482,6 +482,11 @@ fn execute_account_cli(conf: Configuration) {
|
|||||||
for &(addr, _) in &secret_store.accounts().unwrap() {
|
for &(addr, _) in &secret_store.accounts().unwrap() {
|
||||||
println!("{:?}", addr);
|
println!("{:?}", addr);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if conf.args.cmd_import {
|
||||||
|
let imported = util::keys::import_keys_paths(&mut secret_store, &conf.args.arg_path).unwrap();
|
||||||
|
println!("Imported {} keys", imported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
util/res/pat/p1.json
Normal file
21
util/res/pat/p1.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"address": "3f49624084b67849c7b4e805c5988c21a430f9d9",
|
||||||
|
"Crypto": {
|
||||||
|
"cipher": "aes-128-ctr",
|
||||||
|
"ciphertext": "9f27e3dd4fc73e7103ed61e5493662189a3eb52223ae49e3d1deacc04c889eae",
|
||||||
|
"cipherparams": {
|
||||||
|
"iv": "457494bf05f2618c397dc74dbb5181c0"
|
||||||
|
},
|
||||||
|
"kdf": "scrypt",
|
||||||
|
"kdfparams": {
|
||||||
|
"dklen": 32,
|
||||||
|
"n": 262144,
|
||||||
|
"p": 1,
|
||||||
|
"r": 8,
|
||||||
|
"salt": "db14edb18c41ee7f5ec4397df89c3a2ae4d0af60884c52bb54ce490574f8df33"
|
||||||
|
},
|
||||||
|
"mac": "572d24532438d31fdf513c744a3ff26c933ffda5744ee42bc71661cbe3f2112e"
|
||||||
|
},
|
||||||
|
"id": "62a0ad73-556d-496a-8e1c-0783d30d3ace",
|
||||||
|
"version": 3
|
||||||
|
}
|
21
util/res/pat/p2.json
Normal file
21
util/res/pat/p2.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"address": "5ba4dcf897e97c2bdf8315b9ef26c13c085988cf",
|
||||||
|
"Crypto": {
|
||||||
|
"cipher": "aes-128-ctr",
|
||||||
|
"ciphertext": "d4a08ec930163778273920f6ad1d49b71836337be6fd9863993ac700a612fddd",
|
||||||
|
"cipherparams": {
|
||||||
|
"iv": "89ce5ec129fc27cd5bcbeb8c92bdad50"
|
||||||
|
},
|
||||||
|
"kdf": "scrypt",
|
||||||
|
"kdfparams": {
|
||||||
|
"dklen": 32,
|
||||||
|
"n": 262144,
|
||||||
|
"p": 1,
|
||||||
|
"r": 8,
|
||||||
|
"salt": "612ab108dc37e69ee8af37a7b24bf7f2234086d7bbf945bacdeccce331f7f84a"
|
||||||
|
},
|
||||||
|
"mac": "4152caa7444e06784223d735cea80cd2690b4c587ad8db3d5529442227b25695"
|
||||||
|
},
|
||||||
|
"id": "35086353-fb12-4029-b56b-033cd61ce35b",
|
||||||
|
"version": 3
|
||||||
|
}
|
@ -80,9 +80,10 @@ pub fn import_geth_key(secret_store: &mut SecretStore, geth_keyfile_path: &Path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Imports all geth keys in the directory
|
/// Imports all geth keys in the directory
|
||||||
pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: &Path) -> Result<(), ImportError> {
|
pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: &Path) -> Result<usize, ImportError> {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
let geth_files = try!(enumerate_geth_keys(geth_keyfiles_directory));
|
let geth_files = try!(enumerate_geth_keys(geth_keyfiles_directory));
|
||||||
|
let mut total = 0;
|
||||||
for &(ref address, ref file_path) in &geth_files {
|
for &(ref address, ref file_path) in &geth_files {
|
||||||
let mut path = PathBuf::new();
|
let mut path = PathBuf::new();
|
||||||
path.push(geth_keyfiles_directory);
|
path.push(geth_keyfiles_directory);
|
||||||
@ -90,18 +91,45 @@ pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory:
|
|||||||
if let Err(e) = import_geth_key(secret_store, Path::new(&path)) {
|
if let Err(e) = import_geth_key(secret_store, Path::new(&path)) {
|
||||||
warn!("Skipped geth address {}, error importing: {:?}", address, e)
|
warn!("Skipped geth address {}, error importing: {:?}", address, e)
|
||||||
}
|
}
|
||||||
|
else { total = total + 1}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(total)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Gets the default geth keystore directory.
|
/// Gets the default geth keystore directory.
|
||||||
///
|
|
||||||
/// Based on https://github.com/ethereum/go-ethereum/blob/e553215/common/path.go#L75
|
|
||||||
pub fn keystore_dir(is_testnet: bool) -> PathBuf {
|
pub fn keystore_dir(is_testnet: bool) -> PathBuf {
|
||||||
path::ethereum::with_default(if is_testnet {"testnet/keystore"} else {"keystore"})
|
path::ethereum::with_default(if is_testnet {"testnet/keystore"} else {"keystore"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Imports key(s) from provided file/directory
|
||||||
|
pub fn import_keys_path(secret_store: &mut SecretStore, path: &str) -> Result<usize, ImportError> {
|
||||||
|
// check if it is just one file or directory
|
||||||
|
if let Ok(meta) = fs::metadata(path) {
|
||||||
|
if meta.is_file() {
|
||||||
|
try!(import_geth_key(secret_store, Path::new(path)));
|
||||||
|
return Ok(1);
|
||||||
|
}
|
||||||
|
else if meta.is_dir() {
|
||||||
|
return Ok(try!(fs::read_dir(path)).fold(
|
||||||
|
0,
|
||||||
|
|total, p|
|
||||||
|
total +
|
||||||
|
match p {
|
||||||
|
Ok(dir_entry) => import_keys_path(secret_store, dir_entry.path().to_str().unwrap()).unwrap_or_else(|_| 0),
|
||||||
|
Err(e) => { warn!("Error importing dir entry: {:?}", e); 0 },
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Imports all keys from list of provided files/directories
|
||||||
|
pub fn import_keys_paths(secret_store: &mut SecretStore, path: &[String]) -> Result<usize, ImportError> {
|
||||||
|
Ok(path.iter().fold(0, |total, ref p| total + import_keys_path(secret_store, &p).unwrap_or_else(|_| 0)))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -115,10 +143,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pat_path() -> &'static str {
|
||||||
|
match ::std::fs::metadata("res") {
|
||||||
|
Ok(_) => "res/pat",
|
||||||
|
Err(_) => "util/res/pat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_path_param(param_val: &'static str) -> String {
|
fn test_path_param(param_val: &'static str) -> String {
|
||||||
test_path().to_owned() + param_val
|
test_path().to_owned() + param_val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pat_path_param(param_val: &'static str) -> String {
|
||||||
|
pat_path().to_owned() + param_val
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_enumerate() {
|
fn can_enumerate() {
|
||||||
let keys = enumerate_geth_keys(Path::new(test_path())).unwrap();
|
let keys = enumerate_geth_keys(Path::new(test_path())).unwrap();
|
||||||
@ -191,4 +230,32 @@ mod tests {
|
|||||||
assert!(val.is_ok());
|
assert!(val.is_ok());
|
||||||
assert_eq!(32, val.unwrap().len());
|
assert_eq!(32, val.unwrap().len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_import_by_filename() {
|
||||||
|
let temp = ::devtools::RandomTempPath::create_dir();
|
||||||
|
let mut secret_store = SecretStore::new_in(temp.as_path());
|
||||||
|
|
||||||
|
let amount = import_keys_path(&mut secret_store, &pat_path_param("/p1.json")).unwrap();
|
||||||
|
assert_eq!(1, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_import_by_dir() {
|
||||||
|
let temp = ::devtools::RandomTempPath::create_dir();
|
||||||
|
let mut secret_store = SecretStore::new_in(temp.as_path());
|
||||||
|
|
||||||
|
let amount = import_keys_path(&mut secret_store, pat_path()).unwrap();
|
||||||
|
assert_eq!(2, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_import_mulitple() {
|
||||||
|
let temp = ::devtools::RandomTempPath::create_dir();
|
||||||
|
let mut secret_store = SecretStore::new_in(temp.as_path());
|
||||||
|
|
||||||
|
let amount = import_keys_paths(&mut secret_store, &[pat_path_param("/p1.json"), pat_path_param("/p2.json")]).unwrap();
|
||||||
|
assert_eq!(2, amount);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,3 +23,4 @@ mod test_account_provider;
|
|||||||
|
|
||||||
pub use self::store::AccountProvider;
|
pub use self::store::AccountProvider;
|
||||||
pub use self::test_account_provider::{TestAccount, TestAccountProvider};
|
pub use self::test_account_provider::{TestAccount, TestAccountProvider};
|
||||||
|
pub use self::geth_import::import_keys_paths;
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
//! Trie interface and implementation.
|
//! Trie interface and implementation.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// Export the trietraits module.
|
/// Export the trietraits module.
|
||||||
pub mod trietraits;
|
pub mod trietraits;
|
||||||
/// Export the standardmap module.
|
/// Export the standardmap module.
|
||||||
@ -33,9 +35,22 @@ pub mod sectriedb;
|
|||||||
/// Export the sectriedbmut module.
|
/// Export the sectriedbmut module.
|
||||||
pub mod sectriedbmut;
|
pub mod sectriedbmut;
|
||||||
|
|
||||||
pub use self::trietraits::*;
|
pub use self::trietraits::{Trie, TrieMut};
|
||||||
pub use self::standardmap::*;
|
pub use self::standardmap::{Alphabet, StandardMap, ValueMode};
|
||||||
pub use self::triedbmut::*;
|
pub use self::triedbmut::TrieDBMut;
|
||||||
pub use self::triedb::*;
|
pub use self::triedb::TrieDB;
|
||||||
pub use self::sectriedbmut::*;
|
pub use self::sectriedbmut::SecTrieDBMut;
|
||||||
pub use self::sectriedb::*;
|
pub use self::sectriedb::SecTrieDB;
|
||||||
|
|
||||||
|
/// Trie Errors
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TrieError {
|
||||||
|
/// Attempted to create a trie with a state root not in the DB.
|
||||||
|
InvalidStateRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TrieError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Trie Error: Invalid state root.")
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
use hash::*;
|
use hash::*;
|
||||||
use sha3::*;
|
use sha3::*;
|
||||||
use hashdb::*;
|
use hashdb::HashDB;
|
||||||
use super::triedb::*;
|
use super::triedb::TrieDB;
|
||||||
use super::trietraits::*;
|
use super::trietraits::Trie;
|
||||||
|
use super::TrieError;
|
||||||
|
|
||||||
/// A `Trie` implementation which hashes keys and uses a generic `HashDB` backing database.
|
/// A `Trie` implementation which hashes keys and uses a generic `HashDB` backing database.
|
||||||
///
|
///
|
||||||
@ -29,10 +30,12 @@ pub struct SecTrieDB<'db> {
|
|||||||
|
|
||||||
impl<'db> SecTrieDB<'db> {
|
impl<'db> SecTrieDB<'db> {
|
||||||
/// Create a new trie with the backing database `db` and empty `root`
|
/// Create a new trie with the backing database `db` and empty `root`
|
||||||
|
///
|
||||||
/// Initialise to the state entailed by the genesis block.
|
/// Initialise to the state entailed by the genesis block.
|
||||||
/// This guarantees the trie is built correctly.
|
/// This guarantees the trie is built correctly.
|
||||||
pub fn new(db: &'db HashDB, root: &'db H256) -> Self {
|
/// Returns an error if root does not exist.
|
||||||
SecTrieDB { raw: TrieDB::new(db, root) }
|
pub fn new(db: &'db HashDB, root: &'db H256) -> Result<Self, TrieError> {
|
||||||
|
Ok(SecTrieDB { raw: try!(TrieDB::new(db, root)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to the underlying raw `TrieDB` struct.
|
/// Get a reference to the underlying raw `TrieDB` struct.
|
||||||
@ -60,8 +63,9 @@ impl<'db> Trie for SecTrieDB<'db> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn trie_to_sectrie() {
|
fn trie_to_sectrie() {
|
||||||
use memorydb::*;
|
use memorydb::MemoryDB;
|
||||||
use super::triedbmut::*;
|
use super::triedbmut::TrieDBMut;
|
||||||
|
use super::trietraits::TrieMut;
|
||||||
|
|
||||||
let mut memdb = MemoryDB::new();
|
let mut memdb = MemoryDB::new();
|
||||||
let mut root = H256::new();
|
let mut root = H256::new();
|
||||||
@ -69,6 +73,6 @@ fn trie_to_sectrie() {
|
|||||||
let mut t = TrieDBMut::new(&mut memdb, &mut root);
|
let mut t = TrieDBMut::new(&mut memdb, &mut root);
|
||||||
t.insert(&(&[0x01u8, 0x23]).sha3(), &[0x01u8, 0x23]);
|
t.insert(&(&[0x01u8, 0x23]).sha3(), &[0x01u8, 0x23]);
|
||||||
}
|
}
|
||||||
let t = SecTrieDB::new(&memdb, &root);
|
let t = SecTrieDB::new(&memdb, &root).unwrap();
|
||||||
assert_eq!(t.get(&[0x01u8, 0x23]).unwrap(), &[0x01u8, 0x23]);
|
assert_eq!(t.get(&[0x01u8, 0x23]).unwrap(), &[0x01u8, 0x23]);
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
use hash::*;
|
use hash::*;
|
||||||
use sha3::*;
|
use sha3::*;
|
||||||
use hashdb::*;
|
use hashdb::HashDB;
|
||||||
use super::triedbmut::*;
|
use super::triedbmut::TrieDBMut;
|
||||||
use super::trietraits::*;
|
use super::trietraits::{Trie, TrieMut};
|
||||||
|
use super::TrieError;
|
||||||
|
|
||||||
/// A mutable `Trie` implementation which hashes keys and uses a generic `HashDB` backing database.
|
/// A mutable `Trie` implementation which hashes keys and uses a generic `HashDB` backing database.
|
||||||
///
|
///
|
||||||
@ -35,10 +36,11 @@ impl<'db> SecTrieDBMut<'db> {
|
|||||||
SecTrieDBMut { raw: TrieDBMut::new(db, root) }
|
SecTrieDBMut { raw: TrieDBMut::new(db, root) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new trie with the backing database `db` and `root`
|
/// Create a new trie with the backing database `db` and `root`.
|
||||||
/// Panics, if `root` does not exist
|
///
|
||||||
pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self {
|
/// Returns an error if root does not exist.
|
||||||
SecTrieDBMut { raw: TrieDBMut::from_existing(db, root) }
|
pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Result<Self, TrieError> {
|
||||||
|
Ok(SecTrieDBMut { raw: try!(TrieDBMut::from_existing(db, root)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the backing database.
|
/// Get the backing database.
|
||||||
@ -81,6 +83,6 @@ fn sectrie_to_trie() {
|
|||||||
let mut t = SecTrieDBMut::new(&mut memdb, &mut root);
|
let mut t = SecTrieDBMut::new(&mut memdb, &mut root);
|
||||||
t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]);
|
t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]);
|
||||||
}
|
}
|
||||||
let t = TrieDB::new(&memdb, &root);
|
let t = TrieDB::new(&memdb, &root).unwrap();
|
||||||
assert_eq!(t.get(&(&[0x01u8, 0x23]).sha3()).unwrap(), &[0x01u8, 0x23]);
|
assert_eq!(t.get(&(&[0x01u8, 0x23]).sha3()).unwrap(), &[0x01u8, 0x23]);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,9 @@ use common::*;
|
|||||||
use hashdb::*;
|
use hashdb::*;
|
||||||
use nibbleslice::*;
|
use nibbleslice::*;
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
use super::trietraits::*;
|
use super::trietraits::Trie;
|
||||||
use super::node::*;
|
use super::node::Node;
|
||||||
|
use super::TrieError;
|
||||||
|
|
||||||
/// A `Trie` implementation using a generic `HashDB` backing database.
|
/// A `Trie` implementation using a generic `HashDB` backing database.
|
||||||
///
|
///
|
||||||
@ -41,7 +42,7 @@ use super::node::*;
|
|||||||
/// let mut memdb = MemoryDB::new();
|
/// let mut memdb = MemoryDB::new();
|
||||||
/// let mut root = H256::new();
|
/// let mut root = H256::new();
|
||||||
/// TrieDBMut::new(&mut memdb, &mut root).insert(b"foo", b"bar");
|
/// TrieDBMut::new(&mut memdb, &mut root).insert(b"foo", b"bar");
|
||||||
/// let t = TrieDB::new(&memdb, &root);
|
/// let t = TrieDB::new(&memdb, &root).unwrap();
|
||||||
/// assert!(t.contains(b"foo"));
|
/// assert!(t.contains(b"foo"));
|
||||||
/// assert_eq!(t.get(b"foo").unwrap(), b"bar");
|
/// assert_eq!(t.get(b"foo").unwrap(), b"bar");
|
||||||
/// assert!(t.db_items_remaining().is_empty());
|
/// assert!(t.db_items_remaining().is_empty());
|
||||||
@ -57,16 +58,16 @@ pub struct TrieDB<'db> {
|
|||||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||||
impl<'db> TrieDB<'db> {
|
impl<'db> TrieDB<'db> {
|
||||||
/// Create a new trie with the backing database `db` and `root`
|
/// Create a new trie with the backing database `db` and `root`
|
||||||
/// Panics, if `root` does not exist
|
/// Returns an error if `root` does not exist
|
||||||
pub fn new(db: &'db HashDB, root: &'db H256) -> Self {
|
pub fn new(db: &'db HashDB, root: &'db H256) -> Result<Self, TrieError> {
|
||||||
if !db.contains(root) {
|
if !db.contains(root) {
|
||||||
flushln!("TrieDB::new({}): Trie root not found!", root);
|
Err(TrieError::InvalidStateRoot)
|
||||||
panic!("Trie root not found!");
|
} else {
|
||||||
}
|
Ok(TrieDB {
|
||||||
TrieDB {
|
db: db,
|
||||||
db: db,
|
root: root,
|
||||||
root: root,
|
hash_count: 0
|
||||||
hash_count: 0
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +357,7 @@ impl<'db> fmt::Debug for TrieDB<'db> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn iterator() {
|
fn iterator() {
|
||||||
|
use super::trietraits::TrieMut;
|
||||||
use memorydb::*;
|
use memorydb::*;
|
||||||
use super::triedbmut::*;
|
use super::triedbmut::*;
|
||||||
|
|
||||||
@ -369,6 +371,6 @@ fn iterator() {
|
|||||||
t.insert(&x, &x);
|
t.insert(&x, &x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(d.iter().map(|i|i.to_vec()).collect::<Vec<_>>(), TrieDB::new(&memdb, &root).iter().map(|x|x.0).collect::<Vec<_>>());
|
assert_eq!(d.iter().map(|i|i.to_vec()).collect::<Vec<_>>(), TrieDB::new(&memdb, &root).unwrap().iter().map(|x|x.0).collect::<Vec<_>>());
|
||||||
assert_eq!(d, TrieDB::new(&memdb, &root).iter().map(|x|x.1).collect::<Vec<_>>());
|
assert_eq!(d, TrieDB::new(&memdb, &root).unwrap().iter().map(|x|x.1).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,10 @@ use common::*;
|
|||||||
use hashdb::*;
|
use hashdb::*;
|
||||||
use nibbleslice::*;
|
use nibbleslice::*;
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
use super::node::*;
|
use super::node::Node;
|
||||||
use super::journal::*;
|
use super::journal::Journal;
|
||||||
use super::trietraits::*;
|
use super::trietraits::{Trie, TrieMut};
|
||||||
|
use super::TrieError;
|
||||||
|
|
||||||
/// A `Trie` implementation using a generic `HashDB` backing database.
|
/// A `Trie` implementation using a generic `HashDB` backing database.
|
||||||
///
|
///
|
||||||
@ -84,17 +85,16 @@ impl<'db> TrieDBMut<'db> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new trie with the backing database `db` and `root`.
|
/// Create a new trie with the backing database `db` and `root`.
|
||||||
/// Panics, if `root` does not exist.
|
/// Returns an error if `root` does not exist.
|
||||||
// TODO: return Result<Self, TrieError>
|
pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Result<Self, TrieError> {
|
||||||
pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self {
|
|
||||||
if !db.exists(root) {
|
if !db.exists(root) {
|
||||||
flushln!("Trie root not found {}", root);
|
Err(TrieError::InvalidStateRoot)
|
||||||
panic!("Trie root not found!");
|
} else {
|
||||||
}
|
Ok(TrieDBMut {
|
||||||
TrieDBMut {
|
db: db,
|
||||||
db: db,
|
root: root,
|
||||||
root: root,
|
hash_count: 0
|
||||||
hash_count: 0
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user