diff --git a/CHANGELOG.md b/CHANGELOG.md index 8144e93a7..5d9cd9408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Next release +- code docs: documented how get_storage_at is implemented - fix: L1 rpc <=> network mismatch - feat: rpc versioning - feat: bumping Starknet version from v0.13.2 to Starknet v0.13.2.1 diff --git a/crates/client/db/docs/flat_storage.md b/crates/client/db/docs/flat_storage.md new file mode 100644 index 000000000..fea89c68f --- /dev/null +++ b/crates/client/db/docs/flat_storage.md @@ -0,0 +1,28 @@ +# Key value flat storage + +We are interested in the operation `get_storage_at(block_id, contract_address, storage_key) -> value` here. +Bonsai-trie does not have an history of the key-values, it only has a flat storage for the latest state. +We may want to remove that flat storage from bonsai-trie as it's not used and we don't plan on using it. + +Instead, we have implemented our own optimized lookup, which is implemented with a column that looks like this: + +![schema flat_storage](./flat_storage.png) + +The trick here is to rely on the fact that rocksdb columns are sorted trees. +The rocksdb `get` operation does not allow getting the value of (contract_1, key_1) at block 15 here, because +the key has not been modified at that block. +Instead, we use rocksdb iterators. + +![schema flat_storage_iterator](./flat_storage_iterator.png) + +This allows us to get the most recent value for a (contract, key) at that block, by using a single rocksdb lookup. + +In addition, we also set up a [rocksdb prefix extractor](https://github.com/facebook/rocksdb/wiki/Prefix-Seek) for +that column, so that rocksdb can know +to treat the ` || ` part differently from the block_n part, which allows optimisations. + +## Other columns + +We also use this exact technique to store contract class hash history and contract nonce history - so that we're +able to quickly get the nonce/class hash of a +contract at a specific block. diff --git a/crates/client/db/docs/flat_storage.png b/crates/client/db/docs/flat_storage.png new file mode 100644 index 000000000..343ae1ff3 Binary files /dev/null and b/crates/client/db/docs/flat_storage.png differ diff --git a/crates/client/db/docs/flat_storage_iterator.png b/crates/client/db/docs/flat_storage_iterator.png new file mode 100644 index 000000000..e9a55fd4b Binary files /dev/null and b/crates/client/db/docs/flat_storage_iterator.png differ diff --git a/crates/client/db/src/contract_db.rs b/crates/client/db/src/contract_db.rs index d9c38c91b..7c6069516 100644 --- a/crates/client/db/src/contract_db.rs +++ b/crates/client/db/src/contract_db.rs @@ -1,10 +1,4 @@ -//! Contract history values are stored using a fixed prefix extractor in rocksdb. -//! -//! This means that we can access the last value of a history column (e.g. the last class hash of a contract) -//! from a any block in the blockchain by seeking to it using a rocksdb iterator, setting iteration to reverse mode, -//! and getting the next value. -//! -//! Insertion is batched and done in parallel using rayon: this is not intended for use in the RPCs. +#![doc = include_str!("../docs/flat_storage.md")] use std::sync::Arc;