Skip to content

Commit

Permalink
docs(network code example): send raw fragment to node
Browse files Browse the repository at this point in the history
toy network client for sending raw vote fragments
  • Loading branch information
cong-or committed Nov 18, 2023
1 parent 25906a4 commit cbed21d
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 7 deletions.
136 changes: 136 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions src/sign/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ serde_json = "1.0"
serde_yaml = "0.8.17"
rand = "0.8.3"
bech32 = "0.8"


rand_core = { version = "0.5.1", default-features = false }


ed25519-dalek = "1.0.1"
ed25519-dalek = "1.0.1"
reqwest = { version = "*", features = ["blocking","json"] }
4 changes: 2 additions & 2 deletions src/sign/src/fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ mod tests {
use jormungandr_lib::interfaces::AccountIdentifier;

#[test]
fn test_fragment_generation() {
fn fragment_generation() {
let mut csprng = OsRng;

// User key for signing witness
Expand Down Expand Up @@ -289,7 +289,7 @@ mod tests {
}

#[test]
fn test_encrypted_vote_generation() {
fn encrypted_vote_generation() {
let mut rng = ChaCha20Rng::from_seed([0u8; 32]);

// vote plan id
Expand Down
1 change: 1 addition & 0 deletions src/sign/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::error::Error;
use crate::fragment::{compose_encrypted_vote_part, generate_vote_fragment};

mod fragment;
mod network;

///
/// Args defines and declares CLI behaviour within the context of clap
Expand Down
141 changes: 141 additions & 0 deletions src/sign/src/network.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//!
//! Test code
//! Example code on how to send a raw vote fragment
//!

use color_eyre::Result;

use reqwest::blocking::Client;
use reqwest::header::HeaderMap;

use reqwest::Url;
use serde::Deserialize as Deser;
use serde::Serialize as Ser;

use reqwest::header::{HeaderValue, CONTENT_TYPE};

/// Node responds with yay or nay and associated metadata such as fragment id hash
#[derive(Ser, Deser, Debug)]
pub struct NodeResponse {
pub accepted: Vec<String>,
pub rejected: Vec<Rejected>,
}

/// Vote fragment rejected
#[derive(Ser, Deser, Debug)]
pub struct Rejected {
pub id: String,
pub reason: String,
}

/// Vote fragment accepted
#[derive(Ser, Deser, Debug)]
pub struct Accepted {
pub id: String,
}

/// Simple toy network network client for sending vote fragments
pub struct Network {
pub client: Client,
/// URL for posting a signed vote fragment
/// e.g https://core.projectcatalyst.io/api/v0/message
pub fragment_url: String,
}

impl Network {
pub fn new(fragment_url: String) -> Self {
Self {
client: Client::new(),
fragment_url,
}
}

// Send single vote fragment to node
pub fn send_fragment(
&self,
fragment: Vec<u8>,
) -> Result<reqwest::blocking::Response, Box<dyn std::error::Error>> {
Ok(self
.client
.post(Url::parse(&self.fragment_url)?)
.headers(self.construct_headers())
.body(fragment)
.send()?)
}

/// construct headers for octet-stream
fn construct_headers(&self) -> HeaderMap {
let mut headers = HeaderMap::new();
headers.insert(
CONTENT_TYPE,
HeaderValue::from_static("application/octet-stream"),
);
headers
}
}

mod tests {
use crate::network::{Network, NodeResponse};
use ed25519_dalek::Keypair;
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
use rand_core::OsRng;

use crate::fragment::{compose_encrypted_vote_part, generate_vote_fragment};
use chain_vote::{Crs, ElectionPublicKey, MemberCommunicationKey, MemberState};

fn create_election_pub_key(shared_string: String, mut rng: ChaCha20Rng) -> ElectionPublicKey {
let h = Crs::from_hash(shared_string.as_bytes());
let mc1 = MemberCommunicationKey::new(&mut rng);
let mc = [mc1.to_public()];
let threshold = 1;
let m1 = MemberState::new(&mut rng, threshold, &h, &mc, 0);
let participants = vec![m1.public_key()];
ElectionPublicKey::from_participants(&participants)
}

#[test]
fn send_raw_fragment() {
let client = Network::new("https://core.dev.projectcatalyst.io/api/v0/message".to_string());

let mut csprng = OsRng;

// User key for signing witness
let keypair = Keypair::generate(&mut csprng);

let mut rng = ChaCha20Rng::from_seed([0u8; 32]);

// vote plan id
let vote_plan_id =
"36ad42885189a0ac3438cdb57bc8ac7f6542e05a59d1f2e4d1d38194c9d4ac7b".to_owned();

// election public key
let ek = create_election_pub_key(vote_plan_id.clone(), rng.clone());

// vote
let vote = chain_vote::Vote::new(2, 1_usize).unwrap();

let crs = chain_vote::Crs::from_hash(vote_plan_id.as_bytes());

let (ciphertexts, proof) = ek.encrypt_and_prove_vote(&mut rng, &crs, vote);
let (proof, encrypted_vote) =
compose_encrypted_vote_part(ciphertexts.clone(), proof).unwrap();

// generate fragment
let fragment_bytes = generate_vote_fragment(
keypair,
encrypted_vote,
proof,
5,
&hex::decode(vote_plan_id.clone()).unwrap(),
560,
120,
)
.unwrap();

let response = client.send_fragment(fragment_bytes).unwrap();

let resp_json = response.json::<NodeResponse>().unwrap();

println!("{:?}", resp_json);
}
}

0 comments on commit cbed21d

Please sign in to comment.