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

feat: distance

parent 81476521
No related branches found
No related tags found
1 merge request!105Distance Oracle
......@@ -1571,6 +1571,7 @@ dependencies = [
"clap 4.1.4",
"dubp-wot",
"flate2",
"fnv",
"num-traits",
"parity-scale-codec",
"rayon",
......@@ -2035,7 +2036,7 @@ checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"redox_syscall 0.2.16",
"windows-sys 0.42.0",
]
......@@ -4287,9 +4288,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "lock_api"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
......@@ -5008,11 +5009,11 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.17.0"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
dependencies = [
"parking_lot_core 0.9.7",
"parking_lot_core 0.9.8",
]
[[package]]
......@@ -5813,7 +5814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core 0.9.7",
"parking_lot_core 0.9.8",
]
[[package]]
......@@ -5825,22 +5826,22 @@ dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
"redox_syscall 0.2.16",
"smallvec",
"winapi 0.3.9",
]
[[package]]
name = "parking_lot_core"
version = "0.9.7"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"redox_syscall 0.3.5",
"smallvec",
"windows-sys 0.45.0",
"windows-targets 0.48.1",
]
[[package]]
......@@ -6462,6 +6463,15 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.3"
......@@ -6469,7 +6479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.8",
"redox_syscall",
"redox_syscall 0.2.16",
"thiserror",
]
......@@ -9399,7 +9409,7 @@ dependencies = [
"cfg-if 1.0.0",
"fastrand",
"libc",
"redox_syscall",
"redox_syscall 0.2.16",
"remove_dir_all",
"winapi 0.3.9",
]
......@@ -10554,12 +10564,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_gnullvm 0.42.1",
"windows_aarch64_msvc 0.42.1",
"windows_i686_gnu 0.42.1",
"windows_i686_msvc 0.42.1",
"windows_x86_64_gnu 0.42.1",
"windows_x86_64_gnullvm",
"windows_x86_64_gnullvm 0.42.1",
"windows_x86_64_msvc 0.42.1",
]
......@@ -10569,7 +10579,7 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
"windows-targets 0.42.1",
]
[[package]]
......@@ -10578,21 +10588,42 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_gnullvm 0.42.1",
"windows_aarch64_msvc 0.42.1",
"windows_i686_gnu 0.42.1",
"windows_i686_msvc 0.42.1",
"windows_x86_64_gnu 0.42.1",
"windows_x86_64_gnullvm",
"windows_x86_64_gnullvm 0.42.1",
"windows_x86_64_msvc 0.42.1",
]
[[package]]
name = "windows-targets"
version = "0.48.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.34.0"
......@@ -10611,6 +10642,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.34.0"
......@@ -10629,6 +10666,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.34.0"
......@@ -10647,6 +10690,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.34.0"
......@@ -10665,12 +10714,24 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.34.0"
......@@ -10689,6 +10750,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winreg"
version = "0.10.1"
......
......@@ -10,6 +10,7 @@ edition = "2021"
sp-distance = { path = "../primitives/distance" }
codec = { package = "parity-scale-codec", version = "3.1.5" }
fnv = "1.0.7"
num-traits = "0.2.15"
rayon = "1.7.0"
sp-core = { git = "https://github.com/duniter/substrate.git", branch = "duniter-substrate-v0.9.32" }
......
// Copyright 2023 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
use crate::{
gdev,
gdev::runtime_types::{
runtime,
runtime::runtime_types::{
pallet_distance::median::MedianAcc,
sp_arithmetic::per_things::Perbill,
sp_core::bounded::{bounded_btree_set::BoundedBTreeSet, bounded_vec::BoundedVec},
......@@ -8,8 +24,9 @@ use crate::{
};
use sp_core::H256;
use subxt::storage::StorageKey;
pub type Client = subxt::OnlineClient<crate::GdevConfig>;
pub type Client = subxt::OnlineClient<crate::RuntimeConfig>;
pub type AccountId = subxt::ext::sp_runtime::AccountId32;
pub type IdtyIndex = u32;
pub type EvaluationPool<AccountId, IdtyIndex> = (
......@@ -24,7 +41,7 @@ pub async fn client(rpc_url: String) -> Client {
pub async fn parent_hash(client: &Client) -> H256 {
client
.storage()
.fetch(&gdev::storage().system().parent_hash(), None)
.fetch(&runtime::storage().system().parent_hash(), None)
.await
.unwrap()
.unwrap()
......@@ -34,7 +51,7 @@ pub async fn current_session(client: &Client, parent_hash: H256) -> u32 {
client
.storage()
.fetch(
&gdev::storage().session().current_index(),
&runtime::storage().session().current_index(),
Some(parent_hash),
)
.await
......@@ -51,9 +68,9 @@ pub async fn current_pool(
.storage()
.fetch(
&match current_session % 3 {
0 => gdev::storage().distance().evaluation_pool1(),
1 => gdev::storage().distance().evaluation_pool2(),
2 => gdev::storage().distance().evaluation_pool0(),
0 => runtime::storage().distance().evaluation_pool1(),
1 => runtime::storage().distance().evaluation_pool2(),
2 => runtime::storage().distance().evaluation_pool0(),
_ => unreachable!("n%3<3"),
},
Some(parent_hash),
......@@ -66,7 +83,7 @@ pub async fn evaluation_block(client: &Client, parent_hash: H256) -> H256 {
client
.storage()
.fetch(
&gdev::storage().distance().evaluation_block(),
&runtime::storage().distance().evaluation_block(),
Some(parent_hash),
)
.await
......@@ -74,40 +91,74 @@ pub async fn evaluation_block(client: &Client, parent_hash: H256) -> H256 {
.unwrap()
}
pub async fn member_iter(
client: &Client,
evaluation_block: H256,
) -> subxt::storage::KeyIter<
crate::GdevConfig,
Client,
subxt::metadata::DecodeStaticType<gdev::runtime_types::sp_membership::MembershipData<u32>>,
> {
pub async fn member_iter(client: &Client, evaluation_block: H256) -> MemberIter {
MemberIter(
client
.storage()
.iter(
gdev::storage().membership().membership(0),
runtime::storage().membership().membership(0),
100,
Some(evaluation_block),
)
.await
.unwrap()
.unwrap(),
)
}
pub async fn cert_iter(
client: &Client,
evaluation_block: H256,
) -> subxt::storage::KeyIter<
crate::GdevConfig,
pub struct MemberIter(
subxt::storage::KeyIter<
crate::RuntimeConfig,
Client,
subxt::metadata::DecodeStaticType<Vec<(u32, u32)>>,
> {
subxt::metadata::DecodeStaticType<
runtime::runtime_types::sp_membership::MembershipData<u32>,
>,
>,
);
impl MemberIter {
pub async fn next(&mut self) -> Result<Option<IdtyIndex>, subxt::error::Error> {
Ok(self
.0
.next()
.await?
.map(|(storage_key, _membership_data)| idty_id_from_storage_key(&storage_key)))
}
}
pub async fn cert_iter(client: &Client, evaluation_block: H256) -> CertIter {
CertIter(
client
.storage()
.iter(
gdev::storage().cert().certs_by_receiver(0),
runtime::storage().cert().certs_by_receiver(0),
100,
Some(evaluation_block),
)
.await
.unwrap()
.unwrap(),
)
}
pub struct CertIter(
subxt::storage::KeyIter<
crate::RuntimeConfig,
Client,
subxt::metadata::DecodeStaticType<Vec<(IdtyIndex, u32)>>,
>,
);
impl CertIter {
pub async fn next(
&mut self,
) -> Result<Option<(IdtyIndex, Vec<(IdtyIndex, u32)>)>, subxt::error::Error> {
Ok(self
.0
.next()
.await?
.map(|(storage_key, issuers)| (idty_id_from_storage_key(&storage_key), issuers)))
}
}
fn idty_id_from_storage_key(storage_key: &StorageKey) -> IdtyIndex {
u32::from_le_bytes(storage_key.as_ref()[40..44].try_into().unwrap())
}
// Copyright 2023 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
#[cfg(not(test))]
mod api;
pub mod api;
#[cfg(test)]
mod mock;
pub mod mock;
#[cfg(test)]
mod tests;
#[cfg(test)]
use mock as api;
pub use mock as api;
use api::{AccountId, IdtyIndex};
use codec::Encode;
use fnv::{FnvHashMap, FnvHashSet};
use rayon::iter::IntoParallelRefIterator;
use rayon::iter::ParallelIterator;
use std::collections::{HashMap, HashSet};
use std::io::Write;
use std::path::PathBuf;
use subxt::storage::StorageKey;
// TODO select metadata file using features
#[subxt::subxt(runtime_metadata_path = "../resources/metadata.scale")]
pub mod gdev {}
pub mod runtime {}
pub enum GdevConfig {}
impl subxt::config::Config for GdevConfig {
pub enum RuntimeConfig {}
impl subxt::config::Config for RuntimeConfig {
type Index = u32;
type BlockNumber = u32;
type Hash = sp_core::H256;
......@@ -71,8 +87,8 @@ impl Default for Settings {
}
}
pub async fn run_and_save(settings: Settings) {
let Some((evaluation, current_session, evaluation_result_path)) = run(&settings, true).await else {return};
pub async fn run_and_save(client: &api::Client, settings: Settings) {
let Some((evaluation, current_session, evaluation_result_path)) = run(client, &settings, true).await else {return};
let mut evaluation_result_file = std::fs::OpenOptions::new()
.write(true)
......@@ -108,17 +124,16 @@ pub async fn run_and_save(settings: Settings) {
/// Returns `(evaluation, current_session, evaluation_result_path)`
pub async fn run(
client: &api::Client,
settings: &Settings,
handle_fs: bool,
) -> Option<(Vec<sp_runtime::Perbill>, u32, PathBuf)> {
let client = api::client(settings.rpc_url.clone()).await;
let parent_hash = api::parent_hash(&client).await;
let parent_hash = api::parent_hash(client).await;
let current_session = api::current_session(&client, parent_hash).await;
let current_session = api::current_session(client, parent_hash).await;
// Fetch the pending identities
let Some(evaluation_pool) = api::current_pool(&client, parent_hash, current_session).await
let Some(evaluation_pool) = api::current_pool(client, parent_hash, current_session).await
else {
println!("Pool does not exist");
return None
......@@ -144,14 +159,14 @@ pub async fn run(
std::fs::create_dir_all(&settings.evaluation_result_dir).unwrap();
}
let evaluation_block = api::evaluation_block(&client, parent_hash).await;
let evaluation_block = api::evaluation_block(client, parent_hash).await;
// member idty -> issued certs
let mut members = HashMap::<IdtyIndex, u32>::new();
let mut members = FnvHashMap::<IdtyIndex, u32>::default();
let mut members_iter = api::member_iter(&client, evaluation_block).await;
while let Some((member_idty, _membership_expire)) = members_iter.next().await.unwrap() {
members.insert(idty_id_from_storage_key(&member_idty), 0);
let mut members_iter = api::member_iter(client, evaluation_block).await;
while let Some(member_idty) = members_iter.next().await.unwrap() {
members.insert(member_idty, 0);
}
let min_certs_for_referee = (members.len() as f32)
......@@ -159,22 +174,19 @@ pub async fn run(
.ceil() as u32;
// idty -> received certs
let mut received_certs = HashMap::<IdtyIndex, Vec<IdtyIndex>>::new();
let mut received_certs = FnvHashMap::<IdtyIndex, Vec<IdtyIndex>>::default();
let mut certs_iter = api::cert_iter(&client, evaluation_block).await;
let mut certs_iter = api::cert_iter(client, evaluation_block).await;
while let Some((receiver, issuers)) = certs_iter.next().await.unwrap() {
let receiver = idty_id_from_storage_key(&receiver);
// Update members' issued certs count
if issuers.len() as u32 >= min_certs_for_referee {
if (issuers.len() as u32) < min_certs_for_referee {
// This member is not referee
members.remove(&receiver);
}
for (issuer, _removable_on) in issuers.iter() {
if let Some(issued_certs) = members.get_mut(issuer) {
*issued_certs += 1;
}
}
} else {
// This member is not referee
members.remove(&receiver);
}
received_certs.insert(
receiver,
issuers
......@@ -185,7 +197,6 @@ pub async fn run(
}
// Only retain referees
// TODO benchmark: can it be faster? (maybe using drain_filter)
members.retain(|_idty, issued_certs| *issued_certs >= min_certs_for_referee);
let referees = members;
......@@ -194,66 +205,82 @@ pub async fn run(
.0
.as_slice()
.par_iter()
.map(|(idty, _)| {
sp_runtime::Perbill::from_rational(
distance_rule(&received_certs, &referees, settings.max_depth, *idty),
referees.len() as u32,
)
})
.map(|(idty, _)| distance_rule(&received_certs, &referees, settings.max_depth, *idty))
.collect();
Some((evaluation, current_session, evaluation_result_path))
}
fn distance_rule_recursive(
received_certs: &HashMap<IdtyIndex, Vec<IdtyIndex>>,
referees: &HashMap<IdtyIndex, u32>,
received_certs: &FnvHashMap<IdtyIndex, Vec<IdtyIndex>>,
referees: &FnvHashMap<IdtyIndex, u32>,
idty: IdtyIndex,
accessible_referees: &mut std::collections::HashSet<IdtyIndex>,
accessible_referees: &mut FnvHashSet<IdtyIndex>,
known_idties: &mut FnvHashMap<IdtyIndex, u32>,
depth: u32,
) {
// Do not re-explore identities that have already been explored at least as deeply
match known_idties.entry(idty) {
std::collections::hash_map::Entry::Occupied(mut entry) => {
if *entry.get() >= depth {
return;
} else {
*entry.get_mut() = depth;
}
}
std::collections::hash_map::Entry::Vacant(entry) => {
entry.insert(depth);
}
}
// If referee, add it to the list
if referees.contains_key(&idty) {
accessible_referees.insert(idty);
}
// If reached the maximum distance, stop exploring
if depth == 0 {
return;
}
for &certifier in received_certs.get(&idty).expect("unreachable").iter() {
// Explore certifiers
for &certifier in received_certs.get(&idty).unwrap_or(&vec![]).iter() {
distance_rule_recursive(
received_certs,
referees,
certifier,
accessible_referees,
known_idties,
depth - 1,
);
}
}
/// Returns `(nb_accessible_referees, nb_referees)`
fn distance_rule(
received_certs: &HashMap<IdtyIndex, Vec<IdtyIndex>>,
referees: &HashMap<IdtyIndex, u32>,
received_certs: &FnvHashMap<IdtyIndex, Vec<IdtyIndex>>,
referees: &FnvHashMap<IdtyIndex, u32>,
depth: u32,
idty: IdtyIndex,
) -> u32 {
let mut accessible_referees = HashSet::<u32>::new();
) -> sp_runtime::Perbill {
let mut accessible_referees =
FnvHashSet::<IdtyIndex>::with_capacity_and_hasher(referees.len(), Default::default());
let mut known_idties =
FnvHashMap::<IdtyIndex, u32>::with_capacity_and_hasher(referees.len(), Default::default());
distance_rule_recursive(
received_certs,
referees,
idty,
&mut accessible_referees,
depth + 1,
&mut known_idties,
depth,
);
accessible_referees.len() as u32
if referees.contains_key(&idty) {
sp_runtime::Perbill::from_rational(
accessible_referees.len() as u32 - 1,
referees.len() as u32 - 1,
)
} else {
sp_runtime::Perbill::from_rational(accessible_referees.len() as u32, referees.len() as u32)
}
fn idty_id_from_storage_key(storage_key: &StorageKey) -> IdtyIndex {
u32::from_le_bytes(storage_key.as_ref()[40..44].try_into().unwrap())
}
/*
impl num_traits::Pow<usize> for Perbill {}
impl std::ops::Div<Perbill> for Perbill {}
impl num_traits::Bounded for Perbill {}
impl Ord for Perbill {}
impl Eq for Perbill {}
impl PerThing for Perbill {}*/
// Copyright 2023 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
use clap::Parser;
#[derive(Debug, clap::Parser)]
......@@ -15,10 +31,13 @@ struct Cli {
async fn main() {
let cli = Cli::parse();
distance_oracle::run_and_save(distance_oracle::Settings {
distance_oracle::run_and_save(
&distance_oracle::api::client(cli.rpc_url.clone()).await,
distance_oracle::Settings {
evaluation_result_dir: cli.evaluation_result_dir.into(),
max_depth: cli.max_depth,
rpc_url: cli.rpc_url,
})
},
)
.await;
}
use crate::gdev::runtime_types::{
// Copyright 2023 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
use crate::runtime::runtime_types::{
pallet_distance::median::MedianAcc, sp_arithmetic::per_things::Perbill,
};
use dubp_wot::{data::rusty::RustyWebOfTrust, WebOfTrust, WotId};
use sp_core::H256;
use std::collections::BTreeSet;
pub struct Client;
pub struct Client {
wot: RustyWebOfTrust,
pub pool_len: usize,
}
pub type AccountId = subxt::ext::sp_runtime::AccountId32;
pub type IdtyIndex = u32;
pub type EvaluationPool<AccountId, IdtyIndex> =
((Vec<(IdtyIndex, MedianAcc<Perbill>)>,), BTreeSet<AccountId>);
pub async fn client(_rpc_url: String) -> Client {
Client
unimplemented!()
}
pub fn client_from_wot(wot: RustyWebOfTrust) -> Client {
Client { wot, pool_len: 1 }
}
pub async fn parent_hash(_client: &Client) -> H256 {
......@@ -24,42 +48,71 @@ pub async fn current_session(_client: &Client, _parent_hash: H256) -> u32 {
}
pub async fn current_pool(
_client: &Client,
client: &Client,
_parent_hash: H256,
_current_session: u32,
) -> Option<EvaluationPool<AccountId, IdtyIndex>> {
Some(((vec![],), std::collections::BTreeSet::new()))
Some((
(client
.wot
.get_enabled()
.into_iter()
.chain(client.wot.get_disabled().into_iter())
.zip(0..client.pool_len)
.map(|(wot_id, _)| {
(wot_id.0 as IdtyIndex, unsafe {
std::mem::transmute((Vec::<()>::new(), Option::<u32>::None, 0))
})
})
.collect(),),
std::collections::BTreeSet::new(),
))
}
pub async fn evaluation_block(_client: &Client, _parent_hash: H256) -> H256 {
Default::default()
}
pub async fn member_iter(
_client: &Client,
_evaluation_block: H256,
) -> KeyIter<(subxt::storage::StorageKey, ())> {
KeyIter::new(Vec::new())
pub async fn member_iter(client: &Client, _evaluation_block: H256) -> MemberIter {
MemberIter(client.wot.get_enabled().into_iter())
}
pub async fn cert_iter(
_client: &Client,
_evaluation_block: H256,
) -> KeyIter<(subxt::storage::StorageKey, Vec<(u32, u32)>)> {
KeyIter::new(Vec::new())
}
pub struct MemberIter(std::vec::IntoIter<WotId>);
pub struct KeyIter<T>(std::vec::IntoIter<T>);
impl MemberIter {
pub async fn next(&mut self) -> Result<Option<IdtyIndex>, subxt::error::Error> {
Ok(self.0.next().map(|wot_id| wot_id.0 as u32))
}
}
impl<T> KeyIter<T> {
fn new(items: Vec<T>) -> Self {
Self(items.into_iter())
pub async fn cert_iter(client: &Client, _evaluation_block: H256) -> CertIter {
CertIter(
client
.wot
.get_enabled()
.iter()
.chain(client.wot.get_disabled().iter())
.map(|wot_id| {
(
wot_id.0 as IdtyIndex,
client
.wot
.get_links_source(*wot_id)
.unwrap_or_default()
.into_iter()
.map(|wot_id| (wot_id.0 as IdtyIndex, 0))
.collect::<Vec<(IdtyIndex, u32)>>(),
)
})
.collect::<Vec<_>>()
.into_iter(),
)
}
pub async fn next(&mut self) -> Result<Option<T>, subxt::error::Error>
where
T: Clone,
{
pub struct CertIter(std::vec::IntoIter<(IdtyIndex, Vec<(IdtyIndex, u32)>)>);
impl CertIter {
pub async fn next(&mut self) -> Result<Option<(u32, Vec<(u32, u32)>)>, subxt::error::Error> {
Ok(self.0.next())
}
}
use dubp_wot::data::rusty::RustyWebOfTrust;
// Copyright 2023 Axiom-Team
//
// This file is part of Duniter-v2S.
//
// Duniter-v2S is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// Duniter-v2S is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
use dubp_wot::{
data::rusty::RustyWebOfTrust, operations::distance::DistanceCalculator, WebOfTrust,
};
use flate2::read::ZlibDecoder;
use sp_runtime::Perbill;
use std::{fs::File, io::Read};
#[tokio::test]
#[ignore = "long to execute"]
async fn test_distance_against_v1() {
let _wot = wot_from_v1_file();
let wot = wot_from_v1_file();
let n = wot.size();
let max_depth = 5;
let min_certs_for_referee = (wot.get_enabled().len() as f32).powf(1. / 5.).ceil() as u32;
// Reference implementation
let ref_calculator = dubp_wot::operations::distance::RustyDistanceCalculator;
let t_a = std::time::Instant::now();
let ref_results: Vec<Perbill> = wot
.get_enabled()
.into_iter()
.chain(wot.get_disabled().into_iter())
.zip(0..n)
.map(|(i, _)| {
let result = ref_calculator
.compute_distance(
&wot,
dubp_wot::operations::distance::WotDistanceParameters {
node: i,
sentry_requirement: min_certs_for_referee,
step_max: max_depth,
x_percent: 0.8,
},
)
.unwrap();
Perbill::from_rational(result.success, result.sentries)
})
.collect();
println!("ref time: {}", t_a.elapsed().as_millis());
// Our implementation
let mut client = crate::api::client_from_wot(wot);
client.pool_len = n;
let t_a = std::time::Instant::now();
let results = crate::run(
&client,
&crate::Settings {
max_depth,
..Default::default()
},
false,
)
.await
.unwrap();
println!("new time: {}", t_a.elapsed().as_millis());
assert_eq!(results.0.len(), n);
let mut errors: Vec<_> = results
.0
.iter()
.zip(ref_results.iter())
.map(|(r, r_ref)| r.deconstruct() as i64 - r_ref.deconstruct() as i64)
.collect();
errors.sort_unstable();
println!(
"Error: {:?} / {:?} / {:?} / {:?} / {:?} (min / 1Q / med / 3Q / max)",
errors[0],
errors[errors.len() / 4],
errors[errors.len() / 2],
errors[errors.len() * 3 / 4],
errors[errors.len() - 1]
);
crate::run(&Default::default(), false).await;
let correct_results = results
.0
.iter()
.zip(ref_results.iter())
.map(|(r, r_ref)| (r == r_ref) as usize)
.sum::<usize>();
println!("Correct results: {correct_results} / {n}");
assert_eq!(correct_results, n);
}
fn wot_from_v1_file() -> RustyWebOfTrust {
......
......@@ -46,6 +46,7 @@ pub async fn run_oracle(client: &Client, origin: AccountKeyring, rpc_url: String
let account_id: &AccountId32 = origin.account_id();
if let Some((distances, _current_session, _evaluation_result_path)) = distance_oracle::run(
&distance_oracle::api::client(rpc_url.clone()).await,
&distance_oracle::Settings {
evaluation_result_dir: PathBuf::default(),
max_depth: 5,
......@@ -64,21 +65,16 @@ pub async fn run_oracle(client: &Client, origin: AccountKeyring, rpc_url: String
client
.tx()
.create_signed(
&gdev::tx().sudo().sudo(/*gdev::runtime_types::gdev_runtime::RuntimeCall::UpgradeOrigin(gdev::runtime_types::pallet_upgrade_origin::pallet::Call::dispatch_as_root {
call: Box::new(*/gdev::runtime_types::gdev_runtime::RuntimeCall::Distance(
&gdev::tx().sudo().sudo(gdev::runtime_types::gdev_runtime::RuntimeCall::Distance(
gdev::runtime_types::pallet_distance::pallet::Call::force_update_evaluation {
evaluator: account_id.clone(),
computation_result:
gdev::runtime_types::sp_distance::ComputationResult {
distances: unsafe {
std::mem::transmute(distances)
distances: distances.into_iter().map(|res| unsafe{std::mem::transmute(res)}).collect(),
},
},
},
)/*)
})*/),
//&gdev::tx().upgrade_origin().dispatch_as_root(
//),
)
),
&origin,
BaseExtrinsicParamsBuilder::new(),
)
......
......@@ -513,11 +513,7 @@ async fn should_have_distance_ok(world: &mut DuniterWorld, who: String) -> Resul
.unwrap();
match world
.read(
&gdev::storage()
.distance()
.identities_distance_status(idty_id),
)
.read(&gdev::storage().distance().identity_distance_status(idty_id))
.await?
{
Some(gdev::runtime_types::pallet_distance::types::DistanceStatus::Valid) => Ok(()),
......
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment