mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-05 14:53:06 +00:00
Merge pull request #27 from vacp2p/Pravdyvyi/sequencer-transaction-submit-process
First sequencer main version
This commit is contained in:
commit
5df163de74
149
Cargo.lock
generated
149
Cargo.lock
generated
@ -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,8 @@ dependencies = [
|
||||
"sequencer_core",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"storage",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3707,6 +3786,7 @@ dependencies = [
|
||||
"actix",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"clap",
|
||||
"consensus",
|
||||
"env_logger",
|
||||
"log",
|
||||
@ -3718,6 +3798,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3752,6 +3833,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 +4032,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 +4127,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 +4250,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 +4290,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 +4848,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 +5012,7 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
"displaydoc",
|
||||
"flate2",
|
||||
"indexmap",
|
||||
"indexmap 2.6.0",
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"zopfli",
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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<String>,
|
||||
///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,
|
||||
}
|
||||
|
||||
@ -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,16 +57,138 @@ 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<u64> {
|
||||
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 prev_block_hash = self
|
||||
.store
|
||||
.block_store
|
||||
.get_block_at_id(self.chain_height)?
|
||||
.prev_block_hash;
|
||||
|
||||
let hashable_data = HashableBlockData {
|
||||
block_id: self.chain_height + 1,
|
||||
prev_block_id: self.chain_height,
|
||||
transactions: transactions.into_iter().map(|tx_mem| tx_mem.tx).collect(),
|
||||
data: vec![],
|
||||
prev_block_hash,
|
||||
};
|
||||
|
||||
let block = Block::produce_block_from_hashable_data(hashable_data);
|
||||
@ -48,6 +197,6 @@ impl SequencerCore {
|
||||
|
||||
self.chain_height += 1;
|
||||
|
||||
Ok(())
|
||||
Ok(self.chain_height - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<u8>,
|
||||
viewing_public_key: Vec<u8>,
|
||||
) -> 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<AccountAddress, AccountPublicData>,
|
||||
|
||||
@ -28,15 +28,19 @@ impl SequecerChainStore {
|
||||
let pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
||||
|
||||
let mut data = [0; 32];
|
||||
let mut prev_block_hash = [0; 32];
|
||||
|
||||
if is_genesis_random {
|
||||
OsRng.fill_bytes(&mut data);
|
||||
OsRng.fill_bytes(&mut prev_block_hash);
|
||||
}
|
||||
|
||||
let hashable_data = HashableBlockData {
|
||||
block_id: genesis_id,
|
||||
prev_block_id: genesis_id.saturating_sub(1),
|
||||
transactions: vec![],
|
||||
data: data.to_vec(),
|
||||
prev_block_hash,
|
||||
};
|
||||
|
||||
let genesis_block = Block::produce_block_from_hashable_data(hashable_data);
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ actix-cors.workspace = true
|
||||
futures.workspace = true
|
||||
|
||||
actix-web.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
[dependencies.mempool]
|
||||
path = "../mempool"
|
||||
@ -27,5 +28,8 @@ path = "../networking"
|
||||
[dependencies.sequencer_core]
|
||||
path = "../sequencer_core"
|
||||
|
||||
[dependencies.storage]
|
||||
path = "../storage"
|
||||
|
||||
[dependencies.rpc_primitives]
|
||||
path = "../rpc_primitives"
|
||||
|
||||
@ -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<Mutex<SequencerCore>>,
|
||||
}
|
||||
|
||||
fn respond<T: Serialize>(val: T) -> Result<Value, RpcErr> {
|
||||
|
||||
@ -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<actix_web::dev::Server> {
|
||||
pub fn new_http_server(
|
||||
config: RpcConfig,
|
||||
seuquencer_core: Arc<Mutex<SequencerCore>>,
|
||||
) -> io::Result<actix_web::dev::Server> {
|
||||
let RpcConfig {
|
||||
addr,
|
||||
cors_allowed_origins,
|
||||
@ -46,7 +52,10 @@ pub fn new_http_server(config: RpcConfig) -> io::Result<actix_web::dev::Server>
|
||||
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 || {
|
||||
|
||||
@ -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::{
|
||||
GetBlockDataRequest, GetBlockDataResponse, HelloRequest, HelloResponse,
|
||||
RegisterAccountRequest, RegisterAccountResponse, SendTxRequest, SendTxResponse,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{respond, types::err_rpc::RpcErr, JsonHandler};
|
||||
@ -43,10 +47,65 @@ impl JsonHandler {
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_register_account_request(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
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<Value, RpcErr> {
|
||||
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)
|
||||
}
|
||||
|
||||
async fn process_get_block_data(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let get_block_req = GetBlockDataRequest::parse(Some(request.params))?;
|
||||
|
||||
let block = {
|
||||
let state = self.sequencer_state.lock().await;
|
||||
|
||||
state
|
||||
.store
|
||||
.block_store
|
||||
.get_block_at_id(get_block_req.block_id)?
|
||||
};
|
||||
|
||||
let helperstruct = GetBlockDataResponse { block };
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_request_internal(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
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,
|
||||
"get_block" => self.process_get_block_data(request).await,
|
||||
_ => Err(RpcErr(RpcError::method_not_found(request.method))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,15 +2,52 @@ 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;
|
||||
use storage::block::Block;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct HelloRequest {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct RegisterAccountRequest {
|
||||
pub nullifier_public_key: Vec<u8>,
|
||||
pub viewing_public_key: Vec<u8>,
|
||||
pub address: [u8; 32],
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SendTxRequest {
|
||||
pub transaction: TransactionMempool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct GetBlockDataRequest {
|
||||
pub block_id: u64,
|
||||
}
|
||||
|
||||
parse_request!(HelloRequest);
|
||||
parse_request!(RegisterAccountRequest);
|
||||
parse_request!(SendTxRequest);
|
||||
parse_request!(GetBlockDataRequest);
|
||||
|
||||
#[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,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct GetBlockDataResponse {
|
||||
pub block: Block,
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
8
sequencer_runner/configs/debug/sequencer_config.json
Normal file
8
sequencer_runner/configs/debug/sequencer_config.json
Normal file
@ -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
|
||||
}
|
||||
14
sequencer_runner/src/config.rs
Normal file
14
sequencer_runner/src/config.rs
Normal file
@ -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<SequencerConfig> {
|
||||
let file = File::open(config_home)?;
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
Ok(serde_json::from_reader(reader)?)
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,10 +7,11 @@ pub type BlockHash = [u8; 32];
|
||||
pub type Data = Vec<u8>;
|
||||
pub type BlockId = u64;
|
||||
|
||||
//ToDo: Add fields to block when model is clear
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Block {
|
||||
pub block_id: BlockId,
|
||||
pub prev_block_id: BlockId,
|
||||
pub prev_block_hash: BlockHash,
|
||||
pub hash: BlockHash,
|
||||
pub transactions: Vec<Transaction>,
|
||||
pub data: Data,
|
||||
@ -19,6 +20,8 @@ pub struct Block {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct HashableBlockData {
|
||||
pub block_id: BlockId,
|
||||
pub prev_block_id: BlockId,
|
||||
pub prev_block_hash: BlockHash,
|
||||
pub transactions: Vec<Transaction>,
|
||||
pub data: Data,
|
||||
}
|
||||
@ -31,9 +34,11 @@ impl Block {
|
||||
|
||||
Self {
|
||||
block_id: hashable_data.block_id,
|
||||
prev_block_id: hashable_data.prev_block_id,
|
||||
hash,
|
||||
transactions: hashable_data.transactions,
|
||||
data: hashable_data.data,
|
||||
prev_block_hash: hashable_data.prev_block_hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,27 @@ 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<u8>,
|
||||
///Tx output data (public_part)
|
||||
pub execution_output: Vec<u8>,
|
||||
///Tx output utxo commitments
|
||||
pub utxo_commitments_created_hashes: Vec<TreeHashType>,
|
||||
///Tx output nullifiers
|
||||
pub nullifier_created_hashes: Vec<TreeHashType>,
|
||||
///Execution proof (private part)
|
||||
pub execution_proof_private: String,
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user