From ffb275dbf18926ea7e076bf9a82d4a5795ed2dfa Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Fri, 29 Mar 2024 08:29:14 +0500 Subject: [PATCH] tests: add test for storage --- Cargo.lock | 165 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + store/Cargo.toml | 1 + store/src/db/tests.rs | 139 ++++++++++++++++++++++++++++++++++- store/src/state.rs | 3 +- 5 files changed, 302 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f3c7bb94..0393c81e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -335,6 +344,12 @@ version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -431,6 +446,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "colorchoice" version = "1.0.0" @@ -458,6 +479,12 @@ dependencies = [ "libc", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crypto-common" version = "0.1.6" @@ -546,6 +573,35 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -699,6 +755,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -724,6 +789,20 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -785,6 +864,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.28" @@ -1102,6 +1187,7 @@ dependencies = [ "cc", "glob", "libc", + "serde", "winter-crypto", "winter-math", "winter-utils", @@ -1110,13 +1196,30 @@ dependencies = [ [[package]] name = "miden-lib" version = "0.2.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#86a81277b236a29b9bb85d329137f1fcc84b6063" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#cc2bec3511ad9a22416a8be0fc7977eb42c4014c" dependencies = [ "miden-assembly", "miden-objects", "miden-stdlib", ] +[[package]] +name = "miden-mock" +version = "0.2.0" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#cc2bec3511ad9a22416a8be0fc7977eb42c4014c" +dependencies = [ + "env_logger", + "hex", + "miden-lib", + "miden-objects", + "miden-processor", + "miden-prover", + "postcard", + "rand", + "rand_pcg", + "winter-rand-utils", +] + [[package]] name = "miden-node" version = "0.2.0" @@ -1217,6 +1320,7 @@ dependencies = [ "figment", "hex", "miden-lib", + "miden-mock", "miden-node-proto", "miden-node-utils", "miden-objects", @@ -1258,13 +1362,15 @@ dependencies = [ [[package]] name = "miden-objects" version = "0.2.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#86a81277b236a29b9bb85d329137f1fcc84b6063" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#cc2bec3511ad9a22416a8be0fc7977eb42c4014c" dependencies = [ + "log", "miden-assembly", "miden-core", "miden-crypto", "miden-processor", "miden-verifier", + "serde", "winter-rand-utils", ] @@ -1304,7 +1410,7 @@ dependencies = [ [[package]] name = "miden-tx" version = "0.2.0" -source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#86a81277b236a29b9bb85d329137f1fcc84b6063" +source = "git+https://github.com/0xPolygonMiden/miden-base.git?branch=next#cc2bec3511ad9a22416a8be0fc7977eb42c4014c" dependencies = [ "miden-lib", "miden-objects", @@ -1588,6 +1694,18 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "heapless", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1794,6 +1912,16 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core", + "serde", +] + [[package]] name = "rand_xorshift" version = "0.3.0" @@ -1903,6 +2031,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.31" @@ -1946,6 +2083,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + [[package]] name = "serde" version = "1.0.197" @@ -2042,6 +2185,21 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.0" @@ -2798,6 +2956,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0dff7a27296595fbdc653751b3718acd9518288df646e860ecb48915ff0d6c3" dependencies = [ + "serde", "winter-utils", ] diff --git a/Cargo.toml b/Cargo.toml index 9018bfd66..1da084dcf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ exclude = [".github/"] [workspace.dependencies] miden-air = { version = "0.8", default-features = false } miden-lib = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "next" } +miden-mock = { 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.8" } miden-stdlib = { version = "0.8", default-features = false } diff --git a/store/Cargo.toml b/store/Cargo.toml index db5f8b0a3..20b6fb9b2 100644 --- a/store/Cargo.toml +++ b/store/Cargo.toml @@ -42,4 +42,5 @@ tracing-subscriber = { workspace = true } [dev-dependencies] figment = { version = "0.10", features = ["toml", "env", "test"] } +miden-mock = { workspace = true } miden-node-utils = { path = "../utils", version = "0.2", features = ["tracing-forest"] } diff --git a/store/src/db/tests.rs b/store/src/db/tests.rs index 08a3b33c9..42740ea6d 100644 --- a/store/src/db/tests.rs +++ b/store/src/db/tests.rs @@ -1,15 +1,26 @@ +use miden_lib::transaction::TransactionKernel; +use miden_mock::mock::account::{ + generate_account_seed, mock_account_code, AccountSeedType, + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, +}; use miden_objects::{ + accounts::{ + Account, AccountDelta, AccountId, AccountStorage, AccountStorageDelta, AccountVaultDelta, + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, + }, + assets::{Asset, AssetVault, FungibleAsset, NonFungibleAsset, NonFungibleAssetDetails}, crypto::{ hash::rpo::RpoDigest, merkle::{LeafIndex, MerklePath, SimpleSmt}, }, notes::{Nullifier, NOTE_LEAF_DEPTH}, - BlockHeader, Felt, FieldElement, + transaction::AccountDetails, + BlockHeader, Felt, FieldElement, Word, ONE, ZERO, }; use rusqlite::{vtab::array, Connection}; use super::{sql, AccountInfo, Note, NoteCreated, NullifierInfo}; -use crate::db::migrations; +use crate::{db::migrations, errors::DatabaseError}; fn create_db() -> Connection { let mut conn = Connection::open_in_memory().unwrap(); @@ -179,6 +190,124 @@ fn test_sql_select_accounts() { } } +#[test] +fn test_sql_public_account_details() { + let mut conn = create_db(); + + let block_num = 1; + create_block(&mut conn, block_num); + + let (account_id, _seed) = + generate_account_seed(AccountSeedType::RegularAccountUpdatableCodeOnChain); + let fungible_faucet_id = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN).unwrap(); + let non_fungible_faucet_id = + AccountId::try_from(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN).unwrap(); + + let mut storage = AccountStorage::new(vec![]).unwrap(); + storage.set_item(1, num_to_word(1)).unwrap(); + storage.set_item(3, num_to_word(3)).unwrap(); + storage.set_item(5, num_to_word(5)).unwrap(); + + let nft1 = Asset::NonFungible( + NonFungibleAsset::new( + &NonFungibleAssetDetails::new(non_fungible_faucet_id, vec![1, 2, 3]).unwrap(), + ) + .unwrap(), + ); + + let mut account = Account::new( + account_id.try_into().unwrap(), + AssetVault::new(&[ + Asset::Fungible(FungibleAsset::new(fungible_faucet_id, 150).unwrap()), + nft1, + ]) + .unwrap(), + storage, + mock_account_code(&TransactionKernel::assembler()), + ZERO, + ); + + // test querying empty table + let res = sql::get_account_details(&mut conn, account_id.into()); + assert!(matches!(res, Err(DatabaseError::AccountNotOnChain(_)))); + + let transaction = conn.transaction().unwrap(); + let inserted = sql::upsert_accounts( + &transaction, + &[(account_id.into(), Some(AccountDetails::Full(account.clone())), account.hash())], + block_num, + ) + .unwrap(); + + assert_eq!(inserted, 1, "One element must have been inserted"); + + transaction.commit().unwrap(); + + let account_read = sql::get_account_details(&mut conn, account_id.into()).unwrap(); + + // TODO: substitute by a single check, once code imports deserialization is fixed: + // assert_eq!(account_read, account); + assert_eq!(account_read.id(), account.id()); + assert_eq!(account_read.vault(), account.vault()); + assert_eq!(account_read.storage(), account.storage()); + assert_eq!(account_read.nonce(), account.nonce()); + + let storage_delta = AccountStorageDelta { + cleared_items: vec![3], + updated_items: vec![(4, num_to_word(5)), (5, num_to_word(6))], + }; + + let nft2 = Asset::NonFungible( + NonFungibleAsset::new( + &NonFungibleAssetDetails::new(non_fungible_faucet_id, vec![4, 5, 6]).unwrap(), + ) + .unwrap(), + ); + + let vault_delta = AccountVaultDelta { + added_assets: vec![nft2], + removed_assets: vec![nft1], + }; + + let delta = AccountDelta::new(storage_delta, vault_delta, Some(ONE)).unwrap(); + + account.apply_delta(&delta).unwrap(); + + let transaction = conn.transaction().unwrap(); + let inserted = sql::upsert_accounts( + &transaction, + &[(account_id.into(), Some(AccountDetails::Delta(delta.clone())), account.hash())], + block_num, + ) + .unwrap(); + + assert_eq!(inserted, 1, "One element must have been inserted"); + + transaction.commit().unwrap(); + + let mut account_read = sql::get_account_details(&mut conn, account_id.into()).unwrap(); + + assert_eq!(account_read.id(), account.id()); + assert_eq!(account_read.vault(), account.vault()); + assert_eq!(account_read.nonce(), account.nonce()); + + // Cleared item was not serialized, check it and apply delta only with clear item second time: + assert_eq!(account_read.storage().get_item(3), RpoDigest::default()); + + let storage_delta = AccountStorageDelta { + cleared_items: vec![3], + updated_items: vec![], + }; + account_read + .apply_delta( + &AccountDelta::new(storage_delta, AccountVaultDelta::default(), Some(Felt::new(2))) + .unwrap(), + ) + .unwrap(); + + assert_eq!(account_read.storage(), account.storage()); +} + #[test] fn test_sql_select_nullifiers_by_block_range() { let mut conn = create_db(); @@ -519,7 +648,11 @@ fn test_notes() { // UTILITIES // ------------------------------------------------------------------------------------------- fn num_to_rpo_digest(n: u64) -> RpoDigest { - RpoDigest::new([Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::new(n)]) + RpoDigest::new(num_to_word(n)) +} + +fn num_to_word(n: u64) -> Word { + [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::new(n)] } fn num_to_nullifier(n: u64) -> Nullifier { diff --git a/store/src/state.rs b/store/src/state.rs index 048b6ac16..e53d54386 100644 --- a/store/src/state.rs +++ b/store/src/state.rs @@ -12,7 +12,7 @@ use miden_objects::{ hash::rpo::RpoDigest, merkle::{LeafIndex, Mmr, MmrDelta, MmrPeaks, SimpleSmt, SmtProof, ValuePath}, }, - notes::{NoteMetadata, Nullifier, NOTE_LEAF_DEPTH}, + notes::{NoteMetadata, NoteType, Nullifier, NOTE_LEAF_DEPTH}, transaction::AccountDetails, AccountError, BlockHeader, Word, ACCOUNT_TREE_DEPTH, }; @@ -493,6 +493,7 @@ pub fn build_notes_tree( for note in notes.iter() { let note_metadata = NoteMetadata::new( note.sender.try_into()?, + NoteType::OffChain, // TODO: provide correct note type note.tag .try_into() .expect("tag value is greater than or equal to the field modulus"),