-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
5,876 additions
and
330 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
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 |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
"ignorePaths": ["Cargo.toml"], | ||
"words": [ | ||
"aarch", | ||
"ruint", | ||
"Uniffi", | ||
"WalletKit", | ||
"Worldcoin", | ||
|
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
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,10 @@ | ||
use thiserror::Error; | ||
|
||
#[derive(Debug, Error, uniffi::Error)] | ||
#[uniffi(flat_error)] | ||
pub enum Error { | ||
#[error("fetching_inclusion_proof_failed")] | ||
FetchingInclusionProofFailed, | ||
#[error("invalid_hex_string")] | ||
U256ParsingError(#[from] ruint::ParseError), | ||
} |
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,28 @@ | ||
#[derive(uniffi::Object, Debug, PartialEq, Eq, Clone)] | ||
/// A field element in the Semaphore protocol. | ||
pub struct Field(pub semaphore::Field); | ||
|
||
impl Field { | ||
#[must_use] | ||
pub fn to_hex_string(&self) -> String { | ||
format!("{:#04x}", self.0) | ||
} | ||
} | ||
|
||
impl From<&Field> for semaphore::Field { | ||
fn from(val: &Field) -> Self { | ||
val.0 | ||
} | ||
} | ||
|
||
impl From<Field> for semaphore::Field { | ||
fn from(val: Field) -> Self { | ||
val.0 | ||
} | ||
} | ||
|
||
impl std::fmt::Display for Field { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.to_hex_string()) | ||
} | ||
} |
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,49 @@ | ||
use ruint::aliases::U256; | ||
use semaphore::protocol::generate_nullifier_hash; | ||
|
||
use crate::proof::Context; | ||
|
||
#[derive(Clone, PartialEq, Eq, Debug, uniffi::Object)] | ||
pub struct Identity(pub semaphore::identity::Identity); | ||
|
||
impl From<Identity> for semaphore::identity::Identity { | ||
fn from(identity: Identity) -> Self { | ||
identity.0 | ||
} | ||
} | ||
|
||
impl Identity { | ||
#[must_use] | ||
pub fn new(secret: &[u8]) -> Self { | ||
let mut secret_key = secret.to_vec(); | ||
let identity = semaphore::identity::Identity::from_secret(&mut secret_key, None); | ||
Self(identity) | ||
} | ||
|
||
/// Generates a nullifier hash for a particular context (i.e. app + action) and the identity. | ||
/// The nullifier hash is a unique pseudo-random number for the particular identity and context. | ||
/// More information can be found [here](https://docs.world.org/world-id/concepts#vocabulary) | ||
/// | ||
/// [Protocol Reference](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#nullifier-hash). | ||
/// | ||
/// # Result | ||
/// Outputs a Field element as a `U256` value | ||
#[must_use] | ||
pub fn generate_nullifier_hash(&self, context: &Context) -> U256 { | ||
generate_nullifier_hash(&self.0, context.external_nullifier) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::utils::HexNumber; | ||
|
||
use super::*; | ||
#[test] | ||
fn test() { | ||
let identity = Identity::new(b"not_a_real_secret"); | ||
let context = Context::new(b"app_id", b"action"); | ||
let nullifier_hash = identity.generate_nullifier_hash(&context); | ||
println!("{}", nullifier_hash.to_hex_string()); | ||
} | ||
} |
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 |
---|---|---|
@@ -1,5 +1,10 @@ | ||
#![deny(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)] | ||
#![deny(clippy::all, clippy::pedantic, clippy::nursery)] | ||
|
||
pub mod math; | ||
pub mod error; | ||
pub mod field; | ||
pub mod identity; | ||
pub mod proof; | ||
mod utils; | ||
pub use utils::*; | ||
|
||
uniffi::setup_scaffolding!("walletkit_core"); |
This file was deleted.
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,15 @@ | ||
use ruint::aliases::U256; | ||
use semaphore::hash_to_field; | ||
|
||
pub struct Context { | ||
pub external_nullifier: U256, | ||
} | ||
|
||
impl Context { | ||
#[must_use] | ||
pub fn new(app_id: &[u8], action: &[u8]) -> Self { | ||
let external_nullifier = hash_to_field(app_id); | ||
// TODO: handle action properly | ||
Self { external_nullifier } | ||
} | ||
} |
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,84 @@ | ||
use ruint::aliases::U256; | ||
|
||
use crate::error::Error; | ||
|
||
/// A trait for types that can be represented as a hex string. | ||
/// | ||
/// This trait is implemented for `U256` and can be used to convert between hex strings and numbers. | ||
/// Most inputs and outputs from the zero-knowledge proofs are `U256` values. | ||
/// While using `U256` directly is convenient and recommended when working with the proofs, particularly in Rust, | ||
/// it is not a user-friendly type for interactions or communications in other languages / systems. | ||
/// | ||
/// Particularly, when sending proof inputs/outputs as JSON on HTTP requests, the values SHOULD be represented as hex strings. | ||
pub trait HexNumber { | ||
/// Convert the value to a hex string. | ||
fn to_hex_string(&self) -> String; | ||
/// Convert a hex string to a `U256`. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Returns an error if the hex string is invalid as a `U256`. | ||
fn try_from_hex_string(hex: &str) -> Result<Self, Error> | ||
where | ||
Self: std::marker::Sized; | ||
} | ||
|
||
impl HexNumber for U256 { | ||
fn to_hex_string(&self) -> String { | ||
format!("{self:#066x}") | ||
} | ||
|
||
fn try_from_hex_string(hex: &str) -> Result<Self, Error> { | ||
Self::from_str_radix(hex, 16).map_err(Error::U256ParsingError) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use ruint::uint; | ||
|
||
#[test] | ||
fn test_to_hex_string_for_u256() { | ||
assert_eq!( | ||
U256::from(1).to_hex_string(), | ||
"0x0000000000000000000000000000000000000000000000000000000000000001" | ||
); | ||
assert_eq!( | ||
U256::from(42).to_hex_string(), | ||
"0x000000000000000000000000000000000000000000000000000000000000002a" | ||
); | ||
|
||
assert_eq!( | ||
uint!(999999_U256).to_hex_string(), | ||
"0x00000000000000000000000000000000000000000000000000000000000f423f" | ||
); | ||
|
||
assert_eq!( | ||
uint!(80084422859880547211683076133703299733277748156566366325829078699459944778998_U256).to_hex_string(), | ||
"0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6" | ||
); | ||
|
||
assert_eq!( | ||
uint!(0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256).to_hex_string(), | ||
"0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0" | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_try_from_hex_string() { | ||
// Test valid hex strings | ||
assert_eq!(U256::try_from_hex_string("0x2a").unwrap(), U256::from(42)); | ||
assert_eq!(U256::try_from_hex_string("2a").unwrap(), U256::from(42)); | ||
|
||
// Test larger numbers | ||
assert_eq!(U256::try_from_hex_string("0xf423f").unwrap(), U256::from(999999)); | ||
|
||
// Test zero | ||
assert_eq!(U256::try_from_hex_string("0x0").unwrap(), U256::from(0)); | ||
|
||
// Test invalid hex strings | ||
assert!(U256::try_from_hex_string("0xg").is_err()); | ||
assert!(U256::try_from_hex_string("not hex").is_err()); | ||
} | ||
} |