Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ use tari_core::{
base_node::rpc::{BaseNodeWalletQueryService, query_service},
chain_storage::BlockchainBackend,
};
use tari_transaction_components::rpc::models::{GetUtxosDeletedInfoRequest, GetUtxosDeletedInfoResponse};
use tari_transaction_components::rpc::models::{
GetUtxosDeletedInfoRequest,
GetUtxosDeletedInfoResponse,
GetUtxosDeletedInfoResponseV1,
};
use tari_utilities::hex::Hex;
use tonic::service::AxumBody;

Expand All @@ -42,6 +46,8 @@ pub struct GetUtxosDeletedInfoParams {
pub hashes: Vec<Vec<u8>>,
#[serde(deserialize_with = "from_hex")]
pub must_include_header: Vec<u8>,
#[serde(default)]
pub version: u8,
}

impl From<GetUtxosDeletedInfoParams> for GetUtxosDeletedInfoRequest {
Expand All @@ -59,7 +65,8 @@ impl From<GetUtxosDeletedInfoParams> for GetUtxosDeletedInfoRequest {
params(GetUtxosDeletedInfoParams),
path = "/get_utxos_deleted_info",
responses(
(status = 200, description = "UTXOs Deleted Info", body = GetUtxosDeletedInfoResponse),
(status = 200, description = "UTXOs Deleted Info (v0)", body = GetUtxosDeletedInfoResponse),
(status = 200, description = "UTXOs Deleted Info (v1, includes spent_timestamp)", body = GetUtxosDeletedInfoResponseV1),
),
)]
pub async fn handle<B: BlockchainBackend + 'static>(
Expand All @@ -68,15 +75,25 @@ pub async fn handle<B: BlockchainBackend + 'static>(
Extension(cache_cfg): Extension<Arc<HttpCacheConfig>>,
) -> Result<Response<AxumBody>, (StatusCode, Json<ErrorResponse>)> {
debug!(target: LOG_TARGET, "Received get_utxos_deleted_info request: {params}");
let version = params.version;
let request = params.into();

let response = query_service
.get_utxos_deleted_info(request)
.await
.map_err(error_handler_with_message)?;

let body = Json(response);
let mut response = body.into_response();
let mut response = match version {
0 => {
let result = query_service
.get_utxos_deleted_info(request)
.await
.map_err(error_handler_with_message)?;
Json(result).into_response()
},
_ => {
let result = query_service
.get_utxos_deleted_info_v1(request)
.await
.map_err(error_handler_with_message)?;
Json(result).into_response()
},
};
apply_cache_control(response.headers_mut(), &cache_cfg, RouteKey::GetUtxosDeletedInfo, 0, 0);
Ok(response)
}
Expand All @@ -85,14 +102,15 @@ impl Display for GetUtxosDeletedInfoParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"GetUtxosDeletedInfoParams {{ must_include_header: {}, hashes: {:?} }}",
"GetUtxosDeletedInfoParams {{ must_include_header: {}, hashes: {:?}, version: {} }}",
HashOutput::try_from(self.must_include_header.as_slice())
.unwrap_or_default()
.to_hex(),
self.hashes
.iter()
.map(|h| HashOutput::try_from(h.as_slice()).unwrap_or_default().to_hex())
.collect::<Vec<_>>()
.collect::<Vec<_>>(),
self.version
)
}
}
5 changes: 5 additions & 0 deletions base_layer/core/src/base_node/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ pub trait BaseNodeWalletQueryService: Send + Sync + 'static {
request: models::GetUtxosDeletedInfoRequest,
) -> Result<models::GetUtxosDeletedInfoResponse, Self::Error>;

async fn get_utxos_deleted_info_v1(
&self,
request: models::GetUtxosDeletedInfoRequest,
) -> Result<models::GetUtxosDeletedInfoResponseV1, Self::Error>;

async fn generate_kernel_merkle_proof(
&self,
excess_sig: CompressedSignature,
Expand Down
57 changes: 57 additions & 0 deletions base_layer/core/src/base_node/rpc/query_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,63 @@ impl<B: BlockchainBackend + 'static> BaseNodeWalletQueryService for Service<B> {
})
}

async fn get_utxos_deleted_info_v1(
&self,
request: models::GetUtxosDeletedInfoRequest,
) -> Result<models::GetUtxosDeletedInfoResponseV1, Self::Error> {
request.validate()?;

let mut utxos = vec![];

let must_include_header = request.must_include_header.clone().try_into()?;
if self
.db()
.fetch_header_by_block_hash(must_include_header)
.await?
.is_none()
{
return Err(Error::HeaderHashNotFound);
}

let tip_header = self.db().fetch_tip_header().await?;
for hash in request.hashes {
let hash = hash.try_into()?;
let output = self.db().fetch_output(hash).await?;

if let Some(output) = output {
let input = self.db().fetch_input(hash).await?;
if let Some(i) = input {
utxos.push(models::DeletedUtxoInfoV1 {
utxo_hash: hash.to_vec(),
found_in_header: Some((output.mined_height, output.header_hash.to_vec())),
spent_in_header: Some((i.spent_height, i.header_hash.to_vec())),
spent_timestamp: Some(i.spent_timestamp),
});
} else {
utxos.push(models::DeletedUtxoInfoV1 {
utxo_hash: hash.to_vec(),
found_in_header: Some((output.mined_height, output.header_hash.to_vec())),
spent_in_header: None,
spent_timestamp: None,
});
}
} else {
utxos.push(models::DeletedUtxoInfoV1 {
utxo_hash: hash.to_vec(),
found_in_header: None,
spent_in_header: None,
spent_timestamp: None,
});
}
}

Ok(models::GetUtxosDeletedInfoResponseV1 {
utxos,
best_block_hash: tip_header.hash().to_vec(),
best_block_height: tip_header.height(),
})
}

async fn generate_kernel_merkle_proof(
&self,
excess_sig: types::CompressedSignature,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,18 @@ pub struct DeletedUtxoInfo {
pub found_in_header: Option<(u64, Vec<u8>)>,
pub spent_in_header: Option<(u64, Vec<u8>)>,
}

#[derive(Serialize, Deserialize, ToSchema, Debug, Clone)]
pub struct GetUtxosDeletedInfoResponseV1 {
pub utxos: Vec<DeletedUtxoInfoV1>,
pub best_block_hash: Vec<u8>,
pub best_block_height: u64,
}

#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
pub struct DeletedUtxoInfoV1 {
pub utxo_hash: Vec<u8>,
pub found_in_header: Option<(u64, Vec<u8>)>,
pub spent_in_header: Option<(u64, Vec<u8>)>,
pub spent_timestamp: Option<u64>,
}
Loading