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",
"maplit",
"once_cell",
"parking_lot",
"resiter",
"smallvec",
]

View file

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

View file

@ -15,12 +15,13 @@
use crate::*;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct GvaIdtyDbV1 {
pub is_member: bool,
pub joins: SmallVec<[BlockNumber; 2]>,
pub leaves: BTreeSet<BlockNumber>,
pub first_ud: Option<BlockNumber>,
pub wot_id: WotId,
}
impl AsBytes for GvaIdtyDbV1 {

View file

@ -471,8 +471,8 @@ fn collect_uds<BC: BackendCol, I: Iterator<Item = BlockNumber>>(
mod tests {
use super::*;
use duniter_core::dbs::smallvec::smallvec as svec;
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;
#[test]
@ -482,6 +482,7 @@ mod tests {
joins: svec![BlockNumber(26), BlockNumber(51)],
leaves: [BlockNumber(32)].iter().copied().collect(),
first_ud: Some(BlockNumber(29)),
wot_id: WotId(0),
};
let blocks_with_ud = vec![
BlockNumber(3),
@ -531,6 +532,7 @@ mod tests {
joins: svec![BlockNumber(26), BlockNumber(51)],
leaves: [BlockNumber(32)].iter().copied().collect(),
first_ud: Some(BlockNumber(29)),
wot_id: WotId(0),
};
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" }
dubp = { version = "0.54.1", features = ["duniter"] }
lz4_flex = { version = "0.7", default-features = false }
once_cell = "1.5.2"
once_cell = "1.7"
resiter = "0.4.0"
[dev-dependencies]
duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["mem"] }
maplit = "1.0.2"
parking_lot = "0.11"
smallvec = { version = "1.4.0", features = ["serde", "write"] }
[features]

View file

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

View file

@ -36,21 +36,24 @@ use dubp::{
},
wallet::prelude::*,
};
use duniter_core::dbs::{
bincode_db, kv_typed::prelude::*, prelude::*, FileBackend, HashKeyV2, PubKeyKeyV2,
SourceAmountValV2, WalletConditionsV2,
use duniter_core::{
dbs::{
bincode_db, kv_typed::prelude::*, prelude::*, smallvec::smallvec, FileBackend, HashKeyV2,
PubKeyKeyV2, SourceAmountValV2, WalletConditionsV2,
},
wot::{WebOfTrust, WotId, MAIN_WOT},
};
use duniter_gva_db::*;
use once_cell::sync::OnceCell;
use resiter::filter::Filter;
use std::{
collections::{BTreeSet, HashMap},
collections::{BTreeSet, HashMap, HashSet},
ops::AddAssign,
path::Path,
};
static GVA_DB_RO: once_cell::sync::OnceCell<GvaV1DbRo<FileBackend>> =
once_cell::sync::OnceCell::new();
static GVA_DB_RW: once_cell::sync::OnceCell<GvaV1Db<FileBackend>> =
once_cell::sync::OnceCell::new();
static GVA_DB_RO: OnceCell<GvaV1DbRo<FileBackend>> = OnceCell::new();
static GVA_DB_RW: OnceCell<GvaV1Db<FileBackend>> = OnceCell::new();
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())
@ -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 id: UtxoIdV10,
pub amount: SourceAmount,
@ -256,9 +292,13 @@ mod tests {
documents::transaction::TransactionDocumentV10Stringified,
documents_parser::prelude::FromStringObject,
};
use once_cell::sync::Lazy;
static TESTS_MUTEX: Lazy<parking_lot::Mutex<()>> = Lazy::new(|| parking_lot::Mutex::new(()));
#[test]
fn test_gva_apply_block() -> anyhow::Result<()> {
let _ = TESTS_MUTEX.lock();
let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?;
let s1 = WalletScriptV10::single_sig(PublicKey::from_base58(
@ -272,6 +312,7 @@ mod tests {
version: 10,
median_time: 5_243,
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()],
inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()),
signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(),
@ -430,6 +471,7 @@ mod tests {
#[test]
fn test_gva_revert_block() -> anyhow::Result<()> {
let _ = TESTS_MUTEX.lock();
let gva_db = GvaV1Db::<Mem>::open(MemConf::default())?;
let s1 = WalletScriptV10::single_sig(PublicKey::from_base58(
@ -443,6 +485,7 @@ mod tests {
version: 10,
median_time: 5_243,
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()],
inner_hash: Some("0000000A65A12DB95B3153BCD05DB4D5C30CC7F0B1292D9FFBC3DE67F72F6040".to_owned()),
signature: "7B0hvcfajE2G8nBLp0vLVaQcQdQIyli21Gu8F2l+nimKHRe+fUNi+MWd1e/u29BYZa+RZ1yxhbHIbFzytg7fAA==".to_owned(),