Merge pull request #24 from vacp2p/Pravdyvy/sequencer-core

Sequencer core
This commit is contained in:
Pravdyvy 2024-11-26 14:24:07 +02:00 committed by GitHub
commit e7323466f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 236 additions and 4 deletions

2
Cargo.lock generated
View File

@ -3669,10 +3669,12 @@ dependencies = [
name = "sequencer_core"
version = "0.1.0"
dependencies = [
"accounts",
"anyhow",
"env_logger",
"log",
"mempool",
"rand 0.8.5",
"serde",
"serde_json",
"storage",

View File

@ -15,9 +15,12 @@ use crate::key_management::{
AddressKeyHolder,
};
pub type PublicKey = AffinePoint;
pub type AccountAddress = TreeHashType;
pub struct Account {
pub key_holder: AddressKeyHolder,
pub address: TreeHashType,
pub address: AccountAddress,
pub balance: u64,
pub utxo_tree: UTXOSparseMerkleTree,
}

View File

@ -6,6 +6,8 @@ use k256::AffinePoint;
use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder};
use storage::merkle_tree_public::TreeHashType;
use crate::account_core::PublicKey;
pub mod constants_types;
pub mod ephemeral_key_holder;
pub mod secret_holders;
@ -18,8 +20,8 @@ pub struct AddressKeyHolder {
top_secret_key_holder: TopSecretKeyHolder,
utxo_secret_key_holder: UTXOSecretKeyHolder,
pub address: TreeHashType,
pub nullifer_public_key: AffinePoint,
pub viewing_public_key: AffinePoint,
pub nullifer_public_key: PublicKey,
pub viewing_public_key: PublicKey,
}
impl AddressKeyHolder {

View File

@ -9,9 +9,13 @@ serde_json.workspace = true
env_logger.workspace = true
log.workspace = true
serde.workspace = true
rand.workspace = true
[dependencies.storage]
path = "../storage"
[dependencies.mempool]
path = "../mempool"
[dependencies.accounts]
path = "../accounts"

View File

@ -0,0 +1,15 @@
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SequencerConfig {
///Home dir of sequencer storage
pub home: PathBuf,
///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,
}

View File

@ -1 +1,53 @@
use anyhow::Result;
use config::SequencerConfig;
use mempool::MemPool;
use sequecer_store::SequecerChainStore;
use storage::block::{Block, HashableBlockData};
use transaction_mempool::TransactionMempool;
pub mod config;
pub mod sequecer_store;
pub mod transaction_mempool;
pub struct SequencerCore {
pub store: SequecerChainStore,
pub mempool: MemPool<TransactionMempool>,
pub sequencer_config: SequencerConfig,
pub chain_height: u64,
}
impl SequencerCore {
pub fn start_from_config(config: SequencerConfig) -> Self {
Self {
store: SequecerChainStore::new_with_genesis(
&config.home,
config.genesis_id,
config.is_genesis_random,
),
mempool: MemPool::<TransactionMempool>::default(),
chain_height: config.genesis_id,
sequencer_config: config,
}
}
///Produces new block from transaction outputs in mempool
pub fn produce_new_block_simple(&mut self) -> Result<()> {
let transactions = self
.mempool
.pop_size(self.sequencer_config.max_num_tx_in_block);
let hashable_data = HashableBlockData {
block_id: self.chain_height + 1,
transactions: transactions.into_iter().map(|tx_mem| tx_mem.tx).collect(),
data: vec![],
};
let block = Block::produce_block_from_hashable_data(hashable_data);
self.store.block_store.put_block_at_id(block)?;
self.chain_height += 1;
Ok(())
}
}

View File

@ -0,0 +1,38 @@
use std::collections::HashMap;
use accounts::account_core::{AccountAddress, PublicKey};
#[derive(Debug, Clone)]
pub struct AccountPublicData {
pub nullifier_public_key: PublicKey,
pub viewing_public_key: PublicKey,
pub address: AccountAddress,
}
#[derive(Debug, Clone)]
pub struct SequencerAccountsStore {
pub accounts: HashMap<AccountAddress, AccountPublicData>,
}
impl SequencerAccountsStore {
pub fn new() -> Self {
Self {
accounts: HashMap::new(),
}
}
pub fn register_account(&mut self, account_pub_data: AccountPublicData) {
self.accounts
.insert(account_pub_data.address, account_pub_data);
}
pub fn unregister_account(&mut self, account_addr: AccountAddress) {
self.accounts.remove(&account_addr);
}
}
impl Default for SequencerAccountsStore {
fn default() -> Self {
Self::new()
}
}

View File

@ -0,0 +1,33 @@
use std::path::Path;
use anyhow::Result;
use storage::{block::Block, RocksDBIO};
pub struct SequecerBlockStore {
dbio: RocksDBIO,
}
impl SequecerBlockStore {
///Starting database at the start of new chain.
/// Creates files if necessary.
///
/// ATTENTION: Will overwrite genesis block.
pub fn open_db_with_genesis(location: &Path, genesis_block: Option<Block>) -> Result<Self> {
Ok(Self {
dbio: RocksDBIO::new(location, genesis_block)?,
})
}
///Reopening existing database
pub fn open_db_restart(location: &Path) -> Result<Self> {
SequecerBlockStore::open_db_with_genesis(location, None)
}
pub fn get_block_at_id(&self, id: u64) -> Result<Block> {
Ok(self.dbio.get_block(id)?)
}
pub fn put_block_at_id(&self, block: Block) -> Result<()> {
Ok(self.dbio.put_block(block)?)
}
}

View File

@ -0,0 +1,60 @@
use std::path::Path;
use accounts_store::SequencerAccountsStore;
use block_store::SequecerBlockStore;
use rand::{rngs::OsRng, RngCore};
use storage::{
block::{Block, HashableBlockData},
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
nullifier_sparse_merkle_tree::NullifierSparseMerkleTree,
};
pub mod accounts_store;
pub mod block_store;
pub struct SequecerChainStore {
pub acc_store: SequencerAccountsStore,
pub block_store: SequecerBlockStore,
pub nullifier_store: NullifierSparseMerkleTree,
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
pub pub_tx_store: PublicTransactionMerkleTree,
}
impl SequecerChainStore {
pub fn new_with_genesis(home_dir: &Path, genesis_id: u64, is_genesis_random: bool) -> Self {
let acc_store = SequencerAccountsStore::default();
let nullifier_store = NullifierSparseMerkleTree::default();
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
let pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
let mut data = [0; 32];
if is_genesis_random {
OsRng.fill_bytes(&mut data);
}
let hashable_data = HashableBlockData {
block_id: genesis_id,
transactions: vec![],
data: data.to_vec(),
};
let genesis_block = Block::produce_block_from_hashable_data(hashable_data);
//Sequencer should panic if unable to open db,
//as fixing this issue may require actions non-native to program scope
let block_store = SequecerBlockStore::open_db_with_genesis(
&home_dir.join("rocksdb"),
Some(genesis_block),
)
.unwrap();
Self {
acc_store,
block_store,
nullifier_store,
utxo_commitments_store,
pub_tx_store,
}
}
}

View File

@ -1,6 +1,7 @@
use rs_merkle::Hasher;
use serde::{Deserialize, Serialize};
use crate::transaction::Transaction;
use crate::{merkle_tree_public::hasher::OwnHasher, transaction::Transaction};
pub type BlockHash = [u8; 32];
pub type Data = Vec<u8>;
@ -14,3 +15,25 @@ pub struct Block {
pub transactions: Vec<Transaction>,
pub data: Data,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HashableBlockData {
pub block_id: BlockId,
pub transactions: Vec<Transaction>,
pub data: Data,
}
impl Block {
pub fn produce_block_from_hashable_data(hashable_data: HashableBlockData) -> Self {
let data = serde_json::to_vec(&hashable_data).unwrap();
let hash = OwnHasher::hash(&data);
Self {
block_id: hashable_data.block_id,
hash,
transactions: hashable_data.transactions,
data: hashable_data.data,
}
}
}