From 0df801ab4e3e7c2c6f9519dd7d7ed866816c90dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Fri, 24 Jun 2022 18:36:13 +0300 Subject: [PATCH] Feature/expose validator cosmos address (#1404) * Move coconut validator api req out of coconut interface and expose a new cosmos-address endpoint * Finish cosmos address endpoint * Guard under coconut feature gateway & validator-api code * Update CHANGELOG --- CHANGELOG.md | 2 + Cargo.lock | 6 + .../client-libs/validator-client/Cargo.toml | 2 +- .../validator-client/src/client.rs | 6 +- .../validator-client/src/validator_api/mod.rs | 23 ++- .../src/validator_api/routes.rs | 1 + common/coconut-interface/src/lib.rs | 165 ---------------- common/credentials/Cargo.toml | 1 + common/credentials/src/coconut/utils.rs | 4 +- gateway/Cargo.toml | 3 +- .../connection_handler/authenticated.rs | 11 +- validator-api/Cargo.toml | 2 +- validator-api/src/coconut/client.rs | 3 +- validator-api/src/coconut/deposit.rs | 2 +- validator-api/src/coconut/mod.rs | 18 +- validator-api/src/coconut/tests.rs | 10 +- validator-api/src/nymd_client.rs | 5 + .../validator-api-requests/Cargo.toml | 8 +- .../validator-api-requests/src/coconut.rs | 186 ++++++++++++++++++ .../validator-api-requests/src/lib.rs | 2 + 20 files changed, 270 insertions(+), 190 deletions(-) create mode 100644 validator-api/validator-api-requests/src/coconut.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c49e6f3ec3..069c19012d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328]) - wallet: when simulating gas costs, an automatic adjustment is being used ([#1388]). - mixnode: Added basic mixnode hardware reporting to the HTTP API ([#1308]). +- validator-api: endpoint, in coconut mode, for returning the validator-api cosmos address ([#1404]). ### Fixed @@ -57,6 +58,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// [#1376]: https://github.com/nymtech/nym/pull/1376 [#1388]: https://github.com/nymtech/nym/pull/1388 [#1393]: https://github.com/nymtech/nym/pull/1393 +[#1404]: https://github.com/nymtech/nym/pull/1404 ## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22) diff --git a/Cargo.lock b/Cargo.lock index 861fe09f08..54e7b3726d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -924,6 +924,7 @@ dependencies = [ "rand 0.7.3", "thiserror", "url", + "validator-api-requests", "validator-client", ] @@ -3120,6 +3121,7 @@ dependencies = [ "tokio-tungstenite", "tokio-util 0.7.3", "url", + "validator-api-requests", "validator-client", "vergen", "version-checker", @@ -6254,6 +6256,10 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" name = "validator-api-requests" version = "0.1.0" dependencies = [ + "bs58", + "coconut-interface", + "cosmrs", + "getset", "mixnet-contract-common", "schemars", "serde", diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index ff2a6714a1..4e0ca6be12 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -27,7 +27,7 @@ futures = "0.3" coconut-interface = { path = "../../coconut-interface" } network-defaults = { path = "../../network-defaults" } -validator-api-requests = { path = "../../../validator-api/validator-api-requests" } +validator-api-requests = { path = "../../../validator-api/validator-api-requests", features = ["coconut"] } # required for nymd-client # at some point it might be possible to make it wasm-compatible diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index 8bd355e985..85a3524f77 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{validator_api, ValidatorClientError}; -use coconut_interface::{ +use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond}; +use url::Url; +use validator_api_requests::coconut::{ BlindSignRequestBody, BlindedSignatureResponse, ExecuteReleaseFundsRequestBody, ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, VerificationKeyResponse, VerifyCredentialBody, VerifyCredentialResponse, }; -use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond}; -use url::Url; use validator_api_requests::models::{ CoreNodeStatusResponse, MixnodeStatusResponse, RewardEstimationResponse, diff --git a/common/client-libs/validator-client/src/validator_api/mod.rs b/common/client-libs/validator-client/src/validator_api/mod.rs index be0ad92727..f6c1d16e20 100644 --- a/common/client-libs/validator-client/src/validator_api/mod.rs +++ b/common/client-libs/validator-client/src/validator_api/mod.rs @@ -3,15 +3,15 @@ use crate::validator_api::error::ValidatorAPIError; use crate::validator_api::routes::{CORE_STATUS_COUNT, SINCE_ARG}; -use coconut_interface::{ - BlindSignRequestBody, BlindedSignatureResponse, ExecuteReleaseFundsRequestBody, - ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, VerificationKeyResponse, - VerifyCredentialBody, VerifyCredentialResponse, -}; use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use url::Url; +use validator_api_requests::coconut::{ + BlindSignRequestBody, BlindedSignatureResponse, CosmosAddressResponse, + ExecuteReleaseFundsRequestBody, ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, + VerificationKeyResponse, VerifyCredentialBody, VerifyCredentialResponse, +}; use validator_api_requests::models::{ CoreNodeStatusResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeStatusResponse, RewardEstimationResponse, StakeSaturationResponse, UptimeResponse, @@ -376,6 +376,19 @@ impl Client { .await } + pub async fn get_cosmos_address(&self) -> Result { + self.query_validator_api( + &[ + routes::API_VERSION, + routes::COCONUT_ROUTES, + routes::BANDWIDTH, + routes::COCONUT_COSMOS_ADDRESS, + ], + NO_PARAMS, + ) + .await + } + pub async fn verify_bandwidth_credential( &self, request_body: &VerifyCredentialBody, diff --git a/common/client-libs/validator-client/src/validator_api/routes.rs b/common/client-libs/validator-client/src/validator_api/routes.rs index b6939d18ab..4c156e06db 100644 --- a/common/client-libs/validator-client/src/validator_api/routes.rs +++ b/common/client-libs/validator-client/src/validator_api/routes.rs @@ -17,6 +17,7 @@ pub const BANDWIDTH: &str = "bandwidth"; pub const COCONUT_BLIND_SIGN: &str = "blind-sign"; pub const COCONUT_PARTIAL_BANDWIDTH_CREDENTIAL: &str = "partial-bandwidth-credential"; pub const COCONUT_VERIFICATION_KEY: &str = "verification-key"; +pub const COCONUT_COSMOS_ADDRESS: &str = "cosmos-address"; pub const COCONUT_VERIFY_BANDWIDTH_CREDENTIAL: &str = "verify-bandwidth-credential"; pub const COCONUT_PROPOSE_RELEASE_FUNDS: &str = "propose-release-funds"; pub const COCONUT_EXECUTE_RELEASE_FUNDS: &str = "execute-release-funds"; diff --git a/common/coconut-interface/src/lib.rs b/common/coconut-interface/src/lib.rs index 8cb345dbf5..fea67641d4 100644 --- a/common/coconut-interface/src/lib.rs +++ b/common/coconut-interface/src/lib.rs @@ -127,171 +127,6 @@ impl Bytable for Credential { impl Base58 for Credential {} -#[derive(Serialize, Deserialize, Getters, CopyGetters)] -pub struct VerifyCredentialBody { - #[getset(get = "pub")] - credential: Credential, - #[getset(get = "pub")] - proposal_id: u64, -} - -impl VerifyCredentialBody { - pub fn new(credential: Credential, proposal_id: u64) -> VerifyCredentialBody { - VerifyCredentialBody { - credential, - proposal_id, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct VerifyCredentialResponse { - pub verification_result: bool, -} - -impl VerifyCredentialResponse { - pub fn new(verification_result: bool) -> Self { - VerifyCredentialResponse { - verification_result, - } - } -} - -// All strings are base58 encoded representations of structs -#[derive(Clone, Serialize, Deserialize, Debug, Getters, CopyGetters)] -pub struct BlindSignRequestBody { - #[getset(get = "pub")] - blind_sign_request: BlindSignRequest, - #[getset(get = "pub")] - tx_hash: String, - #[getset(get = "pub")] - signature: String, - public_attributes: Vec, - #[getset(get = "pub")] - public_attributes_plain: Vec, - #[getset(get = "pub")] - total_params: u32, -} - -impl BlindSignRequestBody { - pub fn new( - blind_sign_request: &BlindSignRequest, - tx_hash: String, - signature: String, - public_attributes: &[Attribute], - public_attributes_plain: Vec, - total_params: u32, - ) -> BlindSignRequestBody { - BlindSignRequestBody { - blind_sign_request: blind_sign_request.clone(), - tx_hash, - signature, - 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() - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct BlindedSignatureResponse { - pub remote_key: [u8; 32], - pub encrypted_signature: Vec, -} - -impl BlindedSignatureResponse { - pub fn new(encrypted_signature: Vec, remote_key: [u8; 32]) -> BlindedSignatureResponse { - BlindedSignatureResponse { - encrypted_signature, - remote_key, - } - } - - pub fn to_base58_string(&self) -> String { - bs58::encode(&self.to_bytes()).into_string() - } - - pub fn from_base58_string>(val: I) -> Result { - let bytes = bs58::decode(val).into_vec()?; - Self::from_bytes(&bytes) - } - - pub fn to_bytes(&self) -> Vec { - let mut bytes = self.remote_key.to_vec(); - bytes.extend_from_slice(&self.encrypted_signature); - bytes - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() < 32 { - return Err(CoconutInterfaceError::InvalidByteLength(bytes.len(), 32)); - } - let mut remote_key = [0u8; 32]; - remote_key.copy_from_slice(&bytes[..32]); - let encrypted_signature = bytes[32..].to_vec(); - Ok(BlindedSignatureResponse { - remote_key, - encrypted_signature, - }) - } -} - -#[derive(Serialize, Deserialize)] -pub struct VerificationKeyResponse { - pub key: VerificationKey, -} - -impl VerificationKeyResponse { - pub fn new(key: VerificationKey) -> VerificationKeyResponse { - VerificationKeyResponse { key } - } -} - -#[derive(Serialize, Deserialize, Getters, CopyGetters)] -pub struct ProposeReleaseFundsRequestBody { - #[getset(get = "pub")] - credential: Credential, -} - -impl ProposeReleaseFundsRequestBody { - pub fn new(credential: Credential) -> Self { - ProposeReleaseFundsRequestBody { credential } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ProposeReleaseFundsResponse { - pub proposal_id: u64, -} - -impl ProposeReleaseFundsResponse { - pub fn new(proposal_id: u64) -> Self { - ProposeReleaseFundsResponse { proposal_id } - } -} - -#[derive(Debug, Serialize, Deserialize, Getters, CopyGetters)] -pub struct ExecuteReleaseFundsRequestBody { - #[getset(get = "pub")] - proposal_id: u64, -} - -impl ExecuteReleaseFundsRequestBody { - pub fn new(proposal_id: u64) -> Self { - ExecuteReleaseFundsRequestBody { proposal_id } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/common/credentials/Cargo.toml b/common/credentials/Cargo.toml index 94dc68b785..827e257e92 100644 --- a/common/credentials/Cargo.toml +++ b/common/credentials/Cargo.toml @@ -15,6 +15,7 @@ url = "2.2" coconut-interface = { path = "../coconut-interface" } crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "hashing"] } network-defaults = { path = "../network-defaults" } +validator-api-requests = { path = "../../validator-api/validator-api-requests" } validator-client = { path = "../client-libs/validator-client" } [dev-dependencies] diff --git a/common/credentials/src/coconut/utils.rs b/common/credentials/src/coconut/utils.rs index 0ffee7abdc..537ea801ff 100644 --- a/common/credentials/src/coconut/utils.rs +++ b/common/credentials/src/coconut/utils.rs @@ -3,13 +3,13 @@ use coconut_interface::{ aggregate_signature_shares, aggregate_verification_keys, prove_bandwidth_credential, Attribute, - BlindSignRequestBody, BlindedSignature, Credential, Parameters, Signature, SignatureShare, - VerificationKey, + BlindedSignature, Credential, Parameters, Signature, SignatureShare, VerificationKey, }; use crypto::asymmetric::encryption::PublicKey; use crypto::shared_key::recompute_shared_key; use crypto::symmetric::stream_cipher; use url::Url; +use validator_api_requests::coconut::BlindSignRequestBody; use crate::coconut::bandwidth::{BandwidthVoucher, PRIVATE_ATTRIBUTES, PUBLIC_ATTRIBUTES}; use crate::coconut::params::{ diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 2d0205002b..5d12664be1 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -52,11 +52,12 @@ network-defaults = { path = "../common/network-defaults" } nymsphinx = { path = "../common/nymsphinx" } pemstore = { path = "../common/pemstore" } statistics-common = { path = "../common/statistics" } +validator-api-requests = { path = "../validator-api/validator-api-requests" } validator-client = { path = "../common/client-libs/validator-client", features = ["nymd-client"] } version-checker = { path = "../common/version-checker" } [features] -coconut = ["coconut-interface", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut"] +coconut = ["coconut-interface", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "validator-api-requests/coconut"] eth = [] [build-dependencies] diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index c6ea692b33..4eaa4232e0 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -223,7 +223,9 @@ where )); } - let req = coconut_interface::ProposeReleaseFundsRequestBody::new(credential.clone()); + let req = validator_api_requests::coconut::ProposeReleaseFundsRequestBody::new( + credential.clone(), + ); let proposal_id = self .inner .coconut_verifier @@ -237,7 +239,10 @@ where .await? .proposal_id; - let req = coconut_interface::VerifyCredentialBody::new(credential.clone(), proposal_id); + let req = validator_api_requests::coconut::VerifyCredentialBody::new( + credential.clone(), + proposal_id, + ); for client in self.inner.coconut_verifier.api_clients().iter().skip(1) { if !client .verify_bandwidth_credential(&req) @@ -248,7 +253,7 @@ where } } - let req = coconut_interface::ExecuteReleaseFundsRequestBody::new(proposal_id); + let req = validator_api_requests::coconut::ExecuteReleaseFundsRequestBody::new(proposal_id); self.inner .coconut_verifier .api_clients() diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index 1c4f97c8d3..6bd1f3f22e 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -70,7 +70,7 @@ console-subscriber = { version = "0.1.1", optional = true} cfg-if = "1.0" [features] -coconut = ["coconut-interface", "credentials", "gateway-client/coconut", "credentials/coconut"] +coconut = ["coconut-interface", "credentials", "gateway-client/coconut", "credentials/coconut", "validator-api-requests/coconut"] no-reward = [] generate-ts = [] diff --git a/validator-api/src/coconut/client.rs b/validator-api/src/coconut/client.rs index c606152cc9..a8b3646692 100644 --- a/validator-api/src/coconut/client.rs +++ b/validator-api/src/coconut/client.rs @@ -3,10 +3,11 @@ use crate::coconut::error::Result; use multisig_contract_common::msg::ProposalResponse; -use validator_client::nymd::{Fee, TxResponse}; +use validator_client::nymd::{AccountId, Fee, TxResponse}; #[async_trait] pub trait Client { + async fn address(&self) -> AccountId; async fn get_tx(&self, tx_hash: &str) -> Result; async fn get_proposal(&self, proposal_id: u64) -> Result; async fn propose_release_funds( diff --git a/validator-api/src/coconut/deposit.rs b/validator-api/src/coconut/deposit.rs index 8c3dbcb899..8dba92a705 100644 --- a/validator-api/src/coconut/deposit.rs +++ b/validator-api/src/coconut/deposit.rs @@ -5,10 +5,10 @@ use coconut_bandwidth_contract_common::events::{ DEPOSITED_FUNDS_EVENT_TYPE, DEPOSIT_ENCRYPTION_KEY, DEPOSIT_IDENTITY_KEY, DEPOSIT_INFO, DEPOSIT_VALUE, }; -use coconut_interface::BlindSignRequestBody; use credentials::coconut::bandwidth::BandwidthVoucher; use crypto::asymmetric::encryption; use crypto::asymmetric::identity::{self, Signature}; +use validator_api_requests::coconut::BlindSignRequestBody; use validator_client::nymd::TxResponse; use super::error::{CoconutError, Result}; diff --git a/validator-api/src/coconut/mod.rs b/validator-api/src/coconut/mod.rs index 8d98cf977f..f4c8203d2d 100644 --- a/validator-api/src/coconut/mod.rs +++ b/validator-api/src/coconut/mod.rs @@ -13,10 +13,7 @@ use crate::coconut::error::{CoconutError, Result}; use crate::ValidatorApiStorage; use coconut_interface::{ - Attribute, BlindSignRequest, BlindSignRequestBody, BlindedSignature, BlindedSignatureResponse, - ExecuteReleaseFundsRequestBody, KeyPair, Parameters, ProposeReleaseFundsRequestBody, - ProposeReleaseFundsResponse, VerificationKey, VerificationKeyResponse, VerifyCredentialBody, - VerifyCredentialResponse, + Attribute, BlindSignRequest, BlindedSignature, KeyPair, Parameters, VerificationKey, }; use config::defaults::VALIDATOR_API_VERSION; use credentials::coconut::params::{ @@ -26,6 +23,11 @@ use credentials::obtain_aggregate_verification_key; use crypto::asymmetric::encryption; use crypto::shared_key::new_ephemeral_shared_key; use crypto::symmetric::stream_cipher; +use validator_api_requests::coconut::{ + BlindSignRequestBody, BlindedSignatureResponse, CosmosAddressResponse, + ExecuteReleaseFundsRequestBody, ProposeReleaseFundsRequestBody, ProposeReleaseFundsResponse, + VerificationKeyResponse, VerifyCredentialBody, VerifyCredentialResponse, +}; use validator_client::validator_api::routes::{BANDWIDTH, COCONUT_ROUTES}; use getset::{CopyGetters, Getters}; @@ -170,6 +172,7 @@ impl InternalSignRequest { routes![ post_blind_sign, get_verification_key, + get_cosmos_address, post_partial_bandwidth_credential, verify_bandwidth_credential, post_propose_release_funds, @@ -248,6 +251,13 @@ pub async fn get_verification_key( ))) } +#[get("/cosmos-address")] +pub async fn get_cosmos_address(state: &RocketState) -> Result> { + Ok(Json(CosmosAddressResponse::new( + state.client.address().await, + ))) +} + #[post("/verify-bandwidth-credential", data = "")] pub async fn verify_bandwidth_credential( verify_credential_body: Json, diff --git a/validator-api/src/coconut/tests.rs b/validator-api/src/coconut/tests.rs index 021902e32d..61fdb6dc4c 100644 --- a/validator-api/src/coconut/tests.rs +++ b/validator-api/src/coconut/tests.rs @@ -7,7 +7,6 @@ use coconut_bandwidth_contract_common::events::{ DEPOSITED_FUNDS_EVENT_TYPE, DEPOSIT_ENCRYPTION_KEY, DEPOSIT_IDENTITY_KEY, DEPOSIT_INFO, DEPOSIT_VALUE, }; -use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse}; use config::defaults::VOUCHER_INFO; use credentials::coconut::bandwidth::BandwidthVoucher; use credentials::coconut::params::{ @@ -19,7 +18,10 @@ use multisig_contract_common::msg::ProposalResponse; use nymcoconut::{ prepare_blind_sign, ttp_keygen, Base58, BlindSignRequest, BlindedSignature, KeyPair, Parameters, }; -use validator_client::nymd::{tx::Hash, DeliverTx, Event, Fee, Tag, TxResponse}; +use validator_api_requests::coconut::{ + BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse, +}; +use validator_client::nymd::{tx::Hash, AccountId, DeliverTx, Event, Fee, Tag, TxResponse}; use validator_client::validator_api::routes::{ API_VERSION, BANDWIDTH, COCONUT_BLIND_SIGN, COCONUT_PARTIAL_BANDWIDTH_CREDENTIAL, COCONUT_ROUTES, COCONUT_VERIFICATION_KEY, @@ -49,6 +51,10 @@ impl DummyClient { #[async_trait] impl super::client::Client for DummyClient { + async fn address(&self) -> AccountId { + todo!() + } + async fn get_tx(&self, tx_hash: &str) -> Result { self.db .read() diff --git a/validator-api/src/nymd_client.rs b/validator-api/src/nymd_client.rs index 7e5037197a..aaa52d3a60 100644 --- a/validator-api/src/nymd_client.rs +++ b/validator-api/src/nymd_client.rs @@ -22,6 +22,7 @@ use multisig_contract_common::msg::ProposalResponse; use validator_client::nymd::{ cosmwasm_client::logs::find_attribute, traits::{MultisigSigningClient, QueryClient}, + AccountId, }; use validator_client::nymd::{ hash::{Hash, SHA256_HASH_SIZE}, @@ -431,6 +432,10 @@ impl crate::coconut::client::Client for Client where C: SigningCosmWasmClient + Sync + Send, { + async fn address(&self) -> AccountId { + self.0.read().await.nymd.address().clone() + } + async fn get_tx( &self, tx_hash: &str, diff --git a/validator-api/validator-api-requests/Cargo.toml b/validator-api/validator-api-requests/Cargo.toml index c22d04eb23..d8c16f4260 100644 --- a/validator-api/validator-api-requests/Cargo.toml +++ b/validator-api/validator-api-requests/Cargo.toml @@ -6,11 +6,17 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -mixnet-contract-common = { path= ".../../../../common/cosmwasm-smart-contracts/mixnet-contract" } +bs58 = "0.4.0" +cosmrs = { version = "0.7.0" } +getset = "0.1.1" schemars = { version = "0.8", features = ["preserve_order"] } serde = "1.0" ts-rs = "6.1.2" +coconut-interface = { path = "../../common/coconut-interface", optional = true } +mixnet-contract-common = { path= ".../../../../common/cosmwasm-smart-contracts/mixnet-contract" } + [features] default = [] +coconut = ["coconut-interface"] generate-ts = [] \ No newline at end of file diff --git a/validator-api/validator-api-requests/src/coconut.rs b/validator-api/validator-api-requests/src/coconut.rs new file mode 100644 index 0000000000..f50fbc9fec --- /dev/null +++ b/validator-api/validator-api-requests/src/coconut.rs @@ -0,0 +1,186 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use cosmrs::AccountId; +use getset::{CopyGetters, Getters}; +use serde::{Deserialize, Serialize}; + +use coconut_interface::{ + error::CoconutInterfaceError, Attribute, Base58, BlindSignRequest, Credential, VerificationKey, +}; + +#[derive(Serialize, Deserialize, Getters, CopyGetters)] +pub struct VerifyCredentialBody { + #[getset(get = "pub")] + credential: Credential, + #[getset(get = "pub")] + proposal_id: u64, +} + +impl VerifyCredentialBody { + pub fn new(credential: Credential, proposal_id: u64) -> VerifyCredentialBody { + VerifyCredentialBody { + credential, + proposal_id, + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct VerifyCredentialResponse { + pub verification_result: bool, +} + +impl VerifyCredentialResponse { + pub fn new(verification_result: bool) -> Self { + VerifyCredentialResponse { + verification_result, + } + } +} + +// All strings are base58 encoded representations of structs +#[derive(Clone, Serialize, Deserialize, Debug, Getters, CopyGetters)] +pub struct BlindSignRequestBody { + #[getset(get = "pub")] + blind_sign_request: BlindSignRequest, + #[getset(get = "pub")] + tx_hash: String, + #[getset(get = "pub")] + signature: String, + public_attributes: Vec, + #[getset(get = "pub")] + public_attributes_plain: Vec, + #[getset(get = "pub")] + total_params: u32, +} + +impl BlindSignRequestBody { + pub fn new( + blind_sign_request: &BlindSignRequest, + tx_hash: String, + signature: String, + public_attributes: &[Attribute], + public_attributes_plain: Vec, + total_params: u32, + ) -> BlindSignRequestBody { + BlindSignRequestBody { + blind_sign_request: blind_sign_request.clone(), + tx_hash, + signature, + 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() + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct BlindedSignatureResponse { + pub remote_key: [u8; 32], + pub encrypted_signature: Vec, +} + +impl BlindedSignatureResponse { + pub fn new(encrypted_signature: Vec, remote_key: [u8; 32]) -> BlindedSignatureResponse { + BlindedSignatureResponse { + encrypted_signature, + remote_key, + } + } + + pub fn to_base58_string(&self) -> String { + bs58::encode(&self.to_bytes()).into_string() + } + + pub fn from_base58_string>(val: I) -> Result { + let bytes = bs58::decode(val).into_vec()?; + Self::from_bytes(&bytes) + } + + pub fn to_bytes(&self) -> Vec { + let mut bytes = self.remote_key.to_vec(); + bytes.extend_from_slice(&self.encrypted_signature); + bytes + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() < 32 { + return Err(CoconutInterfaceError::InvalidByteLength(bytes.len(), 32)); + } + let mut remote_key = [0u8; 32]; + remote_key.copy_from_slice(&bytes[..32]); + let encrypted_signature = bytes[32..].to_vec(); + Ok(BlindedSignatureResponse { + remote_key, + encrypted_signature, + }) + } +} + +#[derive(Serialize, Deserialize)] +pub struct VerificationKeyResponse { + pub key: VerificationKey, +} + +impl VerificationKeyResponse { + pub fn new(key: VerificationKey) -> VerificationKeyResponse { + VerificationKeyResponse { key } + } +} + +#[derive(Serialize, Deserialize)] +pub struct CosmosAddressResponse { + pub addr: AccountId, +} + +impl CosmosAddressResponse { + pub fn new(addr: AccountId) -> CosmosAddressResponse { + CosmosAddressResponse { addr } + } +} + +#[derive(Serialize, Deserialize, Getters, CopyGetters)] +pub struct ProposeReleaseFundsRequestBody { + #[getset(get = "pub")] + credential: Credential, +} + +impl ProposeReleaseFundsRequestBody { + pub fn new(credential: Credential) -> Self { + ProposeReleaseFundsRequestBody { credential } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ProposeReleaseFundsResponse { + pub proposal_id: u64, +} + +impl ProposeReleaseFundsResponse { + pub fn new(proposal_id: u64) -> Self { + ProposeReleaseFundsResponse { proposal_id } + } +} + +#[derive(Debug, Serialize, Deserialize, Getters, CopyGetters)] +pub struct ExecuteReleaseFundsRequestBody { + #[getset(get = "pub")] + proposal_id: u64, +} + +impl ExecuteReleaseFundsRequestBody { + pub fn new(proposal_id: u64) -> Self { + ExecuteReleaseFundsRequestBody { proposal_id } + } +} diff --git a/validator-api/validator-api-requests/src/lib.rs b/validator-api/validator-api-requests/src/lib.rs index 9beea87f0d..b7eba0b27a 100644 --- a/validator-api/validator-api-requests/src/lib.rs +++ b/validator-api/validator-api-requests/src/lib.rs @@ -1,4 +1,6 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +#[cfg(feature = "coconut")] +pub mod coconut; pub mod models;