Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • network/gdev-800 protected
  • cgeek/issue-297-cpu
  • gdev-800-tests
  • update-docker-compose-rpc-squid-names
  • fix-252
  • 1000i100-test
  • hugo/tmp-0.9.1
  • network/gdev-803 protected
  • hugo/endpoint-gossip
  • network/gdev-802 protected
  • hugo/distance-precompute
  • network/gdev-900 protected
  • tuxmain/anonymous-tx
  • debug/podman
  • hugo/195-doc
  • hugo/195-graphql-schema
  • hugo-tmp-dockerfile-cache
  • release/client-800.2 protected
  • release/runtime-800 protected
  • gdev-900-0.10.1 protected
  • gdev-900-0.10.0 protected
  • gdev-900-0.9.2 protected
  • gdev-800-0.8.0 protected
  • gdev-900-0.9.1 protected
  • gdev-900-0.9.0 protected
  • gdev-803 protected
  • gdev-802 protected
  • runtime-801 protected
  • gdev-800 protected
  • runtime-800-bis protected
  • runtime-800 protected
  • runtime-800-backup protected
  • runtime-701 protected
  • runtime-700 protected
  • runtime-600 protected
  • runtime-500 protected
  • v0.4.1 protected
  • runtime-401 protected
  • v0.4.0 protected
40 results

distance_precompute.rs

Blame
  • distance_precompute.rs 5.18 KiB
    use api::IdtyIndex;
    use distance_oracle::api;
    use fnv::{FnvHashMap, FnvHashSet};
    use log::debug;
    use std::{io::Write, path::PathBuf};
    
    // computes distance result for all identities with status other than Revoked
    // this allows to have a recent estimate of the distance computation
    
    use clap::Parser;
    
    #[derive(Debug, clap::Parser)]
    struct Cli {
        #[clap(short = 'd', long, default_value = "/tmp/duniter/chains/gdev/distance")]
        evaluation_result_dir: String,
        #[clap(short = 'u', long, default_value = "ws://127.0.0.1:9944")]
        rpc_url: String,
        /// Log level (off, error, warn, info, debug, trace)
        #[clap(short = 'l', long, default_value = "info")]
        log: log::LevelFilter,
    }
    
    //
    #[derive(serde::Serialize)]
    struct PrecomputationResult {
        block: sp_core::H256,
        results: FnvHashMap<IdtyIndex, u32>,
        referees: u32,
    }
    
    #[tokio::main]
    async fn main() {
        let cli = Cli::parse();
    
        simple_logger::SimpleLogger::new()
            .with_level(cli.log)
            .init()
            .unwrap();
    
        let client = &distance_oracle::api::client(cli.rpc_url.clone()).await;
        let parent_hash = api::parent_hash(client).await; // get hash of recent block
        let max_depth = api::max_referee_distance(client).await; // get param
        let evaluation_block = parent_hash;
    
        // get certs and member iterators
        let mut certs_iter = api::cert_iter(client, evaluation_block).await;
        let mut members_iter = api::member_iter(client, evaluation_block).await;
    
        // initialize hashmaps
        // member idty -> issued certs count (will only retain referees)
        let mut members = FnvHashMap::<IdtyIndex, u32>::default();
    
        // idty -> received certs (collects once from iterator and is passed to distance function)
        let mut received_certs = FnvHashMap::<IdtyIndex, Vec<IdtyIndex>>::default();
    
        // collect all members
        while let Some(member_idty) = members_iter
            .next()
            .await
            .expect("Cannot fetch next members")
        {
            members.insert(member_idty, 0);
        }
    
        // compute certification threshold as a function of the total member count
        let min_certs_for_referee = (members.len() as f32).powf(1. / (max_depth as f32)).ceil() as u32;
    
        // collect certifications and updates members map at the same time
        while let Some((receiver, issuers)) = certs_iter
            .next()
            .await
            .expect("Cannot fetch next certification")
        {
            if (issuers.len() as u32) < min_certs_for_referee {
                // This member is not referee (not enough received certs)
                members.remove(&receiver);
            }
            for (issuer, _removable_on) in issuers.iter() {
                if let Some(issued_certs) = members.get_mut(issuer) {
                    // update number of issued certs
                    *issued_certs += 1;
                }
            }
            // collect certifications
            received_certs.insert(
                receiver,
                issuers
                    .into_iter()
                    .map(|(issuer, _removable_on)| issuer)
                    .collect(),
            );
        }
    
        // Only retain referees
        members.retain(|_idty, issued_certs| *issued_certs >= min_certs_for_referee);
        let referees = members;
    
        // initialize map of distance results
        let mut results = FnvHashMap::<IdtyIndex, u32>::default();
    
        // compute all distances
        received_certs.keys().into_iter().for_each(|idty| {
            results.insert(
                *idty,
                distance_rule(&received_certs, &referees, max_depth, *idty) as u32,
            );
        });
    
        // structure
        let precomputation_result = PrecomputationResult {
            block: evaluation_block,
            results: results,
            referees: referees.len() as u32,
        };
    
        // ---- SAVE
        let evaluation_result_path =
            Into::<PathBuf>::into(cli.evaluation_result_dir).join("todo-block-number".to_string());
        debug!("Saving distance evaluation result to file `{evaluation_result_path:?}`");
        let mut evaluation_result_file = std::fs::OpenOptions::new()
            .write(true)
            .create_new(true)
            .open(&evaluation_result_path)
            .unwrap_or_else(|e| {
                panic!(
                    "Cannot open distance evaluation result file `{evaluation_result_path:?}`: {e:?}"
                )
            });
        evaluation_result_file
            .write_all(
                &serde_json::to_vec( &precomputation_result).expect("Cannot serialize result"),
            )
            .unwrap_or_else(|e| {
                panic!(
                    "Cannot write distance evaluation result to file `{evaluation_result_path:?}`: {e:?}"
                )
            });
    }
    
    // alternative function which returns number of reached referees
    fn distance_rule(
        received_certs: &FnvHashMap<IdtyIndex, Vec<IdtyIndex>>,
        referees: &FnvHashMap<IdtyIndex, u32>,
        depth: u32,
        idty: IdtyIndex,
    ) -> usize {
        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_oracle::distance_rule_recursive(
            received_certs,
            referees,
            idty,
            &mut accessible_referees,
            &mut known_idties,
            depth,
        );
        accessible_referees.len()
    }