Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add arithmetic types, plaintext, and conversion of plaintext & records to JS objects #944

Open
wants to merge 5 commits into
base: mainnet
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ jobs:
- run:
working_directory: wasm
command: |
cargo fmt -- --check
cargo fmt --all -- --check


workflows:
Expand Down
49 changes: 37 additions & 12 deletions wasm/src/account/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use crate::account::{PrivateKey, Signature, ViewKey};

use crate::types::native::AddressNative;
use crate::{account::compute_key::ComputeKey, types::native::AddressNative};
use core::{convert::TryFrom, fmt, ops::Deref, str::FromStr};
use wasm_bindgen::prelude::*;

Expand All @@ -43,6 +43,13 @@ impl Address {
Self(AddressNative::try_from(**view_key).unwrap())
}

/// Derive an Aleo address from a compute key.
///
/// @param {ComputeKey} compute_key The compute key to derive the address from
pub fn from_compute_key(compute_key: &ComputeKey) -> Self {
compute_key.address()
}

/// Create an aleo address object from a string representation of an address
///
/// @param {string} address String representation of an addressm
Expand All @@ -69,11 +76,17 @@ impl Address {
}
}

impl FromStr for Address {
type Err = anyhow::Error;
impl Deref for Address {
type Target = AddressNative;

fn from_str(address: &str) -> Result<Self, Self::Err> {
Ok(Self(AddressNative::from_str(address)?))
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

Expand All @@ -83,17 +96,29 @@ impl From<AddressNative> for Address {
}
}

impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
impl From<Address> for AddressNative {
fn from(value: Address) -> Self {
value.0
}
}

impl Deref for Address {
type Target = AddressNative;
impl From<&AddressNative> for Address {
fn from(value: &AddressNative) -> Self {
Self(value.clone())
}
}

fn deref(&self) -> &Self::Target {
&self.0
impl From<&Address> for AddressNative {
fn from(value: &Address) -> Self {
value.0
}
}

impl FromStr for Address {
type Err = anyhow::Error;

fn from_str(address: &str) -> Result<Self, Self::Err> {
Ok(Self(AddressNative::from_str(address)?))
}
}

Expand Down
137 changes: 137 additions & 0 deletions wasm/src/account/compute_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright (C) 2019-2023 Aleo Systems Inc.
// This file is part of the Aleo SDK library.

// The Aleo SDK library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The Aleo SDK library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with the Aleo SDK library. If not, see <https://www.gnu.org/licenses/>.

use super::PrivateKey;
use crate::{
types::{native::ComputeKeyNative, Group, Scalar},
Address,
};

use core::{convert::TryFrom, ops::Deref};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ComputeKey(ComputeKeyNative);

#[wasm_bindgen]
impl ComputeKey {
/// Create a new compute key from a private key.
///
/// @param {PrivateKey} private_key Private key
///
/// @returns {ComputeKey} Compute key
pub fn from_private_key(private_key: &PrivateKey) -> Self {
Self(ComputeKeyNative::try_from(**private_key).unwrap())
}

/// Get the address from the compute key.
///
/// @returns {Address}
pub fn address(&self) -> Address {
Address::from(self.0.to_address())
}

/// Get the sk_prf of the compute key.
///
/// @returns {Scalar} sk_prf
pub fn sk_prf(&self) -> Scalar {
Scalar::from(self.0.sk_prf())
}

/// Get the pr_tag of the compute key.
///
/// @returns {Group} pr_tag
pub fn pk_sig(&self) -> Group {
Group::from(self.0.pk_sig())
}

/// Get the pr_sig of the compute key.
///
/// @returns {Group} pr_sig
pub fn pr_sig(&self) -> Group {
Group::from(self.0.pr_sig())
}
}

impl Deref for ComputeKey {
type Target = ComputeKeyNative;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<ComputeKeyNative> for ComputeKey {
fn from(compute_key: ComputeKeyNative) -> Self {
Self(compute_key)
}
}

impl From<ComputeKey> for ComputeKeyNative {
fn from(compute_key: ComputeKey) -> Self {
compute_key.0
}
}

impl From<&ComputeKey> for ComputeKeyNative {
fn from(compute_key: &ComputeKey) -> Self {
compute_key.0.clone()
}
}

impl From<&ComputeKeyNative> for ComputeKey {
fn from(compute_key: &ComputeKeyNative) -> Self {
Self(compute_key.clone())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{
types::native::{AddressNative, CurrentNetwork},
PrivateKey,
};

use snarkvm_console::network::Network;

#[test]
fn test_compute_key_conversions() {
// Create a new private key.
let private_key = PrivateKey::new();
let address = Address::from_private_key(&private_key);

// Get the compute key from the private key.
let compute_key = ComputeKey::from_private_key(&private_key);

// Assert the address derivation can be computed from the compute key components.
// Compute pk_prf := G^sk_prf.
let pk_prf = Group::from(CurrentNetwork::g_scalar_multiply(&*compute_key.sk_prf()));
// Compute the address := pk_sig + pr_sig + pk_prf.
let group = compute_key.pk_sig().add(&compute_key.pr_sig()).add(&pk_prf);
let address_native = AddressNative::new(*group);
let derived_address = Address::from(address_native);

// Assert an address can be derived from the compute key via it's official function.
let compute_key_address = Address::from_compute_key(&compute_key);

// Check the address matches all possible derivations from the compute key.
assert_eq!(address, compute_key.address());
assert_eq!(address, derived_address);
assert_eq!(address, compute_key_address);
}
}
132 changes: 132 additions & 0 deletions wasm/src/account/graph_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright (C) 2019-2023 Aleo Systems Inc.
// This file is part of the Aleo SDK library.

// The Aleo SDK library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The Aleo SDK library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with the Aleo SDK library. If not, see <https://www.gnu.org/licenses/>.

use super::ViewKey;
use crate::types::{native::GraphKeyNative, Field};

use core::{convert::TryFrom, fmt, ops::Deref, str::FromStr};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GraphKey(GraphKeyNative);

#[wasm_bindgen]
impl GraphKey {
/// Create a new graph key from a view key.
///
/// @param {ViewKey} view_key View key
/// @returns {GraphKey} Graph key
pub fn from_view_key(view_key: &ViewKey) -> Self {
Self::from(GraphKeyNative::try_from(**view_key).unwrap())
}

/// Create a new graph key from a string representation of a graph key
///
/// @param {string} graph_key String representation of a graph key
/// @returns {GraphKey} Graph key
pub fn from_string(graph_key: &str) -> Self {
Self::from_str(graph_key).unwrap()
}

/// Get a string representation of a graph key
///
/// @returns {string} String representation of a graph key
#[allow(clippy::inherent_to_string_shadow_display)]
pub fn to_string(&self) -> String {
self.0.to_string()
}

/// Get the sk_tag of the graph key. Used to determine ownership of records.
pub fn sk_tag(&self) -> Field {
Field::from(self.0.sk_tag())
}
}

impl Deref for GraphKey {
type Target = GraphKeyNative;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl fmt::Display for GraphKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

impl FromStr for GraphKey {
type Err = anyhow::Error;

fn from_str(graph_key: &str) -> Result<Self, Self::Err> {
Ok(Self(GraphKeyNative::from_str(graph_key)?))
}
}

impl From<GraphKeyNative> for GraphKey {
fn from(value: GraphKeyNative) -> Self {
Self(value)
}
}

impl From<GraphKey> for GraphKeyNative {
fn from(value: GraphKey) -> Self {
value.0
}
}

impl From<&GraphKey> for GraphKeyNative {
fn from(value: &GraphKey) -> Self {
value.0.clone()
}
}

impl From<&GraphKeyNative> for GraphKey {
fn from(value: &GraphKeyNative) -> Self {
Self(value.clone())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::PrivateKey;

use wasm_bindgen_test::*;

#[wasm_bindgen_test]
fn test_graph_conversions() {
// Derive a new account.
let private_key = PrivateKey::new();
let view_key = ViewKey::from_private_key(&private_key);

// Test conversion from view key to graph key.
let graph_key = GraphKey::from_view_key(&view_key);

// Test to and from string.
let graph_key_string = graph_key.to_string();
let graph_key_from_string = GraphKey::from_string(&graph_key_string);
assert_eq!(graph_key, graph_key_from_string);

// Test conversion of sk_tag to string and back.
let sk_tag = graph_key.sk_tag();
let sk_tag_string = sk_tag.to_string();
let sk_tag_from_string = Field::from_string(&sk_tag_string).unwrap();
assert_eq!(sk_tag, sk_tag_from_string);
}
}
6 changes: 6 additions & 0 deletions wasm/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
pub mod address;
pub use address::*;

pub mod compute_key;
pub use compute_key::*;

pub mod encryptor;
pub use encryptor::*;

pub mod graph_key;
pub use graph_key::*;

pub mod private_key;
pub use private_key::*;

Expand Down
Loading
Loading