diff --git a/lib/modules-lib/bc-db-reader/src/indexes/identities.rs b/lib/modules-lib/bc-db-reader/src/indexes/identities.rs index e51cd888ace369274823f5b511efb3345aca3f39..500e5ce509b48e4bb84daac0be6636f5da23f851 100644 --- a/lib/modules-lib/bc-db-reader/src/indexes/identities.rs +++ b/lib/modules-lib/bc-db-reader/src/indexes/identities.rs @@ -187,6 +187,17 @@ pub fn get_uid<DB: DbReadable>(db: &DB, pubkey: &PubKey) -> Result<Option<String Ok(get_identity_by_pubkey(db, pubkey)?.map(|db_idty| db_idty.idty_doc.username().to_owned())) } +/// Get uid from pubkey +#[inline] +pub fn get_uid_<DB: DbReadable, R: DbReader>( + db: &DB, + r: &R, + pubkey: &PubKey, +) -> Result<Option<String>, DbError> { + Ok(get_identity_by_pubkey_(db, r, pubkey)? + .map(|db_idty| db_idty.idty_doc.username().to_owned())) +} + /// Get wot id from uid pub fn get_wot_id_from_uid<DB: DbReadable>(db: &DB, uid: &str) -> Result<Option<WotId>, DbError> { db.read(|r| { diff --git a/lib/modules-lib/bc-db-reader/src/trait.rs b/lib/modules-lib/bc-db-reader/src/trait.rs index f01d5693c978e49cfaf7ff4f3bbbfb508404764a..96e4b88ee56ebec8dd63bf8edf468d1ebaae153a 100644 --- a/lib/modules-lib/bc-db-reader/src/trait.rs +++ b/lib/modules-lib/bc-db-reader/src/trait.rs @@ -19,6 +19,7 @@ use crate::blocks::DbBlock; use crate::{BcDbRo, Reader}; use dubp_common_doc::{BlockNumber, Blockstamp}; +use dup_crypto::keys::PubKey; use durs_dbs_tools::DbError; #[cfg(feature = "mock")] @@ -37,6 +38,7 @@ pub trait BcDbRoTrait { &self, numbers: Vec<BlockNumber>, ) -> Result<Vec<DbBlock>, DbError>; + fn get_uid_from_pubkey(&self, pubkey: &PubKey) -> Result<Option<String>, DbError>; } pub struct BcDbRoWithReader<'r, 'db: 'r> { @@ -69,4 +71,7 @@ impl<'r, 'db: 'r> BcDbRoTrait for BcDbRoWithReader<'r, 'db> { ) -> Result<Vec<DbBlock>, DbError> { crate::blocks::get_blocks_in_local_blockchain_by_numbers(self.db, self.r, numbers) } + fn get_uid_from_pubkey(&self, pubkey: &PubKey) -> Result<Option<String>, DbError> { + crate::indexes::identities::get_uid_(self.db, self.r, pubkey) + } } diff --git a/lib/modules/gva/resources/schema.gql b/lib/modules/gva/resources/schema.gql index 497a4dffdd980c58d3471a52229cfcab0d3c4e2e..e77a208f7a66f18037a5b5b71b9a8c4577f18c8d 100644 --- a/lib/modules/gva/resources/schema.gql +++ b/lib/modules/gva/resources/schema.gql @@ -80,6 +80,7 @@ type Block { version: Int! currency: String! issuer: String! + issuerName: String, number: Int! hash: String!, commonTime: DateTimeUtc! diff --git a/lib/modules/gva/src/schema/entities/block.rs b/lib/modules/gva/src/schema/entities/block.rs index 9053bcb7e4692d7f204e89c4985840ee7422f7f6..65e0e2b13e51d0b5a2c98e2832b38f8a8074f9a9 100644 --- a/lib/modules/gva/src/schema/entities/block.rs +++ b/lib/modules/gva/src/schema/entities/block.rs @@ -16,70 +16,96 @@ // ! Module define graphql Block type use crate::context::QueryContext; +use crate::schema::query_trails::QueryTrailBlockExtensions; use chrono::NaiveDateTime; use dubp_block_doc::block::BlockDocumentTrait; use dubp_common_doc::traits::Document; use durs_bc_db_reader::blocks::DbBlock; +use durs_bc_db_reader::{BcDbRoTrait, DbError}; use durs_common_tools::fatal_error; use juniper::{Executor, FieldResult}; +use juniper_from_schema::{QueryTrail, Walked}; pub struct Block { version: i32, currency: String, issuer: String, + issuer_name: Option<String>, number: i32, hash: String, common_time: NaiveDateTime, pow_min: i32, } +impl Block { + #[inline] + pub(crate) fn ask_field_issuer_name(trail: &QueryTrail<'_, Block, Walked>) -> bool { + trail.issuer_name() + } + // Convert BlockDb (db entity) into Block (gva entity) + pub(crate) fn from_block_db<DB: BcDbRoTrait>( + db: &DB, + block_db: DbBlock, + ask_issuer_name: bool, + ) -> Result<Block, DbError> { + Ok(Block { + version: block_db.block.version() as i32, + currency: block_db.block.currency().to_string(), + issuer: block_db.block.issuers()[0].to_string(), + issuer_name: if ask_issuer_name { + db.get_uid_from_pubkey(&block_db.block.issuers()[0])? + } else { + None + }, + number: block_db.block.number().0 as i32, + hash: block_db + .block + .hash() + .unwrap_or_else(|| fatal_error!("DbBlock without hash.")) + .to_string(), + common_time: NaiveDateTime::from_timestamp(block_db.block.common_time() as i64, 0), + pow_min: block_db.block.pow_min() as i32, + }) + } +} + impl super::super::BlockFields for Block { + #[inline] fn field_version(&self, _executor: &Executor<'_, QueryContext>) -> FieldResult<&i32> { Ok(&self.version) } - + #[inline] fn field_currency(&self, _executor: &Executor<'_, QueryContext>) -> FieldResult<&String> { Ok(&self.currency) } - + #[inline] fn field_issuer(&self, _executor: &Executor<'_, QueryContext>) -> FieldResult<&String> { Ok(&self.issuer) } - + #[inline] + fn field_issuer_name( + &self, + _executor: &Executor<'_, QueryContext>, + ) -> FieldResult<&Option<String>> { + Ok(&self.issuer_name) + } + #[inline] fn field_number(&self, _executor: &Executor<'_, QueryContext>) -> FieldResult<&i32> { Ok(&self.number) } - + #[inline] fn field_hash(&self, _executor: &Executor<'_, QueryContext>) -> FieldResult<&String> { Ok(&self.hash) } - + #[inline] fn field_common_time( &self, _executor: &Executor<'_, QueryContext>, ) -> FieldResult<&NaiveDateTime> { Ok(&self.common_time) } - + #[inline] fn field_pow_min(&self, _executor: &Executor<'_, QueryContext>) -> FieldResult<&i32> { Ok(&self.pow_min) } } - -impl From<DbBlock> for Block { - fn from(db_block: DbBlock) -> Block { - Block { - version: db_block.block.version() as i32, - currency: db_block.block.currency().to_string(), - issuer: db_block.block.issuers()[0].to_string(), - number: db_block.block.number().0 as i32, - hash: db_block - .block - .hash() - .unwrap_or_else(|| fatal_error!("DbBlock without hash.")) - .to_string(), - common_time: NaiveDateTime::from_timestamp(db_block.block.common_time() as i64, 0), - pow_min: db_block.block.pow_min() as i32, - } - } -} diff --git a/lib/modules/gva/src/schema/entities/blocks_page.rs b/lib/modules/gva/src/schema/entities/blocks_page.rs index 5232d7a0aa6ce5a115955b5f3ca999eb832f30f6..4c87c4b378893ddfd916a39b5d1171cad6b73d33 100644 --- a/lib/modules/gva/src/schema/entities/blocks_page.rs +++ b/lib/modules/gva/src/schema/entities/blocks_page.rs @@ -17,6 +17,7 @@ use crate::context::QueryContext; use crate::schema::entities::block::Block; +use crate::schema::query_trails::QueryTrailBlocksPageExtensions; use juniper::{Executor, FieldResult}; use juniper_from_schema::{QueryTrail, Walked}; @@ -29,6 +30,16 @@ pub struct BlocksPage { pub(crate) total_blocks_count: i32, } +impl BlocksPage { + pub(crate) fn ask_field_blocks_issuer_name(trail: &QueryTrail<'_, BlocksPage, Walked>) -> bool { + if let Some(block_trail) = trail.blocks().walk() { + Block::ask_field_issuer_name(&block_trail) + } else { + false + } + } +} + impl super::super::BlocksPageFields for BlocksPage { #[inline] fn field_blocks( diff --git a/lib/modules/gva/src/schema/queries/block.rs b/lib/modules/gva/src/schema/queries/block.rs index acb725b1a76f11122be8b09f34ba4d6ca3e72a14..884d9b55098633856acfc2eac1b29e4339c823e2 100644 --- a/lib/modules/gva/src/schema/queries/block.rs +++ b/lib/modules/gva/src/schema/queries/block.rs @@ -22,7 +22,7 @@ use juniper_from_schema::{QueryTrail, Walked}; pub(crate) fn execute<DB: BcDbRoTrait>( db: &DB, - _trail: &QueryTrail<'_, Block, Walked>, + trail: &QueryTrail<'_, Block, Walked>, number: i32, ) -> Result<Option<Block>, DbError> { let block_number = if number >= 0 { @@ -31,8 +31,10 @@ pub(crate) fn execute<DB: BcDbRoTrait>( BlockNumber(0) }; - db.get_db_block_in_local_blockchain(block_number) - .map(|db_block_opt| db_block_opt.map(Into::into)) + let ask_field_issuer_name = Block::ask_field_issuer_name(trail); + db.get_db_block_in_local_blockchain(block_number)? + .map(|block_db| Block::from_block_db(db, block_db, ask_field_issuer_name)) + .transpose() } #[cfg(test)] @@ -55,6 +57,7 @@ mod tests { let mut mock_db = BcDbRo::new(); mock_db .expect_get_db_block_in_local_blockchain() + .times(1) .with(eq(BlockNumber(42))) .returning(|_| { let mut block = gen_empty_timed_block_v10( @@ -72,12 +75,17 @@ mod tests { expire_certs: None, })) }); + mock_db + .expect_get_uid_from_pubkey() + .times(1) + .with(eq(pubkey('B'))) + .returning(|_| Ok(Some("issuerName".to_owned()))); let schema = tests::setup(mock_db, unsafe { &mut DB_BLOCK_1 }); tests::test_gql_query( schema.clone(), - "{ block { commonTime, currency, hash, issuer, number, version } }", + "{ block { commonTime, currency, hash, issuer, issuerName, number, version } }", json!({ "errors": [{ "message": "Field \"block\" argument \"number\" of type \"Int!\" is required but not provided", @@ -91,7 +99,7 @@ mod tests { tests::test_gql_query( schema, - "{ block(number: 42) { commonTime, currency, hash, issuer, number, powMin, version } }", + "{ block(number: 42) { commonTime, currency, hash, issuer, issuerName, number, powMin, version } }", json!({ "data": { "block": { @@ -99,6 +107,7 @@ mod tests { "currency": "test_currency", "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "issuer": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + "issuerName": "issuerName", "number": 42, "powMin": 70, "version": 10 diff --git a/lib/modules/gva/src/schema/queries/blocks.rs b/lib/modules/gva/src/schema/queries/blocks.rs index 6737e8502f1fdbcc71fbd7394bd0a98575ea0c43..5e539ad348043dda2cd8e31bb84b59f9a6492b3f 100644 --- a/lib/modules/gva/src/schema/queries/blocks.rs +++ b/lib/modules/gva/src/schema/queries/blocks.rs @@ -21,12 +21,13 @@ use crate::schema::inputs::block_interval::{BlockInterval, FilledBlockInterval}; use crate::schema::inputs::paging::{FilledPaging, Paging}; use crate::schema::inputs::sort_order::SortOrder; use dubp_common_doc::BlockNumber; +use durs_bc_db_reader::blocks::DbBlock; use durs_bc_db_reader::{BcDbRoTrait, DbError}; use juniper_from_schema::{QueryTrail, Walked}; pub(crate) fn execute<DB: BcDbRoTrait>( db: &DB, - _trail: &QueryTrail<'_, BlocksPage, Walked>, + trail: &QueryTrail<'_, BlocksPage, Walked>, paging_opt: Option<Paging>, block_interval_opt: Option<BlockInterval>, step: usize, @@ -75,11 +76,14 @@ pub(crate) fn execute<DB: BcDbRoTrait>( .collect(); // Get blocks - let blocks: Vec<Block> = db - .get_db_blocks_in_local_blockchain(blocks_numbers)? + let blocks: Vec<DbBlock> = db.get_db_blocks_in_local_blockchain(blocks_numbers)?; + + // Convert BlockDb (db entity) into Block (gva entity) + let ask_field_issuer_name = BlocksPage::ask_field_blocks_issuer_name(trail); + let blocks: Vec<Block> = blocks .into_iter() - .map(Into::into) - .collect(); + .map(|block_db| Block::from_block_db(db, block_db, ask_field_issuer_name)) + .collect::<Result<Vec<Block>, DbError>>()?; Ok(BlocksPage { blocks, diff --git a/lib/modules/gva/src/schema/queries/current.rs b/lib/modules/gva/src/schema/queries/current.rs index 6d70554efc6a579683dfc98d978c474884e1b007..ab52fdeebaf1a065dae84da34ca50c83c5007836 100644 --- a/lib/modules/gva/src/schema/queries/current.rs +++ b/lib/modules/gva/src/schema/queries/current.rs @@ -21,10 +21,12 @@ use juniper_from_schema::{QueryTrail, Walked}; pub(crate) fn execute<DB: BcDbRoTrait>( db: &DB, - _trail: &QueryTrail<'_, Block, Walked>, + trail: &QueryTrail<'_, Block, Walked>, ) -> Result<Option<Block>, DbError> { - db.get_current_block() - .map(|db_block_opt| db_block_opt.map(Into::into)) + let ask_field_issuer_name = Block::ask_field_issuer_name(trail); + db.get_current_block()? + .map(|block_db| Block::from_block_db(db, block_db, ask_field_issuer_name)) + .transpose() } #[cfg(test)] @@ -37,6 +39,7 @@ mod tests { use dup_crypto::hashs::Hash; use dup_crypto_tests_tools::mocks::{hash, pubkey}; use durs_bc_db_reader::blocks::DbBlock; + use mockall::predicate::eq; use serde_json::json; static mut DB_TEST_CURRENT_1: Option<BcDbRo> = None; @@ -44,7 +47,7 @@ mod tests { #[test] fn test_graphql_current() { let mut mock_db = BcDbRo::new(); - mock_db.expect_get_current_block().returning(|| { + mock_db.expect_get_current_block().times(1).returning(|| { let mut current_block = gen_empty_timed_block_v10( Blockstamp { id: BlockNumber(42), @@ -60,12 +63,17 @@ mod tests { expire_certs: None, })) }); + mock_db + .expect_get_uid_from_pubkey() + .times(1) + .with(eq(pubkey('B'))) + .returning(|_| Ok(Some("issuerName".to_owned()))); let schema = tests::setup(mock_db, unsafe { &mut DB_TEST_CURRENT_1 }); tests::test_gql_query( schema, - "{ current { commonTime, currency, hash, issuer, number, powMin, version } }", + "{ current { commonTime, currency, hash, issuer, issuerName, number, powMin, version } }", json!({ "data": { "current": { @@ -73,6 +81,7 @@ mod tests { "currency": "test_currency", "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "issuer": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + "issuerName": "issuerName", "number": 42, "powMin": 70, "version": 10