diff --git a/Cargo.lock b/Cargo.lock index a69903f..5a80120 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,6 +569,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[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 = "autocfg" version = "1.4.0" @@ -925,6 +936,45 @@ 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", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck", + "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 = "consensus" version = "0.1.0" @@ -1719,7 +1769,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1766,6 +1816,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[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.3.9" @@ -2066,6 +2125,16 @@ dependencies = [ "icu_properties", ] +[[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.6.0" @@ -2739,6 +2808,12 @@ 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.3" @@ -2885,7 +2960,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit", + "toml_edit 0.22.22", ] [[package]] @@ -3671,7 +3746,9 @@ version = "0.1.0" dependencies = [ "accounts", "anyhow", + "elliptic-curve", "env_logger", + "k256", "log", "mempool", "rand 0.8.5", @@ -3698,6 +3775,7 @@ dependencies = [ "sequencer_core", "serde", "serde_json", + "tokio", ] [[package]] @@ -3707,6 +3785,7 @@ dependencies = [ "actix", "actix-web", "anyhow", + "clap", "consensus", "env_logger", "log", @@ -3718,6 +3797,7 @@ dependencies = [ "serde", "serde_json", "tokio", + "toml", ] [[package]] @@ -3752,6 +3832,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3942,6 +4031,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "1.0.0" @@ -4031,6 +4126,12 @@ dependencies = [ "risc0-build", ] +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + [[package]] name = "thiserror" version = "1.0.68" @@ -4148,11 +4249,39 @@ 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_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +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.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.5.40", +] [[package]] name = "toml_edit" @@ -4160,9 +4289,9 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap", + "indexmap 2.6.0", "toml_datetime", - "winnow", + "winnow 0.6.20", ] [[package]] @@ -4718,6 +4847,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[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.6.20" @@ -4873,7 +5011,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap", + "indexmap 2.6.0", "memchr", "thiserror", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index 3a176db..3bfae89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,13 +37,12 @@ sha2 = "0.10.8" monotree = "0.1.5" hex = "0.4.3" aes-gcm = "0.10.3" +toml = "0.7.4" rocksdb = { version = "0.21.0", default-features = false, features = [ "snappy", ] } -#ToDo: Add necessary risc0 submodules for zkvm module - [workspace.dependencies.rand] features = ["std", "std_rng", "getrandom"] version = "0.8.5" diff --git a/sequencer_core/Cargo.toml b/sequencer_core/Cargo.toml index 7f474b2..634337e 100644 --- a/sequencer_core/Cargo.toml +++ b/sequencer_core/Cargo.toml @@ -10,6 +10,8 @@ env_logger.workspace = true log.workspace = true serde.workspace = true rand.workspace = true +elliptic-curve.workspace = true +k256.workspace = true [dependencies.storage] path = "../storage" diff --git a/sequencer_core/src/config.rs b/sequencer_core/src/config.rs index 0c14948..0767146 100644 --- a/sequencer_core/src/config.rs +++ b/sequencer_core/src/config.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{path::PathBuf, time::Duration}; use serde::{Deserialize, Serialize}; @@ -6,10 +6,14 @@ use serde::{Deserialize, Serialize}; pub struct SequencerConfig { ///Home dir of sequencer storage pub home: PathBuf, + ///Override rust log (env var logging level) + pub override_rust_log: Option, ///Genesis id pub genesis_id: u64, ///If `True`, then adds random sequence of bytes to genesis block pub is_genesis_random: bool, ///Maximum number of transactions in block pub max_num_tx_in_block: usize, + ///Interval in which blocks produced + pub block_create_timeout_millis: Duration, } diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 3e45a55..fd54ecd 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -1,8 +1,17 @@ +use std::fmt::Display; + use anyhow::Result; use config::SequencerConfig; use mempool::MemPool; -use sequecer_store::SequecerChainStore; -use storage::block::{Block, HashableBlockData}; +use sequecer_store::{accounts_store::AccountPublicData, SequecerChainStore}; +use serde::{Deserialize, Serialize}; +use storage::{ + block::{Block, HashableBlockData}, + merkle_tree_public::TreeHashType, + nullifier::UTXONullifier, + transaction::{Transaction, TxKind}, + utxo_commitment::UTXOCommitment, +}; use transaction_mempool::TransactionMempool; pub mod config; @@ -16,6 +25,24 @@ pub struct SequencerCore { pub chain_height: u64, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum TransactionMalformationErrorKind { + PublicTransactionChangedPrivateData { tx: TreeHashType }, + PrivateTransactionChangedPublicData { tx: TreeHashType }, + TxHashAlreadyPresentInTree { tx: TreeHashType }, + NullifierAlreadyPresentInTree { tx: TreeHashType }, + UTXOCommitmentAlreadyPresentInTree { tx: TreeHashType }, + FailedToInsert { tx: TreeHashType, details: String }, +} + +impl Display for TransactionMalformationErrorKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{self:#?}") + } +} + +impl std::error::Error for TransactionMalformationErrorKind {} + impl SequencerCore { pub fn start_from_config(config: SequencerConfig) -> Self { Self { @@ -30,12 +57,125 @@ impl SequencerCore { } } - ///Produces new block from transaction outputs in mempool - pub fn produce_new_block_simple(&mut self) -> Result<()> { + fn execute_check_transaction_on_state( + &mut self, + tx: TransactionMempool, + ) -> Result<(), TransactionMalformationErrorKind> { + let Transaction { + hash, + tx_kind, + ref execution_input, + ref execution_output, + ref utxo_commitments_created_hashes, + ref nullifier_created_hashes, + } = tx.tx; + + //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: 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: hash, + }, + ); + } + } + _ => {} + }; + + //Tree checks + let tx_tree_check = self.store.pub_tx_store.get_tx(hash).is_some(); + let nullifier_tree_check = nullifier_created_hashes + .iter() + .map(|nullifier_hash| { + self.store + .nullifier_store + .search_item_inclusion(*nullifier_hash) + .unwrap_or(false) + }) + .any(|check| check); + let utxo_commitments_check = utxo_commitments_created_hashes + .iter() + .map(|utxo_commitment_hash| { + self.store + .utxo_commitments_store + .get_tx(*utxo_commitment_hash) + .is_some() + }) + .any(|check| check); + + if tx_tree_check { + return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: hash }); + } + + if nullifier_tree_check { + return Err( + TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: hash }, + ); + } + + if utxo_commitments_check { + return Err( + TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { tx: hash }, + ); + } + + 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 { + self.store + .nullifier_store + .insert_item(UTXONullifier { + utxo_hash: *nullifier, + }) + .map_err(|err| TransactionMalformationErrorKind::FailedToInsert { + tx: hash, + details: format!("{err:?}"), + })?; + } + + self.store.pub_tx_store.add_tx(tx.tx); + + Ok(()) + } + + pub fn register_account(&mut self, acc_data: AccountPublicData) { + self.store + .acc_store + .accounts + .insert(acc_data.address, acc_data); + } + + ///Produces new block from transactions in mempool + pub fn produce_new_block_with_mempool_transactions(&mut self) -> Result { let transactions = self .mempool .pop_size(self.sequencer_config.max_num_tx_in_block); + for tx in transactions.clone() { + self.execute_check_transaction_on_state(tx)?; + } + let hashable_data = HashableBlockData { block_id: self.chain_height + 1, transactions: transactions.into_iter().map(|tx_mem| tx_mem.tx).collect(), @@ -48,6 +188,6 @@ impl SequencerCore { self.chain_height += 1; - Ok(()) + Ok(self.chain_height - 1) } } diff --git a/sequencer_core/src/sequecer_store/accounts_store.rs b/sequencer_core/src/sequecer_store/accounts_store.rs index 9ae56ce..c7d4f21 100644 --- a/sequencer_core/src/sequecer_store/accounts_store.rs +++ b/sequencer_core/src/sequecer_store/accounts_store.rs @@ -1,6 +1,6 @@ -use std::collections::HashMap; - use accounts::account_core::{AccountAddress, PublicKey}; +use elliptic_curve::group::GroupEncoding; +use std::collections::HashMap; #[derive(Debug, Clone)] pub struct AccountPublicData { @@ -9,6 +9,22 @@ pub struct AccountPublicData { pub address: AccountAddress, } +impl AccountPublicData { + pub fn from_raw( + address: AccountAddress, + nullifier_public_key: Vec, + viewing_public_key: Vec, + ) -> Self { + Self { + nullifier_public_key: PublicKey::from_bytes(nullifier_public_key.as_slice().into()) + .unwrap(), + viewing_public_key: PublicKey::from_bytes(viewing_public_key.as_slice().into()) + .unwrap(), + address, + } + } +} + #[derive(Debug, Clone)] pub struct SequencerAccountsStore { pub accounts: HashMap, diff --git a/sequencer_core/src/transaction_mempool.rs b/sequencer_core/src/transaction_mempool.rs index 2002212..30a3993 100644 --- a/sequencer_core/src/transaction_mempool.rs +++ b/sequencer_core/src/transaction_mempool.rs @@ -2,7 +2,7 @@ use mempool::mempoolitem::MemPoolItem; use serde::{Deserialize, Serialize}; use storage::{merkle_tree_public::TreeHashType, transaction::Transaction}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TransactionMempool { pub tx: Transaction, } diff --git a/sequencer_rpc/Cargo.toml b/sequencer_rpc/Cargo.toml index 545bfe1..fedb230 100644 --- a/sequencer_rpc/Cargo.toml +++ b/sequencer_rpc/Cargo.toml @@ -14,6 +14,7 @@ actix-cors.workspace = true futures.workspace = true actix-web.workspace = true +tokio.workspace = true [dependencies.mempool] path = "../mempool" diff --git a/sequencer_rpc/src/lib.rs b/sequencer_rpc/src/lib.rs index 71a3b8f..066bdc5 100644 --- a/sequencer_rpc/src/lib.rs +++ b/sequencer_rpc/src/lib.rs @@ -2,20 +2,25 @@ pub mod net_utils; pub mod process; pub mod types; +use std::sync::Arc; + use rpc_primitives::{ errors::{RpcError, RpcErrorKind}, RpcPollingConfig, }; +use sequencer_core::SequencerCore; use serde::Serialize; use serde_json::Value; pub use net_utils::*; +use tokio::sync::Mutex; use self::types::err_rpc::RpcErr; //ToDo: Add necessary fields pub struct JsonHandler { pub polling_config: RpcPollingConfig, + pub sequencer_state: Arc>, } fn respond(val: T) -> Result { diff --git a/sequencer_rpc/src/net_utils.rs b/sequencer_rpc/src/net_utils.rs index 35c46ed..429bcde 100644 --- a/sequencer_rpc/src/net_utils.rs +++ b/sequencer_rpc/src/net_utils.rs @@ -1,4 +1,5 @@ use std::io; +use std::sync::Arc; use actix_cors::Cors; use actix_web::{http, middleware, web, App, Error as HttpError, HttpResponse, HttpServer}; @@ -8,6 +9,8 @@ use log::info; use rpc_primitives::message::Message; use rpc_primitives::RpcConfig; +use sequencer_core::SequencerCore; +use tokio::sync::Mutex; use super::JsonHandler; @@ -38,7 +41,10 @@ fn get_cors(cors_allowed_origins: &[String]) -> Cors { } #[allow(clippy::too_many_arguments)] -pub fn new_http_server(config: RpcConfig) -> io::Result { +pub fn new_http_server( + config: RpcConfig, + seuquencer_core: Arc>, +) -> io::Result { let RpcConfig { addr, cors_allowed_origins, @@ -46,7 +52,10 @@ pub fn new_http_server(config: RpcConfig) -> io::Result limits_config, } = config; info!(target:"network", "Starting http server at {}", addr); - let handler = web::Data::new(JsonHandler { polling_config }); + let handler = web::Data::new(JsonHandler { + polling_config, + sequencer_state: seuquencer_core.clone(), + }); // HTTP server Ok(HttpServer::new(move || { diff --git a/sequencer_rpc/src/process.rs b/sequencer_rpc/src/process.rs index dd6ebdf..c36557b 100644 --- a/sequencer_rpc/src/process.rs +++ b/sequencer_rpc/src/process.rs @@ -1,4 +1,5 @@ use actix_web::Error as HttpError; +use sequencer_core::sequecer_store::accounts_store::AccountPublicData; use serde_json::Value; use rpc_primitives::{ @@ -9,7 +10,10 @@ use rpc_primitives::{ use crate::{ rpc_error_responce_inverter, - types::rpc_structs::{HelloRequest, HelloResponse}, + types::rpc_structs::{ + HelloRequest, HelloResponse, RegisterAccountRequest, RegisterAccountResponse, + SendTxRequest, SendTxResponse, + }, }; use super::{respond, types::err_rpc::RpcErr, JsonHandler}; @@ -43,10 +47,47 @@ 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(AccountPublicData::from_raw( + acc_req.address, + acc_req.nullifier_public_key, + acc_req.viewing_public_key, + )); + } + + 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.mempool.push_item(send_tx_req.transaction); + } + + let helperstruct = SendTxResponse { + status: "Success".to_string(), + }; + + respond(helperstruct) + } + pub async fn process_request_internal(&self, request: Request) -> Result { match request.method.as_ref() { - //Todo : Add handling of more JSON RPC methods "hello" => self.process_temp_hello(request).await, + "register_account" => self.process_register_account_request(request).await, + "send_tx" => self.process_send_tx(request).await, _ => Err(RpcErr(RpcError::method_not_found(request.method))), } } diff --git a/sequencer_rpc/src/types/rpc_structs.rs b/sequencer_rpc/src/types/rpc_structs.rs index 4d7a2c4..cbd17c6 100644 --- a/sequencer_rpc/src/types/rpc_structs.rs +++ b/sequencer_rpc/src/types/rpc_structs.rs @@ -2,15 +2,40 @@ use rpc_primitives::errors::RpcParseError; use rpc_primitives::parse_request; use rpc_primitives::parser::parse_params; use rpc_primitives::parser::RpcRequest; +use sequencer_core::transaction_mempool::TransactionMempool; use serde::{Deserialize, Serialize}; use serde_json::Value; #[derive(Serialize, Deserialize, Debug)] pub struct HelloRequest {} +#[derive(Serialize, Deserialize, Debug)] +pub struct RegisterAccountRequest { + pub nullifier_public_key: Vec, + pub viewing_public_key: Vec, + pub address: [u8; 32], +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct SendTxRequest { + pub transaction: TransactionMempool, +} + parse_request!(HelloRequest); +parse_request!(RegisterAccountRequest); +parse_request!(SendTxRequest); #[derive(Serialize, Deserialize, Debug)] pub struct HelloResponse { pub greeting: String, } + +#[derive(Serialize, Deserialize, Debug)] +pub struct RegisterAccountResponse { + pub status: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct SendTxResponse { + pub status: String, +} diff --git a/sequencer_runner/Cargo.toml b/sequencer_runner/Cargo.toml index 6140725..a574359 100644 --- a/sequencer_runner/Cargo.toml +++ b/sequencer_runner/Cargo.toml @@ -13,6 +13,11 @@ actix.workspace = true actix-web.workspace = true tokio.workspace = true +toml.workspace = true + +[dependencies.clap] +features = ["derive", "env"] +workspace = true [dependencies.mempool] path = "../mempool" diff --git a/sequencer_runner/configs/debug/sequencer_config.json b/sequencer_runner/configs/debug/sequencer_config.json new file mode 100644 index 0000000..91c2ab6 --- /dev/null +++ b/sequencer_runner/configs/debug/sequencer_config.json @@ -0,0 +1,8 @@ +{ + "home": ".", + "override_rust_log": null, + "genesis_id": 1, + "is_genesis_random": true, + "max_num_tx_in_block": 20, + "block_create_timeout_millis": 10000 +} \ No newline at end of file diff --git a/sequencer_runner/src/config.rs b/sequencer_runner/src/config.rs new file mode 100644 index 0000000..175903d --- /dev/null +++ b/sequencer_runner/src/config.rs @@ -0,0 +1,14 @@ +use std::path::PathBuf; + +use anyhow::Result; +use sequencer_core::config::SequencerConfig; + +use std::fs::File; +use std::io::BufReader; + +pub fn from_file(config_home: PathBuf) -> Result { + let file = File::open(config_home)?; + let reader = BufReader::new(file); + + Ok(serde_json::from_reader(reader)?) +} diff --git a/sequencer_runner/src/lib.rs b/sequencer_runner/src/lib.rs index 1c9ed3c..e3a4507 100644 --- a/sequencer_runner/src/lib.rs +++ b/sequencer_runner/src/lib.rs @@ -1,18 +1,65 @@ +use std::{path::PathBuf, sync::Arc}; + use anyhow::Result; +use clap::Parser; use log::info; use rpc_primitives::RpcConfig; +use sequencer_core::SequencerCore; use sequencer_rpc::new_http_server; +use tokio::sync::Mutex; + +pub mod config; + +#[derive(Parser, Debug)] +#[clap(version)] +struct Args { + /// Path to configs + home_dir: PathBuf, +} pub async fn main_runner() -> Result<()> { + let args = Args::parse(); + let Args { home_dir } = args; + + let app_config = config::from_file(home_dir.join("sequencer_config.json"))?; + + let block_timeout = app_config.block_create_timeout_millis; + + if let Some(ref rust_log) = app_config.override_rust_log { + info!("RUST_LOG env var set to {rust_log:?}"); + + std::env::set_var("RUST_LOG", rust_log); + } + env_logger::init(); - let http_server = new_http_server(RpcConfig::default())?; + let sequencer_core = SequencerCore::start_from_config(app_config); + + info!("Sequncer core set up"); + + let seq_core_wrapped = Arc::new(Mutex::new(sequencer_core)); + + let http_server = new_http_server(RpcConfig::default(), seq_core_wrapped.clone())?; info!("HTTP server started"); let _http_server_handle = http_server.handle(); tokio::spawn(http_server); + info!("Starting main sequencer loop"); + #[allow(clippy::empty_loop)] loop { - //ToDo: Insert activity into main loop + tokio::time::sleep(block_timeout).await; + + info!("Collecting transactions from mempool, block creation"); + + let id = { + let mut state = seq_core_wrapped.lock().await; + + state.produce_new_block_with_mempool_transactions()? + }; + + info!("Block with id {id} created"); + + info!("Waiting for new transactions"); } } diff --git a/storage/src/transaction.rs b/storage/src/transaction.rs index d9ba928..2acb005 100644 --- a/storage/src/transaction.rs +++ b/storage/src/transaction.rs @@ -2,9 +2,25 @@ use serde::{Deserialize, Serialize}; use crate::merkle_tree_public::TreeHashType; -//ToDo: Update Tx model, when it is clear +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +pub enum TxKind { + Public, + Private, + Shielded, + Deshielded, +} + #[derive(Debug, Serialize, Deserialize, Clone)] ///General transaction object pub struct Transaction { pub hash: TreeHashType, + pub tx_kind: TxKind, + ///Tx input data (public part) + pub execution_input: Vec, + ///Tx output data (public_part) + pub execution_output: Vec, + ///Tx output utxo commitments + pub utxo_commitments_created_hashes: Vec, + ///Tx output nullifiers + pub nullifier_created_hashes: Vec, }