diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index 8e88065a..7dc52f56 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -5,7 +5,7 @@ use cuprate_types::TransactionVerificationData; use std::collections::HashMap; use std::{collections::HashSet, sync::Arc}; -use crate::types::{TransactionBlobHash, TransactionHash}; +use crate::types::{KeyImage, TransactionBlobHash, TransactionHash}; //---------------------------------------------------------------------------------------------------- TxpoolReadRequest /// The transaction pool [`tower::Service`] read request type. @@ -68,6 +68,11 @@ pub enum TxpoolWriteRequest { /// /// Returns [`TxpoolWriteResponse::Ok`]. Promote(TransactionHash), + + NewBlock { + blockchain_height: usize, + spent_key_images: Vec, + }, } //---------------------------------------------------------------------------------------------------- TxpoolWriteResponse diff --git a/storage/txpool/src/service/write.rs b/storage/txpool/src/service/write.rs index 84916c85..2a4a5bba 100644 --- a/storage/txpool/src/service/write.rs +++ b/storage/txpool/src/service/write.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use cuprate_database::{ConcreteEnv, DatabaseRw, Env, EnvInner, RuntimeError, TxRw}; +use cuprate_database::{ConcreteEnv, DatabaseRo, DatabaseRw, Env, EnvInner, RuntimeError, TxRw}; use cuprate_database_service::DatabaseWriteHandle; use cuprate_types::TransactionVerificationData; @@ -10,8 +10,8 @@ use crate::{ interface::{TxpoolWriteRequest, TxpoolWriteResponse}, types::TxpoolWriteHandle, }, - tables::{OpenTables, TransactionInfos}, - types::{TransactionHash, TxStateFlags}, + tables::{OpenTables, Tables, TablesMut, TransactionInfos}, + types::{KeyImage, PoolInfo, TransactionHash, TxStateFlags}, }; //---------------------------------------------------------------------------------------------------- init_write_service @@ -32,6 +32,10 @@ fn handle_txpool_request( } TxpoolWriteRequest::RemoveTransaction(tx_hash) => remove_transaction(env, tx_hash), TxpoolWriteRequest::Promote(tx_hash) => promote(env, tx_hash), + TxpoolWriteRequest::NewBlock { + blockchain_height, + spent_key_images, + } => new_block(env, *blockchain_height, spent_key_images), } } @@ -118,5 +122,60 @@ fn promote( Some(info) })?; + drop(tx_infos); + + TxRw::commit(tx_rw)?; + Ok(TxpoolWriteResponse::Ok) +} + +fn new_block( + env: &ConcreteEnv, + blockchain_height: usize, + spent_key_images: &[KeyImage], +) -> Result { + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw()?; + + // FIXME: use try blocks once stable. + let result = || { + let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; + + for key_image in spent_key_images { + match tables_mut + .spent_key_images() + .get(key_image) + .and_then(|tx_hash| ops::remove_transaction(&tx_hash, &mut tables_mut)) + { + Ok(()) | Err(RuntimeError::KeyNotFound) => (), + Err(e) => return Err(e), + } + } + + let res = tables_mut.pool_stats_mut().update(&(), |mut info| { + info.last_known_blockchain_height = blockchain_height; + + Some(info) + }); + + match res { + Ok(()) => (), + Err(RuntimeError::KeyNotFound) => tables_mut.pool_stats_mut().put( + &(), + &PoolInfo { + last_known_blockchain_height: blockchain_height, + }, + )?, + Err(e) => return Err(e), + } + + Ok(()) + }; + + if let Err(e) = result() { + TxRw::abort(tx_rw)?; + return Err(e); + } + + TxRw::commit(tx_rw)?; Ok(TxpoolWriteResponse::Ok) } diff --git a/storage/txpool/src/tables.rs b/storage/txpool/src/tables.rs index 1f2d4490..d1d44686 100644 --- a/storage/txpool/src/tables.rs +++ b/storage/txpool/src/tables.rs @@ -17,7 +17,8 @@ use cuprate_database::{define_tables, StorableVec}; use crate::types::{ - KeyImage, RawCachedVerificationState, TransactionBlobHash, TransactionHash, TransactionInfo, + KeyImage, PoolInfo, RawCachedVerificationState, TransactionBlobHash, TransactionHash, + TransactionInfo, }; define_tables! { @@ -48,4 +49,7 @@ define_tables! { /// Transaction blob hashes that are in the pool. 4 => KnownBlobHashes, TransactionBlobHash => TransactionHash, + + 5 => PoolStats, + () => PoolInfo, } diff --git a/storage/txpool/src/types.rs b/storage/txpool/src/types.rs index 2acb819e..f1c1d0f7 100644 --- a/storage/txpool/src/types.rs +++ b/storage/txpool/src/types.rs @@ -19,6 +19,12 @@ pub type TransactionHash = [u8; 32]; /// A transaction blob hash. pub type TransactionBlobHash = [u8; 32]; +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)] +#[repr(C)] +pub struct PoolInfo { + pub last_known_blockchain_height: usize, +} + bitflags::bitflags! { /// Flags representing the state of the transaction in the pool. #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Pod, Zeroable)]