Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[parallel executor] table storage parallel #3891

Merged
merged 12 commits into from
Jul 31, 2023
13 changes: 10 additions & 3 deletions state/api/src/chain_state.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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);
}
}
127 changes: 93 additions & 34 deletions state/statedb/src/lib.rs
Original file line number Diff line number Diff line change
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,7 @@ use starcoin_types::{
state_set::{AccountStateSet, ChainStateSet},
};
use starcoin_vm_types::access_path::{DataPath, ModuleName};
use starcoin_vm_types::account_config::table_handle_address;
use starcoin_vm_types::account_config::{TABLE_ADDRESS_LIST_LEN, 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 +217,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 +239,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 +344,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 +368,40 @@ 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 idx = idx & (TABLE_ADDRESS_LIST_LEN - 1);
nkysg marked this conversation as resolved.
Show resolved Hide resolved
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 +536,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 +657,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 +709,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
Loading
Loading