Skip to content

Conversation

drahnr
Copy link
Contributor

@drahnr drahnr commented Aug 22, 2025

Follow up to #1158

Changes

Previously we used the Serializable/Deserializable implementations for PartialSmt which uses more leaves than the theoretical minimum required to reconstruct all intermediate nodes.

The PR implements a DFS per sibling required, calculating all inner nodes dynamically. Recomputation is avoided by using lookup cache per node index.

@drahnr drahnr changed the title optimize merkle node compression store API proto AccountProof: optimize merkle node compression Aug 22, 2025
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the complexity of the code, I wonder if this should actually live in miden-base. The main reason is that the client would need to deserialize this data but the client doesn't get anything from the node except for protobuf files.

In miden-base, we could attach the logic to the PartialStorageMap struct. Basically, we need two things there:

  • Given a PartialStorageMap we need to get SmtLeafs and InnerNodes from it. Not sure what the name of the function would be - but getting this data shouldn't be too difficult.
  • Given a set of SmtLeafs and InnerNodes, we need a constructor that would build the underlying PartialSmt from this.

Then, here in miden-node we'll just need to convert these to/from protobuf structs - so, the logic will be pretty straight-forward.

message AccountStateHeader {
// Represents a single storage slot with the requested keys and their respective values.
message StorageSlotMapProof {
message StorageSlotMapPartialSmt {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this message could be just PartialStorageMap.

Comment on lines +217 to +232
impl From<NodeIndex> for proto::primitives::NodeIndex {
fn from(value: NodeIndex) -> Self {
proto::primitives::NodeIndex {
depth: value.depth() as u32,
value: value.value(),
}
}
}
impl TryFrom<proto::primitives::NodeIndex> for NodeIndex {
type Error = ConversionError;
fn try_from(index: proto::primitives::NodeIndex) -> Result<Self, Self::Error> {
let depth = u8::try_from(index.depth)?;
let value = index.value;
Ok(NodeIndex::new(depth, value)?)
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably nothing, but we encode the depth as u32 and then cast it to u8. Should a comment be added about why is it always valid?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants