Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[parallel executor] table storage parallel (#3891)
* refactor table storage

* add TableHandle get_idx

* add get_state_tree_table_handles

* modify test_state_db_with_table_item_once

* update TABLE_ADDRESS_LIST

* update TABLE_ADDRESS_LIST

* update TABLE_ADDRESS_LIST

* fmt code

* update TABLE_ADDRESS_LIST_LEN

* fix test

* remove unused code, we get idx from get_idx()? function

* fix warning
  • Loading branch information
nkysg committed Jul 31, 2023
1 parent 224e299 commit 236c0f2
Show file tree
Hide file tree
Showing 7 changed files with 478 additions and 95 deletions.
13 changes: 10 additions & 3 deletions state/api/src/chain_state.rs
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::StateReaderExt;
use crate::TABLE_PATH;
use crate::TABLE_PATH_LIST;
use anyhow::{ensure, Result};
use forkable_jellyfish_merkle::{blob::Blob, proof::SparseMerkleProof, RawKey};
use serde::de::DeserializeOwned;
Expand All @@ -16,7 +16,7 @@ use starcoin_types::{
access_path::AccessPath, account_address::AccountAddress, account_config::AccountResource,
account_state::AccountState, state_set::ChainStateSet,
};
use starcoin_vm_types::account_config::table_handle_address;
use starcoin_vm_types::account_config::TABLE_HANDLE_ADDRESS_LIST;
use starcoin_vm_types::genesis_config::ChainId;
use starcoin_vm_types::on_chain_resource::{Epoch, EpochInfo, GlobalTimeOnChain};
use starcoin_vm_types::state_store::table::TableHandle;
Expand Down Expand Up @@ -253,9 +253,16 @@ impl StateWithTableItemProof {
}

pub fn verify(&self, handle: &TableHandle, key: &[u8]) -> Result<()> {
let idx = handle.get_idx()?;
let handle_address = TABLE_HANDLE_ADDRESS_LIST
.get(idx)
.expect("get TABLE_HANDLE_ADDRESS_LIST should always succeed");
let table_path = TABLE_PATH_LIST
.get(idx)
.expect("get TABLE_PATH_LIST should always succeed");
self.state_proof.0.proof.verify(
self.state_proof.1,
AccessPath::new(table_handle_address(), TABLE_PATH.clone()),
AccessPath::new(*handle_address, table_path.clone()),
self.state_proof.0.state.as_deref(),
)?;
self.table_handle_proof.1.verify(
Expand Down
67 changes: 59 additions & 8 deletions state/api/src/lib.rs
Expand Up @@ -19,7 +19,7 @@ use serde::de::DeserializeOwned;
pub use starcoin_state_tree::StateNodeStore;
use starcoin_types::state_set::AccountStateSet;
use starcoin_vm_types::access_path::DataPath;
use starcoin_vm_types::account_config::table_handle_address;
use starcoin_vm_types::account_config::TABLE_HANDLE_ADDRESS_LIST;
use starcoin_vm_types::move_resource::MoveResource;
use starcoin_vm_types::state_store::table::TableHandle;
pub use starcoin_vm_types::state_view::{StateReaderExt, StateView};
Expand All @@ -28,13 +28,16 @@ mod chain_state;
pub mod message;
pub mod mock;

pub static TABLE_PATH: Lazy<DataPath> = Lazy::new(|| {
let str = format!(
"{}/1/{}::TableHandles::TableHandles",
table_handle_address(),
table_handle_address()
);
AccessPath::from_str(str.as_str()).unwrap().path
pub static TABLE_PATH_LIST: Lazy<Vec<DataPath>> = Lazy::new(|| {
let mut path_list = vec![];
for handle_address in &*TABLE_HANDLE_ADDRESS_LIST {
let str = format!(
"{}/1/{}::TableHandles::TableHandles",
handle_address, handle_address,
);
path_list.push(AccessPath::from_str(str.as_str()).unwrap().path);
}
path_list
});

#[async_trait::async_trait]
Expand Down Expand Up @@ -214,3 +217,51 @@ where
}
}
}

#[cfg(test)]
mod tests {
use crate::TABLE_PATH_LIST;

#[test]
fn test_table_path_list() {
let mut path_list = vec![];
let str_list = vec![
"1/0x00000000000000000000000000000031::TableHandles::TableHandles",
"1/0x00000000000000000000000000000032::TableHandles::TableHandles",
"1/0x00000000000000000000000000000033::TableHandles::TableHandles",
"1/0x00000000000000000000000000000034::TableHandles::TableHandles",
"1/0x00000000000000000000000000000035::TableHandles::TableHandles",
"1/0x00000000000000000000000000000036::TableHandles::TableHandles",
"1/0x00000000000000000000000000000037::TableHandles::TableHandles",
"1/0x00000000000000000000000000000038::TableHandles::TableHandles",
"1/0x00000000000000000000000000000039::TableHandles::TableHandles",
"1/0x0000000000000000000000000000003a::TableHandles::TableHandles",
"1/0x0000000000000000000000000000003b::TableHandles::TableHandles",
"1/0x0000000000000000000000000000003c::TableHandles::TableHandles",
"1/0x0000000000000000000000000000003d::TableHandles::TableHandles",
"1/0x0000000000000000000000000000003e::TableHandles::TableHandles",
"1/0x0000000000000000000000000000003f::TableHandles::TableHandles",
"1/0x00000000000000000000000000000040::TableHandles::TableHandles",
"1/0x00000000000000000000000000000041::TableHandles::TableHandles",
"1/0x00000000000000000000000000000042::TableHandles::TableHandles",
"1/0x00000000000000000000000000000043::TableHandles::TableHandles",
"1/0x00000000000000000000000000000044::TableHandles::TableHandles",
"1/0x00000000000000000000000000000045::TableHandles::TableHandles",
"1/0x00000000000000000000000000000046::TableHandles::TableHandles",
"1/0x00000000000000000000000000000047::TableHandles::TableHandles",
"1/0x00000000000000000000000000000048::TableHandles::TableHandles",
"1/0x00000000000000000000000000000049::TableHandles::TableHandles",
"1/0x0000000000000000000000000000004a::TableHandles::TableHandles",
"1/0x0000000000000000000000000000004b::TableHandles::TableHandles",
"1/0x0000000000000000000000000000004c::TableHandles::TableHandles",
"1/0x0000000000000000000000000000004d::TableHandles::TableHandles",
"1/0x0000000000000000000000000000004e::TableHandles::TableHandles",
"1/0x0000000000000000000000000000004f::TableHandles::TableHandles",
"1/0x00000000000000000000000000000050::TableHandles::TableHandles",
];
for table_path in TABLE_PATH_LIST.iter() {
path_list.push(format!("{}", table_path));
}
assert_eq!(path_list, str_list);
}
}
128 changes: 94 additions & 34 deletions state/statedb/src/lib.rs
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::StateError::AccountNotExist;
use anyhow::{bail, ensure, Result};
use anyhow::{bail, ensure, format_err, Result};
use bcs_ext::BCSCodec;
use forkable_jellyfish_merkle::proof::SparseMerkleProof;
use forkable_jellyfish_merkle::RawKey;
Expand All @@ -12,7 +12,7 @@ use starcoin_crypto::hash::SPARSE_MERKLE_PLACEHOLDER_HASH;
use starcoin_crypto::HashValue;
use starcoin_logger::prelude::*;
pub use starcoin_state_api::{ChainStateReader, ChainStateWriter, StateProof, StateWithProof};
use starcoin_state_api::{StateWithTableItemProof, TABLE_PATH};
use starcoin_state_api::{StateWithTableItemProof, TABLE_PATH_LIST};
use starcoin_state_tree::mock::MockStateNodeStore;
use starcoin_state_tree::AccountStateSetIterator;
use starcoin_state_tree::{StateNodeStore, StateTree};
Expand All @@ -24,7 +24,9 @@ use starcoin_types::{
state_set::{AccountStateSet, ChainStateSet},
};
use starcoin_vm_types::access_path::{DataPath, ModuleName};
use starcoin_vm_types::account_config::table_handle_address;
#[cfg(test)]
use starcoin_vm_types::account_config::TABLE_ADDRESS_LIST_LEN;
use starcoin_vm_types::account_config::TABLE_HANDLE_ADDRESS_LIST;
use starcoin_vm_types::language_storage::StructTag;
use starcoin_vm_types::state_store::{state_key::StateKey, table::TableHandle};
use starcoin_vm_types::state_view::StateView;
Expand Down Expand Up @@ -217,9 +219,11 @@ pub struct ChainStateDB {
updates: RwLock<HashSet<AccountAddress>>,
updates_table_handle: RwLock<HashSet<TableHandle>>,
cache_table_handle: Mutex<LruCache<TableHandle, Arc<TableHandleStateObject>>>,
/// state_tree_table_handles root_hash save in table_handle_address() TABLE_PATH
/// state_tree_table_handles_list root_hash Vec save in TABLE_PATH_LIST
/// state_tree_table_handles is element of state_tree_table_handles_list
/// state_tree_table_handles SMT save TableHandle -> TableHandleState.root_hash
state_tree_table_handles: StateTree<TableHandle>,
state_tree_table_handles_list: Vec<StateTree<TableHandle>>,
update_table_handle_idx_list: Mutex<HashSet<usize>>,
}

static G_DEFAULT_CACHE_SIZE: usize = 10240;
Expand All @@ -237,17 +241,30 @@ impl ChainStateDB {
updates: RwLock::new(HashSet::new()),
updates_table_handle: RwLock::new(HashSet::new()),
cache_table_handle: Mutex::new(LruCache::new(G_DEFAULT_CACHE_SIZE)),
state_tree_table_handles: StateTree::new(store.clone(), None),
state_tree_table_handles_list: vec![],
update_table_handle_idx_list: Mutex::new(HashSet::new()),
};
let account_state_object = chain_statedb
.get_account_state_object(&table_handle_address(), true)
.expect("get account state success");
let state_root = account_state_object
.get(&TABLE_PATH)
.expect("get state_root success");
if let Some(state_root) = state_root {
let hash = HashValue::from_slice(state_root.as_slice()).expect("hash value success");
chain_statedb.state_tree_table_handles = StateTree::new(store, Some(hash));
for (handle_address, table_path) in
TABLE_HANDLE_ADDRESS_LIST.iter().zip(TABLE_PATH_LIST.iter())
{
let account_state_object = chain_statedb
.get_account_state_object(handle_address, true)
.expect("get account state success");
let state_root = account_state_object
.get(table_path)
.expect("get state_root success");
match state_root {
Some(state_root) => {
let hash =
HashValue::from_slice(state_root.as_slice()).expect("hash value success");
chain_statedb
.state_tree_table_handles_list
.push(StateTree::new(store.clone(), Some(hash)));
}
None => chain_statedb
.state_tree_table_handles_list
.push(StateTree::new(store.clone(), None)),
};
}
chain_statedb
}
Expand Down Expand Up @@ -329,12 +346,13 @@ impl ChainStateDB {
&self,
handle: &TableHandle,
) -> Result<Arc<TableHandleStateObject>> {
let idx = handle.get_idx()?;
let mut cache = self.cache_table_handle.lock();
let item = cache.get(handle);
let object = match item {
Some(item) => item.clone(),
None => {
let val = self.state_tree_table_handles.get(handle)?;
let val = self.get_state_tree_table_handles(idx)?.get(handle)?;
let hash = match val {
Some(val) => HashValue::from_slice(val)?,
None => *SPARSE_MERKLE_PLACEHOLDER_HASH,
Expand All @@ -352,20 +370,39 @@ impl ChainStateDB {
}

#[cfg(test)]
fn table_handles_root_hash(&self) -> HashValue {
self.state_tree_table_handles.root_hash()
fn table_handles_root_hash(&self, idx: usize) -> Result<HashValue> {
let state_tree_table_handles = self.get_state_tree_table_handles(idx)?;
Ok(state_tree_table_handles.root_hash())
}

#[cfg(test)]
fn table_handle_address_root_hash(&self) -> HashValue {
fn table_handle_address_root_hash(&self, idx: usize) -> HashValue {
let idx = idx & (TABLE_ADDRESS_LIST_LEN - 1);
let handle_address = TABLE_HANDLE_ADDRESS_LIST
.get(idx)
.expect("get TABLE_HANDLE_ADDRESS_LIST should always succeed");
let table_path = TABLE_PATH_LIST
.get(idx)
.expect("get TABLE_PATH_LIST should always succeed");
let account_state_object = self
.get_account_state_object(&table_handle_address(), true)
.get_account_state_object(handle_address, true)
.expect("get account state success");
let state_root = account_state_object
.get(&TABLE_PATH)
.get(table_path)
.expect("get state_root success");
HashValue::from_slice(state_root.unwrap()).unwrap()
}

fn get_state_tree_table_handles(&self, idx: usize) -> Result<&StateTree<TableHandle>> {
let state_tree_table_handles = self.state_tree_table_handles_list.get(idx);
match state_tree_table_handles {
Some(state_tree_table_handles) => Ok(state_tree_table_handles),
_ => Err(format_err!(
"get state_tree_table_handles index should success {}",
idx
)),
}
}
}

impl StateView for ChainStateDB {
Expand Down Expand Up @@ -500,17 +537,25 @@ impl ChainStateReader for ChainStateDB {
handle: &TableHandle,
key: &[u8],
) -> Result<StateWithTableItemProof> {
let idx = handle.get_idx()?;
let handle_address = TABLE_HANDLE_ADDRESS_LIST
.get(idx)
.expect("get TABLE_HANDLE_ADDRESS_LIST should always succeed");
let table_path = TABLE_PATH_LIST
.get(idx)
.expect("get TABLE_PATH_LIST should always succeed");
let table_path_proof =
self.get_with_proof(&AccessPath::new(table_handle_address(), TABLE_PATH.clone()))?;
let table_handle_proof = self.state_tree_table_handles.get_with_proof(handle)?;
self.get_with_proof(&AccessPath::new(*handle_address, table_path.clone()))?;
let state_tree_table_handle = self.get_state_tree_table_handles(idx)?;
let table_handle_proof = state_tree_table_handle.get_with_proof(handle)?;
let table_handle_state_object = self.get_table_handle_state_object(handle)?;
let key_proof = table_handle_state_object.get_with_proof(&key.to_vec())?;
Ok(StateWithTableItemProof::new(
(table_path_proof, self.state_root()),
(
table_handle_proof.0,
table_handle_proof.1,
self.state_tree_table_handles.root_hash(),
state_tree_table_handle.root_hash(),
),
(
key_proof.0,
Expand Down Expand Up @@ -613,26 +658,37 @@ impl ChainStateWriter for ChainStateDB {
/// Commit
fn commit(&self) -> Result<HashValue> {
// cache commit
let len = self.updates_table_handle.read().len();

for handle in self.updates_table_handle.read().iter() {
let table_handle_state_object = self.get_table_handle_state_object(handle)?;
table_handle_state_object.commit()?;
let idx = handle.get_idx()?;
self.update_table_handle_idx_list.lock().insert(idx);
// put table_handle_state_object commit
self.state_tree_table_handles
self.get_state_tree_table_handles(idx)?
.put(*handle, table_handle_state_object.root_hash().to_vec());
}
if len > 0 {
self.state_tree_table_handles.commit()?;
for idx in self.update_table_handle_idx_list.lock().iter() {
let state_tree_table_handle = self
.state_tree_table_handles_list
.get(*idx)
.expect("get state_tree_table_handles index should success");
state_tree_table_handle.commit()?;

// update table_handle_address state
let handle_address = TABLE_HANDLE_ADDRESS_LIST
.get(*idx)
.expect("get TABLE_HANDLE_ADDRESS_LIST should always succeed");
let table_path: &DataPath = TABLE_PATH_LIST
.get(*idx)
.expect("get TABLE_PATH_LIST should always succeed");

let mut locks = self.updates.write();
locks.insert(table_handle_address());
locks.insert(*handle_address);
let table_handle_account_state_object =
self.get_account_state_object(&table_handle_address(), true)?;
self.get_account_state_object(handle_address, true)?;
table_handle_account_state_object.set(
TABLE_PATH.clone(),
self.state_tree_table_handles.root_hash().to_vec(),
table_path.clone(),
state_tree_table_handle.root_hash().to_vec(),
);
}

Expand All @@ -654,7 +710,11 @@ impl ChainStateWriter for ChainStateDB {
}
locks_table_handle.clear();

self.state_tree_table_handles.flush()?;
for idx in self.update_table_handle_idx_list.lock().iter() {
let state_tree_table_handle = self.get_state_tree_table_handles(*idx)?;
state_tree_table_handle.flush()?;
}
self.update_table_handle_idx_list.lock().clear();

let mut locks = self.updates.write();
for address in locks.iter() {
Expand Down

0 comments on commit 236c0f2

Please sign in to comment.