-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: [email protected]
- Loading branch information
Showing
12 changed files
with
632 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[alias] | ||
lint = "clippy --all-targets --all-features -- -W clippy::pedantic -A clippy::missing_errors_doc -A clippy::module_name_repetitions" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
data | ||
target | ||
result |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "neurons" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
anyhow = "1.0.80" | ||
camino = "1.1.6" | ||
serde = { version = "1.0.197", features = ["derive"] } | ||
serde_json = "1.0.114" | ||
serde_repr = "0.1.18" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Neurons | ||
|
||
This code is an implementation of `neurons` | ||
from the [Neural Quorum Governance](https://stellarcommunityfund.gitbook.io/module-library). | ||
The data computed by this package is uploaded to the voting contract. | ||
|
||
This is the source code used to calculate voting powers for each neuron used in NQG mechanism. | ||
It also normalized the votes of voters (converts delegations to final votes) for them to be uploaded to the contract. | ||
|
||
## Inputs | ||
|
||
Neurons expect the inputs to be provided in `json` format. The inputs are loaded from `data/` directory. | ||
|
||
## Outputs | ||
|
||
Computed voting powers and normalized votes are written to `result/` directory. | ||
|
||
## Running | ||
|
||
```shell | ||
cargo run | ||
``` | ||
|
||
## Neurons | ||
|
||
### Assigned Reputation Neuron | ||
|
||
Assigns voting power based on voter discord rank. | ||
|
||
### Prior Voting History Neuron | ||
|
||
Assigns voting power based on rounds voter previously participated in. | ||
|
||
### Trust Graph Neuron | ||
|
||
Assigns voting power based on trust assigned to voter by other voters. | ||
It uses min-max normalized PageRank algorithm to compute the score. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
pub mod neurons; | ||
pub mod quorum; | ||
|
||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)] | ||
pub enum Vote { | ||
Yes, | ||
No, | ||
Delegate, | ||
Abstain, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use camino::Utf8Path; | ||
use neurons::neurons::assigned_reputation::AssignedReputationNeuron; | ||
use neurons::neurons::prior_voting_history::PriorVotingHistoryNeuron; | ||
use neurons::neurons::trust_graph::TrustGraphNeuron; | ||
use neurons::neurons::Neuron; | ||
use neurons::quorum::normalize_votes; | ||
use neurons::Vote; | ||
use serde::Serialize; | ||
use std::collections::{BTreeMap, HashMap}; | ||
use std::fs; | ||
|
||
pub const DECIMALS: i64 = 1_000_000_000_000_000_000; | ||
|
||
fn write_result<T>(file_name: &str, data: &T) | ||
where | ||
T: Serialize, | ||
{ | ||
let serialized = serde_json::to_string(&data).unwrap(); | ||
fs::write(file_name, serialized).unwrap(); | ||
} | ||
|
||
fn to_sorted_map<K, L>(data: HashMap<K, L>) -> BTreeMap<K, L> | ||
where | ||
K: Ord, | ||
{ | ||
data.into_iter().collect() | ||
} | ||
|
||
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)] | ||
fn to_fixed_point_decimal(val: f64) -> i128 { | ||
(val * DECIMALS as f64) as i128 | ||
} | ||
|
||
fn calculate_neuron_results(users: &[String], neurons: Vec<Box<dyn Neuron>>) { | ||
for neuron in neurons { | ||
let result = neuron.calculate_result(users); | ||
let result: HashMap<String, String> = result | ||
.into_iter() | ||
.map(|(key, value)| (key, to_fixed_point_decimal(value).to_string())) | ||
.collect(); | ||
let result = to_sorted_map(result); | ||
write_result(&format!("result/{}.json", neuron.name()), &result); | ||
} | ||
} | ||
|
||
fn main() { | ||
let path = Utf8Path::new("data/previous_rounds_for_users.json"); | ||
let prior_voting_history_neuron = PriorVotingHistoryNeuron::try_from_file(path).unwrap(); | ||
|
||
let path = Utf8Path::new("data/users_reputation.json"); | ||
let assigned_reputation_neuron = AssignedReputationNeuron::try_from_file(path).unwrap(); | ||
|
||
let path = Utf8Path::new("data/trusted_for_user.json"); | ||
let trust_graph_neuron = TrustGraphNeuron::try_from_file(path).unwrap(); | ||
|
||
let users_raw = fs::read_to_string("data/voters.json").unwrap(); | ||
let users: Vec<String> = serde_json::from_str(users_raw.as_str()).unwrap(); | ||
|
||
let votes_raw = fs::read_to_string("data/votes.json").unwrap(); | ||
let votes: HashMap<String, HashMap<String, Vote>> = | ||
serde_json::from_str(votes_raw.as_str()).unwrap(); | ||
let delegatees_for_user_raw = fs::read_to_string("data/delegatees_for_user.json").unwrap(); | ||
let delegatees_for_user: HashMap<String, Vec<String>> = | ||
serde_json::from_str(delegatees_for_user_raw.as_str()).unwrap(); | ||
let normalized_votes = normalize_votes(votes, &delegatees_for_user).unwrap(); | ||
write_result( | ||
"result/normalized_votes.json", | ||
&to_sorted_map(normalized_votes), | ||
); | ||
|
||
calculate_neuron_results( | ||
&users, | ||
vec![ | ||
Box::new(prior_voting_history_neuron), | ||
Box::new(assigned_reputation_neuron), | ||
Box::new(trust_graph_neuron), | ||
], | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use std::collections::HashMap; | ||
|
||
pub mod assigned_reputation; | ||
pub mod prior_voting_history; | ||
pub mod trust_graph; | ||
|
||
pub trait Neuron { | ||
fn name(&self) -> String; | ||
|
||
fn calculate_result(&self, users: &[String]) -> HashMap<String, f64>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use crate::neurons::Neuron; | ||
use anyhow::Result; | ||
use camino::Utf8Path; | ||
use serde_repr::Deserialize_repr; | ||
use std::collections::HashMap; | ||
use std::fs::File; | ||
use std::io::BufReader; | ||
|
||
#[derive(Deserialize_repr, Clone, Debug)] | ||
#[repr(i32)] | ||
pub enum ReputationTier { | ||
Unknown = -1, | ||
Verified = 0, | ||
Pathfinder = 1, | ||
Navigator = 2, | ||
Pilot = 3, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct AssignedReputationNeuron { | ||
users_reputation: HashMap<String, ReputationTier>, | ||
} | ||
|
||
impl AssignedReputationNeuron { | ||
pub fn try_from_file(path: &Utf8Path) -> Result<Self> { | ||
let file = File::open(path)?; | ||
let reader = BufReader::new(file); | ||
|
||
let users_reputation = serde_json::from_reader(reader)?; | ||
Ok(Self { users_reputation }) | ||
} | ||
} | ||
|
||
fn reputation_bonus(reputation_tier: &ReputationTier) -> f64 { | ||
match reputation_tier { | ||
ReputationTier::Unknown | ReputationTier::Verified => 0.0, | ||
ReputationTier::Pathfinder => 0.1, | ||
ReputationTier::Navigator => 0.2, | ||
ReputationTier::Pilot => 0.3, | ||
} | ||
} | ||
|
||
impl Neuron for AssignedReputationNeuron { | ||
fn name(&self) -> String { | ||
"assigned_reputation_neuron".to_string() | ||
} | ||
|
||
fn calculate_result(&self, users: &[String]) -> HashMap<String, f64> { | ||
let mut result = HashMap::new(); | ||
|
||
for user in users { | ||
let bonus = reputation_bonus(self.users_reputation.get(user).unwrap()); | ||
result.insert(user.into(), bonus); | ||
} | ||
|
||
result | ||
} | ||
} |
Oops, something went wrong.