feat(db): attribute a wot_id to each identity
This commit is contained in:
parent
4a7d3270df
commit
6d7a35dd8b
7 changed files with 90 additions and 16 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1025,6 +1025,7 @@ dependencies = [
|
||||||
"lz4_flex",
|
"lz4_flex",
|
||||||
"maplit",
|
"maplit",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"parking_lot",
|
||||||
"resiter",
|
"resiter",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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())?;
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue