Skip to content
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* [BREAKING] Fixed `createP2IDNote` and `createP2IDENote` convenience functions in the Web Client ([#1142](https://github.com/0xMiden/miden-client/pull/1142)).
* Reexported utils to parse token amounts as base units ([#1161](https://github.com/0xMiden/miden-client/pull/1161)).
* [BREAKING] Rename `export/importNote` to `export/importNoteFile`, expose serialization functions for `Note` in Web Client ([#1159](https://github.com/0xMiden/miden-client/pull/1159)).
* [BREAKING] Change protobuf `AccountStateHeader` definition for reduced redundancy ([#1167](https://github.com/0xMiden/miden-client/pull/1167)).
* Added support for `MockRpcApi` to web client ([#1096](https://github.com/0xMiden/miden-client/pull/1096)).

### Features
Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 17 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@ version = "0.11.0"
[workspace.dependencies]
# Miden dependencies
miden-lib = { branch = "next", default-features = false, git = "https://github.com/0xMiden/miden-base" }
miden-node-block-producer = { branch = "next", git = "https://github.com/0xMiden/miden-node" }
miden-node-ntx-builder = { branch = "next", git = "https://github.com/0xMiden/miden-node" }
miden-node-proto-build = { branch = "next", default-features = false, git = "https://github.com/0xMiden/miden-node" }
miden-node-rpc = { branch = "next", git = "https://github.com/0xMiden/miden-node" }
miden-node-store = { branch = "next", git = "https://github.com/0xMiden/miden-node" }
miden-node-utils = { branch = "next", git = "https://github.com/0xMiden/miden-node" }
miden-node-block-producer = { branch = "bernhard-617-batch-proof", git = "https://github.com/0xMiden/miden-node" }
miden-node-ntx-builder = { branch = "bernhard-617-batch-proof", git = "https://github.com/0xMiden/miden-node" }
miden-node-proto-build = { branch = "bernhard-617-batch-proof", default-features = false, git = "https://github.com/0xMiden/miden-node" }
miden-node-rpc = { branch = "bernhard-617-batch-proof", git = "https://github.com/0xMiden/miden-node" }
miden-node-store = { branch = "bernhard-617-batch-proof", git = "https://github.com/0xMiden/miden-node" }
miden-node-utils = { branch = "bernhard-617-batch-proof", git = "https://github.com/0xMiden/miden-node" }
miden-objects = { branch = "next", default-features = false, git = "https://github.com/0xMiden/miden-base" }
miden-remote-prover = { branch = "next", features = ["concurrent"], git = "https://github.com/0xMiden/miden-node" }
miden-remote-prover-client = { branch = "next", default-features = false, features = [
miden-remote-prover = { branch = "bernhard-617-batch-proof", features = [
"concurrent",
], git = "https://github.com/0xMiden/miden-node" }
miden-remote-prover-client = { branch = "bernhard-617-batch-proof", default-features = false, features = [
"tx-prover",
], git = "https://github.com/0xMiden/miden-node" }
miden-testing = { branch = "next", default-features = false, features = [
Expand All @@ -52,10 +54,11 @@ tracing = { version = "0.1" }
# Pedantic lints are set to a lower priority which allows lints in the group to be selectively enabled.
pedantic = { level = "warn", priority = -1 }
# cast_possible_truncation = "allow" # Overly many instances especially regarding indices.
ignored_unit_patterns = "allow" # Stylistic choice.
missing_errors_doc = "allow" # TODO: fixup and enable this.
missing_panics_doc = "allow" # TODO: fixup and enable this.
module_name_repetitions = "allow" # Many triggers, and is a stylistic choice.
must_use_candidate = "allow" # This marks many fn's which isn't helpful.
should_panic_without_expect = "allow" # We don't care about the specific panic message.
from_iter_instead_of_collect = "allow" # from_iter oftentimes is more expressive
ignored_unit_patterns = "allow" # Stylistic choice.
missing_errors_doc = "allow" # TODO: fixup and enable this.
missing_panics_doc = "allow" # TODO: fixup and enable this.
module_name_repetitions = "allow" # Many triggers, and is a stylistic choice.
must_use_candidate = "allow" # This marks many fn's which isn't helpful.
should_panic_without_expect = "allow" # We don't care about the specific panic message.
# End of pedantic lints.
42 changes: 22 additions & 20 deletions crates/rust-client/src/rpc/domain/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use miden_objects::account::{
AccountStorageHeader,
};
use miden_objects::block::{AccountWitness, BlockNumber};
use miden_objects::crypto::merkle::{MerklePath, SmtProof};
use miden_objects::crypto::merkle::{MerklePath, PartialSmt};
use miden_tx::utils::{Deserializable, Serializable, ToHex};
use thiserror::Error;

Expand Down Expand Up @@ -175,16 +175,18 @@ impl proto::rpc_store::account_proofs::account_proof::AccountStateHeader {
account_id: AccountId,
known_account_codes: &BTreeMap<Word, AccountCode>,
) -> Result<StateHeaders, crate::rpc::RpcError> {
use miden_objects::crypto::merkle::PartialSmt;

use crate::rpc::RpcError;
use crate::rpc::domain::MissingFieldHelper;
use crate::rpc::generated::rpc_store::account_proofs::account_proof::account_state_header::StorageSlotMapProof;

let proto::rpc_store::account_proofs::account_proof::AccountStateHeader {
header,
storage_header,
account_code,
storage_maps,
partial_storage_smts,
} = self;

let account_header = header
.ok_or(
proto::rpc_store::account_proofs::account_proof::AccountStateHeader::missing_field(
Expand Down Expand Up @@ -213,28 +215,28 @@ impl proto::rpc_store::account_proofs::account_proof::AccountStateHeader {
}
};

// Get map values into slot |-> (key, value, proof) mapping
let mut storage_slot_proofs: BTreeMap<u8, Vec<SmtProof>> = BTreeMap::new();
for StorageSlotMapProof { storage_slot, smt_proof } in storage_maps {
let proof = SmtProof::read_from_bytes(&smt_proof)?;
match storage_slot_proofs
.get_mut(&(u8::try_from(storage_slot).expect("there are no more than 256 slots")))
{
Some(list) => list.push(proof),
None => {
_ = storage_slot_proofs.insert(
u8::try_from(storage_slot).expect("only 256 storage slots"),
vec![proof],
);
},
let partial_storage_smts = Result::<BTreeMap<u8, PartialSmt>, _>::from_iter(
partial_storage_smts.into_iter().map(|entry| {
let slot = u8::try_from(entry.storage_slot)
.map_err(crate::rpc::RpcError::SlotOutOfBounds)?;
let partial_smt = PartialSmt::read_from_bytes(&entry.partial_smt)?;
Ok::<_, crate::rpc::RpcError>((slot, partial_smt))
}),
)?;

partial_storage_smts.iter().try_for_each(|(_slot, partial_smt)| {
for (key, _value) in partial_smt.entries() {
// validate all required inner nodes of the merkle path for the specific leaf exist
let _proof = partial_smt.open(key)?;
}
}
Ok::<_, crate::rpc::RpcError>(())
})?;
Comment on lines +227 to +233
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this needed? Checking the internal logic of PartialSmt and Smt, PartialSmt::entries will return an iterator over the tracked leaves and PartialSmt::open will only fail if the leaf isn't tracked.


Ok(StateHeaders {
account_header,
storage_header,
code,
storage_slots: storage_slot_proofs,
storage_slots: partial_storage_smts,
})
}
}
Expand All @@ -252,7 +254,7 @@ pub struct StateHeaders {
pub account_header: AccountHeader,
pub storage_header: AccountStorageHeader,
pub code: AccountCode,
pub storage_slots: BTreeMap<StorageSlotIndex, Vec<SmtProof>>,
pub storage_slots: BTreeMap<StorageSlotIndex, PartialSmt>,
}

/// Represents a proof of existence of an account's state at a specific block number.
Expand Down
4 changes: 4 additions & 0 deletions crates/rust-client/src/rpc/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ pub enum RpcError {
NoteNotFound(NoteId),
#[error("rpc request failed for {0}: {1}")]
RequestError(String, String),
#[error("merkle proof is not conetained")]
MerkleError(#[from] MerkleError),
#[error("slot index out of bounds")]
SlotOutOfBounds(#[source] TryFromIntError),
}

impl From<DeserializationError> for RpcError {
Expand Down
20 changes: 16 additions & 4 deletions crates/rust-client/src/rpc/generated/nostd/rpc_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,26 @@ pub mod account_proofs {
/// the current one.
#[prost(bytes = "vec", optional, tag = "3")]
pub account_code: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
/// Storage slots information for this account
#[prost(message, repeated, tag = "4")]
pub storage_maps: ::prost::alloc::vec::Vec<
account_state_header::StorageSlotMapProof,
/// A sparse merkle tree per storage slot, including all relevant merkle proofs for storage entries.
#[prost(message, repeated, tag = "5")]
pub partial_storage_smts: ::prost::alloc::vec::Vec<
account_state_header::StorageSlotMapPartialSmt,
>,
}
/// Nested message and enum types in `AccountStateHeader`.
pub mod account_state_header {
/// Represents a single storage slot with the requested keys and their respective values.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StorageSlotMapPartialSmt {
/// The storage slot index (\[0..255\]).
#[prost(uint32, tag = "1")]
pub storage_slot: u32,
/// Merkle proofs of the map value as partial sparse merkle tree for compression.
/// The respective rust types is `SparseMerkleTree` and the transformation to and from
/// bytes is done via the traits `Serializable::to_bytes` and `Deserializable::from_bytes`.
#[prost(bytes = "vec", tag = "2")]
pub partial_smt: ::prost::alloc::vec::Vec<u8>,
}
/// Represents a single storage slot with the requested keys and their respective values.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StorageSlotMapProof {
Expand Down
20 changes: 16 additions & 4 deletions crates/rust-client/src/rpc/generated/std/rpc_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,26 @@ pub mod account_proofs {
/// the current one.
#[prost(bytes = "vec", optional, tag = "3")]
pub account_code: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
/// Storage slots information for this account
#[prost(message, repeated, tag = "4")]
pub storage_maps: ::prost::alloc::vec::Vec<
account_state_header::StorageSlotMapProof,
/// A sparse merkle tree per storage slot, including all relevant merkle proofs for storage entries.
#[prost(message, repeated, tag = "5")]
pub partial_storage_smts: ::prost::alloc::vec::Vec<
account_state_header::StorageSlotMapPartialSmt,
>,
}
/// Nested message and enum types in `AccountStateHeader`.
pub mod account_state_header {
/// Represents a single storage slot with the requested keys and their respective values.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StorageSlotMapPartialSmt {
/// The storage slot index (\[0..255\]).
#[prost(uint32, tag = "1")]
pub storage_slot: u32,
/// Merkle proofs of the map value as partial sparse merkle tree for compression.
/// The respective rust types is `SparseMerkleTree` and the transformation to and from
/// bytes is done via the traits `Serializable::to_bytes` and `Deserializable::from_bytes`.
#[prost(bytes = "vec", tag = "2")]
pub partial_smt: ::prost::alloc::vec::Vec<u8>,
}
/// Represents a single storage slot with the requested keys and their respective values.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StorageSlotMapProof {
Expand Down
4 changes: 2 additions & 2 deletions crates/rust-client/src/test_utils/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use miden_objects::account::{
};
use miden_objects::asset::Asset;
use miden_objects::block::{BlockHeader, BlockNumber, ProvenBlock};
use miden_objects::crypto::merkle::{Forest, Mmr, MmrProof, SmtProof};
use miden_objects::crypto::merkle::{Forest, Mmr, MmrProof, PartialSmt, SmtProof};
use miden_objects::note::{NoteId, NoteTag, Nullifier};
use miden_objects::transaction::ProvenTransaction;
use miden_objects::{LexicographicWord, Word};
Expand Down Expand Up @@ -389,7 +389,7 @@ impl NodeRpcClient for MockRpcApi {
.iter()
.map(|map_key| storage_map.open(map_key))
.collect::<Vec<_>>();
storage_slots.insert(*index, proofs);
storage_slots.insert(*index, PartialSmt::from_proofs(proofs)?);
} else {
panic!("Storage slot at index {} is not a map", index);
}
Expand Down
4 changes: 2 additions & 2 deletions crates/rust-client/src/transaction/request/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ impl TryFrom<AccountProof> for AccountInputs {
{
// discard slot indices - not needed for execution
let mut storage_map_proofs = Vec::with_capacity(storage_slots.len());
for (_, slots) in storage_slots {
let storage_map = PartialStorageMap::new(PartialSmt::from_proofs(slots)?);
for (_, partial_smt) in storage_slots {
let storage_map = PartialStorageMap::new(partial_smt);
storage_map_proofs.push(storage_map);
}

Expand Down