Skip to content
Snippets Groups Projects
Commit f3f86442 authored by Pascal Engélibert's avatar Pascal Engélibert :bicyclist:
Browse files

feat(db+indexer+gql): idty_by_username

parent c8d178fd
No related branches found
No related tags found
No related merge requests found
...@@ -41,8 +41,8 @@ pub(crate) use duniter_core::dbs::kv_typed::db_schema; ...@@ -41,8 +41,8 @@ pub(crate) use duniter_core::dbs::kv_typed::db_schema;
pub(crate) use duniter_core::dbs::kv_typed::prelude::*; pub(crate) use duniter_core::dbs::kv_typed::prelude::*;
pub(crate) use duniter_core::dbs::smallvec::SmallVec; pub(crate) use duniter_core::dbs::smallvec::SmallVec;
pub(crate) use duniter_core::dbs::{ pub(crate) use duniter_core::dbs::{
bincode_db, CorruptedBytes, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, ToDumpString, bincode_db, CorruptedBytes, HashKeyV2, PubKeyKeyV2, PubKeyValV2, SourceAmountValV2,
WalletConditionsV2, ToDumpString, WalletConditionsV2,
}; };
pub(crate) use duniter_core::wallet::prelude::*; pub(crate) use duniter_core::wallet::prelude::*;
pub(crate) use duniter_core::wot::WotId; pub(crate) use duniter_core::wot::WotId;
...@@ -67,6 +67,7 @@ db_schema!( ...@@ -67,6 +67,7 @@ db_schema!(
GvaUtxoIdDbV1, GvaUtxoIdDbV1,
SourceAmountValV2 SourceAmountValV2
], ],
["idty_by_username", IdtyByUsername, String, PubKeyValV2],
[ [
"scripts_by_pubkey", "scripts_by_pubkey",
ScriptsByPubkey, ScriptsByPubkey,
......
...@@ -21,6 +21,7 @@ pub struct GvaIdtyDbV1 { ...@@ -21,6 +21,7 @@ pub struct GvaIdtyDbV1 {
pub joins: SmallVec<[BlockNumber; 2]>, pub joins: SmallVec<[BlockNumber; 2]>,
pub leaves: BTreeSet<BlockNumber>, pub leaves: BTreeSet<BlockNumber>,
pub first_ud: Option<BlockNumber>, pub first_ud: Option<BlockNumber>,
pub username: String,
pub wot_id: WotId, pub wot_id: WotId,
} }
......
...@@ -159,6 +159,11 @@ pub trait DbsReader { ...@@ -159,6 +159,11 @@ pub trait DbsReader {
bc_db: &BcV2DbRo<FileBackend>, bc_db: &BcV2DbRo<FileBackend>,
pubkey: PublicKey, pubkey: PublicKey,
) -> KvResult<Option<duniter_core::dbs::IdtyDbV2>>; ) -> KvResult<Option<duniter_core::dbs::IdtyDbV2>>;
fn idty_by_username(
&self,
bc_db: &BcV2DbRo<FileBackend>,
username: &String,
) -> KvResult<Option<(PublicKey, duniter_core::dbs::IdtyDbV2)>>;
fn peers_and_heads<DB: 'static + NetworkV1DbReadable>( fn peers_and_heads<DB: 'static + NetworkV1DbReadable>(
&self, &self,
dunp_db: &DB, dunp_db: &DB,
...@@ -353,6 +358,21 @@ impl DbsReader for DbsReaderImpl { ...@@ -353,6 +358,21 @@ impl DbsReader for DbsReaderImpl {
self.idty_(bc_db, pubkey) self.idty_(bc_db, pubkey)
} }
fn idty_by_username(
&self,
bc_db: &BcV2DbRo<FileBackend>,
username: &String,
) -> KvResult<Option<(PublicKey, duniter_core::dbs::IdtyDbV2)>> {
self.0
.idty_by_username()
.get(username)?
.map_or(Ok(None), |pubkey| match self.idty_(bc_db, pubkey.0) {
Ok(Some(idty)) => Ok(Some((pubkey.0, idty))),
Ok(None) => Ok(None),
Err(e) => Err(e),
})
}
fn peers_and_heads<DB: 'static + NetworkV1DbReadable>( fn peers_and_heads<DB: 'static + NetworkV1DbReadable>(
&self, &self,
dunp_db: &DB, dunp_db: &DB,
......
...@@ -482,6 +482,7 @@ mod tests { ...@@ -482,6 +482,7 @@ mod tests {
joins: svec![BlockNumber(26), BlockNumber(51)], joins: svec![BlockNumber(26), BlockNumber(51)],
leaves: [BlockNumber(32)].iter().copied().collect(), leaves: [BlockNumber(32)].iter().copied().collect(),
first_ud: Some(BlockNumber(29)), first_ud: Some(BlockNumber(29)),
username: String::from("Toto"),
wot_id: WotId(0), wot_id: WotId(0),
}; };
let blocks_with_ud = vec![ let blocks_with_ud = vec![
...@@ -532,6 +533,7 @@ mod tests { ...@@ -532,6 +533,7 @@ mod tests {
joins: svec![BlockNumber(26), BlockNumber(51)], joins: svec![BlockNumber(26), BlockNumber(51)],
leaves: [BlockNumber(32)].iter().copied().collect(), leaves: [BlockNumber(32)].iter().copied().collect(),
first_ud: Some(BlockNumber(29)), first_ud: Some(BlockNumber(29)),
username: String::from("Toto"),
wot_id: WotId(0), wot_id: WotId(0),
}; };
......
...@@ -13,8 +13,11 @@ ...@@ -13,8 +13,11 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::*;
#[derive(Clone, Debug, async_graphql::SimpleObject)] #[derive(Clone, Debug, async_graphql::SimpleObject)]
pub(crate) struct Identity { pub(crate) struct Identity {
pub is_member: bool, pub is_member: bool,
pub pubkey: PubKeyGva,
pub username: String, pub username: String,
} }
...@@ -34,6 +34,27 @@ impl IdtyQuery { ...@@ -34,6 +34,27 @@ impl IdtyQuery {
.await?? .await??
.map(|idty| Identity { .map(|idty| Identity {
is_member: idty.is_member, is_member: idty.is_member,
pubkey,
username: idty.username,
}))
}
/// Get identity by username
async fn idty_by_username(
&self,
ctx: &async_graphql::Context<'_>,
#[graphql(desc = "username")] username: String,
) -> async_graphql::Result<Option<Identity>> {
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
Ok(data
.dbs_pool
.execute(move |dbs| dbs_reader.idty_by_username(&dbs.bc_db_ro, &username))
.await??
.map(|(pubkey, idty)| Identity {
is_member: idty.is_member,
pubkey: PubKeyGva(pubkey),
username: idty.username, username: idty.username,
})) }))
} }
...@@ -79,4 +100,41 @@ mod tests { ...@@ -79,4 +100,41 @@ mod tests {
); );
Ok(()) Ok(())
} }
#[tokio::test]
async fn test_idty_by_username() -> anyhow::Result<()> {
let mut dbs_reader = MockDbsReader::new();
dbs_reader
.expect_idty_by_username()
.withf(|_, s| s == &String::from("JohnDoe"))
.times(1)
.returning(|_, _| {
Ok(Some((
PublicKey::from_base58("DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP")
.expect("wrong pubkey"),
duniter_core::dbs::IdtyDbV2 {
is_member: true,
username: String::from("JohnDoe"),
..Default::default()
},
)))
});
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
r#"{ idtyByUsername(username: "JohnDoe") {isMember, pubkey} }"#
)
.await?,
serde_json::json!({
"data": {
"idtyByUsername": {
"isMember": true,
"pubkey": "DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP"
}
}
})
);
Ok(())
}
} }
...@@ -91,6 +91,7 @@ impl WalletsQuery { ...@@ -91,6 +91,7 @@ impl WalletsQuery {
balance: AmountWithBase::from(pk_with_sa.1), balance: AmountWithBase::from(pk_with_sa.1),
idty: idty_opt.map(|idty_db| Identity { idty: idty_opt.map(|idty_db| Identity {
is_member: idty_db.is_member, is_member: idty_db.is_member,
pubkey: PubKeyGva(pk_with_sa.0),
username: idty_db.username, username: idty_db.username,
}), }),
}) })
...@@ -136,10 +137,17 @@ impl WalletsQuery { ...@@ -136,10 +137,17 @@ impl WalletsQuery {
.map(|WalletWithIdtyOpt(script_with_sa, idty_opt)| Wallet { .map(|WalletWithIdtyOpt(script_with_sa, idty_opt)| Wallet {
script: script_with_sa.0.to_string(), script: script_with_sa.0.to_string(),
balance: AmountWithBase::from(script_with_sa.1), balance: AmountWithBase::from(script_with_sa.1),
idty: idty_opt.map(|idty_db| Identity { idty: if let (Some(idty_db), Some(pubkey)) =
(idty_opt, script_with_sa.0.as_single_sig())
{
Some(Identity {
is_member: idty_db.is_member, is_member: idty_db.is_member,
pubkey: PubKeyGva(pubkey),
username: idty_db.username, username: idty_db.username,
}), })
} else {
None
},
}) })
.collect() .collect()
}) })
......
...@@ -18,6 +18,7 @@ use crate::*; ...@@ -18,6 +18,7 @@ use crate::*;
pub(crate) fn update_identities<B: Backend>( pub(crate) fn update_identities<B: Backend>(
block: &DubpBlockV10, block: &DubpBlockV10,
identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>,
idty_by_username: &mut TxColRw<B::Col, IdtyByUsernameEvent>,
) -> KvResult<()> { ) -> KvResult<()> {
let mut identities_pubkeys = HashSet::new(); let mut identities_pubkeys = HashSet::new();
for idty in block.identities() { for idty in block.identities() {
...@@ -32,9 +33,11 @@ pub(crate) fn update_identities<B: Backend>( ...@@ -32,9 +33,11 @@ pub(crate) fn update_identities<B: Backend>(
joins: smallvec![block.number()], joins: smallvec![block.number()],
leaves: BTreeSet::new(), leaves: BTreeSet::new(),
first_ud: None, first_ud: None,
username: idty.username().into(),
wot_id, wot_id,
}, },
); );
idty_by_username.upsert(idty.username().into(), PubKeyValV2(pubkey));
} }
for mb in block.joiners() { for mb in block.joiners() {
let pubkey = mb.issuers()[0]; let pubkey = mb.issuers()[0];
...@@ -70,6 +73,7 @@ pub(crate) fn update_identities<B: Backend>( ...@@ -70,6 +73,7 @@ pub(crate) fn update_identities<B: Backend>(
pub(crate) fn revert_identities<B: Backend>( pub(crate) fn revert_identities<B: Backend>(
block: &DubpBlockV10, block: &DubpBlockV10,
identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>,
idty_by_username: &mut TxColRw<B::Col, IdtyByUsernameEvent>,
) -> KvResult<()> { ) -> KvResult<()> {
for mb in block.joiners() { for mb in block.joiners() {
let pubkey = mb.issuers()[0]; let pubkey = mb.issuers()[0];
...@@ -83,6 +87,9 @@ pub(crate) fn revert_identities<B: Backend>( ...@@ -83,6 +87,9 @@ pub(crate) fn revert_identities<B: Backend>(
} }
for idty in block.identities() { for idty in block.identities() {
let pubkey = idty.issuers()[0]; let pubkey = idty.issuers()[0];
if let Some(idty) = identities.get(&PubKeyKeyV2(pubkey))? {
idty_by_username.remove(idty.username);
}
identities.remove(PubKeyKeyV2(pubkey)); identities.remove(PubKeyKeyV2(pubkey));
crate::revert_wot_id(); crate::revert_wot_id();
} }
......
...@@ -41,7 +41,7 @@ use duniter_core::{ ...@@ -41,7 +41,7 @@ use duniter_core::{
use duniter_core::{ use duniter_core::{
dbs::{ dbs::{
bincode_db, kv_typed::prelude::*, prelude::*, smallvec::smallvec, FileBackend, HashKeyV2, bincode_db, kv_typed::prelude::*, prelude::*, smallvec::smallvec, FileBackend, HashKeyV2,
PubKeyKeyV2, SourceAmountValV2, WalletConditionsV2, PubKeyKeyV2, PubKeyValV2, SourceAmountValV2, WalletConditionsV2,
}, },
wot::{WebOfTrust, WotId, MAIN_WOT}, wot::{WebOfTrust, WotId, MAIN_WOT},
}; };
...@@ -126,7 +126,11 @@ pub fn apply_block<B: Backend>( ...@@ -126,7 +126,11 @@ pub fn apply_block<B: Backend>(
.upsert(U64BE(block.common_time()), block.number().0); .upsert(U64BE(block.common_time()), block.number().0);
db.blockchain_time db.blockchain_time
.upsert(U32BE(block.number().0), block.common_time()); .upsert(U32BE(block.number().0), block.common_time());
identities::update_identities::<B>(&block, &mut db.gva_identities)?; identities::update_identities::<B>(
&block,
&mut db.gva_identities,
&mut db.idty_by_username,
)?;
if let Some(divident_amount) = block.dividend() { if let Some(divident_amount) = block.dividend() {
db.blocks_with_ud.upsert(U32BE(blockstamp.number.0), ()); db.blocks_with_ud.upsert(U32BE(blockstamp.number.0), ());
apply_ud::<B>( apply_ud::<B>(
...@@ -153,7 +157,11 @@ pub fn revert_block<B: Backend>( ...@@ -153,7 +157,11 @@ pub fn revert_block<B: Backend>(
gva_db.write(|mut db| { gva_db.write(|mut db| {
db.blocks_by_common_time.remove(U64BE(block.common_time())); db.blocks_by_common_time.remove(U64BE(block.common_time()));
db.blockchain_time.remove(U32BE(block.number().0)); db.blockchain_time.remove(U32BE(block.number().0));
identities::revert_identities::<B>(&block, &mut db.gva_identities)?; identities::revert_identities::<B>(
&block,
&mut db.gva_identities,
&mut db.idty_by_username,
)?;
if let Some(divident_amount) = block.dividend() { if let Some(divident_amount) = block.dividend() {
db.blocks_with_ud.remove(U32BE(block.number().0)); db.blocks_with_ud.remove(U32BE(block.number().0));
revert_ud::<B>( revert_ud::<B>(
...@@ -331,6 +339,12 @@ mod tests { ...@@ -331,6 +339,12 @@ mod tests {
Some(SourceAmountValV2(SourceAmount::with_base0(1000))) Some(SourceAmountValV2(SourceAmount::with_base0(1000)))
); );
assert_eq!(gva_db.txs_by_block().count()?, 0); assert_eq!(gva_db.txs_by_block().count()?, 0);
assert_eq!(
gva_db.idty_by_username().get(&String::from("elois"))?,
Some(PubKeyValV2(PublicKey::from_base58(
"D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx",
)?))
);
let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified { let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified {
number: 1, number: 1,
...@@ -644,6 +658,10 @@ mod tests { ...@@ -644,6 +658,10 @@ mod tests {
); );
assert_eq!(gva_db.balances().get(&WalletConditionsV2(s2))?, None); assert_eq!(gva_db.balances().get(&WalletConditionsV2(s2))?, None);
revert_block(&b0, currency_params, &gva_db)?;
assert_eq!(gva_db.idty_by_username().count()?, 0);
Ok(()) Ok(())
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment