feat(db): attribute a wot_id to each identity

This commit is contained in:
librelois 2021-05-17 23:29:22 +02:00
parent 4a7d3270df
commit 6d7a35dd8b
7 changed files with 90 additions and 16 deletions

1
Cargo.lock generated
View file

@ -1025,6 +1025,7 @@ dependencies = [
"lz4_flex", "lz4_flex",
"maplit", "maplit",
"once_cell", "once_cell",
"parking_lot",
"resiter", "resiter",
"smallvec", "smallvec",
] ]

View file

@ -45,6 +45,7 @@ pub(crate) use duniter_core::dbs::{
bincode_db, CorruptedBytes, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, ToDumpString, bincode_db, CorruptedBytes, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, ToDumpString,
WalletConditionsV2, WalletConditionsV2,
}; };
pub(crate) use duniter_core::wot::WotId;
pub(crate) use serde::{Deserialize, Serialize}; pub(crate) use serde::{Deserialize, Serialize};
pub(crate) use std::collections::BTreeSet; pub(crate) use std::collections::BTreeSet;

View file

@ -15,12 +15,13 @@
use crate::*; use crate::*;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct GvaIdtyDbV1 { pub struct GvaIdtyDbV1 {
pub is_member: bool, pub is_member: bool,
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 wot_id: WotId,
} }
impl AsBytes for GvaIdtyDbV1 { impl AsBytes for GvaIdtyDbV1 {

View file

@ -471,8 +471,8 @@ fn collect_uds<BC: BackendCol, I: Iterator<Item = BlockNumber>>(
mod tests { mod tests {
use super::*; use super::*;
use duniter_core::dbs::smallvec::smallvec as svec;
use duniter_core::dbs::{databases::bc_v2::BcV2DbWritable, SourceAmountValV2, UdIdV2}; use duniter_core::dbs::{databases::bc_v2::BcV2DbWritable, SourceAmountValV2, UdIdV2};
use duniter_core::{dbs::smallvec::smallvec as svec, wot::WotId};
use duniter_gva_db::GvaV1DbWritable; use duniter_gva_db::GvaV1DbWritable;
#[test] #[test]
@ -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)),
wot_id: WotId(0),
}; };
let blocks_with_ud = vec![ let blocks_with_ud = vec![
BlockNumber(3), BlockNumber(3),
@ -531,6 +532,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)),
wot_id: WotId(0),
}; };
let bc_db = duniter_core::dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?; let bc_db = duniter_core::dbs::databases::bc_v2::BcV2Db::<Mem>::open(MemConf::default())?;

View file

@ -18,12 +18,13 @@ duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core" }
duniter-gva-db = { path = "../db" } duniter-gva-db = { path = "../db" }
dubp = { version = "0.54.1", features = ["duniter"] } dubp = { version = "0.54.1", features = ["duniter"] }
lz4_flex = { version = "0.7", default-features = false } lz4_flex = { version = "0.7", default-features = false }
once_cell = "1.5.2" once_cell = "1.7"
resiter = "0.4.0" resiter = "0.4.0"
[dev-dependencies] [dev-dependencies]
duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["mem"] } duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["mem"] }
maplit = "1.0.2" maplit = "1.0.2"
parking_lot = "0.11"
smallvec = { version = "1.4.0", features = ["serde", "write"] } smallvec = { version = "1.4.0", features = ["serde", "write"] }
[features] [features]

View file

@ -19,13 +19,35 @@ pub(crate) fn update_identities<B: Backend>(
block: &DubpBlockV10, block: &DubpBlockV10,
identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>, identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>,
) -> KvResult<()> { ) -> KvResult<()> {
let mut identities_pubkeys = HashSet::new();
for idty in block.identities() {
let pubkey = idty.issuers()[0];
identities_pubkeys.insert(pubkey);
let wot_id = crate::get_next_wot_id();
identities.upsert(
PubKeyKeyV2(pubkey),
GvaIdtyDbV1 {
is_member: true,
joins: smallvec![block.number()],
leaves: BTreeSet::new(),
first_ud: None,
wot_id,
},
);
}
for mb in block.joiners() { for mb in block.joiners() {
let pubkey = mb.issuers()[0]; let pubkey = mb.issuers()[0];
let mut idty = identities.get(&PubKeyKeyV2(pubkey))?.unwrap_or_default(); // Update identity only if the join event concerns an identity already created in the past
idty.is_member = true; if !identities_pubkeys.contains(&pubkey) {
idty.joins.push(block.number()); let mut idty = identities
identities.upsert(PubKeyKeyV2(pubkey), idty); .get(&PubKeyKeyV2(pubkey))?
.ok_or_else(|| KvError::DbCorrupted("Joiner without identity".to_owned()))?;
idty.is_member = true;
idty.joins.push(block.number());
identities.upsert(PubKeyKeyV2(pubkey), idty);
}
} }
for revo in block.revoked() { for revo in block.revoked() {
let pubkey = revo.issuer; let pubkey = revo.issuer;
@ -52,7 +74,9 @@ pub(crate) fn revert_identities<B: Backend>(
for mb in block.joiners() { for mb in block.joiners() {
let pubkey = mb.issuers()[0]; let pubkey = mb.issuers()[0];
let mut idty = identities.get(&PubKeyKeyV2(pubkey))?.unwrap_or_default(); let mut idty = identities
.get(&PubKeyKeyV2(pubkey))?
.ok_or_else(|| KvError::DbCorrupted("Joiner without identity".to_owned()))?;
idty.is_member = false; idty.is_member = false;
idty.joins.pop(); idty.joins.pop();
identities.upsert(PubKeyKeyV2(pubkey), idty); identities.upsert(PubKeyKeyV2(pubkey), idty);
@ -60,6 +84,7 @@ 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];
identities.remove(PubKeyKeyV2(pubkey)); identities.remove(PubKeyKeyV2(pubkey));
crate::revert_wot_id();
} }
for revo in block.revoked() { for revo in block.revoked() {
let pubkey = revo.issuer; let pubkey = revo.issuer;

View file

@ -36,21 +36,24 @@ use dubp::{
}, },
wallet::prelude::*, wallet::prelude::*,
}; };
use duniter_core::dbs::{ use duniter_core::{
bincode_db, kv_typed::prelude::*, prelude::*, FileBackend, HashKeyV2, PubKeyKeyV2, dbs::{
SourceAmountValV2, WalletConditionsV2, bincode_db, kv_typed::prelude::*, prelude::*, smallvec::smallvec, FileBackend, HashKeyV2,
PubKeyKeyV2, SourceAmountValV2, WalletConditionsV2,
},
wot::{WebOfTrust, WotId, MAIN_WOT},
}; };
use duniter_gva_db::*; use duniter_gva_db::*;
use once_cell::sync::OnceCell;
use resiter::filter::Filter; use resiter::filter::Filter;
use std::{ use std::{
collections::{BTreeSet, HashMap}, collections::{BTreeSet, HashMap, HashSet},
ops::AddAssign,
path::Path, path::Path,
}; };
static GVA_DB_RO: once_cell::sync::OnceCell<GvaV1DbRo<FileBackend>> = static GVA_DB_RO: OnceCell<GvaV1DbRo<FileBackend>> = OnceCell::new();
once_cell::sync::OnceCell::new(); static GVA_DB_RW: OnceCell<GvaV1Db<FileBackend>> = OnceCell::new();
static GVA_DB_RW: once_cell::sync::OnceCell<GvaV1Db<FileBackend>> =
once_cell::sync::OnceCell::new();
pub fn get_gva_db_ro(profile_path_opt: Option<&Path>) -> &'static GvaV1DbRo<FileBackend> { pub fn get_gva_db_ro(profile_path_opt: Option<&Path>) -> &'static GvaV1DbRo<FileBackend> {
GVA_DB_RO.get_or_init(|| get_gva_db_rw(profile_path_opt).get_ro_handler()) GVA_DB_RO.get_or_init(|| get_gva_db_rw(profile_path_opt).get_ro_handler())
@ -65,6 +68,39 @@ pub fn get_gva_db_rw(profile_path_opt: Option<&Path>) -> &'static GvaV1Db<FileBa
}) })
} }
static mut NEXT_WOT_ID: Option<usize> = None;
fn get_next_wot_id() -> WotId {
WotId(unsafe {
if let Some(ref mut next_wot_id_) = NEXT_WOT_ID {
let next_wot_id = *next_wot_id_;
next_wot_id_.add_assign(1);
next_wot_id
} else {
NEXT_WOT_ID = Some(if let Some(main_wot) = MAIN_WOT.get() {
main_wot.read().size()
} else {
0
});
0
}
})
}
fn revert_wot_id() {
unsafe {
if let Some(ref mut next_wot_id_) = NEXT_WOT_ID {
use std::ops::SubAssign as _;
next_wot_id_.sub_assign(1);
} else {
NEXT_WOT_ID = Some(if let Some(main_wot) = MAIN_WOT.get() {
main_wot.read().size() - 1
} else {
unreachable!()
});
}
};
}
pub struct UtxoV10<'s> { pub struct UtxoV10<'s> {
pub id: UtxoIdV10, pub id: UtxoIdV10,
pub amount: SourceAmount, pub amount: SourceAmount,
@ -256,9 +292,13 @@ mod tests {
documents::transaction::TransactionDocumentV10Stringified, documents::transaction::TransactionDocumentV10Stringified,
documents_parser::prelude::FromStringObject, documents_parser::prelude::FromStringObject,
}; };
use once_cell::sync::Lazy;
static TESTS_MUTEX: Lazy<parking_lot::Mutex<()>> = Lazy::new(|| parking_lot::Mutex::new(()));
#[test] #[test]
fn test_gva_apply_block() -> anyhow::Result<()> { fn test_gva_apply_block() -> anyhow::Result<()> {
let _ = TESTS_MUTEX.lock();
let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?; let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?;
let s1 = WalletScriptV10::single_sig(PublicKey::from_base58( let s1 = WalletScriptV10::single_sig(PublicKey::from_base58(
@ -272,6 +312,7 @@ mod tests {
version: 10, version: 10,
median_time: 5_243, median_time: 5_243,
dividend: Some(1000), dividend: Some(1000),
identities: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:Ydnclvw76/JHcKSmU9kl9Ie0ne5/X8NYOqPqbGnufIK3eEPRYYdEYaQh+zffuFhbtIRjv6m/DkVLH5cLy/IyAg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()],
joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()], joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()],
inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()),
signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(),
@ -430,6 +471,7 @@ mod tests {
#[test] #[test]
fn test_gva_revert_block() -> anyhow::Result<()> { fn test_gva_revert_block() -> anyhow::Result<()> {
let _ = TESTS_MUTEX.lock();
let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?; let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?;
let s1 = WalletScriptV10::single_sig(PublicKey::from_base58( let s1 = WalletScriptV10::single_sig(PublicKey::from_base58(
@ -443,6 +485,7 @@ mod tests {
version: 10, version: 10,
median_time: 5_243, median_time: 5_243,
dividend: Some(1000), dividend: Some(1000),
identities: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:Ydnclvw76/JHcKSmU9kl9Ie0ne5/X8NYOqPqbGnufIK3eEPRYYdEYaQh+zffuFhbtIRjv6m/DkVLH5cLy/IyAg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()],
joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()], joiners: vec!["D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx:FFeyrvYio9uYwY5aMcDGswZPNjGLrl8THn9l3EPKSNySD3SDSHjCljSfFEwb87sroyzJQoVzPwER0sW/cbZMDg==:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855:elois".to_owned()],
inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()), inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()),
signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(), signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(),