Skip to content

Commit

Permalink
ran clippy, added github action to build and test
Browse files Browse the repository at this point in the history
  • Loading branch information
CluEleSsUK committed Dec 31, 2022
1 parent 078ca08 commit 9855eea
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 81 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: build and test
on:
pull_request:
branches: [ master ]
push:
branches: [ master ]

jobs:
build_and_test:
name: Rust project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- run: cargo fmt -- --check
- run: cargo clippy -- -Dwarnings
- run: cargo test -- --nocapture
- run: cargo build --release --all-features
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ A simple drand client implementation written in rust
- [ ] nicer error messages
- [ ] comprehensive testing
- [ ] rustdoc
- [ ] github actions for testing
- [x] github actions for testing
- [ ] examples
18 changes: 8 additions & 10 deletions src/bls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bls_signatures::{hash, PublicKey, Serialize, Signature, verify};
use crate::chain_info::ChainInfo;
use crate::SchemeError;
use bls_signatures::{hash, verify, PublicKey, Serialize, Signature};

pub trait BlsVerifiable {
fn signature(&self) -> &Vec<u8>;
Expand All @@ -11,20 +11,18 @@ pub(crate) fn bls_verify<B: BlsVerifiable>(info: &ChainInfo, beacon: B) -> Resul
let public_key = PublicKey::from_bytes(info.public_key.as_slice())
.map_err(|_| SchemeError::InvalidChainInfo)?;

let signature = Signature::from_bytes(&beacon.signature().as_slice())
let signature = Signature::from_bytes(beacon.signature().as_slice())
.map_err(|_| SchemeError::InvalidBeacon)?;

let bls_message_bytes = beacon.to_message()
let bls_message_bytes = beacon
.to_message()
.map(|bytes| sha256::digest(bytes.as_slice()))
.and_then(|hex_str| hex::decode(hex_str)
.map_err(|_| SchemeError::InvalidBeacon)
)?;

.and_then(|hex_str| hex::decode(hex_str).map_err(|_| SchemeError::InvalidBeacon))?;

let point_on_curve = hash(bls_message_bytes.as_slice());
if !verify(&signature, &[point_on_curve], &[public_key]) {
return Err(SchemeError::InvalidBeacon);
Err(SchemeError::InvalidBeacon)
} else {
Ok(beacon)
}

return Ok(beacon);
}
2 changes: 1 addition & 1 deletion src/chain_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ pub struct ChainInfo {
pub struct ChainInfoMetadata {
#[serde(alias = "beaconID")]
pub beacon_id: String,
}
}
28 changes: 16 additions & 12 deletions src/chained.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::io::{Write};
use crate::{bls, Scheme, SchemeError};
use crate::bls::BlsVerifiable;
use crate::chain_info::ChainInfo;
use crate::{bls, Scheme, SchemeError};
use serde::Deserialize;
use crate::bls::BlsVerifiable;
use std::io::Write;

#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct ChainedBeacon {
Expand All @@ -20,15 +20,19 @@ pub struct ChainedScheme {}

impl Scheme<ChainedBeacon> for ChainedScheme {
fn supports(&self, scheme_id: &str) -> bool {
return scheme_id.eq_ignore_ascii_case("pedersen-bls-chained");
scheme_id.eq_ignore_ascii_case("pedersen-bls-chained")
}

fn verify(&self, info: &ChainInfo, beacon: ChainedBeacon) -> Result<ChainedBeacon, SchemeError> {
fn verify(
&self,
info: &ChainInfo,
beacon: ChainedBeacon,
) -> Result<ChainedBeacon, SchemeError> {
if !self.supports(&info.scheme_id) {
return Err(SchemeError::InvalidScheme);
Err(SchemeError::InvalidScheme)
} else {
bls::bls_verify(info, beacon)
}

return bls::bls_verify(info, beacon);
}
}

Expand All @@ -44,9 +48,9 @@ impl BlsVerifiable for ChainedBeacon {
return Err(SchemeError::InvalidBeacon);
}
if bytes.write_all(&self.round_number.to_be_bytes()).is_err() {
return Err(SchemeError::InvalidBeacon);
};

return Ok(bytes);
Err(SchemeError::InvalidBeacon)
} else {
Ok(bytes)
}
}
}
16 changes: 8 additions & 8 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ pub struct HttpTransport {
}

impl HttpTransport {
pub fn fetch<'a>(&self, url: &str) -> Result<String, HttpError> {
let res = self.client.get(url)
pub fn fetch(&self, url: &str) -> Result<String, HttpError> {
let res = self
.client
.get(url)
.send()
.map_err(|_| HttpError::Unexpected)?;

return match res.status() {
StatusCode::OK => res.text()
.map_err(|_| HttpError::Unexpected),
match res.status() {
StatusCode::OK => res.text().map_err(|_| HttpError::Unexpected),

StatusCode::NOT_FOUND =>
Err(HttpError::NotFound),
StatusCode::NOT_FOUND => Err(HttpError::NotFound),

_ => Err(HttpError::Unexpected),
};
}
}
}
81 changes: 45 additions & 36 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
extern crate core;

mod bls;
mod chain_info;
mod chained;
mod unchained;
mod http;
mod chain_info;
mod bls;
mod unchained;

use reqwest::blocking::Client;
use serde::de::DeserializeOwned;
use thiserror::Error;
use crate::chain_info::ChainInfo;
use crate::chained::{ChainedBeacon, ChainedScheme};
use crate::DrandClientError::{InvalidChainInfo, InvalidRound};
use crate::http::HttpTransport;
use crate::unchained::{UnchainedBeacon, UnchainedScheme};
use crate::DrandClientError::{InvalidChainInfo, InvalidRound};
use reqwest::blocking::Client;
use serde::de::DeserializeOwned;
use thiserror::Error;

struct DrandClient<'a, B> {
pub struct DrandClient<'a, B> {
scheme: &'a dyn Scheme<B>,
transport: HttpTransport,
base_url: &'a str,
chain_info: ChainInfo,
}

fn new_chained_client(base_url: &str) -> Result<DrandClient<ChainedBeacon>, DrandClientError> {
pub fn new_chained_client(base_url: &str) -> Result<DrandClient<ChainedBeacon>, DrandClientError> {
return new_client(&ChainedScheme {}, base_url);
}

fn new_unchained_client(base_url: &str) -> Result<DrandClient<UnchainedBeacon>, DrandClientError> {
pub fn new_unchained_client(
base_url: &str,
) -> Result<DrandClient<UnchainedBeacon>, DrandClientError> {
return new_client(&UnchainedScheme {}, base_url);
}

fn new_client<'a, S: Scheme<B>, B>(scheme: &'a S, base_url: &'a str) -> Result<DrandClient<'a, B>, DrandClientError> {
pub fn new_client<'a, S: Scheme<B>, B>(
scheme: &'a S,
base_url: &'a str,
) -> Result<DrandClient<'a, B>, DrandClientError> {
let http_transport = HttpTransport {
client: Client::new(),
};
Expand All @@ -41,11 +46,12 @@ fn new_client<'a, S: Scheme<B>, B>(scheme: &'a S, base_url: &'a str) -> Result<D
scheme,
base_url,
};
return Ok(client);

Ok(client)
}

#[derive(Error, Debug, PartialEq)]
enum DrandClientError {
pub enum DrandClientError {
#[error("invalid round")]
InvalidRound,
#[error("invalid beacon")]
Expand All @@ -56,42 +62,45 @@ enum DrandClientError {
NotResponding,
}

fn fetch_chain_info(transport: &HttpTransport, base_url: &str) -> Result<ChainInfo, DrandClientError> {
pub fn fetch_chain_info(
transport: &HttpTransport,
base_url: &str,
) -> Result<ChainInfo, DrandClientError> {
let url = format!("{}/info", base_url);
return match transport.fetch(&url) {
match transport.fetch(&url) {
Err(_) => Err(DrandClientError::NotResponding),
Ok(body) => serde_json::from_str(&body)
.map_err(|_| InvalidChainInfo)
};
Ok(body) => serde_json::from_str(&body).map_err(|_| InvalidChainInfo),
}
}

impl<'a, B> DrandClient<'a, B> where B: DeserializeOwned {
fn latest_randomness(&self) -> Result<B, DrandClientError> {
return self.fetch_beacon_tag("latest");
impl<'a, B> DrandClient<'a, B>
where
B: DeserializeOwned,
{
pub fn latest_randomness(&self) -> Result<B, DrandClientError> {
self.fetch_beacon_tag("latest")
}

fn randomness(&self, round_number: u64) -> Result<B, DrandClientError> {
pub fn randomness(&self, round_number: u64) -> Result<B, DrandClientError> {
if round_number == 0 {
return Err(InvalidRound);
}
return self.fetch_beacon_tag(&format!("{}", round_number));
self.fetch_beacon_tag(&format!("{}", round_number))
}

fn fetch_beacon_tag(&self, tag: &str) -> Result<B, DrandClientError> {
let url = format!("{}/public/{}", self.base_url, tag);
return match self.transport.fetch(&url) {
Err(_) =>
Err(DrandClientError::NotResponding),
match self.transport.fetch(&url) {
Err(_) => Err(DrandClientError::NotResponding),

Ok(body) => match serde_json::from_str(&body) {
Ok(json) => self.scheme.verify(&self.chain_info, json)
Ok(json) => self
.scheme
.verify(&self.chain_info, json)
.map_err(|_| DrandClientError::InvalidBeacon),
Err(e) => {
println!("{:?}", e);
Err(DrandClientError::InvalidBeacon)
}
}
};
Err(_) => Err(DrandClientError::InvalidBeacon),
},
}
}
}

Expand All @@ -105,15 +114,15 @@ pub enum SchemeError {
InvalidChainInfo,
}

trait Scheme<B> {
pub trait Scheme<B> {
fn supports(&self, scheme_id: &str) -> bool;
fn verify(&self, info: &ChainInfo, beacon: B) -> Result<B, SchemeError>;
}

#[cfg(test)]
mod test {
use crate::{DrandClientError, new_chained_client, new_unchained_client};
use crate::DrandClientError::InvalidRound;
use crate::{new_chained_client, new_unchained_client, DrandClientError};

#[test]
fn request_chained_randomness_success() -> Result<(), DrandClientError> {
Expand Down Expand Up @@ -160,4 +169,4 @@ mod test {
assert_eq!(result.unwrap_err(), InvalidRound);
return Ok(());
}
}
}
30 changes: 17 additions & 13 deletions src/unchained.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::io::Write;
use crate::{bls, Scheme, SchemeError};
use crate::bls::BlsVerifiable;
use crate::chain_info::ChainInfo;
use crate::{bls, Scheme, SchemeError};
use serde::Deserialize;
use crate::bls::BlsVerifiable;
use std::io::Write;

#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct UnchainedBeacon {
Expand All @@ -18,15 +18,19 @@ pub struct UnchainedScheme {}

impl Scheme<UnchainedBeacon> for UnchainedScheme {
fn supports(&self, scheme_id: &str) -> bool {
return scheme_id.eq_ignore_ascii_case("pedersen-bls-unchained");
scheme_id.eq_ignore_ascii_case("pedersen-bls-unchained")
}

fn verify(&self, info: &ChainInfo, beacon: UnchainedBeacon) -> Result<UnchainedBeacon, SchemeError> {
fn verify(
&self,
info: &ChainInfo,
beacon: UnchainedBeacon,
) -> Result<UnchainedBeacon, SchemeError> {
if !self.supports(&info.scheme_id) {
return Err(SchemeError::InvalidScheme);
Err(SchemeError::InvalidScheme)
} else {
bls::bls_verify(info, beacon)
}

return bls::bls_verify(info, beacon);
}
}

Expand All @@ -39,9 +43,9 @@ impl BlsVerifiable for UnchainedBeacon {
let mut bytes: Vec<u8> = vec![];

if bytes.write_all(&self.round_number.to_be_bytes()).is_err() {
return Err(SchemeError::InvalidBeacon);
};

return Ok(bytes);
Err(SchemeError::InvalidBeacon)
} else {
Ok(bytes)
}
}
}
}

0 comments on commit 9855eea

Please sign in to comment.