From 1300819ff3a24d2f10fd29f13999838187007e83 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:20:06 +0500 Subject: [PATCH 1/2] Migration to the `next` version of Miden dependencies (#297) * feat: migration to the `next` versions of Miden dependencies * fix: `parse_auth_inputs` * chore: use dependencies from crates.io * chore: update deps * fix: compilation errors * fix: address review comments * fix: genesis test --- Cargo.lock | 285 +++++++++++++++--- Cargo.toml | 12 +- .../src/block_builder/prover/block_witness.rs | 4 +- .../src/block_builder/prover/tests.rs | 7 +- block-producer/src/errors.rs | 18 +- block-producer/src/test_utils/proven_tx.rs | 18 +- faucet/Cargo.toml | 4 +- node/Cargo.toml | 1 + node/genesis.toml | 4 +- node/src/commands/genesis/mod.rs | 14 +- proto/src/errors.rs | 4 +- store/src/errors.rs | 4 +- store/src/state.rs | 11 +- 13 files changed, 302 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e873dd380..0b91e7717 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1524,7 +1524,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74fe3da3cee72178aa6d8cdd0e88a4d11a983f6c79a0257abfb6f04056177bee" dependencies = [ - "miden-core", + "miden-core 0.8.0", + "winter-air", + "winter-prover", +] + +[[package]] +name = "miden-air" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695ee3a51649711a6c202e4c7280222b66e987c8abefce9090fdc49412bbcbe" +dependencies = [ + "miden-core 0.9.1", "winter-air", "winter-prover", ] @@ -1535,7 +1546,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4261c0b2593e540004ddff8eb4e04419cf06d4c3794dbaa03bac6b51d09bf5" dependencies = [ - "miden-core", + "miden-core 0.8.0", + "num_enum", + "tracing", +] + +[[package]] +name = "miden-assembly" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015abf93a083b1255a45c5bde02479e5203468c662fd33dd092b6daf1e4a3988" +dependencies = [ + "miden-core 0.9.1", "num_enum", "tracing", ] @@ -1551,10 +1573,10 @@ dependencies = [ "comfy-table", "figment", "lazy_static", - "miden-lib", + "miden-lib 0.1.0", "miden-node-proto 0.1.0", - "miden-objects", - "miden-tx", + "miden-objects 0.1.1", + "miden-tx 0.1.0", "rand", "rusqlite", "rusqlite_migration", @@ -1572,7 +1594,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bb50725295351f6f01e68a03b6f43724a727c3545ddd849a94e21290fbae2ce" dependencies = [ - "miden-crypto", + "miden-crypto 0.8.4", + "winter-math", + "winter-utils", +] + +[[package]] +name = "miden-core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bc7219af4b6c5fb6a01d80b9dfdad68962157ccf986f7a923df01103e853e74" +dependencies = [ + "miden-crypto 0.9.1", "winter-math", "winter-utils", ] @@ -1592,15 +1625,44 @@ dependencies = [ "winter-utils", ] +[[package]] +name = "miden-crypto" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e339568704e3135360528e65edde5a47e585c007b7d14b55d010ba44c735b2" +dependencies = [ + "blake3", + "cc", + "glob", + "num", + "num-complex", + "rand", + "rand_core", + "sha3", + "winter-crypto", + "winter-math", + "winter-utils", +] + [[package]] name = "miden-lib" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "825bc94780153bd3783d9adbdf276ea38fab2ff3ce0815067badaa4d404c5fae" dependencies = [ - "miden-assembly", - "miden-objects", - "miden-stdlib", + "miden-assembly 0.8.0", + "miden-objects 0.1.1", + "miden-stdlib 0.8.0", +] + +[[package]] +name = "miden-lib" +version = "0.2.0" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#d6af2ae8ce3da19e9dcd66ce3ad81a724a8d8a7a" +dependencies = [ + "miden-assembly 0.9.1", + "miden-objects 0.2.0", + "miden-stdlib 0.9.1", ] [[package]] @@ -1610,12 +1672,13 @@ dependencies = [ "anyhow", "clap", "figment", - "miden-lib", + "miden-lib 0.2.0", "miden-node-block-producer", "miden-node-rpc", "miden-node-store", "miden-node-utils 0.2.0", - "miden-objects", + "miden-objects 0.2.0", + "rand_chacha", "serde", "tokio", "tracing", @@ -1631,15 +1694,15 @@ dependencies = [ "clap", "figment", "itertools 0.12.1", - "miden-air", + "miden-air 0.9.1", "miden-node-proto 0.2.0", "miden-node-store", "miden-node-test-macro", "miden-node-utils 0.2.0", - "miden-objects", - "miden-processor", - "miden-stdlib", - "miden-tx", + "miden-objects 0.2.0", + "miden-processor 0.9.1", + "miden-stdlib 0.9.1", + "miden-tx 0.2.0", "once_cell", "serde", "thiserror", @@ -1663,10 +1726,10 @@ dependencies = [ "derive_more", "figment", "miden-client", - "miden-lib", + "miden-lib 0.1.0", "miden-node-proto 0.2.0", "miden-node-utils 0.2.0", - "miden-objects", + "miden-objects 0.1.1", "serde", "tracing", "tracing-subscriber", @@ -1680,7 +1743,7 @@ checksum = "3fdcb2af46af307aaf5d80e940200c08e86d7d7491854f5a9cc33bb3ada7e757" dependencies = [ "hex", "miden-node-utils 0.1.0", - "miden-objects", + "miden-objects 0.1.1", "miette", "prost", "prost-build", @@ -1696,7 +1759,7 @@ version = "0.2.0" dependencies = [ "hex", "miden-node-utils 0.2.0", - "miden-objects", + "miden-objects 0.2.0", "miette", "proptest", "prost", @@ -1720,8 +1783,8 @@ dependencies = [ "miden-node-proto 0.2.0", "miden-node-store", "miden-node-utils 0.2.0", - "miden-objects", - "miden-tx", + "miden-objects 0.2.0", + "miden-tx 0.2.0", "prost", "serde", "tokio", @@ -1741,10 +1804,10 @@ dependencies = [ "directories", "figment", "hex", - "miden-lib", + "miden-lib 0.2.0", "miden-node-proto 0.2.0", "miden-node-utils 0.2.0", - "miden-objects", + "miden-objects 0.2.0", "once_cell", "prost", "rusqlite", @@ -1775,7 +1838,7 @@ dependencies = [ "anyhow", "figment", "itertools 0.12.1", - "miden-objects", + "miden-objects 0.1.1", "serde", "tracing", "tracing-subscriber", @@ -1788,7 +1851,7 @@ dependencies = [ "anyhow", "figment", "itertools 0.12.1", - "miden-objects", + "miden-objects 0.2.0", "serde", "tracing", "tracing-forest", @@ -1801,23 +1864,48 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7379df161104e3ba97812a89e33b4cff8183964af848074d62dd49f34f00aeed" dependencies = [ - "miden-assembly", - "miden-core", - "miden-crypto", - "miden-processor", - "miden-verifier", + "miden-assembly 0.8.0", + "miden-core 0.8.0", + "miden-crypto 0.8.4", + "miden-processor 0.8.0", + "miden-verifier 0.8.0", "serde", "winter-rand-utils", ] +[[package]] +name = "miden-objects" +version = "0.2.0" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#d6af2ae8ce3da19e9dcd66ce3ad81a724a8d8a7a" +dependencies = [ + "miden-assembly 0.9.1", + "miden-core 0.9.1", + "miden-crypto 0.9.1", + "miden-processor 0.9.1", + "miden-verifier 0.9.1", + "winter-rand-utils", +] + [[package]] name = "miden-processor" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e355306e8495f40685aac012d7ec62f86c42b89dcd8d88d26a507b363d4e5de5" dependencies = [ - "miden-air", - "miden-core", + "miden-air 0.8.0", + "miden-core 0.8.0", + "tracing", + "winter-prover", +] + +[[package]] +name = "miden-processor" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "682f881050c637bbf01bee5970d5f13d818b544b7f0ea3ecb1b624aa54ec04e3" +dependencies = [ + "miden-air 0.9.1", + "miden-core 0.9.1", "tracing", "winter-prover", ] @@ -1828,8 +1916,20 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "757e94100fd703d9b76ef0b4772a6e983e895454fd43da8ba8145b57976e9f69" dependencies = [ - "miden-air", - "miden-processor", + "miden-air 0.8.0", + "miden-processor 0.8.0", + "tracing", + "winter-prover", +] + +[[package]] +name = "miden-prover" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a685fc0e9ba2b5c4b7203b759ee2dea469600813f213de381461996c6775c8" +dependencies = [ + "miden-air 0.9.1", + "miden-processor 0.9.1", "tracing", "winter-prover", ] @@ -1840,7 +1940,16 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a560cf74e712c121b4f531aa6df2de5f9daef29dfc328a0ee91064ce6720d5d" dependencies = [ - "miden-assembly", + "miden-assembly 0.8.0", +] + +[[package]] +name = "miden-stdlib" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60994609096a8cb1e32f1fcf1c8ed63bed9b24b32730658609bad841e8caeaf9" +dependencies = [ + "miden-assembly 0.9.1", ] [[package]] @@ -1849,11 +1958,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d59fa14ff23132a14fd3cf215e681d99aad83d819500319f0b20c251179c671" dependencies = [ - "miden-lib", - "miden-objects", - "miden-processor", - "miden-prover", - "miden-verifier", + "miden-lib 0.1.0", + "miden-objects 0.1.1", + "miden-processor 0.8.0", + "miden-prover 0.8.0", + "miden-verifier 0.8.0", +] + +[[package]] +name = "miden-tx" +version = "0.2.0" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#d6af2ae8ce3da19e9dcd66ce3ad81a724a8d8a7a" +dependencies = [ + "miden-lib 0.2.0", + "miden-objects 0.2.0", + "miden-processor 0.9.1", + "miden-prover 0.9.1", + "miden-verifier 0.9.1", ] [[package]] @@ -1862,8 +1983,20 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a54fb6a52f8a3a0874718bf2cb41526e4a59972e8918db9a7796a7a73ab37f" dependencies = [ - "miden-air", - "miden-core", + "miden-air 0.8.0", + "miden-core 0.8.0", + "tracing", + "winter-verifier", +] + +[[package]] +name = "miden-verifier" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8af794328085d13d11bd0ff009464b0af74206cd43f51c8aa3b1c42f17993b62" +dependencies = [ + "miden-air 0.9.1", + "miden-core 0.9.1", "tracing", "winter-verifier", ] @@ -1968,12 +2101,78 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.18" diff --git a/Cargo.toml b/Cargo.toml index 8c7fc933a..02576560d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,12 +23,12 @@ repository = "https://github.com/0xPolygonMiden/miden-node" exclude = [".github/"] [workspace.dependencies] -miden-air = { version = "0.8", default-features = false } -miden-lib = { version = "0.1" } -miden-objects = { version = "0.1" } -miden-processor = { version = "0.8" } -miden-stdlib = { version = "0.8", default-features = false } -miden-tx = { version = "0.1" } +miden-air = { version = "0.9", default-features = false } +miden-lib = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } +miden-objects = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } +miden-processor = { version = "0.9" } +miden-stdlib = { version = "0.9", default-features = false } +miden-tx = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } thiserror = { version = "1.0" } tracing = { version = "0.1" } tracing-subscriber = { version = "0.3", features = [ diff --git a/block-producer/src/block_builder/prover/block_witness.rs b/block-producer/src/block_builder/prover/block_witness.rs index 87bcbcd0e..ba7e7f6a5 100644 --- a/block-producer/src/block_builder/prover/block_witness.rs +++ b/block-producer/src/block_builder/prover/block_witness.rs @@ -261,7 +261,9 @@ impl BlockWitness { .expect("updated accounts number is greater than or equal to the field modulus"), ); - StackInputs::new(stack_inputs) + // TODO: We need provide produced nullifier different way, because such big stack inputs + // will cause problem in recursive proofs + StackInputs::new(stack_inputs).expect("Stack inputs count extends max limit") } /// Builds the advice inputs to the block kernel diff --git a/block-producer/src/block_builder/prover/tests.rs b/block-producer/src/block_builder/prover/tests.rs index 11f0324eb..5c698cfa0 100644 --- a/block-producer/src/block_builder/prover/tests.rs +++ b/block-producer/src/block_builder/prover/tests.rs @@ -6,7 +6,7 @@ use miden_objects::{ EmptySubtreeRoots, LeafIndex, MerklePath, Mmr, MmrPeaks, SimpleSmt, Smt, SmtLeaf, SmtProof, SMT_DEPTH, }, - notes::{NoteEnvelope, NoteMetadata}, + notes::{NoteEnvelope, NoteMetadata, NoteType}, BLOCK_OUTPUT_NOTES_TREE_DEPTH, ONE, ZERO, }; @@ -381,7 +381,10 @@ async fn test_compute_note_root_success() { .into_iter() .zip(account_ids.iter()) .map(|(note_digest, &account_id)| { - NoteEnvelope::new(note_digest.into(), NoteMetadata::new(account_id, Felt::new(1u64))) + NoteEnvelope::new( + note_digest.into(), + NoteMetadata::new(account_id, NoteType::OffChain, 0.into(), ONE).unwrap(), + ) }) .collect(); diff --git a/block-producer/src/errors.rs b/block-producer/src/errors.rs index a597714a1..e8cc22dd2 100644 --- a/block-producer/src/errors.rs +++ b/block-producer/src/errors.rs @@ -13,7 +13,7 @@ use thiserror::Error; // Transaction verification errors // ================================================================================================= -#[derive(Error, Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum VerifyTxError { /// The account that the transaction modifies has already been modified and isn't yet committed /// to a block @@ -49,7 +49,7 @@ pub enum VerifyTxError { // Transaction adding errors // ================================================================================================= -#[derive(Error, Debug)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum AddTransactionError { #[error("Transaction verification failed: {0}")] VerificationFailed(#[from] VerifyTxError), @@ -63,7 +63,7 @@ pub enum AddTransactionError { /// These errors are returned from the batch builder to the transaction queue, instead of /// dropping the transactions, they are included into the error values, so that the transaction /// queue can re-queue them. -#[derive(Error, Debug)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum BuildBatchError { #[error("Too many notes in the batch. Got: {0}, max: {}", MAX_NOTES_PER_BATCH)] TooManyNotesCreated(usize, Vec), @@ -84,13 +84,13 @@ impl BuildBatchError { // Block prover errors // ================================================================================================= -#[derive(Error, Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum BlockProverError { #[error("Received invalid merkle path")] InvalidMerklePaths(MerkleError), - #[error("program execution failed")] + #[error("Program execution failed")] ProgramExecutionFailed(ExecutionError), - #[error("failed to retrieve {0} root from stack outputs")] + #[error("Failed to retrieve {0} root from stack outputs")] InvalidRootOutput(&'static str), } @@ -98,7 +98,7 @@ pub enum BlockProverError { // ================================================================================================= #[allow(clippy::enum_variant_names)] -#[derive(Debug, PartialEq, Error)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum BlockInputsError { #[error("failed to parse protobuf message: {0}")] ParseError(#[from] ParseError), @@ -122,7 +122,7 @@ pub enum ApplyBlockError { // Block building errors // ================================================================================================= -#[derive(Debug, Error, PartialEq)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum BuildBlockError { #[error("failed to compute new block: {0}")] BlockProverFailed(#[from] BlockProverError), @@ -146,7 +146,7 @@ pub enum BuildBlockError { // Transaction inputs errors // ================================================================================================= -#[derive(Debug, PartialEq, Error)] +#[derive(Debug, PartialEq, Eq, Error)] pub enum TxInputsError { #[error("gRPC client failed with error: {0}")] GrpcClientError(String), diff --git a/block-producer/src/test_utils/proven_tx.rs b/block-producer/src/test_utils/proven_tx.rs index 1f8f11b53..51d1813a0 100644 --- a/block-producer/src/test_utils/proven_tx.rs +++ b/block-producer/src/test_utils/proven_tx.rs @@ -3,8 +3,8 @@ use std::ops::Range; use miden_air::HashFunction; use miden_objects::{ accounts::AccountId, - notes::{NoteEnvelope, NoteMetadata, Nullifier}, - transaction::{InputNotes, OutputNotes, ProvenTransaction}, + notes::{NoteEnvelope, NoteMetadata, NoteType, Nullifier}, + transaction::{ProvenTransaction, ProvenTransactionBuilder}, vm::ExecutionProof, Digest, Felt, Hasher, ONE, }; @@ -82,7 +82,10 @@ impl MockProvenTxBuilder { .map(|note_index| { let note_hash = Hasher::hash(¬e_index.to_be_bytes()); - NoteEnvelope::new(note_hash.into(), NoteMetadata::new(self.account_id, ONE)) + NoteEnvelope::new( + note_hash.into(), + NoteMetadata::new(self.account_id, NoteType::OffChain, 0.into(), ONE).unwrap(), + ) }) .collect(); @@ -90,15 +93,16 @@ impl MockProvenTxBuilder { } pub fn build(self) -> ProvenTransaction { - ProvenTransaction::new( + ProvenTransactionBuilder::new( self.account_id, self.initial_account_hash, self.final_account_hash, - InputNotes::new(self.nullifiers.unwrap_or_default()).unwrap(), - OutputNotes::new(self.notes_created.unwrap_or_default()).unwrap(), - None, Digest::default(), ExecutionProof::new(StarkProof::new_dummy(), HashFunction::Blake3_192), ) + .add_input_notes(self.nullifiers.unwrap_or_default()) + .add_output_notes(self.notes_created.unwrap_or_default()) + .build() + .unwrap() } } diff --git a/faucet/Cargo.toml b/faucet/Cargo.toml index 50fc69be6..d7815297f 100644 --- a/faucet/Cargo.toml +++ b/faucet/Cargo.toml @@ -15,11 +15,11 @@ actix-files = "0.6.5" actix-cors = "0.7.0" derive_more = "0.99.17" figment = { version = "0.10", features = ["toml", "env"] } -miden-lib = { workspace = true } +miden-lib = { version = "0.1.0" } # Version of miden-base is pinned due to client requirement miden-client = { version = "0.1.0", features = ["concurrent"] } miden-node-proto = { path = "../proto", version = "0.2" } miden-node-utils = { path = "../utils", version = "0.2" } -miden-objects = { workspace = true } +miden-objects = { version = "0.1.0" } # Version of miden-base is pinned due to client requirement serde = { version = "1.0", features = ["derive"] } clap = { version = "4.5.1", features = ["derive"] } async-mutex = "1.4.0" diff --git a/node/Cargo.toml b/node/Cargo.toml index e9fdcc236..b61fe5af9 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -25,6 +25,7 @@ miden-node-rpc = { path = "../rpc", version = "0.2" } miden-node-store = { path = "../store", version = "0.2" } miden-node-utils = { path = "../utils", version = "0.2" } miden-objects = { workspace = true } +rand_chacha = "0.3" serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.29", features = ["rt-multi-thread", "net", "macros"] } tracing = { workspace = true } diff --git a/node/genesis.toml b/node/genesis.toml index 4e864d46c..a0afd9189 100644 --- a/node/genesis.toml +++ b/node/genesis.toml @@ -7,13 +7,13 @@ timestamp = 1672531200 type = "BasicWallet" init_seed = "0xa123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" auth_scheme = "RpoFalcon512" -auth_seed = "0xb123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +auth_seed = "0xb123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" [[accounts]] type = "BasicFungibleFaucet" init_seed = "0xc123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" auth_scheme = "RpoFalcon512" -auth_seed = "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" +auth_seed = "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" token_symbol = "POL" decimals = 12 max_supply = 1000000 diff --git a/node/src/commands/genesis/mod.rs b/node/src/commands/genesis/mod.rs index eb4a9d0bc..f05fb9fb2 100644 --- a/node/src/commands/genesis/mod.rs +++ b/node/src/commands/genesis/mod.rs @@ -15,11 +15,12 @@ use miden_objects::{ accounts::{Account, AccountData, AccountType, AuthData}, assets::TokenSymbol, crypto::{ - dsa::rpo_falcon512::KeyPair, + dsa::rpo_falcon512::SecretKey, utils::{hex_to_bytes, Serializable}, }, Felt, ONE, }; +use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; mod inputs; @@ -183,11 +184,12 @@ fn parse_auth_inputs( ) -> Result<(AuthScheme, AuthData)> { match auth_scheme_input { AuthSchemeInput::RpoFalcon512 => { - let auth_seed = hex_to_bytes(auth_seed)?; - let keypair = KeyPair::from_seed(&auth_seed)?; + let auth_seed: [u8; 32] = hex_to_bytes(auth_seed)?; + let mut rng = ChaCha20Rng::from_seed(auth_seed); + let secret = SecretKey::with_rng(&mut rng); let auth_scheme = AuthScheme::RpoFalcon512 { - pub_key: keypair.public_key(), + pub_key: secret.public_key(), }; let auth_info = AuthData::RpoFalcon512Seed(auth_seed); @@ -226,13 +228,13 @@ mod tests { type = "BasicWallet" init_seed = "0xa123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" auth_scheme = "RpoFalcon512" - auth_seed = "0xb123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + auth_seed = "0xb123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" [[accounts]] type = "BasicFungibleFaucet" init_seed = "0xc123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" auth_scheme = "RpoFalcon512" - auth_seed = "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + auth_seed = "0xd123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" token_symbol = "POL" decimals = 12 max_supply = 1000000 diff --git a/proto/src/errors.rs b/proto/src/errors.rs index 5b432c661..da0e29577 100644 --- a/proto/src/errors.rs +++ b/proto/src/errors.rs @@ -3,7 +3,7 @@ use std::any::type_name; use miden_objects::crypto::merkle::{SmtLeafError, SmtProofError}; use thiserror::Error; -#[derive(Error, Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Error)] pub enum ParseError { #[error("Hex error: {0}")] HexError(#[from] hex::FromHexError), @@ -26,6 +26,8 @@ pub enum ParseError { }, } +impl Eq for ParseError {} + pub trait MissingFieldHelper { fn missing_field(field_name: &'static str) -> ParseError; } diff --git a/store/src/errors.rs b/store/src/errors.rs index 2856b5f96..9cc54c3dd 100644 --- a/store/src/errors.rs +++ b/store/src/errors.rs @@ -7,7 +7,7 @@ use miden_objects::{ utils::DeserializationError, }, notes::Nullifier, - AccountError, BlockHeader, + AccountError, BlockHeader, NoteError, }; use rusqlite::types::FromSqlError; use thiserror::Error; @@ -108,6 +108,8 @@ pub enum ApplyBlockError { DatabaseError(#[from] DatabaseError), #[error("Account error: {0}")] AccountError(#[from] AccountError), + #[error("Note error: {0}")] + NoteError(#[from] NoteError), #[error("Concurrent write detected")] ConcurrentWrite, #[error("New block number must be 1 greater than the current block number")] diff --git a/store/src/state.rs b/store/src/state.rs index b34a93026..06246d958 100644 --- a/store/src/state.rs +++ b/store/src/state.rs @@ -11,8 +11,8 @@ use miden_objects::{ hash::rpo::RpoDigest, merkle::{LeafIndex, Mmr, MmrDelta, MmrPeaks, SimpleSmt, SmtProof, ValuePath}, }, - notes::{NoteMetadata, Nullifier, NOTE_LEAF_DEPTH}, - AccountError, BlockHeader, Word, ACCOUNT_TREE_DEPTH, + notes::{NoteMetadata, NoteType, Nullifier, NOTE_LEAF_DEPTH}, + AccountError, BlockHeader, NoteError, Word, ACCOUNT_TREE_DEPTH, ZERO, }; use tokio::{ sync::{oneshot, Mutex, RwLock}, @@ -481,12 +481,15 @@ pub fn build_notes_tree( let mut entries: Vec<(u64, Word)> = Vec::with_capacity(notes.len() * 2); for note in notes.iter() { + let note_type = NoteType::OffChain; // TODO: provide correct note type let note_metadata = NoteMetadata::new( note.sender.try_into()?, + note_type, note.tag .try_into() - .expect("tag value is greater than or equal to the field modulus"), - ); + .map_err(|_| NoteError::InconsistentNoteTag(note_type, note.tag))?, + ZERO, + )?; let index = note.note_index as u64; entries.push((index, note.note_id.into())); entries.push((index + 1, note_metadata.into())); From 1cbe5a897b05473db17c8836e10c6d3ade9d3e13 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:34:39 +0500 Subject: [PATCH 2/2] Implemented support for note trees in Miden node (#295) * feat: migration to the `next` versions of Miden dependencies * fix: address review comments * fix: update to the latest `next` * feat: support of `BatchNoteTree` and `BlockNoteTree` * feat: support of `BatchNoteTree` and `BlockNoteTree`, use `batch_index` instead of encoding it into the note index * docs: add comments in SQL for batch and note indexes --- block-producer/src/batch_builder/batch.rs | 18 ++++----- block-producer/src/block.rs | 2 +- block-producer/src/block_builder/mod.rs | 10 ++--- block-producer/src/test_utils/block.rs | 39 ++++++++----------- block-producer/src/test_utils/store.rs | 11 +++--- proto/proto/note.proto | 9 +++-- proto/src/domain/notes.rs | 7 ++-- proto/src/generated/note.rs | 8 ++-- store/src/db/migrations.rs | 4 +- store/src/db/mod.rs | 1 + store/src/db/sql.rs | 45 ++++++++++++++++------ store/src/db/tests.rs | 41 +++++++++++++------- store/src/errors.rs | 2 +- store/src/server/api.rs | 1 + store/src/state.rs | 47 +++++++++++------------ 15 files changed, 138 insertions(+), 107 deletions(-) diff --git a/block-producer/src/batch_builder/batch.rs b/block-producer/src/batch_builder/batch.rs index 2f4752f1d..864948cec 100644 --- a/block-producer/src/batch_builder/batch.rs +++ b/block-producer/src/batch_builder/batch.rs @@ -2,12 +2,10 @@ use std::collections::BTreeMap; use miden_objects::{ accounts::AccountId, - crypto::{ - hash::blake::{Blake3Digest, Blake3_256}, - merkle::SimpleSmt, - }, + batches::BatchNoteTree, + crypto::hash::blake::{Blake3Digest, Blake3_256}, notes::{NoteEnvelope, Nullifier}, - Digest, BATCH_OUTPUT_NOTES_TREE_DEPTH, MAX_NOTES_PER_BATCH, + Digest, MAX_NOTES_PER_BATCH, }; use tracing::instrument; @@ -27,7 +25,7 @@ pub struct TransactionBatch { id: BatchId, updated_accounts: BTreeMap, produced_nullifiers: Vec, - created_notes_smt: SimpleSmt, + created_notes_smt: BatchNoteTree, /// The notes stored `created_notes_smt` created_notes: Vec, } @@ -74,10 +72,10 @@ impl TransactionBatch { // TODO: document under what circumstances SMT creating can fail ( created_notes.clone(), - SimpleSmt::::with_contiguous_leaves( - created_notes.into_iter().flat_map(|note_envelope| { - [note_envelope.note_id().into(), note_envelope.metadata().into()] - }), + BatchNoteTree::with_contiguous_leaves( + created_notes + .iter() + .map(|note_envelope| (note_envelope.note_id(), note_envelope.metadata())), ) .map_err(|e| BuildBatchError::NotesSmtError(e, txs))?, ) diff --git a/block-producer/src/block.rs b/block-producer/src/block.rs index e2f818cf7..cfc026aee 100644 --- a/block-producer/src/block.rs +++ b/block-producer/src/block.rs @@ -18,7 +18,7 @@ use crate::store::BlockInputsError; pub struct Block { pub header: BlockHeader, pub updated_accounts: Vec<(AccountId, Digest)>, - pub created_notes: BTreeMap, + pub created_notes: Vec<(usize, usize, NoteEnvelope)>, pub produced_nullifiers: Vec, // TODO: // - full states for updated public accounts diff --git a/block-producer/src/block_builder/mod.rs b/block-producer/src/block_builder/mod.rs index d92bd7943..615b687e3 100644 --- a/block-producer/src/block_builder/mod.rs +++ b/block-producer/src/block_builder/mod.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use async_trait::async_trait; use miden_node_utils::formatting::{format_array, format_blake3_digest}; -use miden_objects::{accounts::AccountId, notes::Nullifier, Digest, MAX_NOTES_PER_BATCH}; +use miden_objects::{accounts::AccountId, notes::Nullifier, Digest}; use tracing::{debug, info, instrument}; use crate::{ @@ -83,10 +83,10 @@ where .iter() .enumerate() .flat_map(|(batch_idx, batch)| { - batch.created_notes().enumerate().map(move |(note_idx_in_batch, note)| { - let note_idx_in_block = batch_idx * MAX_NOTES_PER_BATCH + note_idx_in_batch; - (note_idx_in_block as u64, *note) - }) + batch + .created_notes() + .enumerate() + .map(move |(note_idx_in_batch, note)| (batch_idx, note_idx_in_batch, *note)) }) .collect(); let produced_nullifiers: Vec = diff --git a/block-producer/src/test_utils/block.rs b/block-producer/src/test_utils/block.rs index a158a8d72..5bfd2c00f 100644 --- a/block-producer/src/test_utils/block.rs +++ b/block-producer/src/test_utils/block.rs @@ -1,11 +1,9 @@ -use std::collections::BTreeMap; - use miden_objects::{ accounts::AccountId, + block::BlockNoteTree, crypto::merkle::{Mmr, SimpleSmt}, notes::{NoteEnvelope, Nullifier}, - BlockHeader, Digest, ACCOUNT_TREE_DEPTH, BLOCK_OUTPUT_NOTES_TREE_DEPTH, MAX_NOTES_PER_BATCH, - ONE, ZERO, + BlockHeader, Digest, ACCOUNT_TREE_DEPTH, ONE, ZERO, }; use super::MockStoreSuccess; @@ -92,7 +90,7 @@ pub struct MockBlockBuilder { last_block_header: BlockHeader, updated_accounts: Option>, - created_notes: Option>, + created_notes: Option>, produced_nullifiers: Option>, } @@ -124,7 +122,7 @@ impl MockBlockBuilder { pub fn created_notes( mut self, - created_notes: BTreeMap, + created_notes: Vec<(usize, usize, NoteEnvelope)>, ) -> Self { self.created_notes = Some(created_notes); @@ -149,7 +147,7 @@ impl MockBlockBuilder { self.store_chain_mmr.peaks(self.store_chain_mmr.forest()).unwrap().hash_peaks(), self.store_accounts.root(), Digest::default(), - note_created_smt_from_envelopes(created_notes.iter()).root(), + note_created_smt_from_envelopes(created_notes.iter().cloned()).root(), Digest::default(), Digest::default(), ZERO, @@ -165,28 +163,23 @@ impl MockBlockBuilder { } } -pub(crate) fn note_created_smt_from_envelopes<'a>( - note_iterator: impl Iterator -) -> SimpleSmt { - SimpleSmt::::with_leaves(note_iterator.flat_map( - |(note_idx_in_block, note)| { - let index = note_idx_in_block * 2; - [(index, note.note_id().into()), (index + 1, note.metadata().into())] - }, - )) +pub(crate) fn note_created_smt_from_envelopes( + note_iterator: impl Iterator +) -> BlockNoteTree { + BlockNoteTree::with_entries(note_iterator.map(|(batch_idx, note_idx_in_batch, note)| { + (batch_idx, note_idx_in_batch, (note.note_id().into(), *note.metadata())) + })) .unwrap() } pub(crate) fn note_created_smt_from_batches<'a>( batches: impl Iterator -) -> SimpleSmt { - let note_leaf_iterator = batches.enumerate().flat_map(|(batch_index, batch)| { - let subtree_index = batch_index * MAX_NOTES_PER_BATCH * 2; - batch.created_notes().enumerate().flat_map(move |(note_index, note)| { - let index = (subtree_index + note_index * 2) as u64; - [(index, note.note_id().into()), (index + 1, note.metadata().into())] +) -> BlockNoteTree { + let note_leaf_iterator = batches.enumerate().flat_map(|(batch_idx, batch)| { + batch.created_notes().enumerate().map(move |(note_idx_in_batch, note)| { + (batch_idx, note_idx_in_batch, (note.note_id().into(), *note.metadata())) }) }); - SimpleSmt::::with_leaves(note_leaf_iterator).unwrap() + BlockNoteTree::with_entries(note_leaf_iterator).unwrap() } diff --git a/block-producer/src/test_utils/store.rs b/block-producer/src/test_utils/store.rs index 00f26a2a1..1fbb675e4 100644 --- a/block-producer/src/test_utils/store.rs +++ b/block-producer/src/test_utils/store.rs @@ -2,9 +2,10 @@ use std::collections::BTreeSet; use async_trait::async_trait; use miden_objects::{ + block::BlockNoteTree, crypto::merkle::{Mmr, SimpleSmt, Smt, ValuePath}, notes::{NoteEnvelope, Nullifier}, - BlockHeader, ACCOUNT_TREE_DEPTH, BLOCK_OUTPUT_NOTES_TREE_DEPTH, EMPTY_WORD, ONE, ZERO, + BlockHeader, ACCOUNT_TREE_DEPTH, EMPTY_WORD, ONE, ZERO, }; use super::*; @@ -22,7 +23,7 @@ use crate::{ #[derive(Debug)] pub struct MockStoreSuccessBuilder { accounts: Option>, - notes: Option>, + notes: Option, produced_nullifiers: Option>, chain_mmr: Option, block_num: Option, @@ -68,9 +69,9 @@ impl MockStoreSuccessBuilder { } } - pub fn initial_notes<'a>( + pub fn initial_notes( mut self, - notes: impl Iterator, + notes: impl Iterator, ) -> Self { self.notes = Some(note_created_smt_from_envelopes(notes)); @@ -107,7 +108,7 @@ impl MockStoreSuccessBuilder { pub fn build(self) -> MockStoreSuccess { let block_num = self.block_num.unwrap_or(1); let accounts_smt = self.accounts.unwrap_or(SimpleSmt::new().unwrap()); - let notes_smt = self.notes.unwrap_or(SimpleSmt::new().unwrap()); + let notes_smt = self.notes.unwrap_or_default(); let chain_mmr = self.chain_mmr.unwrap_or_default(); let nullifiers_smt = self .produced_nullifiers diff --git a/proto/proto/note.proto b/proto/proto/note.proto index 5fbc0784a..fed3ea755 100644 --- a/proto/proto/note.proto +++ b/proto/proto/note.proto @@ -23,8 +23,9 @@ message NoteSyncRecord { } message NoteCreated { - uint32 note_index = 1; - digest.Digest note_id = 2; - account.AccountId sender = 3; - fixed64 tag = 4; + uint32 batch_index = 1; + uint32 note_index = 2; + digest.Digest note_id = 3; + account.AccountId sender = 4; + fixed64 tag = 5; } \ No newline at end of file diff --git a/proto/src/domain/notes.rs b/proto/src/domain/notes.rs index 8e03252e6..d27d6e95a 100644 --- a/proto/src/domain/notes.rs +++ b/proto/src/domain/notes.rs @@ -20,13 +20,14 @@ impl From for note::NoteSyncRecord { // NoteCreated // ================================================================================================ -impl From<(u64, NoteEnvelope)> for note::NoteCreated { - fn from((note_idx, note): (u64, NoteEnvelope)) -> Self { +impl From<(usize, usize, NoteEnvelope)> for note::NoteCreated { + fn from((batch_idx, note_idx, note): (usize, usize, NoteEnvelope)) -> Self { Self { + batch_index: batch_idx as u32, + note_index: note_idx as u32, note_id: Some(note.note_id().into()), sender: Some(note.metadata().sender().into()), tag: note.metadata().tag().into(), - note_index: note_idx as u32, } } } diff --git a/proto/src/generated/note.rs b/proto/src/generated/note.rs index b6c5849ed..05d5ef286 100644 --- a/proto/src/generated/note.rs +++ b/proto/src/generated/note.rs @@ -35,11 +35,13 @@ pub struct NoteSyncRecord { #[derive(Clone, PartialEq, ::prost::Message)] pub struct NoteCreated { #[prost(uint32, tag = "1")] + pub batch_index: u32, + #[prost(uint32, tag = "2")] pub note_index: u32, - #[prost(message, optional, tag = "2")] - pub note_id: ::core::option::Option, #[prost(message, optional, tag = "3")] + pub note_id: ::core::option::Option, + #[prost(message, optional, tag = "4")] pub sender: ::core::option::Option, - #[prost(fixed64, tag = "4")] + #[prost(fixed64, tag = "5")] pub tag: u64, } diff --git a/store/src/db/migrations.rs b/store/src/db/migrations.rs index 3eec2bc0b..48905976f 100644 --- a/store/src/db/migrations.rs +++ b/store/src/db/migrations.rs @@ -18,7 +18,8 @@ pub static MIGRATIONS: Lazy = Lazy::new(|| { notes ( block_num INTEGER NOT NULL, - note_index INTEGER NOT NULL, + batch_index INTEGER NOT NULL, -- Index of batch in block, starting from 0 + note_index INTEGER NOT NULL, -- Index of note in batch, starting from 0 note_hash BLOB NOT NULL, sender INTEGER NOT NULL, tag INTEGER NOT NULL, @@ -27,6 +28,7 @@ pub static MIGRATIONS: Lazy = Lazy::new(|| { PRIMARY KEY (block_num, note_index), CONSTRAINT fk_block_num FOREIGN KEY (block_num) REFERENCES block_headers (block_num), CONSTRAINT notes_block_number_is_u32 CHECK (block_num >= 0 AND block_num < 4294967296), + CONSTRAINT notes_batch_index_is_u32 CHECK (batch_index BETWEEN 0 AND 0xFFFFFFFF) CONSTRAINT notes_note_index_is_u32 CHECK (note_index >= 0 AND note_index < 4294967296) ) STRICT, WITHOUT ROWID; diff --git a/store/src/db/mod.rs b/store/src/db/mod.rs index e6ea9ee76..493d08731 100644 --- a/store/src/db/mod.rs +++ b/store/src/db/mod.rs @@ -45,6 +45,7 @@ pub struct NullifierInfo { #[derive(Debug, Clone, PartialEq)] pub struct NoteCreated { + pub batch_index: u32, pub note_index: u32, pub note_id: RpoDigest, pub sender: AccountId, diff --git a/store/src/db/sql.rs b/store/src/db/sql.rs index 55d2ddf65..ff39c06bb 100644 --- a/store/src/db/sql.rs +++ b/store/src/db/sql.rs @@ -248,24 +248,40 @@ pub fn select_nullifiers_by_block_range( /// /// A vector with notes, or an error. pub fn select_notes(conn: &mut Connection) -> Result> { - let mut stmt = conn.prepare("SELECT * FROM notes ORDER BY block_num ASC;")?; + let mut stmt = conn.prepare( + " + SELECT + block_num, + batch_index, + note_index, + note_hash, + sender, + tag, + merkle_path + FROM + notes + ORDER BY + block_num ASC; + ", + )?; let mut rows = stmt.query([])?; let mut notes = vec![]; while let Some(row) = rows.next()? { - let note_id_data = row.get_ref(2)?.as_blob()?; + let note_id_data = row.get_ref(3)?.as_blob()?; let note_id = deserialize(note_id_data)?; - let merkle_path_data = row.get_ref(5)?.as_blob()?; + let merkle_path_data = row.get_ref(6)?.as_blob()?; let merkle_path = deserialize(merkle_path_data)?; notes.push(Note { block_num: row.get(0)?, note_created: NoteCreated { - note_index: row.get(1)?, + batch_index: row.get(1)?, + note_index: row.get(2)?, note_id, - sender: column_value_as_u64(row, 3)?, - tag: column_value_as_u64(row, 4)?, + sender: column_value_as_u64(row, 4)?, + tag: column_value_as_u64(row, 5)?, }, merkle_path, }) @@ -293,6 +309,7 @@ pub fn insert_notes( notes ( block_num, + batch_index, note_index, note_hash, sender, @@ -301,7 +318,7 @@ pub fn insert_notes( ) VALUES ( - ?1, ?2, ?3, ?4, ?5, ?6 + ?1, ?2, ?3, ?4, ?5, ?6, ?7 );", )?; @@ -309,6 +326,7 @@ pub fn insert_notes( for note in notes.iter() { count += stmt.execute(params![ note.block_num, + note.note_created.batch_index, note.note_created.note_index, note.note_created.note_id.to_bytes(), u64_to_value(note.note_created.sender), @@ -345,6 +363,7 @@ pub fn select_notes_since_block_by_tag_and_sender( " SELECT block_num, + batch_index, note_index, note_hash, sender, @@ -376,17 +395,19 @@ pub fn select_notes_since_block_by_tag_and_sender( let mut res = Vec::new(); while let Some(row) = rows.next()? { let block_num = row.get(0)?; - let note_index = row.get(1)?; - let note_id_data = row.get_ref(2)?.as_blob()?; + let batch_index = row.get(1)?; + let note_index = row.get(2)?; + let note_id_data = row.get_ref(3)?.as_blob()?; let note_id = deserialize(note_id_data)?; - let sender = column_value_as_u64(row, 3)?; - let tag = column_value_as_u64(row, 4)?; - let merkle_path_data = row.get_ref(5)?.as_blob()?; + let sender = column_value_as_u64(row, 4)?; + let tag = column_value_as_u64(row, 5)?; + let merkle_path_data = row.get_ref(6)?.as_blob()?; let merkle_path = deserialize(merkle_path_data)?; let note = Note { block_num, note_created: NoteCreated { + batch_index, note_index, note_id, sender, diff --git a/store/src/db/tests.rs b/store/src/db/tests.rs index 57af54176..ae7edcffd 100644 --- a/store/src/db/tests.rs +++ b/store/src/db/tests.rs @@ -1,10 +1,9 @@ use miden_objects::{ - crypto::{ - hash::rpo::RpoDigest, - merkle::{LeafIndex, MerklePath, SimpleSmt}, - }, - notes::{Nullifier, NOTE_LEAF_DEPTH}, - BlockHeader, Felt, FieldElement, + accounts::AccountId, + block::BlockNoteTree, + crypto::{hash::rpo::RpoDigest, merkle::MerklePath}, + notes::{NoteMetadata, NoteType, Nullifier}, + BlockHeader, Digest, Felt, FieldElement, ZERO, }; use rusqlite::{vtab::array, Connection}; @@ -129,6 +128,7 @@ fn test_sql_select_notes() { let note = Note { block_num, note_created: NoteCreated { + batch_index: 0, note_index: i, note_id: num_to_rpo_digest(i as u64), sender: i as u64, @@ -428,20 +428,32 @@ fn test_notes() { assert!(res.is_empty()); // test insertion + let batch_index = 0u32; let note_index = 2u32; - let tag = 5; - let note_hash = num_to_rpo_digest(3); - let values = [(note_index as u64, *note_hash)]; - let notes_db = SimpleSmt::::with_leaves(values.iter().cloned()).unwrap(); - let idx = LeafIndex::::new(note_index as u64).unwrap(); - let merkle_path = MerklePath::new(notes_db.open(&idx).path.nodes().to_vec()); + let note_id = num_to_rpo_digest(3); + let tag = 5u64; + // Precomputed seed for regular off-chain account for zeroed initial seed: + let seed = [ + Felt::new(9826372627067279707), + Felt::new(8305692282416592320), + Felt::new(2014458279716538454), + Felt::new(11038932562555857644), + ]; + let sender = AccountId::new(seed, Digest::default(), Digest::default()).unwrap(); + let note_metadata = + NoteMetadata::new(sender, NoteType::OffChain, (tag as u32).into(), ZERO).unwrap(); + + let values = [(batch_index as usize, note_index as usize, (note_id, note_metadata))]; + let notes_db = BlockNoteTree::with_entries(values.iter().cloned()).unwrap(); + let merkle_path = notes_db.merkle_path(batch_index as usize, note_index as usize).unwrap(); let note = Note { block_num: block_num_1, note_created: NoteCreated { + batch_index, note_index, - note_id: num_to_rpo_digest(3), - sender: 4, + note_id, + sender: sender.into(), tag, }, merkle_path: merkle_path.clone(), @@ -482,6 +494,7 @@ fn test_notes() { let note2 = Note { block_num: block_num_2, note_created: NoteCreated { + batch_index: note.note_created.batch_index, note_index: note.note_created.note_index, note_id: num_to_rpo_digest(3), sender: note.note_created.sender, diff --git a/store/src/errors.rs b/store/src/errors.rs index 9cc54c3dd..3263333e5 100644 --- a/store/src/errors.rs +++ b/store/src/errors.rs @@ -131,7 +131,7 @@ pub enum ApplyBlockError { #[error("Block applying was broken because of closed channel on database side: {0}")] BlockApplyingBrokenBecauseOfClosedChannel(RecvError), #[error("Failed to create notes tree: {0}")] - FailedToCreateNotesTree(MerkleError), + FailedToCreateNoteTree(MerkleError), #[error("Database doesn't have any block header data")] DbBlockHeaderEmpty, #[error("Failed to get MMR peaks for forest ({forest}): {error}")] diff --git a/store/src/server/api.rs b/store/src/server/api.rs index dc682bfb4..abfbb84d4 100644 --- a/store/src/server/api.rs +++ b/store/src/server/api.rs @@ -207,6 +207,7 @@ impl api_server::Api for StoreApi { .into_iter() .map(|note| { Ok(NoteCreated { + batch_index: note.batch_index, note_index: note.note_index, note_id: note .note_id diff --git a/store/src/state.rs b/store/src/state.rs index 06246d958..4f9065815 100644 --- a/store/src/state.rs +++ b/store/src/state.rs @@ -7,12 +7,13 @@ use std::{mem, sync::Arc}; use miden_node_proto::{AccountInputRecord, NullifierWitness}; use miden_node_utils::formatting::{format_account_id, format_array}; use miden_objects::{ + block::BlockNoteTree, crypto::{ hash::rpo::RpoDigest, merkle::{LeafIndex, Mmr, MmrDelta, MmrPeaks, SimpleSmt, SmtProof, ValuePath}, }, - notes::{NoteMetadata, NoteType, Nullifier, NOTE_LEAF_DEPTH}, - AccountError, BlockHeader, NoteError, Word, ACCOUNT_TREE_DEPTH, ZERO, + notes::{NoteMetadata, NoteType, Nullifier}, + AccountError, BlockHeader, NoteError, ACCOUNT_TREE_DEPTH, ZERO, }; use tokio::{ sync::{oneshot, Mutex, RwLock}, @@ -188,7 +189,7 @@ impl State { } // build notes tree - let note_tree = build_notes_tree(¬es)?; + let note_tree = build_note_tree(¬es)?; if note_tree.root() != block_header.note_root() { return Err(ApplyBlockError::NewBlockInvalidNoteRoot); } @@ -197,22 +198,17 @@ impl State { let notes = notes .into_iter() - .map(|note| { - // Safety: This should never happen, the note_tree is created directly form - // this list of notes - let leaf_index = LeafIndex::::new(note.note_index as u64) + .map(|note_created| { + let merkle_path = note_tree + .merkle_path( + note_created.batch_index as usize, + note_created.note_index as usize, + ) .map_err(ApplyBlockError::UnableToCreateProofForNote)?; - let merkle_path = note_tree.open(&leaf_index).path; - Ok(Note { block_num: block_header.block_num(), - note_created: NoteCreated { - note_id: note.note_id, - sender: note.sender, - note_index: note.note_index, - tag: note.tag, - }, + note_created, merkle_path, }) }) @@ -472,16 +468,15 @@ impl State { // UTILITIES // ================================================================================================ -/// Creates a [SimpleSmt] tree from the `notes`. +/// Creates a [BlockNoteTree] from the `notes`. #[instrument(target = "miden-store", skip_all)] -pub fn build_notes_tree( - notes: &[NoteCreated] -) -> Result, ApplyBlockError> { +pub fn build_note_tree(notes: &[NoteCreated]) -> Result { // TODO: create SimpleSmt without this allocation - let mut entries: Vec<(u64, Word)> = Vec::with_capacity(notes.len() * 2); + let mut entries: Vec<(usize, usize, (RpoDigest, NoteMetadata))> = + Vec::with_capacity(notes.len() * 2); for note in notes.iter() { - let note_type = NoteType::OffChain; // TODO: provide correct note type + let note_type = NoteType::OffChain; // TODO: Provide correct note type let note_metadata = NoteMetadata::new( note.sender.try_into()?, note_type, @@ -490,12 +485,14 @@ pub fn build_notes_tree( .map_err(|_| NoteError::InconsistentNoteTag(note_type, note.tag))?, ZERO, )?; - let index = note.note_index as u64; - entries.push((index, note.note_id.into())); - entries.push((index + 1, note_metadata.into())); + entries.push(( + note.batch_index as usize, + note.note_index as usize, + (note.note_id, note_metadata), + )); } - SimpleSmt::with_leaves(entries).map_err(ApplyBlockError::FailedToCreateNotesTree) + BlockNoteTree::with_entries(entries).map_err(ApplyBlockError::FailedToCreateNoteTree) } #[instrument(target = "miden-store", skip_all)]