diff --git a/src/serve/grpc/convert.rs b/src/serve/grpc/convert.rs new file mode 100644 index 00000000..19b343b0 --- /dev/null +++ b/src/serve/grpc/convert.rs @@ -0,0 +1,12 @@ +use bytes::Bytes; +use pallas::crypto::hash::Hash; +use tonic::Status; + +pub fn bytes_to_hash32(data: &Bytes) -> Result, Status> { + let array: [u8; 32] = data + .as_ref() + .try_into() + .map_err(|_| Status::invalid_argument("invalid hash value, needs to be 32-bytes long"))?; + + Ok(Hash::<32>::new(array)) +} diff --git a/src/serve/grpc/mod.rs b/src/serve/grpc/mod.rs index 33304903..6d0a4228 100644 --- a/src/serve/grpc/mod.rs +++ b/src/serve/grpc/mod.rs @@ -9,6 +9,7 @@ use crate::ledger::store::LedgerStore; use crate::wal::redb::WalStore; use crate::{prelude::*, submit::Transaction}; +mod convert; mod query; mod submit; mod sync; diff --git a/src/serve/grpc/query.rs b/src/serve/grpc/query.rs index 0391bc21..ccdd2acd 100644 --- a/src/serve/grpc/query.rs +++ b/src/serve/grpc/query.rs @@ -1,7 +1,6 @@ use crate::ledger::{store::LedgerStore, EraCbor, TxoRef}; use futures_core::Stream; -use itertools::Itertools; -use pallas::crypto::hash::Hash; +use itertools::Itertools as _; use pallas::interop::utxorpc as interop; use pallas::interop::utxorpc::spec as u5c; use pallas::ledger::traverse::MultiEraOutput; @@ -23,11 +22,6 @@ impl QueryServiceImpl { } } -fn bytes_to_hash(raw: &[u8]) -> Hash<32> { - let array: [u8; 32] = raw.try_into().unwrap(); - Hash::<32>::new(array) -} - fn find_matching_set( ledger: &LedgerStore, query: u5c::cardano::TxOutputPattern, @@ -47,6 +41,11 @@ fn find_matching_set( Ok(set) } +fn from_u5c_txoref(txo: u5c::query::TxoRef) -> Result { + let hash = super::convert::bytes_to_hash32(&txo.hash)?; + Ok(TxoRef(hash, txo.index)) +} + fn into_u5c_utxo( txo: &TxoRef, body: &EraCbor, @@ -94,14 +93,15 @@ impl u5c::query::query_service_server::QueryService for QueryServiceImpl { info!("received new grpc query"); - let keys = message + let keys: Vec<_> = message .keys .into_iter() - .map(|x| TxoRef(bytes_to_hash(&x.hash), x.index)); + .map(from_u5c_txoref) + .try_collect()?; let utxos = self .ledger - .get_utxos(keys.collect_vec()) + .get_utxos(keys) .map_err(|e| Status::internal(e.to_string()))?; let items: Vec<_> = utxos diff --git a/src/serve/grpc/sync.rs b/src/serve/grpc/sync.rs index 5d9cd95d..3a6d11fe 100644 --- a/src/serve/grpc/sync.rs +++ b/src/serve/grpc/sync.rs @@ -9,8 +9,11 @@ use tonic::{Request, Response, Status}; use crate::ledger; use crate::wal::{self, RawBlock, WalReader as _}; -fn u5c_to_chain_point(block_ref: u5c::sync::BlockRef) -> wal::ChainPoint { - wal::ChainPoint::Specific(block_ref.index, block_ref.hash.as_ref().into()) +fn u5c_to_chain_point(block_ref: u5c::sync::BlockRef) -> Result { + Ok(wal::ChainPoint::Specific( + block_ref.index, + super::convert::bytes_to_hash32(&block_ref.hash)?, + )) } // fn raw_to_anychain2(raw: &[u8]) -> AnyChainBlock { @@ -73,7 +76,11 @@ impl u5c::sync::chain_sync_service_server::ChainSyncService for ChainSyncService ) -> Result, Status> { let message = request.into_inner(); - let points: Vec<_> = message.r#ref.into_iter().map(u5c_to_chain_point).collect(); + let points: Vec<_> = message + .r#ref + .into_iter() + .map(u5c_to_chain_point) + .try_collect()?; let out = self .wal @@ -94,7 +101,7 @@ impl u5c::sync::chain_sync_service_server::ChainSyncService for ChainSyncService ) -> Result, Status> { let msg = request.into_inner(); - let from = msg.start_token.map(u5c_to_chain_point); + let from = msg.start_token.map(u5c_to_chain_point).transpose()?; let len = msg.max_items as usize + 1; @@ -145,7 +152,7 @@ impl u5c::sync::chain_sync_service_server::ChainSyncService for ChainSyncService .intersect .into_iter() .map(u5c_to_chain_point) - .collect(); + .try_collect()?; self.wal .find_intersect(&intersect)