-
Notifications
You must be signed in to change notification settings - Fork 91
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
[feature/jmt 1/4] Jmt: Integration of Storage traits with crate jmt #891
base: master
Are you sure you want to change the base?
Conversation
let storage = self.storage_read(); | ||
let Some(value) = | ||
<StorageType as StorageInspect<ValueTableType>>::get(&*storage, &key_hash) | ||
.map_err(|_e| anyhow::anyhow!("Version Storage Error"))? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps
.map_err(|_e| anyhow::anyhow!("Version Storage Error"))? | |
.map_err(|e| anyhow::anyhow!("could not get value: {}", e.err()))? |
let Some(value) = | ||
<StorageType as StorageInspect<ValueTableType>>::get(&*storage, &key_hash) | ||
.map_err(|_e| anyhow::anyhow!("Version Storage Error"))? | ||
.filter(|v| v.0 <= max_version) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any way we can optimize this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial questions
@@ -11,13 +11,16 @@ repository = { workspace = true } | |||
description = "Fuel Merkle tree libraries." | |||
|
|||
[dependencies] | |||
anyhow = { version = "1.0", default-features = false } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While benchmarking I think this is fine, but I'd advocate for using dedicated error types before merging to master (or as a follow-up)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the jmt crate that exposes traits whose signature return a anyhow::Result
value.
See https://github.com/FuelLabs/fuel-vm/blob/68bbb4c52d4a749832cb07c11a9f467b54ec6b1f/fuel-merkle/src/jellyfish/jmt_integration.rs#L47 for example
Otherwise I'd be very happy to remove it :)
StorageType, | ||
StorageError, | ||
> { | ||
inner: Arc<RwLock<StorageType>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels weird to dictate the lock type over the Storage. Shouldn't we just use traits to dictate the storage behavior, and let any potential locking mechanism be an implementation detail of the particular storage implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. In practice I don't think we'll need a Lock, and we can use RefCell instead.
On the other hand, it could be wise to have a trait for the "locking/borrowing" functions and parameterise over it. WIll amend
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a cell even? Can't this just hold the StorageType
directly the same way we do in the SMT struct:
#[derive(Debug)]
pub struct MerkleTree<TableType, StorageType> {
root_node: Node,
storage: StorageType,
phantom_table: PhantomData<TableType>,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should, but again it's because of a constraint on the Jmt trait signatures.
Specifically TreeWriter::write_node_batch(&self, _: &NodeBatch)
takes a non-mutable reference, but its implementation requires to call StorageInspect::inspect
, which instead requires a mutable reference.
If we decide to fork jmt at some point, we can amend the trait signatures to avoid having to use cells or locks
{ | ||
fn write_node_batch(&self, node_batch: &JmtNodeBatch) -> anyhow::Result<()> { | ||
for (key, node) in node_batch.nodes() { | ||
// TODO: Do we really need locks here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah commented above. I don't think we should have to care about locks in this context.
}; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct JellyfishMerkleTreeStorage< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it will be more obvious when I look at the following PRs, but why do we need to declare a specific storage type for the JMTs? I don't find anything directly equivalent in our SMT implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe JellyFishMerkleTreeStorage
is not the best name, but the Sparse merkle tree implementation follows the same pattern:
pub struct MerkleTree<TableType, StorageType> {
root_node: Node,
storage: StorageType,
phantom_table: PhantomData<TableType>,
}
and at a later point StorageType
is required to implement StorageInspect<TableType>
, with TableType: Mappable<...>
see
fuel-vm/fuel-merkle/src/sparse/merkle_tree.rs
Lines 193 to 196 in c329ea7
impl<TableType, StorageType, StorageError> MerkleTree<TableType, StorageType> | |
where | |
TableType: Mappable<Key = Bytes32, Value = Primitive, OwnedValue = Primitive>, | |
StorageType: StorageInspect<TableType, Error = StorageError>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right yeah, perhaps we should just omit Storage
from the name then?
In order to integrate Jellyfish Merkle Trees from the jmt crate, we must implement three traits from that crate:
This PR connects the storage traits on the fuel-vm side with jmt crate as follows:
Tests are provided in the last PR of the feature branch.
[Short description of the changes.]
Checklist
Before requesting review
After merging, notify other teams
[Add or remove entries as needed]