Skip to content

Commit

Permalink
piecrust: introduced tree positions file
Browse files Browse the repository at this point in the history
  • Loading branch information
miloszm committed Nov 22, 2024
1 parent 0f4a3c5 commit 306bdc1
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 19 deletions.
91 changes: 76 additions & 15 deletions piecrust/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use tree::{Hash, NewContractIndex};
use crate::store::commit::Hulk;
use crate::store::tree::{
position_from_contract, BaseInfo, ContractIndexElement, ContractsMerkle,
TreePos,
};
pub use bytecode::Bytecode;
pub use memory::{Memory, PAGE_SIZE};
Expand All @@ -44,6 +45,7 @@ const BYTECODE_DIR: &str = "bytecode";
const MEMORY_DIR: &str = "memory";
const LEAF_DIR: &str = "leaf";
const BASE_FILE: &str = "base";
const TREE_POS_FILE: &str = "tree_pos";
const ELEMENT_FILE: &str = "element";
const OBJECTCODE_EXTENSION: &str = "a";
const METADATA_EXTENSION: &str = "m";
Expand Down Expand Up @@ -283,7 +285,7 @@ impl ContractStore {

fn session_with_base(&self, base: Option<Hash>) -> ContractSession {
let base_commit = base.and_then(|hash| {
self.commit_store.lock().unwrap().get_commit(&hash).cloned() //todo: clone
self.commit_store.lock().unwrap().get_commit(&hash).cloned()
});
ContractSession::new(
&self.root_dir,
Expand Down Expand Up @@ -362,6 +364,16 @@ fn base_path_main<P: AsRef<Path>, S: AsRef<str>>(
Ok(dir.join(BASE_FILE))
}

fn tree_pos_path_main<P: AsRef<Path>, S: AsRef<str>>(
main_dir: P,
commit_id: S,
) -> io::Result<PathBuf> {
let commit_id = commit_id.as_ref();
let dir = main_dir.as_ref().join(commit_id);
fs::create_dir_all(&dir)?;
Ok(dir.join(TREE_POS_FILE))
}

fn commit_id_to_hash<S: AsRef<str>>(commit_id: S) -> Hash {
let hash: [u8; 32] = hex::decode(commit_id.as_ref())
.expect("Hex decoding of commit id string should succeed")
Expand Down Expand Up @@ -408,8 +420,20 @@ fn commit_from_dir<P: AsRef<Path>>(
let leaf_dir = main_dir.join(LEAF_DIR);
tracing::trace!("before index_merkle_from_path");

let index =
index_from_path(main_dir, leaf_dir, &maybe_hash, commit_store.clone())?;
let tree_pos = if let Some(ref hash_hex) = commit_id {
let tree_pos_path = main_dir.join(hash_hex).join(TREE_POS_FILE);
Some(tree_pos_from_path(tree_pos_path)?.tree_pos)
} else {
None
};

let (index, contracts_merkle) = index_merkle_from_path(
main_dir,
leaf_dir,
&maybe_hash,
commit_store.clone(),
tree_pos.as_ref(),
)?;
tracing::trace!("after index_merkle_from_path");

let bytecode_dir = main_dir.join(BYTECODE_DIR);
Expand Down Expand Up @@ -465,12 +489,11 @@ fn commit_from_dir<P: AsRef<Path>>(
}
}

let (base, contracts_merkle) = if let Some(hash_hex) = commit_id {
let base = if let Some(ref hash_hex) = commit_id {
let base_info_path = main_dir.join(hash_hex).join(BASE_FILE);
let base_info = base_from_path(base_info_path)?;
(base_info.maybe_base, base_info.contracts_merkle)
base_from_path(base_info_path)?.maybe_base
} else {
(None, ContractsMerkle::default())
None
};

Ok(Commit {
Expand All @@ -482,15 +505,17 @@ fn commit_from_dir<P: AsRef<Path>>(
})
}

fn index_from_path(
fn index_merkle_from_path(
main_path: impl AsRef<Path>,
leaf_dir: impl AsRef<Path>,
maybe_commit_id: &Option<Hash>,
commit_store: Arc<Mutex<CommitStore>>,
) -> io::Result<NewContractIndex> {
maybe_tree_pos: Option<&BTreeMap<u32, (Hash, u64)>>,
) -> io::Result<(NewContractIndex, ContractsMerkle)> {
let leaf_dir = leaf_dir.as_ref();

let mut index: NewContractIndex = NewContractIndex::new();
let mut merkle: ContractsMerkle = ContractsMerkle::default();

for entry in fs::read_dir(leaf_dir)? {
let entry = entry?;
Expand Down Expand Up @@ -533,7 +558,18 @@ fn index_from_path(
}
}

Ok(index)
match maybe_tree_pos {
Some(tree_pos) => {
for (int_pos, (hash, pos)) in tree_pos.iter() {
merkle.insert_with_int_pos(*pos, *int_pos as u64, *hash);
}
}
None => {
unreachable!()
}
}

Ok((index, merkle))
}

fn base_from_path<P: AsRef<Path>>(path: P) -> io::Result<BaseInfo> {
Expand All @@ -550,6 +586,20 @@ fn base_from_path<P: AsRef<Path>>(path: P) -> io::Result<BaseInfo> {
Ok(base_info)
}

fn tree_pos_from_path<P: AsRef<Path>>(path: P) -> io::Result<TreePos> {
let path = path.as_ref();

let tree_pos_bytes = fs::read(path)?;
let tree_pos = rkyv::from_bytes(&tree_pos_bytes).map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Invalid tree positions file \"{path:?}\": {err}"),
)
})?;

Ok(tree_pos)
}

#[derive(Debug, Clone)]
pub(crate) struct Commit {
index: NewContractIndex,
Expand Down Expand Up @@ -1028,8 +1078,6 @@ fn write_commit_inner<P: AsRef<Path>, S: AsRef<str>>(
tracing::trace!("persisting index started");
for (contract_id, element) in commit.index.iter() {
if commit_contracts.contains_key(contract_id) {
// todo: write element to disk at
// main/leaf/{contract_id}/{commit_id}
let element_dir_path = directories
.leaf_main_dir
.join(hex::encode(contract_id.as_bytes()))
Expand All @@ -1048,10 +1096,8 @@ fn write_commit_inner<P: AsRef<Path>, S: AsRef<str>>(
}
tracing::trace!("persisting index finished");

base_info.contracts_merkle = commit.contracts_merkle.clone(); //todo: clone

let base_main_path =
base_path_main(directories.main_dir, commit_id.as_ref())?;
base_path_main(&directories.main_dir, commit_id.as_ref())?;
let base_info_bytes =
rkyv::to_bytes::<_, 128>(&base_info).map_err(|err| {
io::Error::new(
Expand All @@ -1061,6 +1107,19 @@ fn write_commit_inner<P: AsRef<Path>, S: AsRef<str>>(
})?;
fs::write(base_main_path, base_info_bytes)?;

let tree_pos_main_path =
tree_pos_path_main(&directories.main_dir, commit_id.as_ref())?;
let tree_pos_bytes = rkyv::to_bytes::<_, 128>(
commit.contracts_merkle.tree_pos(),
)
.map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Failed serializing tree positions file: {err}"),
)
})?;
fs::write(tree_pos_main_path, tree_pos_bytes)?;

Ok(())
}

Expand Down Expand Up @@ -1101,6 +1160,7 @@ fn finalize_commit<P: AsRef<Path>>(
let root = hex::encode(root);
let commit_path = main_dir.join(&root);
let base_info_path = commit_path.join(BASE_FILE);
let tree_pos_path = commit_path.join(TREE_POS_FILE);
let base_info = base_from_path(&base_info_path)?;
for contract_hint in base_info.contract_hints {
let contract_hex = hex::encode(contract_hint);
Expand Down Expand Up @@ -1130,6 +1190,7 @@ fn finalize_commit<P: AsRef<Path>>(
}

fs::remove_file(base_info_path)?;
fs::remove_file(tree_pos_path)?;
fs::remove_dir(commit_path)?;

Ok(())
Expand Down
6 changes: 3 additions & 3 deletions piecrust/src/store/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl ContractSession {
.base
.as_ref()
.map(|c| c.fast_clone(&mut self.contracts.keys()))
.unwrap_or(Commit::new(&self.commit_store, None)); // todo: what about None here
.unwrap_or(Commit::new(&self.commit_store, None));
for (contract, entry) in &self.contracts {
commit.insert(*contract, &entry.memory);
}
Expand All @@ -116,7 +116,7 @@ impl ContractSession {
let mut commit = self
.base
.clone()
.unwrap_or(Commit::new(&self.commit_store, None)); // todo: what about None here
.unwrap_or(Commit::new(&self.commit_store, None));
for (contract, entry) in &self.contracts {
commit.insert(*contract, &entry.memory);
}
Expand Down Expand Up @@ -152,7 +152,7 @@ impl ContractSession {
let (replier, receiver) = mpsc::sync_channel(1);

let mut contracts = BTreeMap::new();
let base = self.base.clone(); // todo: clone
let base = self.base.clone();

mem::swap(&mut self.contracts, &mut contracts);

Expand Down
19 changes: 18 additions & 1 deletion piecrust/src/store/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ impl NewContractIndex {
pub struct ContractsMerkle {
inner_tree: Tree,
dict: BTreeMap<u64, u64>,
tree_pos: BTreeMap<u32, (Hash, u64)>,
}

impl Default for ContractsMerkle {
fn default() -> Self {
Self {
inner_tree: Tree::new(),
dict: BTreeMap::new(),
tree_pos: BTreeMap::new(),
}
}
}
Expand All @@ -119,12 +121,14 @@ impl ContractsMerkle {
Some(p) => *p,
};
self.inner_tree.insert(new_pos, hash);
self.tree_pos.insert(new_pos as u32, (hash, pos));
new_pos
}

pub fn insert_with_int_pos(&mut self, pos: u64, int_pos: u64, hash: Hash) {
self.dict.insert(pos, int_pos);
self.inner_tree.insert(int_pos, hash);
self.tree_pos.insert(int_pos as u32, (hash, pos));
}

pub fn opening(&self, pos: u64) -> Option<TreeOpening> {
Expand All @@ -135,6 +139,14 @@ impl ContractsMerkle {
pub fn root(&self) -> Ref<Hash> {
self.inner_tree.root()
}

pub fn tree_pos(&self) -> &BTreeMap<u32, (Hash, u64)> {
&self.tree_pos
}

pub fn len(&self) -> u64 {
self.inner_tree.len()
}
}

#[derive(Debug, Clone, Archive, Deserialize, Serialize)]
Expand All @@ -151,7 +163,12 @@ pub struct ContractIndex {
pub struct BaseInfo {
pub contract_hints: Vec<ContractId>,
pub maybe_base: Option<Hash>,
pub contracts_merkle: ContractsMerkle,
}

#[derive(Debug, Clone, Default, Archive, Deserialize, Serialize)]
#[archive_attr(derive(CheckBytes))]
pub struct TreePos {
pub tree_pos: BTreeMap<u32, (Hash, u64)>,
}

#[derive(Debug, Clone, Archive, Deserialize, Serialize)]
Expand Down

0 comments on commit 306bdc1

Please sign in to comment.