From 1aca03d31903f82d093174244ff9fe6f7ad5e985 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 9 Sep 2024 18:10:29 -0400 Subject: [PATCH] blockchain: add `KeyImageSpent` request --- storage/blockchain/src/service/read.rs | 18 +++++++++++++++++- types/src/blockchain.rs | 12 ++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 057e3781..23a8151f 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -34,7 +34,7 @@ use crate::{ free::{compact_history_genesis_not_included, compact_history_index_to_height_offset}, types::{BlockchainReadHandle, ResponseResult}, }, - tables::{BlockHeights, BlockInfos, OpenTables, Tables}, + tables::{BlockHeights, BlockInfos, KeyImages, OpenTables, Tables}, types::{Amount, AmountIndex, BlockHash, BlockHeight, KeyImage, PreRctOutputId}, }; @@ -100,6 +100,7 @@ fn map_request( R::GeneratedCoins(height) => generated_coins(env, height), R::Outputs(map) => outputs(env, map), R::NumberOutputsWithAmount(vec) => number_outputs_with_amount(env, vec), + R::KeyImageSpent(set) => key_image_spent(env, set), R::KeyImagesSpent(set) => key_images_spent(env, set), R::CompactChainHistory => compact_chain_history(env), R::FindFirstUnknown(block_ids) => find_first_unknown(env, &block_ids), @@ -414,6 +415,21 @@ fn number_outputs_with_amount(env: &ConcreteEnv, amounts: Vec) -> Respon Ok(BlockchainResponse::NumberOutputsWithAmount(map)) } +/// [`BlockchainReadRequest::KeyImageSpent`]. +#[inline] +fn key_image_spent(env: &ConcreteEnv, key_image: KeyImage) -> ResponseResult { + // Single-threaded, no `ThreadLocal` required. + let env_inner = env.env_inner(); + let tx_ro = env_inner.tx_ro()?; + let table_key_images = env_inner.open_db_ro::(&tx_ro)?; + + match key_image_exists(&key_image, &table_key_images) { + Ok(false) => Ok(BlockchainResponse::KeyImagesSpent(false)), // Key image was NOT found. + Ok(true) => Ok(BlockchainResponse::KeyImagesSpent(true)), // Key image was found. + Err(e) => Err(e), // A database error occurred. + } +} + /// [`BlockchainReadRequest::KeyImagesSpent`]. #[inline] fn key_images_spent(env: &ConcreteEnv, key_images: HashSet) -> ResponseResult { diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 6fbe99d2..3d6fefda 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -98,6 +98,11 @@ pub enum BlockchainReadRequest { /// The input is a list of output amounts. NumberOutputsWithAmount(Vec), + /// Check that a single key image is not spent. + /// + /// Input is a key image hash. + KeyImageSpent([u8; 32]), + /// Check that all key images within a set are not spent. /// /// Input is a set of key images. @@ -198,6 +203,13 @@ pub enum BlockchainResponse { /// - Value = count of outputs with the same amount NumberOutputsWithAmount(HashMap), + /// Response to [`BlockchainReadRequest::KeyImageSpent`]. + /// + /// The inner value is `true` if the key image + /// was spent (existed in the database already), + /// else `false`. + KeyImageSpent(bool), + /// Response to [`BlockchainReadRequest::KeyImagesSpent`]. /// /// The inner value is `true` if _any_ of the key images