diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index b68b5444..8e165f2a 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -84,7 +84,7 @@ async fn test_template( let request = BlockchainWriteRequest::WriteBlock(block); let response_channel = writer.call(request); let response = response_channel.await.unwrap(); - assert_eq!(response, BlockchainResponse::WriteBlockOk); + assert_eq!(response, BlockchainResponse::WriteBlock); } //----------------------------------------------------------------------- Reset the transaction diff --git a/storage/blockchain/src/service/write.rs b/storage/blockchain/src/service/write.rs index 816afc4f..6f32ca2b 100644 --- a/storage/blockchain/src/service/write.rs +++ b/storage/blockchain/src/service/write.rs @@ -11,6 +11,7 @@ use cuprate_types::{ }; use crate::{ + ops, service::types::{BlockchainWriteHandle, ResponseResult}, tables::OpenTables, }; @@ -29,6 +30,7 @@ fn handle_blockchain_request( ) -> Result { match req { BlockchainWriteRequest::WriteBlock(block) => write_block(env, block), + BlockchainWriteRequest::PopBlocks(nblocks) => pop_blocks(env, *nblocks), } } @@ -49,13 +51,42 @@ fn write_block(env: &ConcreteEnv, block: &VerifiedBlockInformation) -> ResponseR let result = { let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; - crate::ops::block::add_block(block, &mut tables_mut) + ops::block::add_block(block, &mut tables_mut) }; match result { Ok(()) => { TxRw::commit(tx_rw)?; - Ok(BlockchainResponse::WriteBlockOk) + Ok(BlockchainResponse::WriteBlock) + } + Err(e) => { + // INVARIANT: ensure database atomicity by aborting + // the transaction on `add_block()` failures. + TxRw::abort(tx_rw) + .expect("could not maintain database atomicity by aborting write transaction"); + Err(e) + } + } +} + +/// [`BlockchainWriteRequest::PopBlocks`]. +#[inline] +fn pop_blocks(env: &ConcreteEnv, nblocks: u64) -> ResponseResult { + let env_inner = env.env_inner(); + let tx_rw = env_inner.tx_rw()?; + + let result = || { + let mut tables_mut = env_inner.open_tables_mut(&tx_rw)?; + for _ in 0..nblocks { + ops::block::pop_block(&mut tables_mut)?; + } + Ok(()) + }; + + match result() { + Ok(()) => { + TxRw::commit(tx_rw)?; + Ok(BlockchainResponse::WriteBlock) } Err(e) => { // INVARIANT: ensure database atomicity by aborting diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 3d6fefda..009c6a70 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -125,13 +125,17 @@ pub enum BlockchainReadRequest { /// /// There is currently only 1 write request to the database, /// as such, the only valid [`BlockchainResponse`] to this request is -/// the proper response for a [`BlockchainResponse::WriteBlockOk`]. +/// the proper response for a [`BlockchainResponse::WriteBlock`]. #[derive(Debug, Clone, PartialEq, Eq)] +#[allow(clippy::large_enum_variant)] // TODO pub enum BlockchainWriteRequest { /// Request that a block be written to the database. /// /// Input is an already verified block. WriteBlock(VerifiedBlockInformation), + + /// TODO + PopBlocks(u64), } //---------------------------------------------------------------------------------------------------- Response @@ -240,7 +244,10 @@ pub enum BlockchainResponse { /// /// This response indicates that the requested block has /// successfully been written to the database without error. - WriteBlockOk, + WriteBlock, + + /// TODO + PopBlocks, } //---------------------------------------------------------------------------------------------------- Tests