From ea0dbfea0375cfbdfbf9ed0a281e7d8610fd7319 Mon Sep 17 00:00:00 2001 From: Simon Wicky Date: Fri, 20 Oct 2023 13:06:03 +0200 Subject: [PATCH] ecash issuance api side --- nym-api/Cargo.toml | 1 + nym-api/nym-api-requests/Cargo.toml | 1 + nym-api/nym-api-requests/src/coconut.rs | 49 +++++++++++---------- nym-api/src/coconut/deposit.rs | 19 +++++---- nym-api/src/coconut/error.rs | 3 ++ nym-api/src/coconut/mod.rs | 57 ++++++++++++++----------- 6 files changed, 73 insertions(+), 57 deletions(-) diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 243e152d52..6850b0be4f 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -79,6 +79,7 @@ nym-bandwidth-controller = { path = "../common/bandwidth-controller" } nym-coconut-bandwidth-contract-common = { path = "../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" } nym-coconut-dkg-common = { path = "../common/cosmwasm-smart-contracts/coconut-dkg" } nym-coconut-interface = { path = "../common/coconut-interface" } +nym_compact_ecash = { path = "../common/nym_offline_compact_ecash" } nym-ephemera-common = { path = "../common/cosmwasm-smart-contracts/ephemera" } nym-config = { path = "../common/config" } cosmwasm-std = { workspace = true } diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index d9869bd7ae..093d967a9c 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -15,6 +15,7 @@ serde = { workspace = true, features = ["derive"] } ts-rs = { workspace = true, optional = true } nym-coconut-interface = { path = "../../common/coconut-interface" } +nym_compact_ecash = { path = "../../common/nym_offline_compact_ecash" } nym-mixnet-contract-common = { path= "../../common/cosmwasm-smart-contracts/mixnet-contract" } nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false } diff --git a/nym-api/nym-api-requests/src/coconut.rs b/nym-api/nym-api-requests/src/coconut.rs index 6f79bc2f21..836ef3409f 100644 --- a/nym-api/nym-api-requests/src/coconut.rs +++ b/nym-api/nym-api-requests/src/coconut.rs @@ -3,12 +3,10 @@ use cosmrs::AccountId; use getset::{CopyGetters, Getters}; +use nym_coconut_interface::{Credential, VerificationKey}; +use nym_compact_ecash::{error::CompactEcashError, scheme::withdrawal::WithdrawalRequest}; use serde::{Deserialize, Serialize}; -use nym_coconut_interface::{ - error::CoconutInterfaceError, Attribute, Base58, BlindSignRequest, Credential, VerificationKey, -}; - #[derive(Serialize, Deserialize, Getters, CopyGetters)] pub struct VerifyCredentialBody { #[getset(get = "pub")] @@ -50,12 +48,14 @@ impl VerifyCredentialResponse { #[derive(Clone, Serialize, Deserialize, Debug, Getters, CopyGetters)] pub struct BlindSignRequestBody { #[getset(get = "pub")] - blind_sign_request: BlindSignRequest, + withdrawal_request: WithdrawalRequest, #[getset(get = "pub")] tx_hash: String, #[getset(get = "pub")] signature: String, - public_attributes: Vec, + #[getset(get = "pub")] + ecash_pubkey: String, + //public_attributes: Vec, #[getset(get = "pub")] public_attributes_plain: Vec, #[getset(get = "pub")] @@ -64,32 +64,34 @@ pub struct BlindSignRequestBody { impl BlindSignRequestBody { pub fn new( - blind_sign_request: &BlindSignRequest, + withdrawal_request: &WithdrawalRequest, tx_hash: String, signature: String, - public_attributes: &[Attribute], + ecash_pubkey: String, + //public_attributes: &[Attribute], public_attributes_plain: Vec, total_params: u32, ) -> BlindSignRequestBody { BlindSignRequestBody { - blind_sign_request: blind_sign_request.clone(), + withdrawal_request: withdrawal_request.clone(), tx_hash, signature, - public_attributes: public_attributes - .iter() - .map(|attr| attr.to_bs58()) - .collect(), + ecash_pubkey, + // public_attributes: public_attributes + // .iter() + // .map(|attr| attr.to_bs58()) + // .collect(), public_attributes_plain, total_params, } } - pub fn public_attributes(&self) -> Vec { - self.public_attributes - .iter() - .map(|x| Attribute::try_from_bs58(x).unwrap()) - .collect() - } + // pub fn public_attributes(&self) -> Vec { + // self.public_attributes + // .iter() + // .map(|x| Attribute::try_from_bs58(x).unwrap()) + // .collect() + // } } #[derive(Debug, Serialize, Deserialize)] @@ -110,7 +112,7 @@ impl BlindedSignatureResponse { bs58::encode(&self.to_bytes()).into_string() } - pub fn from_base58_string>(val: I) -> Result { + pub fn from_base58_string>(val: I) -> Result { let bytes = bs58::decode(val).into_vec()?; Self::from_bytes(&bytes) } @@ -121,9 +123,12 @@ impl BlindedSignatureResponse { bytes } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() < 32 { - return Err(CoconutInterfaceError::InvalidByteLength(bytes.len(), 32)); + return Err(CompactEcashError::DeserializationMinLength { + min: 32, + actual: bytes.len(), + }); } let mut remote_key = [0u8; 32]; remote_key.copy_from_slice(&bytes[..32]); diff --git a/nym-api/src/coconut/deposit.rs b/nym-api/src/coconut/deposit.rs index d7db423d60..6bca4179fa 100644 --- a/nym-api/src/coconut/deposit.rs +++ b/nym-api/src/coconut/deposit.rs @@ -6,7 +6,6 @@ use nym_coconut_bandwidth_contract_common::events::{ DEPOSITED_FUNDS_EVENT_TYPE, DEPOSIT_ENCRYPTION_KEY, DEPOSIT_IDENTITY_KEY, DEPOSIT_INFO, DEPOSIT_VALUE, }; -use nym_credentials::coconut::bandwidth::BandwidthVoucher; use nym_crypto::asymmetric::encryption; use nym_crypto::asymmetric::identity::{self, Signature}; use nym_validator_client::nyxd::TxResponse; @@ -17,16 +16,16 @@ pub async fn extract_encryption_key( blind_sign_request_body: &BlindSignRequestBody, tx: TxResponse, ) -> Result { - let blind_sign_request = blind_sign_request_body.blind_sign_request(); - let public_attributes = blind_sign_request_body.public_attributes(); + let withdrawal_request = blind_sign_request_body.withdrawal_request(); + //let public_attributes = blind_sign_request_body.public_attributes(); let public_attributes_plain = blind_sign_request_body.public_attributes_plain(); - if !BandwidthVoucher::verify_against_plain(&public_attributes, public_attributes_plain) { - return Err(CoconutError::InconsistentPublicAttributes); - } + // if !BandwidthVoucher::verify_against_plain(&public_attributes, public_attributes_plain) { + // return Err(CoconutError::InconsistentPublicAttributes); + // } let tx_hash_str = blind_sign_request_body.tx_hash(); - let mut message = blind_sign_request.to_bytes(); + let mut message = withdrawal_request.to_bytes(); message.extend_from_slice(tx_hash_str.as_bytes()); let signature = Signature::from_base58_string(blind_sign_request_body.signature())?; @@ -93,7 +92,8 @@ pub async fn extract_encryption_key( mod test { use super::*; use crate::coconut::tests::tx_entry_fixture; - use nym_coconut::{prepare_blind_sign, BlindSignRequest, Parameters}; + use nym_compact_ecash::generate_keypair_user; + use nym_compact_ecash::setup::GroupParameters; use nym_config::defaults::VOUCHER_INFO; use nym_validator_client::nyxd::Hash; use nym_validator_client::nyxd::{Event, EventAttribute}; @@ -106,7 +106,7 @@ mod test { Hash::from_str("6B27412050B823E58BB38447D7870BBC8CBE3C51C905BEA89D459ACCDA80A00E") .unwrap(); let mut tx_entry = tx_entry_fixture(&tx_hash.to_string()); - let params = Parameters::new(4).unwrap(); + let params = GroupParametersParameters::new().unwrap(); let mut rng = OsRng; let voucher = BandwidthVoucher::new( ¶ms, @@ -123,6 +123,7 @@ mod test { &encryption::KeyPair::new(&mut rng).private_key().to_bytes(), ) .unwrap(), + generate_keypair_user(¶ms), ); let (_, blind_sign_req) = prepare_blind_sign( ¶ms, diff --git a/nym-api/src/coconut/error.rs b/nym-api/src/coconut/error.rs index 14f7b2f933..7ec0d88d5c 100644 --- a/nym-api/src/coconut/error.rs +++ b/nym-api/src/coconut/error.rs @@ -48,6 +48,9 @@ pub enum CoconutError { #[error("Coconut internal error - {0}")] CoconutInternalError(#[from] nym_coconut::CoconutError), + #[error("Compact ecash internal error - {0}")] + CompactEcashInternalError(#[from] nym_compact_ecash::error::CompactEcashError), + #[error("Could not find a deposit event in the transaction provided")] DepositEventNotFound, diff --git a/nym-api/src/coconut/mod.rs b/nym-api/src/coconut/mod.rs index 7059e95160..13dbaf5ed2 100644 --- a/nym-api/src/coconut/mod.rs +++ b/nym-api/src/coconut/mod.rs @@ -16,10 +16,12 @@ use nym_coconut_bandwidth_contract_common::spend_credential::{ funds_from_cosmos_msgs, SpendCredentialStatus, }; use nym_coconut_dkg_common::types::EpochId; -use nym_coconut_interface::KeyPair as CoconutKeyPair; -use nym_coconut_interface::{ - Attribute, BlindSignRequest, BlindedSignature, Parameters, VerificationKey, -}; + +use nym_compact_ecash::scheme::keygen::{KeyPairAuth, SecretKeyAuth}; +use nym_compact_ecash::scheme::withdrawal::WithdrawalRequest; +use nym_compact_ecash::setup::GroupParameters; +use nym_compact_ecash::utils::BlindedSignature; +use nym_compact_ecash::{PublicKeyUser, VerificationKeyAuth}; use nym_config::defaults::NYM_API_VERSION; use nym_credentials::coconut::params::{ NymApiCredentialEncryptionAlgorithm, NymApiCredentialHkdfAlgorithm, @@ -135,7 +137,10 @@ impl State { } } - pub async fn verification_key(&self, epoch_id: EpochId) -> Result { + pub async fn verification_key( + &self, + epoch_id: EpochId, + ) -> Result { self.comm_channel .aggregated_verification_key(epoch_id) .await @@ -144,25 +149,20 @@ impl State { #[derive(Getters, CopyGetters, Debug)] pub(crate) struct InternalSignRequest { - // Total number of parameters to generate for - #[getset(get_copy)] - total_params: u32, #[getset(get)] - public_attributes: Vec, + withdrawal_request: WithdrawalRequest, #[getset(get)] - blind_sign_request: BlindSignRequest, + ecash_pubkey: PublicKeyUser, } impl InternalSignRequest { pub fn new( - total_params: u32, - public_attributes: Vec, - blind_sign_request: BlindSignRequest, + withdrawal_request: WithdrawalRequest, + ecash_pubkey: PublicKeyUser, ) -> InternalSignRequest { InternalSignRequest { - total_params, - public_attributes, - blind_sign_request, + withdrawal_request, + ecash_pubkey, } } @@ -188,13 +188,13 @@ impl InternalSignRequest { } } -fn blind_sign(request: InternalSignRequest, key_pair: &CoconutKeyPair) -> Result { - let params = Parameters::new(request.total_params())?; - Ok(nym_coconut_interface::blind_sign( +fn blind_sign(request: InternalSignRequest, key_pair: KeyPairAuth) -> Result { + let params = GroupParameters::new()?; + Ok(nym_compact_ecash::scheme::withdrawal::issue_wallet( ¶ms, - &key_pair.secret_key(), - request.blind_sign_request(), - request.public_attributes(), + key_pair.secret_key(), + request.ecash_pubkey().clone(), + request.withdrawal_request(), )?) } @@ -217,12 +217,17 @@ pub async fn post_blind_sign( .await?; let encryption_key = extract_encryption_key(&blind_sign_request_body, tx).await?; let internal_request = InternalSignRequest::new( - *blind_sign_request_body.total_params(), - blind_sign_request_body.public_attributes(), - blind_sign_request_body.blind_sign_request().clone(), + blind_sign_request_body.withdrawal_request().clone(), + PublicKeyUser::from_base58_string(blind_sign_request_body.ecash_pubkey())?, ); let blinded_signature = if let Some(keypair) = state.key_pair.get().await.as_ref() { - blind_sign(internal_request, keypair)? + let secret_key_auth = SecretKeyAuth::from_bytes(&keypair.secret_key().to_bytes())?; + let verification_key_auth = + VerificationKeyAuth::from_bytes(&keypair.verification_key().to_bytes())?; + let index = keypair.index; + + let keypair_auth = KeyPairAuth::new(secret_key_auth, verification_key_auth, index); + blind_sign(internal_request, keypair_auth)? } else { return Err(CoconutError::KeyPairNotDerivedYet); };