Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 52 additions & 94 deletions crates/storage/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2379,65 +2379,7 @@ impl Store {
state_trie: &mut Trie,
account_updates: impl IntoIterator<Item = &'a AccountUpdate>,
) -> Result<AccountUpdatesList, StoreError> {
let mut ret_storage_updates = Vec::new();
let mut code_updates = Vec::new();
let state_root = state_trie.hash_no_commit(&NativeCrypto);
for update in account_updates {
let hashed_address = hash_address_fixed(&update.address);
if update.removed {
// Remove account from trie
state_trie.remove(hashed_address.as_bytes())?;
continue;
}
// Add or update AccountState in the trie
// Fetch current state or create a new state to be inserted
let mut account_state = match state_trie.get(hashed_address.as_bytes())? {
Some(encoded_state) => AccountState::decode(&encoded_state)?,
None => AccountState::default(),
};
if update.removed_storage {
account_state.storage_root = EMPTY_TRIE_HASH;
}
if let Some(info) = &update.info {
account_state.nonce = info.nonce;
account_state.balance = info.balance;
account_state.code_hash = info.code_hash;
// Store updated code in DB
if let Some(code) = &update.code {
code_updates.push((info.code_hash, code.clone()));
}
}
// Store the added storage in the account's storage trie and compute its new root
if !update.added_storage.is_empty() {
let mut storage_trie =
self.open_storage_trie(hashed_address, state_root, account_state.storage_root)?;
for (storage_key, storage_value) in &update.added_storage {
let hashed_key = hash_key(storage_key);
if storage_value.is_zero() {
storage_trie.remove(&hashed_key)?;
} else {
storage_trie.insert(hashed_key, storage_value.encode_to_vec())?;
}
}
let (storage_hash, storage_updates) =
storage_trie.collect_changes_since_last_hash(&NativeCrypto);
account_state.storage_root = storage_hash;
ret_storage_updates.push((hashed_address, storage_updates));
}
state_trie.insert(
hashed_address.as_bytes().to_vec(),
account_state.encode_to_vec(),
)?;
}
let (state_trie_hash, state_updates) =
state_trie.collect_changes_since_last_hash(&NativeCrypto);

Ok(AccountUpdatesList {
state_trie_hash,
state_updates,
storage_updates: ret_storage_updates,
code_updates,
})
self.apply_account_updates_from_trie_inner(state_trie, account_updates, None)
}

/// Performs the same actions as apply_account_updates_from_trie
Expand All @@ -2448,92 +2390,108 @@ impl Store {
account_updates: &[AccountUpdate],
mut storage_tries: StorageTries,
) -> Result<(StorageTries, AccountUpdatesList), StoreError> {
let mut ret_storage_updates = Vec::new();
let account_updates_list = self.apply_account_updates_from_trie_inner(
&mut state_trie,
account_updates,
Some(&mut storage_tries),
)?;
Ok((storage_tries, account_updates_list))
}

/// Applies account updates to the given state trie.
///
/// With `storage_tries`, storage tries are opened through [`TrieLogger`] and
/// cached in the map (keyed by unhashed address) so witness recording spans
/// updates; without it, a fresh storage trie is opened per account at its
/// current storage root.
fn apply_account_updates_from_trie_inner<'a>(
&self,
state_trie: &mut Trie,
account_updates: impl IntoIterator<Item = &'a AccountUpdate>,
mut storage_tries: Option<&mut StorageTries>,
) -> Result<AccountUpdatesList, StoreError> {
let mut ret_storage_updates = Vec::new();
let mut code_updates = Vec::new();

let state_root = state_trie.hash_no_commit(&NativeCrypto);

for update in account_updates.iter() {
let hashed_address = hash_address(&update.address);

for update in account_updates {
let hashed_address = hash_address_fixed(&update.address);
if update.removed {
// Remove account from trie
state_trie.remove(&hashed_address)?;

state_trie.remove(hashed_address.as_bytes())?;
continue;
}

// Add or update AccountState in the trie
// Fetch current state or create a new state to be inserted
let mut account_state = match state_trie.get(&hashed_address)? {
let mut account_state = match state_trie.get(hashed_address.as_bytes())? {
Some(encoded_state) => AccountState::decode(&encoded_state)?,
None => AccountState::default(),
};

if update.removed_storage {
account_state.storage_root = EMPTY_TRIE_HASH;
}

if let Some(info) = &update.info {
account_state.nonce = info.nonce;

account_state.balance = info.balance;

account_state.code_hash = info.code_hash;

// Store updated code in DB
if let Some(code) = &update.code {
code_updates.push((info.code_hash, code.clone()));
}
}

// Store the added storage in the account's storage trie and compute its new root
if !update.added_storage.is_empty() {
let (_witness, storage_trie) = match storage_tries.entry(update.address) {
Entry::Occupied(value) => value.into_mut(),
Entry::Vacant(vacant) => {
let trie = self.open_storage_trie(
H256::from_slice(&hashed_address),
let mut local_trie;
let storage_trie = match storage_tries.as_deref_mut() {
Some(tries) => {
let (_witness, storage_trie) = match tries.entry(update.address) {
Entry::Occupied(value) => value.into_mut(),
Entry::Vacant(vacant) => {
let trie = self.open_storage_trie(
hashed_address,
state_root,
account_state.storage_root,
)?;
vacant.insert(TrieLogger::open_trie(trie))
}
};
storage_trie
}
None => {
local_trie = self.open_storage_trie(
hashed_address,
state_root,
account_state.storage_root,
)?;
vacant.insert(TrieLogger::open_trie(trie))
&mut local_trie
}
};

for (storage_key, storage_value) in &update.added_storage {
let hashed_key = hash_key(storage_key);

if storage_value.is_zero() {
storage_trie.remove(&hashed_key)?;
} else {
storage_trie.insert(hashed_key, storage_value.encode_to_vec())?;
}
}

let (storage_hash, storage_updates) =
storage_trie.collect_changes_since_last_hash(&NativeCrypto);

account_state.storage_root = storage_hash;

ret_storage_updates.push((H256::from_slice(&hashed_address), storage_updates));
ret_storage_updates.push((hashed_address, storage_updates));
}

state_trie.insert(hashed_address, account_state.encode_to_vec())?;
state_trie.insert(
hashed_address.as_bytes().to_vec(),
account_state.encode_to_vec(),
)?;
}

let (state_trie_hash, state_updates) =
state_trie.collect_changes_since_last_hash(&NativeCrypto);

let account_updates_list = AccountUpdatesList {
Ok(AccountUpdatesList {
state_trie_hash,
state_updates,
storage_updates: ret_storage_updates,
code_updates,
};

Ok((storage_tries, account_updates_list))
})
}

/// Adds all genesis accounts and returns the genesis block's state_root
Expand Down
Loading