Files
nym/common/credentials/src/utils.rs
T
Jędrzej Stuczyński a274edffba Feature/nymd client integration (#736)
* Calculating gas fees

* Ability to set custom fees

* Added extra test

* Removed commented code

* Moved all msg types to common contract crate

* Temporarily disabling get_tx method

* Finishing up nymd client API

* Comment fix

* Remaining fee values

* Some cleanup

* Removed needless borrow

* Fixed imports in contract tests

* Moved error types around

* New ValidatorClient

* Experiment with new type of defaults

* Removed dead module

* Dealt with unwrap

* Migrated mixnode to use new validator client

* Migrated gateway to use new validator client

* Mixnode and gateway adjustments

* More exported defaults

* Clients using new validator client

* Fixed mixnode upgrade

* Moved default values to a new crate

* Changed behaviour of validator client features

* Migrated basic functions of validator api

* Updated config + fixed startup

* Fixed wasm client build

* Integration with the explorer api

* Removed tokio dev dependency

* Needless borrow

* Fixex wasm client build

* Fixed tauri client build

* Needless borrows

* Fixed client upgrade print

* Removed redundant comments

* Made note on aggregated verification key into a doc comment

* Removed mixnet contract references from verloc

* Modified default validators structure

* Reformatted validator-api Cargo.toml file

* Removed commented code

* Made the doc comment example a no-run

* Fixed a upgrade print... again

* Adjusted the doc example

* Removed unused import
2021-08-18 14:41:00 +01:00

135 lines
4.4 KiB
Rust

// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::Error;
use coconut_interface::{
aggregate_signature_shares, aggregate_verification_keys, prepare_blind_sign, prove_credential,
Attribute, BlindSignRequestBody, Credential, Parameters, Signature, SignatureShare,
VerificationKey,
};
use url::Url;
/// Contacts all provided validators and then aggregate their verification keys.
///
/// # Arguments
///
/// * `validators`: list of validators to obtain verification keys from.
///
/// Note: list of validators must be correctly ordered by the polynomial coordinates used
/// during key generation and it is responsibility of the caller to ensure that correct
/// number of them is provided
///
/// # Examples
///
/// ```no_run
/// use url::{Url, ParseError};
/// use credentials::obtain_aggregate_verification_key;
///
/// async fn example() -> Result<(), ParseError> {
/// let validators = vec!["https://testnet-milhon-validator1.nymtech.net/api".parse()?, "https://testnet-milhon-validator2.nymtech.net/api".parse()?];
/// let aggregated_key = obtain_aggregate_verification_key(&validators).await;
/// // deal with the obtained Result
/// Ok(())
/// }
/// ```
pub async fn obtain_aggregate_verification_key(
validators: &[Url],
) -> Result<VerificationKey, Error> {
if validators.is_empty() {
return Err(Error::NoValidatorsAvailable);
}
let mut indices = Vec::with_capacity(validators.len());
let mut shares = Vec::with_capacity(validators.len());
let mut client = validator_client::ApiClient::new(validators[0].clone());
let response = client.get_coconut_verification_key().await?;
indices.push(0);
shares.push(response.key);
for (id, validator_url) in validators.iter().enumerate().skip(1) {
client.change_validator_api(validator_url.clone());
let response = client.get_coconut_verification_key().await?;
indices.push(id as u64);
shares.push(response.key);
}
Ok(aggregate_verification_keys(&shares, Some(&indices))?)
}
async fn obtain_partial_credential(
params: &Parameters,
public_attributes: &[Attribute],
private_attributes: &[Attribute],
client: &validator_client::ApiClient,
) -> Result<Signature, Error> {
let elgamal_keypair = coconut_interface::elgamal_keygen(params);
let blind_sign_request = prepare_blind_sign(
params,
elgamal_keypair.public_key(),
private_attributes,
public_attributes,
)?;
let blind_sign_request_body = BlindSignRequestBody::new(
blind_sign_request,
elgamal_keypair.public_key(),
public_attributes,
(public_attributes.len() + private_attributes.len()) as u32,
);
let blinded_signature = client
.blind_sign(&blind_sign_request_body)
.await?
.blinded_signature;
Ok(blinded_signature.unblind(elgamal_keypair.private_key()))
}
pub async fn obtain_aggregate_signature(
params: &Parameters,
public_attributes: &[Attribute],
private_attributes: &[Attribute],
validators: &[Url],
) -> Result<Signature, Error> {
if validators.is_empty() {
return Err(Error::NoValidatorsAvailable);
}
let mut shares = Vec::with_capacity(validators.len());
let mut client = validator_client::ApiClient::new(validators[0].clone());
let first =
obtain_partial_credential(params, public_attributes, private_attributes, &client).await?;
shares.push(SignatureShare::new(first, 0));
for (id, validator_url) in validators.iter().enumerate().skip(1) {
client.change_validator_api(validator_url.clone());
let signature =
obtain_partial_credential(params, public_attributes, private_attributes, &client)
.await?;
let share = SignatureShare::new(signature, id as u64);
shares.push(share)
}
Ok(aggregate_signature_shares(&shares)?)
}
// TODO: better type flow
pub fn prepare_credential_for_spending(
params: &Parameters,
public_attributes: &[Attribute],
private_attributes: &[Attribute],
signature: &Signature,
verification_key: &VerificationKey,
) -> Result<Credential, Error> {
let theta = prove_credential(params, verification_key, signature, private_attributes)?;
Ok(Credential::new(
(public_attributes.len() + private_attributes.len()) as u32,
theta,
public_attributes,
signature,
))
}