diff --git a/Cargo.lock b/Cargo.lock index 07f1410..e78bd99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,7 +147,6 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ - "actix-macros", "futures-core", "tokio", ] @@ -627,17 +626,6 @@ dependencies = [ "critical-section", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "auto_ops" version = "0.3.0" @@ -972,45 +960,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_derive", - "clap_lex", - "indexmap 1.9.3", - "once_cell", - "strsim 0.10.0", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "cobs" version = "0.3.0" @@ -1029,6 +978,7 @@ dependencies = [ "hex", "k256", "log", + "nssa", "reqwest 0.11.27", "risc0-zkvm 2.3.1 (git+https://github.com/risc0/risc0.git?branch=release-2.3)", "rs_merkle", @@ -1262,7 +1212,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", + "strsim", "syn 2.0.104", ] @@ -1952,13 +1902,19 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.10.0", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "hash32" version = "0.2.1" @@ -2030,15 +1986,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.5.2" @@ -2365,16 +2312,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.10.0" @@ -2394,32 +2331,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "integration_tests" -version = "0.1.0" -dependencies = [ - "accounts", - "actix", - "actix-web", - "anyhow", - "clap", - "common", - "env_logger", - "hex", - "log", - "node_core", - "node_rpc", - "node_runner", - "sequencer_core", - "sequencer_rpc", - "sequencer_runner", - "serde", - "serde_json", - "tempfile", - "tokio", - "toml 0.7.8", -] - [[package]] name = "inventory" version = "0.3.20" @@ -2462,7 +2373,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.2", + "hermit-abi", "libc", "windows-sys 0.59.0", ] @@ -2973,88 +2884,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5b0c77c1b780822bc749a33e39aeb2c07584ab93332303babeabb645298a76e" -[[package]] -name = "node_core" -version = "0.1.0" -dependencies = [ - "accounts", - "actix-rt", - "anyhow", - "bincode", - "common", - "elliptic-curve", - "env_logger", - "hex", - "k256", - "log", - "rand 0.8.5", - "reqwest 0.11.27", - "risc0-zkvm 2.3.1 (git+https://github.com/risc0/risc0.git?branch=release-2.3)", - "sc_core", - "secp256k1-zkp", - "serde", - "serde_json", - "sha2", - "storage", - "tempfile", - "thiserror 1.0.69", - "tokio", - "utxo", - "zkvm", -] - -[[package]] -name = "node_rpc" -version = "0.1.0" -dependencies = [ - "accounts", - "actix", - "actix-cors", - "actix-web", - "anyhow", - "common", - "consensus", - "env_logger", - "futures", - "hex", - "log", - "networking", - "node_core", - "serde", - "serde_json", - "storage", - "tokio", - "utxo", - "vm", - "zkvm", -] - -[[package]] -name = "node_runner" -version = "0.1.0" -dependencies = [ - "accounts", - "actix", - "actix-web", - "anyhow", - "clap", - "common", - "consensus", - "env_logger", - "hex", - "log", - "networking", - "node_core", - "node_rpc", - "serde", - "serde_json", - "storage", - "tokio", - "utxo", - "vm", - "zkvm", -] - [[package]] name = "nom" version = "7.1.3" @@ -3072,6 +2901,9 @@ dependencies = [ "nssa-core", "program-methods", "risc0-zkvm 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "serde_cbor", + "sha2", ] [[package]] @@ -3248,12 +3080,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "parking_lot" version = "0.12.4" @@ -3412,7 +3238,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ - "toml_edit 0.22.27", + "toml_edit", ] [[package]] @@ -4510,7 +4336,7 @@ dependencies = [ "strum", "tempfile", "thiserror 2.0.12", - "toml 0.8.23", + "toml", "yaml-rust2", ] @@ -4524,7 +4350,7 @@ dependencies = [ "strum", "tempfile", "thiserror 2.0.12", - "toml 0.8.23", + "toml", "yaml-rust2", ] @@ -4672,6 +4498,7 @@ dependencies = [ "k256", "log", "mempool", + "nssa", "rand 0.8.5", "secp256k1-zkp", "serde", @@ -4698,6 +4525,7 @@ dependencies = [ "log", "mempool", "networking", + "nssa", "sequencer_core", "serde", "serde_json", @@ -4706,28 +4534,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "sequencer_runner" -version = "0.1.0" -dependencies = [ - "actix", - "actix-web", - "anyhow", - "clap", - "common", - "consensus", - "env_logger", - "log", - "mempool", - "networking", - "sequencer_core", - "sequencer_rpc", - "serde", - "serde_json", - "tokio", - "toml 0.7.8", -] - [[package]] name = "serde" version = "1.0.219" @@ -4737,6 +4543,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.219" @@ -4953,12 +4769,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -5097,12 +4907,6 @@ dependencies = [ "risc0-build 2.3.1 (git+https://github.com/risc0/risc0.git?branch=release-2.3)", ] -[[package]] -name = "textwrap" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" - [[package]] name = "thiserror" version = "1.0.69" @@ -5260,18 +5064,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", -] - [[package]] name = "toml" version = "0.8.23" @@ -5281,7 +5073,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.27", + "toml_edit", ] [[package]] @@ -5293,31 +5085,18 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.10.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.10.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.12", + "winnow", ] [[package]] @@ -5974,15 +5753,6 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.7.12" @@ -6175,7 +5945,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.10.0", + "indexmap", "memchr", "thiserror 2.0.12", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index a5cdd3a..1385130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,23 +1,19 @@ [workspace] resolver = "2" members = [ - "node_runner", - "sequencer_runner", + # "sequencer_runner", "storage", "accounts", "utxo", "vm", "networking", "consensus", - "node_rpc", "sequencer_rpc", "mempool", "zkvm", - "node_core", "sequencer_core", "common", "sc_core", - "integration_tests", "nssa", ] diff --git a/common/Cargo.toml b/common/Cargo.toml index 7e4e0ab..642d820 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -21,3 +21,6 @@ hex.workspace = true [dependencies.secp256k1-zkp] workspace = true features = ["std", "rand-std", "rand", "serde", "global-context"] + +[dependencies.nssa] +path = "../nssa" diff --git a/common/src/block.rs b/common/src/block.rs index 7757667..bc62dca 100644 --- a/common/src/block.rs +++ b/common/src/block.rs @@ -2,6 +2,7 @@ use rs_merkle::Hasher; use serde::{Deserialize, Serialize}; use crate::{merkle_tree_public::hasher::OwnHasher, transaction::Transaction}; +use nssa; pub type BlockHash = [u8; 32]; pub type Data = Vec; @@ -13,7 +14,7 @@ pub struct Block { pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, pub hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } @@ -22,7 +23,7 @@ pub struct HashableBlockData { pub block_id: BlockId, pub prev_block_id: BlockId, pub prev_block_hash: BlockHash, - pub transactions: Vec, + pub transactions: Vec, pub data: Data, } diff --git a/common/src/rpc_primitives/requests.rs b/common/src/rpc_primitives/requests.rs index 29612c5..4a46162 100644 --- a/common/src/rpc_primitives/requests.rs +++ b/common/src/rpc_primitives/requests.rs @@ -18,7 +18,7 @@ pub struct RegisterAccountRequest { #[derive(Serialize, Deserialize, Debug)] pub struct SendTxRequest { - pub transaction: Transaction, + pub transaction: nssa::PublicTransaction, ///UTXO Commitment Root, Pub Tx Root pub tx_roots: [[u8; 32]; 2], } @@ -89,10 +89,10 @@ pub struct GetLastBlockResponse { #[derive(Serialize, Deserialize, Debug)] pub struct GetAccountBalanceResponse { - pub balance: u64, + pub balance: u128, } #[derive(Serialize, Deserialize, Debug)] pub struct GetTransactionByHashResponse { - pub transaction: Option, + pub transaction: Option, } diff --git a/nssa/Cargo.toml b/nssa/Cargo.toml index 243d3f1..30f0747 100644 --- a/nssa/Cargo.toml +++ b/nssa/Cargo.toml @@ -7,3 +7,6 @@ edition = "2024" risc0-zkvm = "2.2" nssa-core = {path="core"} program-methods = { path = "program_methods" } +serde = "1.0.219" +serde_cbor = "0.11.2" +sha2 = "0.10.9" diff --git a/nssa/core/src/account/mod.rs b/nssa/core/src/account/mod.rs index 1814cdd..5d4cdd9 100644 --- a/nssa/core/src/account/mod.rs +++ b/nssa/core/src/account/mod.rs @@ -11,7 +11,7 @@ pub type Nonce = u128; type Data = Vec; /// Account to be used both in public and private contexts -#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Account { pub program_owner: ProgramId, pub balance: u128, diff --git a/nssa/src/address.rs b/nssa/src/address.rs index 57533a6..4267397 100644 --- a/nssa/src/address.rs +++ b/nssa/src/address.rs @@ -1,12 +1,14 @@ +use serde::{Deserialize, Serialize}; + use crate::signature::PublicKey; -#[derive(Clone, Hash, PartialEq, Eq)] -pub(crate) struct Address { +#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +pub struct Address { pub(crate) value: [u8; 32], } impl Address { - pub(crate) fn new(value: [u8; 32]) -> Self { + pub fn new(value: [u8; 32]) -> Self { Self { value } } diff --git a/nssa/src/lib.rs b/nssa/src/lib.rs index 4c2479f..81f48c3 100644 --- a/nssa/src/lib.rs +++ b/nssa/src/lib.rs @@ -1,16 +1,22 @@ use nssa_core::{ account::{Account, AccountWithMetadata}, - program::{Program, ProgramId}, + program::ProgramId, }; use program_methods::{AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID}; use risc0_zkvm::{ExecutorEnv, ExecutorEnvBuilder, default_executor}; mod address; -mod public_transaction; +pub mod public_transaction; mod signature; -pub mod state; +mod state; -struct AuthenticatedTransferProgram; +pub use address::Address; +pub use nssa_core::program::Program; +pub use public_transaction::PublicTransaction; +pub use signature::PrivateKey; +pub use state::V01State; + +pub struct AuthenticatedTransferProgram; impl Program for AuthenticatedTransferProgram { const PROGRAM_ID: ProgramId = AUTHENTICATED_TRANSFER_ID; const PROGRAM_ELF: &[u8] = AUTHENTICATED_TRANSFER_ELF; diff --git a/nssa/src/public_transaction.rs b/nssa/src/public_transaction.rs index 1812bff..7c150db 100644 --- a/nssa/src/public_transaction.rs +++ b/nssa/src/public_transaction.rs @@ -2,13 +2,16 @@ use nssa_core::{ account::{Account, Nonce}, program::ProgramId, }; +use serde::{Deserialize, Serialize}; +use sha2::{digest::FixedOutput, Digest}; use crate::{ address::Address, signature::{PrivateKey, PublicKey, Signature}, }; -pub(crate) struct Message { +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Message { pub(crate) program_id: ProgramId, pub(crate) addresses: Vec
, pub(crate) nonces: Vec, @@ -17,7 +20,7 @@ pub(crate) struct Message { } impl Message { - pub(crate) fn new( + pub fn new( program_id: ProgramId, addresses: Vec
, nonces: Vec, @@ -37,12 +40,13 @@ impl Message { } } -pub(crate) struct WitnessSet { +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct WitnessSet { pub(crate) signatures_and_public_keys: Vec<(Signature, PublicKey)>, } impl WitnessSet { - pub(crate) fn for_message(message: &Message, private_keys: &[PrivateKey]) -> Self { + pub fn for_message(message: &Message, private_keys: &[PrivateKey]) -> Self { let message_bytes = message.to_bytes(); let signatures_and_public_keys = private_keys .iter() @@ -54,17 +58,18 @@ impl WitnessSet { } } -pub(crate) struct PublicTransaction { +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct PublicTransaction { message: Message, witness_set: WitnessSet, } impl PublicTransaction { - pub(crate) fn message(&self) -> &Message { + pub fn message(&self) -> &Message { &self.message } - pub(crate) fn witness_set(&self) -> &WitnessSet { + pub fn witness_set(&self) -> &WitnessSet { &self.witness_set } @@ -76,10 +81,17 @@ impl PublicTransaction { .collect() } - pub(crate) fn new(message: Message, witness_set: WitnessSet) -> Self { + pub fn new(message: Message, witness_set: WitnessSet) -> Self { Self { message, witness_set, } } + + pub fn hash(&self) -> [u8; 32] { + let bytes = serde_cbor::to_vec(&self).unwrap(); + let mut hasher = sha2::Sha256::new(); + hasher.update(&bytes); + hasher.finalize_fixed().try_into().unwrap() + } } diff --git a/nssa/src/signature.rs b/nssa/src/signature.rs index ea90b56..2f018f1 100644 --- a/nssa/src/signature.rs +++ b/nssa/src/signature.rs @@ -1,10 +1,21 @@ +use serde::{Deserialize, Serialize}; + use crate::{address::Address, public_transaction::Message}; +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub(crate) struct Signature; // TODO: Dummy impl. Replace by actual private key. -pub(crate) struct PrivateKey(pub(crate) u8); +pub struct PrivateKey(pub(crate) u8); + +impl PrivateKey { + pub fn new(dummy_value: u8) -> Self { + Self(dummy_value) + } +} + // TODO: Dummy impl. Replace by actual public key. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub(crate) struct PublicKey(pub(crate) u8); impl PublicKey { diff --git a/nssa/src/state.rs b/nssa/src/state.rs index a636859..2a09c10 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -8,12 +8,28 @@ use nssa_core::{ }; use std::collections::{HashMap, HashSet}; -struct V01State { +pub struct V01State { public_state: HashMap, } impl V01State { - fn transition_from_public_transaction(&mut self, tx: PublicTransaction) -> Result<(), ()> { + pub fn new_with_genesis_accounts(initial_data: &[([u8; 32], u128)]) -> Self { + // TODO:: remove this assert? + let public_state = initial_data + .to_owned() + .into_iter() + .map(|(address_value, balance)| { + let mut account = Account::default(); + account.balance = balance; + account.program_owner = AuthenticatedTransferProgram::PROGRAM_ID; + let address = Address::new(address_value); + (address, account) + }) + .collect(); + Self { public_state } + } + + pub fn transition_from_public_transaction(&mut self, tx: &PublicTransaction) -> Result<(), ()> { let state_diff = self .execute_and_verify_public_transaction(&tx) .map_err(|_| ())?; @@ -36,7 +52,7 @@ impl V01State { .or_insert_with(Account::default) } - fn get_account_by_address(&self, address: &Address) -> Account { + pub fn get_account_by_address(&self, address: &Address) -> Account { self.public_state .get(address) .cloned() @@ -123,26 +139,6 @@ mod tests { use super::*; use crate::{public_transaction, signature::PrivateKey}; - fn genesis_state_for_tests(balances: &[u128], addresses: &[Address]) -> V01State { - assert_eq!(balances.len(), addresses.len()); - let accounts: Vec = balances - .iter() - .map(|balance| { - let mut account = Account::default(); - account.balance = *balance; - account.program_owner = AuthenticatedTransferProgram::PROGRAM_ID; - account - }) - .collect(); - - let public_state = addresses - .to_owned() - .into_iter() - .zip(accounts.into_iter()) - .collect(); - V01State { public_state } - } - fn transfer_transaction_for_tests( from: Address, from_key: PrivateKey, @@ -160,23 +156,22 @@ mod tests { #[test] fn test_1() { - let addresses = [Address::new([1; 32])]; - let balances = [100]; - let mut genesis_state = genesis_state_for_tests(&balances, &addresses); - let from = addresses[0].clone(); + let initial_data = [([1; 32], 100)]; + let mut genesis_state = V01State::new_with_genesis_accounts(&initial_data); + let from = Address::new(initial_data[0].0.clone()); let from_key = PrivateKey(1); let to = Address::new([2; 32]); let balance_to_move = 5; let tx = transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move); - let _ = genesis_state.transition_from_public_transaction(tx); + let _ = genesis_state.transition_from_public_transaction(&tx); assert_eq!( genesis_state.get_account_by_address(&to).balance, balance_to_move ); assert_eq!( genesis_state.get_account_by_address(&from).balance, - balances[0] - balance_to_move + initial_data[0].1 - balance_to_move ); assert_eq!(genesis_state.get_account_by_address(&from).nonce, 1); assert_eq!(genesis_state.get_account_by_address(&to).nonce, 0); @@ -184,20 +179,20 @@ mod tests { #[test] fn test_2() { - let addresses = [Address::new([1; 32]), Address::new([99; 32])]; - let balances = [100, 200]; - let mut genesis_state = genesis_state_for_tests(&balances, &addresses); - let from = addresses[1].clone(); + let initial_data = [([1; 32], 100), ([99; 32], 200)]; + let mut genesis_state = V01State::new_with_genesis_accounts(&initial_data); + let from = Address::new(initial_data[1].0.clone()); let from_key = PrivateKey(99); - let to = addresses[0].clone(); + let to = Address::new(initial_data[0].0.clone()); let balance_to_move = 8; let to_previous_balance = genesis_state.get_account_by_address(&to).balance; - let tx = transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move); - let _ = genesis_state.transition_from_public_transaction(tx); + let tx = + transfer_transaction_for_tests(from.clone(), from_key, 0, to.clone(), balance_to_move); + let _ = genesis_state.transition_from_public_transaction(&tx); assert_eq!(genesis_state.get_account_by_address(&to).balance, 108); assert_eq!( genesis_state.get_account_by_address(&from).balance, - balances[1] - balance_to_move + initial_data[1].1 - balance_to_move ); assert_eq!(genesis_state.get_account_by_address(&from).nonce, 1); assert_eq!(genesis_state.get_account_by_address(&to).nonce, 0); diff --git a/sequencer_core/Cargo.toml b/sequencer_core/Cargo.toml index f148655..2083f42 100644 --- a/sequencer_core/Cargo.toml +++ b/sequencer_core/Cargo.toml @@ -28,6 +28,9 @@ path = "../accounts" [dependencies.common] path = "../common" +[dependencies.nssa] +path = "../nssa" + [dependencies.secp256k1-zkp] workspace = true features = ["std", "rand-std", "rand", "serde", "global-context"] diff --git a/sequencer_core/src/config.rs b/sequencer_core/src/config.rs index 2dda687..4a99f0b 100644 --- a/sequencer_core/src/config.rs +++ b/sequencer_core/src/config.rs @@ -6,7 +6,7 @@ use std::path::PathBuf; pub struct AccountInitialData { ///Hex encoded `AccountAddress` pub addr: String, - pub balance: u64, + pub balance: u128, } #[derive(Clone, Serialize, Deserialize)] diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 80ac760..1275bb2 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -34,7 +34,7 @@ pub enum TransactionMalformationErrorKind { TxHashAlreadyPresentInTree { tx: TreeHashType }, NullifierAlreadyPresentInTree { tx: TreeHashType }, UTXOCommitmentAlreadyPresentInTree { tx: TreeHashType }, - MempoolFullForRound { tx: TreeHashType }, + MempoolFullForRound, ChainStateFurtherThanTransactionState { tx: TreeHashType }, FailedToInsert { tx: TreeHashType, details: String }, InvalidSignature, @@ -67,146 +67,36 @@ impl SequencerCore { } } - pub fn get_tree_roots(&self) -> [[u8; 32]; 2] { - [ - self.store - .utxo_commitments_store - .get_root() - .unwrap_or([0; 32]), - self.store.pub_tx_store.get_root().unwrap_or([0; 32]), - ] - } + // pub fn get_tree_roots(&self) -> [[u8; 32]; 2] { + // [ + // self.store + // .utxo_commitments_store + // .get_root() + // .unwrap_or([0; 32]), + // self.store.pub_tx_store.get_root().unwrap_or([0; 32]), + // ] + // } pub fn transaction_pre_check( &mut self, - tx: Transaction, - tx_roots: [[u8; 32]; 2], - ) -> Result { - let tx = tx - .into_authenticated() - .map_err(|_| TransactionMalformationErrorKind::InvalidSignature)?; - - let TransactionBody { - tx_kind, - ref execution_input, - ref execution_output, - ref utxo_commitments_created_hashes, - ref nullifier_created_hashes, - .. - } = tx.transaction().body(); - - let tx_hash = *tx.hash(); - - let mempool_size = self.mempool.len(); - - if mempool_size >= self.sequencer_config.max_num_tx_in_block { - return Err(TransactionMalformationErrorKind::MempoolFullForRound { tx: tx_hash }); - } - - let curr_sequencer_roots = self.get_tree_roots(); - - if tx_roots != curr_sequencer_roots { - return Err( - TransactionMalformationErrorKind::ChainStateFurtherThanTransactionState { - tx: tx_hash, - }, - ); - } - - //Sanity check - match tx_kind { - TxKind::Public => { - if !utxo_commitments_created_hashes.is_empty() - || !nullifier_created_hashes.is_empty() - { - //Public transactions can not make private operations. - return Err( - TransactionMalformationErrorKind::PublicTransactionChangedPrivateData { - tx: tx_hash, - }, - ); - } - } - TxKind::Private => { - if !execution_input.is_empty() || !execution_output.is_empty() { - //Not entirely necessary, but useful simplification for a future. - //This way only shielded and deshielded transactions can be used for interaction - //between public and private state. - return Err( - TransactionMalformationErrorKind::PrivateTransactionChangedPublicData { - tx: tx_hash, - }, - ); - } - } - _ => {} - }; - - //Native transfers checks - if let Ok(native_transfer_action) = - serde_json::from_slice::(execution_input) - { - let signer_address = address::from_public_key(&tx.transaction().public_key); - - //Correct sender check - if native_transfer_action.from != signer_address { - return Err(TransactionMalformationErrorKind::IncorrectSender); - } - } - - //Tree checks - let tx_tree_check = self.store.pub_tx_store.get_tx(tx_hash).is_some(); - let nullifier_tree_check = nullifier_created_hashes.iter().any(|nullifier_hash| { - self.store.nullifier_store.contains(&UTXONullifier { - utxo_hash: *nullifier_hash, - }) - }); - let utxo_commitments_check = - utxo_commitments_created_hashes - .iter() - .any(|utxo_commitment_hash| { - self.store - .utxo_commitments_store - .get_tx(*utxo_commitment_hash) - .is_some() - }); - - if tx_tree_check { - return Err( - TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: *tx.hash() }, - ); - } - - if nullifier_tree_check { - return Err( - TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: *tx.hash() }, - ); - } - - if utxo_commitments_check { - return Err( - TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { - tx: *tx.hash(), - }, - ); - } - + tx: nssa::PublicTransaction, + // tx_roots: [[u8; 32]; 2], + ) -> Result { + // TODO: Stateless checks here Ok(tx) } pub fn push_tx_into_mempool_pre_check( &mut self, - transaction: Transaction, - tx_roots: [[u8; 32]; 2], + transaction: nssa::PublicTransaction, + // _tx_roots: [[u8; 32]; 2], ) -> Result<(), TransactionMalformationErrorKind> { let mempool_size = self.mempool.len(); if mempool_size >= self.sequencer_config.max_num_tx_in_block { - return Err(TransactionMalformationErrorKind::MempoolFullForRound { - tx: transaction.body().hash(), - }); + return Err(TransactionMalformationErrorKind::MempoolFullForRound); } - let authenticated_tx = self.transaction_pre_check(transaction, tx_roots)?; + let authenticated_tx = self.transaction_pre_check(transaction)?; self.mempool.push_item(authenticated_tx.into()); @@ -215,77 +105,15 @@ impl SequencerCore { fn execute_check_transaction_on_state( &mut self, - mempool_tx: &MempoolTransaction, - ) -> Result<(), TransactionMalformationErrorKind> { - let TransactionBody { - ref utxo_commitments_created_hashes, - ref nullifier_created_hashes, - execution_input, - .. - } = mempool_tx.auth_tx.transaction().body(); + mempool_tx: MempoolTransaction, + ) -> Result { + let tx = mempool_tx.auth_tx; - let tx_hash = *mempool_tx.auth_tx.hash(); + self.store.state.transition_from_public_transaction(&tx)?; - //Balance move - if let Ok(native_transfer_action) = - serde_json::from_slice::(execution_input) - { - // Nonce check - let signer_addres = - address::from_public_key(&mempool_tx.auth_tx.transaction().public_key); - if self.store.acc_store.get_account_nonce(&signer_addres) - != native_transfer_action.nonce - { - return Err(TransactionMalformationErrorKind::NonceMismatch { tx: tx_hash }); - } + // self.store.pub_tx_store.add_tx(mempool_tx.auth_tx); - let from_balance = self - .store - .acc_store - .get_account_balance(&native_transfer_action.from); - let to_balance = self - .store - .acc_store - .get_account_balance(&native_transfer_action.to); - - //Balance check - if from_balance < native_transfer_action.balance_to_move { - return Err(TransactionMalformationErrorKind::BalanceMismatch { tx: tx_hash }); - } - - self.store.acc_store.set_account_balance( - &native_transfer_action.from, - from_balance - native_transfer_action.balance_to_move, - ); - self.store.acc_store.set_account_balance( - &native_transfer_action.to, - to_balance + native_transfer_action.balance_to_move, - ); - - self.store.acc_store.increase_nonce(&signer_addres); - } - - for utxo_comm in utxo_commitments_created_hashes { - self.store - .utxo_commitments_store - .add_tx(&UTXOCommitment { hash: *utxo_comm }); - } - - for nullifier in nullifier_created_hashes.iter() { - self.store.nullifier_store.insert(UTXONullifier { - utxo_hash: *nullifier, - }); - } - - self.store - .pub_tx_store - .add_tx(mempool_tx.auth_tx.transaction()); - - Ok(()) - } - - pub fn register_account(&mut self, account_addr: AccountAddress) { - self.store.acc_store.register_account(account_addr); + Ok(tx) } ///Produces new block from transactions in mempool @@ -298,13 +126,7 @@ impl SequencerCore { let valid_transactions = transactions .into_iter() - .filter_map(|mempool_tx| { - if self.execute_check_transaction_on_state(&mempool_tx).is_ok() { - Some(mempool_tx.auth_tx.into_transaction()) - } else { - None - } - }) + .filter_map(|mempool_tx| self.execute_check_transaction_on_state(mempool_tx).ok()) .collect(); let prev_block_hash = self @@ -340,6 +162,7 @@ mod tests { use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind}; use k256::{ecdsa::SigningKey, FieldBytes}; use mempool_transaction::MempoolTransaction; + use nssa::Program; use secp256k1_zkp::Tweak; fn setup_sequencer_config_variable_initial_accounts( @@ -362,13 +185,15 @@ mod tests { fn setup_sequencer_config() -> SequencerConfig { let acc1_addr = vec![ - 13, 150, 223, 204, 65, 64, 25, 56, 12, 157, 222, 12, 211, 220, 229, 170, 201, 15, 181, - 68, 59, 248, 113, 16, 135, 65, 174, 175, 222, 85, 42, 215, + // 13, 150, 223, 204, 65, 64, 25, 56, 12, 157, 222, 12, 211, 220, 229, 170, 201, 15, 181, + // 68, 59, 248, 113, 16, 135, 65, 174, 175, 222, 85, 42, 215, + 1; 32 ]; let acc2_addr = vec![ - 151, 72, 112, 233, 190, 141, 10, 192, 138, 168, 59, 63, 199, 167, 166, 134, 41, 29, - 135, 50, 80, 138, 186, 152, 179, 96, 128, 243, 156, 44, 243, 100, + // 151, 72, 112, 233, 190, 141, 10, 192, 138, 168, 59, 63, 199, 167, 166, 134, 41, 29, + // 135, 50, 80, 138, 186, 152, 179, 96, 128, 243, 156, 44, 243, 100, + 2; 32 ]; let initial_acc1 = AccountInitialData { @@ -386,92 +211,61 @@ mod tests { setup_sequencer_config_variable_initial_accounts(initial_accounts) } - fn create_dummy_transaction( - nullifier_created_hashes: Vec<[u8; 32]>, - utxo_commitments_spent_hashes: Vec<[u8; 32]>, - utxo_commitments_created_hashes: Vec<[u8; 32]>, - ) -> Transaction { - let mut rng = rand::thread_rng(); - - let body = TransactionBody { - tx_kind: TxKind::Private, - execution_input: vec![], - execution_output: vec![], - utxo_commitments_spent_hashes, - utxo_commitments_created_hashes, - nullifier_created_hashes, - execution_proof_private: "dummy_proof".to_string(), - encoded_data: vec![], - ephemeral_pub_key: vec![10, 11, 12], - commitment: vec![], - tweak: Tweak::new(&mut rng), - secret_r: [0; 32], - sc_addr: "sc_addr".to_string(), - state_changes: (serde_json::Value::Null, 0), - }; - Transaction::new(body, SignaturePrivateKey::random(&mut rng)) + fn create_dummy_transaction() -> nssa::PublicTransaction { + let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; + let addresses = vec![]; + let nonces = vec![]; + let instruction_data = 0; + let message = + nssa::public_transaction::Message::new(program_id, addresses, nonces, instruction_data); + let private_key = nssa::PrivateKey::new(1); + let witness_set = + nssa::public_transaction::WitnessSet::for_message(&message, &[private_key]); + nssa::PublicTransaction::new(message, witness_set) } fn create_dummy_transaction_native_token_transfer( from: [u8; 32], - nonce: u64, + nonce: u128, to: [u8; 32], - balance_to_move: u64, - signing_key: SigningKey, - ) -> Transaction { - let mut rng = rand::thread_rng(); - - let native_token_transfer = PublicNativeTokenSend { - from, - nonce, - to, - balance_to_move, - }; - - let body = TransactionBody { - tx_kind: TxKind::Public, - execution_input: serde_json::to_vec(&native_token_transfer).unwrap(), - execution_output: vec![], - utxo_commitments_spent_hashes: vec![], - utxo_commitments_created_hashes: vec![], - nullifier_created_hashes: vec![], - execution_proof_private: "".to_string(), - encoded_data: vec![], - ephemeral_pub_key: vec![10, 11, 12], - commitment: vec![], - tweak: Tweak::new(&mut rng), - secret_r: [0; 32], - sc_addr: "sc_addr".to_string(), - state_changes: (serde_json::Value::Null, 0), - }; - Transaction::new(body, signing_key) + balance_to_move: u128, + signing_key: nssa::PrivateKey, + ) -> nssa::PublicTransaction { + let addresses = vec![nssa::Address::new(from), nssa::Address::new(to)]; + let nonces = vec![nonce]; + let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; + let message = + nssa::public_transaction::Message::new(program_id, addresses, nonces, balance_to_move); + let witness_set = + nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]); + nssa::PublicTransaction::new(message, witness_set) } - fn create_signing_key_for_account1() -> SigningKey { - let pub_sign_key_acc1 = [ - 133, 143, 177, 187, 252, 66, 237, 236, 234, 252, 244, 138, 5, 151, 3, 99, 217, 231, - 112, 217, 77, 211, 58, 218, 176, 68, 99, 53, 152, 228, 198, 190, - ]; - - let field_bytes = FieldBytes::from_slice(&pub_sign_key_acc1); - SigningKey::from_bytes(field_bytes).unwrap() + fn create_signing_key_for_account1() -> nssa::PrivateKey { + // let pub_sign_key_acc1 = [ + // 133, 143, 177, 187, 252, 66, 237, 236, 234, 252, 244, 138, 5, 151, 3, 99, 217, 231, + // 112, 217, 77, 211, 58, 218, 176, 68, 99, 53, 152, 228, 198, 190, + // ]; + // + // let field_bytes = FieldBytes::from_slice(&pub_sign_key_acc1); + // SigningKey::from_bytes(field_bytes).unwrap() + nssa::PrivateKey::new(1) } - fn create_signing_key_for_account2() -> SigningKey { - let pub_sign_key_acc2 = [ - 54, 90, 62, 225, 71, 225, 228, 148, 143, 53, 210, 23, 137, 158, 171, 156, 48, 7, 139, - 52, 117, 242, 214, 7, 99, 29, 122, 184, 59, 116, 144, 107, - ]; - - let field_bytes = FieldBytes::from_slice(&pub_sign_key_acc2); - SigningKey::from_bytes(field_bytes).unwrap() + fn create_signing_key_for_account2() -> nssa::PrivateKey { + // let pub_sign_key_acc2 = [ + // 54, 90, 62, 225, 71, 225, 228, 148, 143, 53, 210, 23, 137, 158, 171, 156, 48, 7, 139, + // 52, 117, 242, 214, 7, 99, 29, 122, 184, 59, 116, 144, 107, + // ]; + // + // let field_bytes = FieldBytes::from_slice(&pub_sign_key_acc2); + // SigningKey::from_bytes(field_bytes).unwrap() + nssa::PrivateKey::new(2) } fn common_setup(sequencer: &mut SequencerCore) { - let tx = create_dummy_transaction(vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]); - let mempool_tx = MempoolTransaction { - auth_tx: tx.into_authenticated().unwrap(), - }; + let tx = create_dummy_transaction(); + let mempool_tx = MempoolTransaction { auth_tx: tx }; sequencer.mempool.push_item(mempool_tx); sequencer @@ -497,16 +291,16 @@ mod tests { .try_into() .unwrap(); - assert!(sequencer.store.acc_store.contains_account(&acc1_addr)); - assert!(sequencer.store.acc_store.contains_account(&acc2_addr)); + let balance_acc_1 = sequencer.store.state.get_account_by_address(&nssa::Address::new(acc1_addr)).balance; + let balance_acc_2 = sequencer.store.state.get_account_by_address(&nssa::Address::new(acc2_addr)).balance; assert_eq!( 10000, - sequencer.store.acc_store.get_account_balance(&acc1_addr) + balance_acc_1 ); assert_eq!( 20000, - sequencer.store.acc_store.get_account_balance(&acc2_addr) + balance_acc_2 ); } @@ -548,32 +342,16 @@ mod tests { .try_into() .unwrap(); - assert!(sequencer.store.acc_store.contains_account(&acc1_addr)); - assert!(sequencer.store.acc_store.contains_account(&acc2_addr)); - - assert_eq!(sequencer.store.acc_store.len(), intial_accounts_len); - assert_eq!( 10000, - sequencer.store.acc_store.get_account_balance(&acc1_addr) + sequencer.store.state.get_account_by_address(&nssa::Address::new(acc1_addr)).balance ); assert_eq!( 20000, - sequencer.store.acc_store.get_account_balance(&acc2_addr) + sequencer.store.state.get_account_by_address(&nssa::Address::new(acc2_addr)).balance ); } - #[test] - fn test_get_tree_roots() { - let config = setup_sequencer_config(); - let mut sequencer = SequencerCore::start_from_config(config); - - common_setup(&mut sequencer); - - let roots = sequencer.get_tree_roots(); - assert_eq!(roots.len(), 2); // Should return two roots - } - #[test] fn test_transaction_pre_check_pass() { let config = setup_sequencer_config(); @@ -581,9 +359,9 @@ mod tests { common_setup(&mut sequencer); - let tx = create_dummy_transaction(vec![[91; 32]], vec![[71; 32]], vec![[81; 32]]); - let tx_roots = sequencer.get_tree_roots(); - let result = sequencer.transaction_pre_check(tx, tx_roots); + let tx = create_dummy_transaction(); + // let tx_roots = sequencer.get_tree_roots(); + let result = sequencer.transaction_pre_check(tx); assert!(result.is_ok()); } @@ -607,8 +385,7 @@ mod tests { let sign_key1 = create_signing_key_for_account1(); let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 10, sign_key1); - let tx_roots = sequencer.get_tree_roots(); - let result = sequencer.transaction_pre_check(tx, tx_roots); + let result = sequencer.transaction_pre_check(tx); assert!(result.is_ok()); } @@ -632,13 +409,13 @@ mod tests { let sign_key2 = create_signing_key_for_account2(); let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 10, sign_key2); - let tx_roots = sequencer.get_tree_roots(); - let result = sequencer.transaction_pre_check(tx, tx_roots); + // let tx_roots = sequencer.get_tree_roots(); + let tx = sequencer.transaction_pre_check(tx).unwrap(); - assert_eq!( - result.err().unwrap(), - TransactionMalformationErrorKind::IncorrectSender - ); + let result = + sequencer.execute_check_transaction_on_state(MempoolTransaction { auth_tx: tx }); + + assert_eq!(result.err().unwrap(), ()); } #[test] @@ -660,16 +437,19 @@ mod tests { let sign_key1 = create_signing_key_for_account1(); let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 10000000, sign_key1); - let tx_roots = sequencer.get_tree_roots(); - let result = sequencer.transaction_pre_check(tx, tx_roots); + // let tx_roots = sequencer.get_tree_roots(); + let result = sequencer.transaction_pre_check(tx); //Passed pre-check assert!(result.is_ok()); - let result = sequencer.execute_check_transaction_on_state(&result.unwrap().into()); + let result = sequencer.execute_check_transaction_on_state(MempoolTransaction { + auth_tx: result.unwrap(), + }); let is_failed_at_balance_mismatch = matches!( result.err().unwrap(), - TransactionMalformationErrorKind::BalanceMismatch { tx: _ } + // TransactionMalformationErrorKind::BalanceMismatch { tx: _ } + () ); assert!(is_failed_at_balance_mismatch); @@ -696,11 +476,11 @@ mod tests { let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 100, sign_key1); sequencer - .execute_check_transaction_on_state(&tx.into_authenticated().unwrap().into()) + .execute_check_transaction_on_state(MempoolTransaction { auth_tx: tx }) .unwrap(); - let bal_from = sequencer.store.acc_store.get_account_balance(&acc1); - let bal_to = sequencer.store.acc_store.get_account_balance(&acc2); + let bal_from = sequencer.store.state.get_account_by_address(&nssa::Address::new(acc1)).balance; + let bal_to = sequencer.store.state.get_account_by_address(&nssa::Address::new(acc2)).balance; assert_eq!(bal_from, 9900); assert_eq!(bal_to, 20100); @@ -716,16 +496,16 @@ mod tests { common_setup(&mut sequencer); - let tx = create_dummy_transaction(vec![[92; 32]], vec![[72; 32]], vec![[82; 32]]); - let tx_roots = sequencer.get_tree_roots(); + let tx = create_dummy_transaction(); + // let tx_roots = sequencer.get_tree_roots(); // Fill the mempool let dummy_tx = MempoolTransaction { - auth_tx: tx.clone().into_authenticated().unwrap(), + auth_tx: tx.clone(), }; sequencer.mempool.push_item(dummy_tx); - let result = sequencer.push_tx_into_mempool_pre_check(tx, tx_roots); + let result = sequencer.push_tx_into_mempool_pre_check(tx); assert!(matches!( result, @@ -740,10 +520,10 @@ mod tests { common_setup(&mut sequencer); - let tx = create_dummy_transaction(vec![[93; 32]], vec![[73; 32]], vec![[83; 32]]); - let tx_roots = sequencer.get_tree_roots(); + let tx = create_dummy_transaction(); + // let tx_roots = sequencer.get_tree_roots(); - let result = sequencer.push_tx_into_mempool_pre_check(tx, tx_roots); + let result = sequencer.push_tx_into_mempool_pre_check(tx); assert!(result.is_ok()); assert_eq!(sequencer.mempool.len(), 1); } @@ -754,10 +534,8 @@ mod tests { let mut sequencer = SequencerCore::start_from_config(config); let genesis_height = sequencer.chain_height; - let tx = create_dummy_transaction(vec![[94; 32]], vec![[7; 32]], vec![[8; 32]]); - let tx_mempool = MempoolTransaction { - auth_tx: tx.into_authenticated().unwrap(), - }; + let tx = create_dummy_transaction(); + let tx_mempool = MempoolTransaction { auth_tx: tx }; sequencer.mempool.push_item(tx_mempool); let block_id = sequencer.produce_new_block_with_mempool_transactions(); @@ -786,10 +564,10 @@ mod tests { let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 100, sign_key1); let tx_mempool_original = MempoolTransaction { - auth_tx: tx.clone().into_authenticated().unwrap(), + auth_tx: tx.clone(), }; let tx_mempool_replay = MempoolTransaction { - auth_tx: tx.clone().into_authenticated().unwrap(), + auth_tx: tx.clone(), }; // Pushing two copies of the same tx to the mempool @@ -832,7 +610,7 @@ mod tests { // The transaction should be included the first time let tx_mempool_original = MempoolTransaction { - auth_tx: tx.clone().into_authenticated().unwrap(), + auth_tx: tx.clone(), }; sequencer.mempool.push_item(tx_mempool_original); let current_height = sequencer @@ -846,9 +624,7 @@ mod tests { assert_eq!(block.transactions, vec![tx.clone()]); // Add same transaction should fail - let tx_mempool_replay = MempoolTransaction { - auth_tx: tx.into_authenticated().unwrap(), - }; + let tx_mempool_replay = MempoolTransaction { auth_tx: tx }; sequencer.mempool.push_item(tx_mempool_replay); let current_height = sequencer .produce_new_block_with_mempool_transactions() diff --git a/sequencer_core/src/mempool_transaction.rs b/sequencer_core/src/mempool_transaction.rs index 551aaf3..1ba1a2b 100644 --- a/sequencer_core/src/mempool_transaction.rs +++ b/sequencer_core/src/mempool_transaction.rs @@ -2,11 +2,11 @@ use common::{merkle_tree_public::TreeHashType, transaction::AuthenticatedTransac use mempool::mempoolitem::MemPoolItem; pub struct MempoolTransaction { - pub auth_tx: AuthenticatedTransaction, + pub auth_tx: nssa::PublicTransaction, } -impl From for MempoolTransaction { - fn from(auth_tx: AuthenticatedTransaction) -> Self { +impl From for MempoolTransaction { + fn from(auth_tx: nssa::PublicTransaction) -> Self { Self { auth_tx } } } @@ -15,6 +15,6 @@ impl MemPoolItem for MempoolTransaction { type Identifier = TreeHashType; fn identifier(&self) -> Self::Identifier { - *self.auth_tx.hash() + self.auth_tx.hash() } } diff --git a/sequencer_core/src/sequencer_store/block_store.rs b/sequencer_core/src/sequencer_store/block_store.rs index dbefdc2..88afed5 100644 --- a/sequencer_core/src/sequencer_store/block_store.rs +++ b/sequencer_core/src/sequencer_store/block_store.rs @@ -51,12 +51,12 @@ impl SequecerBlockStore { } /// Returns the transaction corresponding to the given hash, if it exists in the blockchain. - pub fn get_transaction_by_hash(&self, hash: TreeHashType) -> Option { + pub fn get_transaction_by_hash(&self, hash: TreeHashType) -> Option { let block_id = self.tx_hash_to_block_map.get(&hash); let block = block_id.map(|&id| self.get_block_at_id(id)); if let Some(Ok(block)) = block { for transaction in block.transactions.into_iter() { - if transaction.body().hash() == hash { + if transaction.hash() == hash { return Some(transaction); } } @@ -69,7 +69,7 @@ fn block_to_transactions_map(block: &Block) -> HashMap { block .transactions .iter() - .map(|transaction| (transaction.body().hash(), block.block_id)) + .map(|transaction| (transaction.hash(), block.block_id)) .collect() } @@ -77,26 +77,18 @@ fn block_to_transactions_map(block: &Block) -> HashMap { mod tests { use super::*; use common::transaction::{SignaturePrivateKey, TransactionBody}; + use nssa::Program; use tempfile::tempdir; - fn create_dummy_block_with_transaction(block_id: u64) -> (Block, Transaction) { - let body = TransactionBody { - tx_kind: common::transaction::TxKind::Public, - execution_input: Default::default(), - execution_output: Default::default(), - utxo_commitments_spent_hashes: Default::default(), - utxo_commitments_created_hashes: Default::default(), - nullifier_created_hashes: Default::default(), - execution_proof_private: Default::default(), - encoded_data: Default::default(), - ephemeral_pub_key: Default::default(), - commitment: Default::default(), - tweak: Default::default(), - secret_r: Default::default(), - sc_addr: Default::default(), - state_changes: Default::default(), - }; - let tx = Transaction::new(body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap()); + fn create_dummy_block_with_transaction(block_id: u64) -> (Block, nssa::PublicTransaction) { + let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; + let addresses = vec![]; + let nonces = vec![]; + let instruction_data = 0; + let message = nssa::public_transaction::Message::new(program_id, addresses, nonces, instruction_data); + let private_key = nssa::PrivateKey::new(1); + let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[private_key]); + let tx = nssa::PublicTransaction::new(message, witness_set); ( Block { block_id, @@ -127,12 +119,12 @@ mod tests { SequecerBlockStore::open_db_with_genesis(path, Some(genesis_block)).unwrap(); let (block, tx) = create_dummy_block_with_transaction(1); // Try retrieve a tx that's not in the chain yet. - let retrieved_tx = node_store.get_transaction_by_hash(tx.body().hash()); + let retrieved_tx = node_store.get_transaction_by_hash(tx.hash()); assert_eq!(None, retrieved_tx); // Add the block with the transaction node_store.put_block_at_id(block).unwrap(); // Try again - let retrieved_tx = node_store.get_transaction_by_hash(tx.body().hash()); + let retrieved_tx = node_store.get_transaction_by_hash(tx.hash()); assert_eq!(Some(tx), retrieved_tx); } } diff --git a/sequencer_core/src/sequencer_store/mod.rs b/sequencer_core/src/sequencer_store/mod.rs index a85fd23..f329591 100644 --- a/sequencer_core/src/sequencer_store/mod.rs +++ b/sequencer_core/src/sequencer_store/mod.rs @@ -1,5 +1,6 @@ use std::{collections::HashSet, path::Path}; +use accounts::account_core::address::AccountAddress; use accounts_store::SequencerAccountsStore; use block_store::SequecerBlockStore; use common::{ @@ -8,6 +9,7 @@ use common::{ nullifier::UTXONullifier, }; use rand::{rngs::OsRng, RngCore}; +use nssa; use crate::config::AccountInitialData; @@ -15,11 +17,11 @@ pub mod accounts_store; pub mod block_store; pub struct SequecerChainStore { - pub acc_store: SequencerAccountsStore, + pub state: nssa::V01State, pub block_store: SequecerBlockStore, pub nullifier_store: HashSet, pub utxo_commitments_store: UTXOCommitmentsMerkleTree, - pub pub_tx_store: PublicTransactionMerkleTree, + // pub pub_tx_store: PublicTransactionMerkleTree, } impl SequecerChainStore { @@ -29,7 +31,7 @@ impl SequecerChainStore { is_genesis_random: bool, initial_accounts: &[AccountInitialData], ) -> Self { - let init_accs: Vec<_> = initial_accounts + let init_accs: Vec<(AccountAddress, u128)> = initial_accounts .iter() .map(|acc_data| { ( @@ -42,10 +44,10 @@ impl SequecerChainStore { }) .collect(); - let acc_store = SequencerAccountsStore::new(&init_accs); + let state = nssa::V01State::new_with_genesis_accounts(&init_accs); let nullifier_store = HashSet::new(); let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]); - let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); + // let pub_tx_store = PublicTransactionMerkleTree::new(vec![]); let mut data = [0; 32]; let mut prev_block_hash = [0; 32]; @@ -74,11 +76,11 @@ impl SequecerChainStore { .unwrap(); Self { - acc_store, + state, block_store, nullifier_store, utxo_commitments_store, - pub_tx_store, + // pub_tx_store, } } } diff --git a/sequencer_rpc/Cargo.toml b/sequencer_rpc/Cargo.toml index fb33c2d..1c1de4a 100644 --- a/sequencer_rpc/Cargo.toml +++ b/sequencer_rpc/Cargo.toml @@ -38,3 +38,6 @@ path = "../storage" [dependencies.common] path = "../common" + +[dependencies.nssa] +path = "../nssa" diff --git a/sequencer_rpc/src/process.rs b/sequencer_rpc/src/process.rs index 77c6e8b..7f4386a 100644 --- a/sequencer_rpc/src/process.rs +++ b/sequencer_rpc/src/process.rs @@ -1,4 +1,5 @@ use actix_web::Error as HttpError; +use nssa; use sequencer_core::config::AccountInitialData; use serde_json::Value; @@ -24,7 +25,6 @@ use common::rpc_primitives::requests::{ use super::{respond, types::err_rpc::RpcErr, JsonHandler}; pub const HELLO: &str = "hello"; -pub const REGISTER_ACCOUNT: &str = "register_account"; pub const SEND_TX: &str = "send_tx"; pub const GET_BLOCK: &str = "get_block"; pub const GET_GENESIS: &str = "get_genesis"; @@ -66,29 +66,13 @@ impl JsonHandler { respond(helperstruct) } - async fn process_register_account_request(&self, request: Request) -> Result { - let acc_req = RegisterAccountRequest::parse(Some(request.params))?; - - { - let mut acc_store = self.sequencer_state.lock().await; - - acc_store.register_account(acc_req.address); - } - - let helperstruct = RegisterAccountResponse { - status: SUCCESS.to_string(), - }; - - respond(helperstruct) - } - async fn process_send_tx(&self, request: Request) -> Result { let send_tx_req = SendTxRequest::parse(Some(request.params))?; { let mut state = self.sequencer_state.lock().await; - state.push_tx_into_mempool_pre_check(send_tx_req.transaction, send_tx_req.tx_roots)?; + state.push_tx_into_mempool_pre_check(send_tx_req.transaction)?; } let helperstruct = SendTxResponse { @@ -164,13 +148,16 @@ impl JsonHandler { let get_account_req = GetAccountBalanceRequest::parse(Some(request.params))?; let address_bytes = hex::decode(get_account_req.address) .map_err(|_| RpcError::invalid_params("invalid hex".to_string()))?; - let address = address_bytes - .try_into() - .map_err(|_| RpcError::invalid_params("invalid length".to_string()))?; + let address = nssa::Address::new( + address_bytes + .try_into() + .map_err(|_| RpcError::invalid_params("invalid length".to_string()))?, + ); let balance = { let state = self.sequencer_state.lock().await; - state.store.acc_store.get_account_balance(&address) + let account = state.store.state.get_account_by_address(&address); + account.balance }; let helperstruct = GetAccountBalanceResponse { balance }; @@ -199,7 +186,6 @@ impl JsonHandler { pub async fn process_request_internal(&self, request: Request) -> Result { match request.method.as_ref() { HELLO => self.process_temp_hello(request).await, - REGISTER_ACCOUNT => self.process_register_account_request(request).await, SEND_TX => self.process_send_tx(request).await, GET_BLOCK => self.process_get_block_data(request).await, GET_GENESIS => self.process_get_genesis(request).await, @@ -221,6 +207,7 @@ mod tests { rpc_primitives::RpcPollingConfig, transaction::{SignaturePrivateKey, Transaction, TransactionBody}, }; + use nssa::Program; use sequencer_core::{ config::{AccountInitialData, SequencerConfig}, SequencerCore, @@ -233,13 +220,15 @@ mod tests { let tempdir = tempdir().unwrap(); let home = tempdir.path().to_path_buf(); let acc1_addr = vec![ - 13, 150, 223, 204, 65, 64, 25, 56, 12, 157, 222, 12, 211, 220, 229, 170, 201, 15, 181, - 68, 59, 248, 113, 16, 135, 65, 174, 175, 222, 85, 42, 215, + // 13, 150, 223, 204, 65, 64, 25, 56, 12, 157, 222, 12, 211, 220, 229, 170, 201, 15, 181, + // 68, 59, 248, 113, 16, 135, 65, 174, 175, 222, 85, 42, 215, + 1; 32 ]; let acc2_addr = vec![ - 151, 72, 112, 233, 190, 141, 10, 192, 138, 168, 59, 63, 199, 167, 166, 134, 41, 29, - 135, 50, 80, 138, 186, 152, 179, 96, 128, 243, 156, 44, 243, 100, + // 151, 72, 112, 233, 190, 141, 10, 192, 138, 168, 59, 63, 199, 167, 166, 134, 41, 29, + // 135, 50, 80, 138, 186, 152, 179, 96, 128, 243, 156, 44, 243, 100, + 2; 32 ]; let initial_acc1 = AccountInitialData { @@ -268,32 +257,25 @@ mod tests { fn json_handler_for_tests() -> (JsonHandler, Vec) { let config = sequencer_config_for_tests(); - let mut sequencer_core = SequencerCore::start_from_config(config); - let initial_accounts = sequencer_core.sequencer_config.initial_accounts.clone(); - let tx_body = TransactionBody { - tx_kind: common::transaction::TxKind::Shielded, - execution_input: Default::default(), - execution_output: Default::default(), - utxo_commitments_spent_hashes: Default::default(), - utxo_commitments_created_hashes: Default::default(), - nullifier_created_hashes: Default::default(), - execution_proof_private: Default::default(), - encoded_data: Default::default(), - ephemeral_pub_key: Default::default(), - commitment: Default::default(), - tweak: Default::default(), - secret_r: Default::default(), - sc_addr: Default::default(), - state_changes: Default::default(), - }; - let tx = Transaction::new(tx_body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap()); + let from = nssa::Address::new([1; 32]); + let signing_key = nssa::PrivateKey::new(1); + let to = nssa::Address::new([2; 32]); + let balance_to_move = 10; + + let addresses = vec![from, to]; + let nonces = vec![0]; + let program_id = nssa::AuthenticatedTransferProgram::PROGRAM_ID; + let message = + nssa::public_transaction::Message::new(program_id, addresses, nonces, balance_to_move); + let witness_set = + nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]); + let tx = nssa::PublicTransaction::new(message, witness_set); + + sequencer_core.push_tx_into_mempool_pre_check(tx).unwrap(); - sequencer_core - .push_tx_into_mempool_pre_check(tx, [[0; 32]; 2]) - .unwrap(); sequencer_core .produce_new_block_with_mempool_transactions() .unwrap(); @@ -414,7 +396,7 @@ mod tests { "id": 1, "jsonrpc": "2.0", "result": { - "balance": 10000 + "balance": 10000 - 10 } }); @@ -499,7 +481,7 @@ mod tests { let request = serde_json::json!({ "jsonrpc": "2.0", "method": "get_transaction_by_hash", - "params": { "hash": "a5210ef33912a448cfe6eda43878c144df81f7bdf51d19b5ddf97be11806a6ed"}, + "params": { "hash": "e5f0c9b4b7732a2f4946b8e7a5f7c641b004559b1a13b1ccc600f29477725240"}, "id": 1 }); @@ -508,24 +490,20 @@ mod tests { "jsonrpc": "2.0", "result": { "transaction": { - "body": { - "commitment": [], - "encoded_data": [], - "ephemeral_pub_key": [], - "execution_input": [], - "execution_output": [], - "execution_proof_private": "", - "nullifier_created_hashes": [], - "sc_addr": "", - "secret_r": vec![0; 32], - "state_changes": [null, 0], - "tweak": "0".repeat(64), - "tx_kind": "Shielded", - "utxo_commitments_created_hashes": [], - "utxo_commitments_spent_hashes": [], + "message": { + "addresses": [ + { "value": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, + { "value": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] } + ], + "instruction_data": 10, + "nonces": [0], + "program_id": nssa::AuthenticatedTransferProgram::PROGRAM_ID, }, - "public_key": "3056301006072A8648CE3D020106052B8104000A034200041B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F70BEAF8F588B541507FED6A642C5AB42DFDF8120A7F639DE5122D47A69A8E8D1", - "signature": "A4E0D6A25BE829B006124F0DFD766427967AA3BEA96C29219E79BB2CC871891F384748C27E28718A4450AA78709FBF1A57DB33BCD575A2C819D2A439C2D878E6" + "witness_set": { + "signatures_and_public_keys": [ + [null, 1] + ] + } } } });