Compare commits

..

4 Commits

Author SHA1 Message Date
Jędrzej Stuczyński 2cc99b486e being VERY explicit about loading coconut keys 2023-12-14 10:09:52 +00:00
Jędrzej Stuczyński 556d980c01 fixed node indexing 2023-12-14 09:27:39 +00:00
Jędrzej Stuczyński b86ae7520e hardcoded migration data 2023-12-14 09:05:47 +00:00
Jędrzej Stuczyński 43da0e3aa7 ignore dkg 2023-12-14 08:30:49 +00:00
488 changed files with 9690 additions and 33551 deletions
-21
View File
@@ -1,21 +0,0 @@
name: ci-cargo-deny
on: [workflow_dispatch]
jobs:
cargo-deny:
runs-on: ubuntu-22.04
strategy:
matrix:
checks:
# - advisories
- licenses
- bans sources
continue-on-error: ${{ matrix.checks == 'licenses' }}
steps:
- uses: actions/checkout@v3
- uses: EmbarkStudios/cargo-deny-action@v1
with:
log-level: warn
command: check ${{ matrix.checks }}
argument: --all-features
-3
View File
@@ -17,9 +17,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install yarn in root
run: cd ../.. yarn install
- name: Install npm
run: npm install
-1
View File
@@ -9,7 +9,6 @@
target
.env
.env.dev
envs/devnet.env
/.vscode/settings.json
validator/.vscode
sample-configs/validator-config.toml
Generated
+295 -275
View File
File diff suppressed because it is too large Load Diff
+2 -19
View File
@@ -67,7 +67,6 @@ members = [
"common/nymsphinx/params",
"common/nymsphinx/routing",
"common/nymsphinx/types",
"common/nyxd-scraper",
"common/pemstore",
"common/socks5-client-core",
"common/socks5/proxy-helpers",
@@ -102,7 +101,6 @@ members = [
"nym-node",
"nym-node/nym-node-requests",
"nym-outfox",
"nym-validator-rewarder",
"tools/internal/ssl-inject",
"tools/internal/sdk-version-bump",
"tools/nym-cli",
@@ -125,7 +123,6 @@ default-members = [
"nym-api",
"tools/nymvisor",
"explorer-api",
"nym-validator-rewarder",
]
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles"]
@@ -162,12 +159,10 @@ reqwest = "0.11.22"
schemars = "0.8.1"
serde = "1.0.152"
serde_json = "1.0.91"
sqlx = "0.6.3"
tap = "1.0.1"
time = "0.3.30"
thiserror = "1.0.48"
tokio = "1.33.0"
tokio-util = "0.7.10"
tokio = "1.24.1"
tokio-tungstenite = "0.20.1"
tracing = "0.1.37"
tungstenite = { version = "0.20.1", default-features = false }
@@ -177,14 +172,6 @@ utoipa-swagger-ui = "3.1.5"
url = "2.4"
zeroize = "1.6.0"
# coconut/DKG related
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch ="feature/gt-serialization-0.8.0" }
group = "0.13.0"
ff = "0.13.0"
# cosmwasm-related
cosmwasm-derive = "=1.3.0"
cosmwasm-schema = "=1.3.0"
@@ -203,11 +190,7 @@ cw-controllers = { version = "=1.1.0" }
# cosmrs-related
bip32 = "0.5.1"
# temporarily using a fork again (yay.) because we need staking and slashing support
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch ="nym-temp/all-validator-features" }
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
tendermint = "0.34" # same version as used by cosmrs
cosmrs = "=0.15.0"
tendermint-rpc = "0.34" # same version as used by cosmrs
prost = "0.12"
-70
View File
@@ -1,70 +0,0 @@
<html>
<head>
<style>
@media (prefers-color-scheme: dark) {
body {
background: #333;
color: white;
}
a {
color: skyblue;
}
}
.container {
font-family: sans-serif;
max-width: 800px;
margin: 0 auto;
}
.intro {
text-align: center;
}
.licenses-list {
list-style-type: none;
margin: 0;
padding: 0;
}
.license-used-by {
margin-top: -10px;
}
.license-text {
max-height: 200px;
overflow-y: scroll;
white-space: pre-wrap;
}
</style>
</head>
<body>
<main class="container">
<div class="intro">
<h1>Third Party Licenses</h1>
<p>This page lists the licenses of the projects used in cargo-about.</p>
</div>
<h2>Overview of licenses:</h2>
<ul class="licenses-overview">
{{#each overview}}
<li><a href="#{{id}}">{{name}}</a> ({{count}})</li>
{{/each}}
</ul>
<h2>All license text:</h2>
<ul class="licenses-list">
{{#each licenses}}
<li class="license">
<h3 id="{{id}}">{{name}}</h3>
<h4>Used by:</h4>
<ul class="license-used-by">
{{#each used_by}}
<li><a href="{{#if crate.repository}} {{crate.repository}} {{else}} https://crates.io/crates/{{crate.name}} {{/if}}">{{crate.name}} {{crate.version}}</a></li>
{{/each}}
</ul>
<pre class="license-text">{{text}}</pre>
</li>
{{/each}}
</ul>
</main>
</body>
</html>
-19
View File
@@ -1,19 +0,0 @@
private = { ignore = true }
accepted = [
"0BSD",
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"CC0-1.0",
"ISC",
"MIT",
"MPL-2.0",
"Unicode-DFS-2016",
"OpenSSL",
]
workarounds = [
"ring",
"rustls",
]
-1
View File
@@ -5,7 +5,6 @@ authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej St
description = "Implementation of the Nym Client"
edition = "2021"
rust-version = "1.65"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -1667,9 +1667,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
"dev": true,
"funding": [
{
@@ -5800,9 +5800,9 @@
}
},
"follow-redirects": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
"dev": true
},
"forwarded": {
@@ -3,7 +3,6 @@ name = "nym-client-websocket-requests"
version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-1
View File
@@ -5,7 +5,6 @@ authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021"
rust-version = "1.56"
license.workspace = true
[dependencies]
clap = { workspace = true, features = ["cargo", "derive"] }
-4
View File
@@ -1,4 +0,0 @@
module.exports = {
ConfigHandler: require('./config/configHandler.ts'),
RestClient: require('./restClient/RestClient.ts')
};
-1
View File
@@ -2,7 +2,6 @@
name = "async-file-watcher"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-2
View File
@@ -2,7 +2,6 @@
name = "nym-bandwidth-controller"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,7 +10,6 @@ bip39 = { workspace = true }
rand = "0.7.3"
thiserror = { workspace = true }
url = { workspace = true }
zeroize = { workspace = true }
nym-coconut-interface = { path = "../coconut-interface" }
nym-credential-storage = { path = "../credential-storage" }
+15 -12
View File
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError;
use nym_coconut_interface::Base58;
use nym_coconut_interface::{Base58, Parameters};
use nym_credential_storage::storage::Storage;
use nym_credentials::coconut::bandwidth::BandwidthVoucher;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_credentials::coconut::utils::obtain_aggregate_signature;
use nym_crypto::asymmetric::{encryption, identity};
use nym_network_defaults::VOUCHER_INFO;
@@ -12,8 +12,10 @@ use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nyxd::contract_traits::CoconutBandwidthSigningClient;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use nym_validator_client::nyxd::Coin;
use nym_validator_client::nyxd::Hash;
use rand::rngs::OsRng;
use state::State;
use state::{KeyPair, State};
use std::str::FromStr;
pub mod state;
@@ -22,29 +24,30 @@ where
C: CoconutBandwidthSigningClient + Sync,
{
let mut rng = OsRng;
let signing_key = identity::PrivateKey::new(&mut rng);
let encryption_key = encryption::PrivateKey::new(&mut rng);
let params = BandwidthVoucher::default_parameters();
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
let voucher_value = amount.amount.to_string();
let tx_hash = client
.deposit(
amount,
String::from(VOUCHER_INFO),
signing_key.public_key().to_base58_string(),
encryption_key.public_key().to_base58_string(),
signing_keypair.public_key.clone(),
encryption_keypair.public_key.clone(),
None,
)
.await?
.transaction_hash;
.transaction_hash
.to_string();
let voucher = BandwidthVoucher::new(
&params,
voucher_value,
VOUCHER_INFO.to_string(),
tx_hash,
signing_key,
encryption_key,
Hash::from_str(&tx_hash).map_err(|_| BandwidthControllerError::InvalidTxHash)?,
identity::PrivateKey::from_base58_string(&signing_keypair.private_key)?,
encryption::PrivateKey::from_base58_string(&encryption_keypair.private_key)?,
);
let state = State { voucher, params };
@@ -2,7 +2,32 @@
// SPDX-License-Identifier: Apache-2.0
use nym_coconut_interface::Parameters;
use nym_credentials::coconut::bandwidth::BandwidthVoucher;
use nym_credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use nym_crypto::asymmetric::{encryption, identity};
pub(crate) struct KeyPair {
pub public_key: String,
pub private_key: String,
}
impl From<identity::KeyPair> for KeyPair {
fn from(kp: identity::KeyPair) -> Self {
Self {
public_key: kp.public_key().to_base58_string(),
private_key: kp.private_key().to_base58_string(),
}
}
}
impl From<encryption::KeyPair> for KeyPair {
fn from(kp: encryption::KeyPair) -> Self {
Self {
public_key: kp.public_key().to_base58_string(),
private_key: kp.private_key().to_base58_string(),
}
}
}
pub struct State {
pub voucher: BandwidthVoucher,
@@ -13,7 +38,7 @@ impl State {
pub fn new(voucher: BandwidthVoucher) -> Self {
State {
voucher,
params: BandwidthVoucher::default_parameters(),
params: Parameters::new(TOTAL_ATTRIBUTES).unwrap(),
}
}
}
+6 -9
View File
@@ -7,7 +7,6 @@ use nym_credential_storage::storage::Storage;
use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use std::str::FromStr;
use zeroize::Zeroizing;
use {
nym_coconut_interface::Base58,
nym_credentials::coconut::{
@@ -47,12 +46,10 @@ impl<C, St: Storage> BandwidthController<C, St> {
let voucher_value = u64::from_str(&bandwidth_credential.voucher_value)
.map_err(|_| StorageError::InconsistentData)?;
let voucher_info = bandwidth_credential.voucher_info.clone();
let serial_number = Zeroizing::new(nym_coconut_interface::Attribute::try_from_bs58(
bandwidth_credential.serial_number,
)?);
let binding_number = Zeroizing::new(nym_coconut_interface::Attribute::try_from_bs58(
bandwidth_credential.binding_number,
)?);
let serial_number =
nym_coconut_interface::Attribute::try_from_bs58(bandwidth_credential.serial_number)?;
let binding_number =
nym_coconut_interface::Attribute::try_from_bs58(bandwidth_credential.binding_number)?;
let signature =
nym_coconut_interface::Signature::try_from_bs58(bandwidth_credential.signature)?;
let epoch_id = u64::from_str(&bandwidth_credential.epoch_id)
@@ -67,8 +64,8 @@ impl<C, St: Storage> BandwidthController<C, St> {
prepare_for_spending(
voucher_value,
voucher_info,
&serial_number,
&binding_number,
serial_number,
binding_number,
epoch_id,
&signature,
&verification_key,
+1 -2
View File
@@ -35,10 +35,9 @@ opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
[build-dependencies]
vergen = { version = "=8.2.6", default-features = false, features = [
vergen = { version = "=7.4.3", default-features = false, features = [
"build",
"git",
"gitcl",
"rustc",
"cargo",
] }
+7 -8
View File
@@ -1,14 +1,13 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::EmitBuilder;
use vergen::{vergen, Config};
fn main() {
EmitBuilder::builder()
.all_build()
.all_git()
.all_rustc()
.all_cargo()
.emit()
.expect("failed to extract build metadata");
let mut config = Config::default();
if std::env::var("DOCS_RS").is_ok() {
// If we don't have access to git information, such as in a docs.rs build, don't error
*config.git_mut().skip_if_error_mut() = true;
}
vergen(config).expect("failed to extract build metadata");
}
+10 -10
View File
@@ -40,9 +40,9 @@ pub struct BinaryBuildInformation {
/// Provides the rustc channel that was used for the build, for example `nightly`.
pub rustc_channel: &'static str,
// VERGEN_CARGO_DEBUG
/// Provides the cargo debug mode that was used for the build.
pub cargo_debug: &'static str,
// VERGEN_CARGO_PROFILE
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: &'static str,
}
impl BinaryBuildInformation {
@@ -57,7 +57,7 @@ impl BinaryBuildInformation {
commit_branch: env!("VERGEN_GIT_BRANCH"),
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_debug: env!("VERGEN_CARGO_DEBUG"),
cargo_profile: env!("VERGEN_CARGO_PROFILE"),
}
}
@@ -71,7 +71,7 @@ impl BinaryBuildInformation {
commit_branch: self.commit_branch.to_owned(),
rustc_version: self.rustc_version.to_owned(),
rustc_channel: self.rustc_channel.to_owned(),
cargo_debug: self.cargo_debug.to_owned(),
cargo_profile: self.cargo_profile.to_owned(),
}
}
@@ -115,9 +115,9 @@ pub struct BinaryBuildInformationOwned {
/// Provides the rustc channel that was used for the build, for example `nightly`.
pub rustc_channel: String,
// VERGEN_CARGO_DEBUG
/// Provides the cargo debug mode that was used for the build.
pub cargo_debug: String,
// VERGEN_CARGO_PROFILE
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: String,
}
impl Display for BinaryBuildInformationOwned {
@@ -151,8 +151,8 @@ impl Display for BinaryBuildInformationOwned {
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Debug:",
self.cargo_debug,
"cargo Profile:",
self.cargo_profile,
)
}
}
+2 -3
View File
@@ -4,7 +4,6 @@ version = "1.1.15"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021"
rust-version = "1.66"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -59,7 +58,7 @@ features = ["time"]
version = "0.20.1"
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
workspace = true
version = "0.6.2"
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]
optional = true
@@ -90,7 +89,7 @@ tempfile = "3.1.0"
[build-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
[features]
default = []
@@ -1,8 +1,6 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![allow(unused_imports)]
use std::time::Duration;
pub use wasmtimer::{std::Instant, tokio::*};
@@ -127,9 +127,7 @@ impl ActionController {
.insert(frag_id, (Arc::new(pending_ack), None))
.is_some()
{
// This used to be a panic, however since we've seen this actually happen in the
// wild, let's not take the whole client (and possibly gateway) down because of it.
error!("Tried to insert duplicate pending ack! This should not be possible!")
panic!("Tried to insert duplicate pending ack")
}
}
}
@@ -3,7 +3,6 @@ name = "nym-gateway-client"
version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+2 -3
View File
@@ -3,15 +3,14 @@ name = "nym-mixnet-client"
version = "0.1.0"
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
futures = { workspace = true }
log = { workspace = true }
tokio = { workspace = true, features = ["time", "net", "rt"] }
tokio-util = { workspace = true, features = ["codec"] }
tokio = { version = "1.24.1", features = ["time", "net", "rt"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
# internal
nym-sphinx = { path = "../../nymsphinx" }
@@ -4,7 +4,6 @@ version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021"
rust-version = "1.56"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -42,14 +42,6 @@ pub struct Config {
nyxd_config: nyxd::Config,
}
impl TryFrom<NymNetworkDetails> for Config {
type Error = ValidatorClientError;
fn try_from(value: NymNetworkDetails) -> Result<Self, Self::Error> {
Config::try_from_nym_network_details(&value)
}
}
impl Config {
pub fn try_from_nym_network_details(
details: &NymNetworkDetails,
@@ -5,24 +5,16 @@ use crate::nym_api::error::NymAPIError;
use crate::nym_api::routes::{CORE_STATUS_COUNT, SINCE_ARG};
use async_trait::async_trait;
use http_api_client::{ApiClient, NO_PARAMS};
pub use nym_api_requests::{
coconut::{
models::{
EpochCredentialsResponse, IssuedCredential, IssuedCredentialBody,
IssuedCredentialResponse, IssuedCredentialsResponse,
},
BlindSignRequestBody, BlindedSignatureResponse, CredentialsRequestBody,
VerifyCredentialBody, VerifyCredentialResponse,
},
models::{
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
StakeSaturationResponse, UptimeResponse,
},
use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_api_requests::models::{
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
StakeSaturationResponse, UptimeResponse,
};
pub use nym_coconut_dkg_common::types::EpochId;
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
use nym_name_service_common::response::NamesListResponse;
@@ -407,60 +399,6 @@ pub trait NymApiClientExt: ApiClient {
.await
}
async fn epoch_credentials(
&self,
dkg_epoch: EpochId,
) -> Result<EpochCredentialsResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::COCONUT_ROUTES,
routes::BANDWIDTH,
routes::COCONUT_EPOCH_CREDENTIALS,
&dkg_epoch.to_string(),
],
NO_PARAMS,
)
.await
}
async fn issued_credential(
&self,
credential_id: i64,
) -> Result<IssuedCredentialResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::COCONUT_ROUTES,
routes::BANDWIDTH,
routes::COCONUT_ISSUED_CREDENTIAL,
&credential_id.to_string(),
],
NO_PARAMS,
)
.await
}
async fn issued_credentials(
&self,
credential_ids: Vec<i64>,
) -> Result<IssuedCredentialsResponse, NymAPIError> {
self.post_json(
&[
routes::API_VERSION,
routes::COCONUT_ROUTES,
routes::BANDWIDTH,
routes::COCONUT_ISSUED_CREDENTIALS,
],
NO_PARAMS,
&CredentialsRequestBody {
credential_ids,
pagination: None,
},
)
.await
}
async fn get_service_providers(&self) -> Result<ServicesListResponse, NymAPIError> {
log::trace!("Getting service providers");
self.get_json(&[routes::API_VERSION, routes::SERVICE_PROVIDERS], NO_PARAMS)
@@ -17,9 +17,6 @@ pub const BANDWIDTH: &str = "bandwidth";
pub const COCONUT_BLIND_SIGN: &str = "blind-sign";
pub const COCONUT_VERIFY_BANDWIDTH_CREDENTIAL: &str = "verify-bandwidth-credential";
pub const COCONUT_EPOCH_CREDENTIALS: &str = "epoch-credentials";
pub const COCONUT_ISSUED_CREDENTIAL: &str = "issued-credential";
pub const COCONUT_ISSUED_CREDENTIALS: &str = "issued-credentials";
pub const STATUS_ROUTES: &str = "status";
pub const MIXNODE: &str = "mixnode";
@@ -8,8 +8,6 @@ use cosmwasm_std::{Fraction, Uint128};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::Div;
use std::str::FromStr;
use thiserror::Error;
#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq)]
pub struct MismatchedDenoms;
@@ -128,37 +126,6 @@ impl From<CosmWasmCoin> for Coin {
}
}
// unfortunately cosmwasm didn't re-export this correct so we just redefine its
#[derive(Error, Debug, PartialEq, Eq)]
pub enum CoinFromStrError {
#[error("Missing denominator")]
MissingDenom,
#[error("Missing amount or non-digit characters in amount")]
MissingAmount,
#[error("Invalid amount: {0}")]
InvalidAmount(#[from] std::num::ParseIntError),
}
impl FromStr for Coin {
type Err = CoinFromStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let pos = s
.find(|c: char| !c.is_ascii_digit())
.ok_or(CoinFromStrError::MissingDenom)?;
let (amount, denom) = s.split_at(pos);
if amount.is_empty() {
return Err(CoinFromStrError::MissingAmount);
}
Ok(Coin {
amount: amount.parse::<u128>()?,
denom: denom.to_string(),
})
}
}
pub trait CoinConverter {
type Target;
@@ -32,7 +32,7 @@ pub trait CoconutBandwidthSigningClient {
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = CoconutBandwidthExecuteMsg::DepositFunds {
data: DepositData::new(info, verification_key, encryption_key),
data: DepositData::new(info.to_string(), verification_key, encryption_key),
};
self.execute_coconut_bandwidth_contract(
fee,
@@ -1,4 +1,4 @@
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::collect_paged;
@@ -7,21 +7,13 @@ use crate::nyxd::error::NyxdError;
use crate::nyxd::CosmWasmClient;
use async_trait::async_trait;
use cosmrs::AccountId;
use nym_coconut_dkg_common::types::ChunkIndex;
use serde::Deserialize;
pub use nym_coconut_dkg_common::{
dealer::{DealerDetailsResponse, PagedDealerResponse},
dealing::{
DealerDealingsStatusResponse, DealingChunkResponse, DealingChunkStatusResponse,
DealingMetadataResponse, DealingStatusResponse,
},
msg::QueryMsg as DkgQueryMsg,
types::{
DealerDetails, DealingIndex, Epoch, EpochId, EpochState, InitialReplacementData, State,
},
verification_key::{ContractVKShare, PagedVKSharesResponse, VkShareResponse},
use nym_coconut_dkg_common::dealer::{
ContractDealing, DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse,
};
use nym_coconut_dkg_common::msg::QueryMsg as DkgQueryMsg;
use nym_coconut_dkg_common::types::{DealerDetails, Epoch, EpochId, InitialReplacementData};
use nym_coconut_dkg_common::verification_key::{ContractVKShare, PagedVKSharesResponse};
use serde::Deserialize;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
@@ -30,16 +22,10 @@ pub trait DkgQueryClient {
where
for<'a> T: Deserialize<'a>;
async fn get_state(&self) -> Result<State, NyxdError> {
let request = DkgQueryMsg::GetState {};
self.query_dkg_contract(request).await
}
async fn get_current_epoch(&self) -> Result<Epoch, NyxdError> {
let request = DkgQueryMsg::GetCurrentEpochState {};
self.query_dkg_contract(request).await
}
async fn get_current_epoch_threshold(&self) -> Result<Option<u64>, NyxdError> {
let request = DkgQueryMsg::GetCurrentEpochThreshold {};
self.query_dkg_contract(request).await
@@ -78,86 +64,17 @@ pub trait DkgQueryClient {
self.query_dkg_contract(request).await
}
async fn get_dealings_metadata(
async fn get_dealings_paged(
&self,
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
) -> Result<DealingMetadataResponse, NyxdError> {
let request = DkgQueryMsg::GetDealingsMetadata {
epoch_id,
dealer,
dealing_index,
idx: u64,
start_after: Option<String>,
limit: Option<u32>,
) -> Result<PagedDealingsResponse, NyxdError> {
let request = DkgQueryMsg::GetDealing {
idx,
limit,
start_after,
};
self.query_dkg_contract(request).await
}
async fn get_dealer_dealings_status(
&self,
epoch_id: EpochId,
dealer: String,
) -> Result<DealerDealingsStatusResponse, NyxdError> {
let request = DkgQueryMsg::GetDealerDealingsStatus { epoch_id, dealer };
self.query_dkg_contract(request).await
}
async fn get_dealing_status(
&self,
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
) -> Result<DealingStatusResponse, NyxdError> {
let request = DkgQueryMsg::GetDealingStatus {
epoch_id,
dealer,
dealing_index,
};
self.query_dkg_contract(request).await
}
async fn get_dealing_chunk_status(
&self,
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
chunk_index: ChunkIndex,
) -> Result<DealingChunkStatusResponse, NyxdError> {
let request = DkgQueryMsg::GetDealingChunkStatus {
epoch_id,
dealer,
dealing_index,
chunk_index,
};
self.query_dkg_contract(request).await
}
async fn get_dealing_chunk(
&self,
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
chunk_index: ChunkIndex,
) -> Result<DealingChunkResponse, NyxdError> {
let request = DkgQueryMsg::GetDealingChunk {
epoch_id,
dealer,
dealing_index,
chunk_index,
};
self.query_dkg_contract(request).await
}
async fn get_vk_share(
&self,
epoch_id: EpochId,
owner: String,
) -> Result<VkShareResponse, NyxdError> {
let request = DkgQueryMsg::GetVerificationKey { epoch_id, owner };
self.query_dkg_contract(request).await
}
@@ -174,11 +91,6 @@ pub trait DkgQueryClient {
};
self.query_dkg_contract(request).await
}
async fn get_contract_cw2_version(&self) -> Result<cw2::ContractVersion, NyxdError> {
self.query_dkg_contract(DkgQueryMsg::GetCW2ContractVersion {})
.await
}
}
// extension trait to the query client to deal with the paged queries
@@ -194,6 +106,10 @@ pub trait PagedDkgQueryClient: DkgQueryClient {
collect_paged!(self, get_past_dealers_paged, dealers)
}
async fn get_all_epoch_dealings(&self, idx: u64) -> Result<Vec<ContractDealing>, NyxdError> {
collect_paged!(self, get_dealings_paged, dealings, idx)
}
async fn get_all_verification_key_shares(
&self,
epoch_id: EpochId,
@@ -227,7 +143,6 @@ where
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::IgnoreValue;
use nym_coconut_dkg_common::msg::QueryMsg;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
@@ -236,7 +151,6 @@ mod tests {
msg: DkgQueryMsg,
) {
match msg {
DkgQueryMsg::GetState {} => client.get_state().ignore(),
DkgQueryMsg::GetCurrentEpochState {} => client.get_current_epoch().ignore(),
DkgQueryMsg::GetCurrentEpochThreshold {} => {
client.get_current_epoch_threshold().ignore()
@@ -251,42 +165,11 @@ mod tests {
DkgQueryMsg::GetPastDealers { limit, start_after } => {
client.get_past_dealers_paged(start_after, limit).ignore()
}
DkgQueryMsg::GetDealingStatus {
epoch_id,
dealer,
dealing_index,
} => client
.get_dealing_status(epoch_id, dealer, dealing_index)
.ignore(),
DkgQueryMsg::GetDealingsMetadata {
epoch_id,
dealer,
dealing_index,
} => client
.get_dealings_metadata(epoch_id, dealer, dealing_index)
.ignore(),
QueryMsg::GetDealerDealingsStatus { epoch_id, dealer } => {
client.get_dealer_dealings_status(epoch_id, dealer).ignore()
}
DkgQueryMsg::GetDealingChunkStatus {
epoch_id,
dealer,
dealing_index,
chunk_index,
} => client
.get_dealing_chunk_status(epoch_id, dealer, dealing_index, chunk_index)
.ignore(),
DkgQueryMsg::GetDealingChunk {
epoch_id,
dealer,
dealing_index,
chunk_index,
} => client
.get_dealing_chunk(epoch_id, dealer, dealing_index, chunk_index)
.ignore(),
DkgQueryMsg::GetVerificationKey { epoch_id, owner } => {
client.get_vk_share(epoch_id, owner).ignore()
}
DkgQueryMsg::GetDealing {
idx,
limit,
start_after,
} => client.get_dealings_paged(idx, start_after, limit).ignore(),
DkgQueryMsg::GetVerificationKeys {
epoch_id,
limit,
@@ -294,7 +177,6 @@ mod tests {
} => client
.get_vk_shares_paged(epoch_id, start_after, limit)
.ignore(),
DkgQueryMsg::GetCW2ContractVersion {} => client.get_contract_cw2_version().ignore(),
};
}
}
@@ -8,11 +8,11 @@ use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
use crate::signing::signer::OfflineSigner;
use async_trait::async_trait;
use cosmrs::AccountId;
use nym_coconut_dkg_common::dealing::{DealingChunkInfo, PartialContractDealing};
use cosmwasm_std::Addr;
use nym_coconut_dkg_common::msg::ExecuteMsg as DkgExecuteMsg;
use nym_coconut_dkg_common::types::{DealingIndex, EncodedBTEPublicKeyWithProof};
use nym_coconut_dkg_common::types::EncodedBTEPublicKeyWithProof;
use nym_coconut_dkg_common::verification_key::VerificationKeyShare;
use nym_contracts_common::IdentityKey;
use nym_contracts_common::dealings::ContractSafeBytes;
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
@@ -25,13 +25,6 @@ pub trait DkgSigningClient {
funds: Vec<Coin>,
) -> Result<ExecuteResult, NyxdError>;
async fn initiate_dkg(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::InitiateDkg {};
self.execute_dkg_contract(fee, req, "initiating the DKG".to_string(), vec![])
.await
}
async fn advance_dkg_epoch_state(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::AdvanceEpochState {};
@@ -49,14 +42,12 @@ pub trait DkgSigningClient {
async fn register_dealer(
&self,
bte_key: EncodedBTEPublicKeyWithProof,
identity_key: IdentityKey,
announce_address: String,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::RegisterDealer {
bte_key_with_proof: bte_key,
identity_key,
announce_address,
resharing,
};
@@ -65,32 +56,18 @@ pub trait DkgSigningClient {
.await
}
async fn submit_dealing_metadata(
async fn submit_dealing_bytes(
&self,
dealing_index: DealingIndex,
chunks: Vec<DealingChunkInfo>,
dealing_bytes: ContractSafeBytes,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::CommitDealingsMetadata {
dealing_index,
chunks,
let req = DkgExecuteMsg::CommitDealing {
dealing_bytes,
resharing,
};
self.execute_dkg_contract(fee, req, "dealing metadata commitment".to_string(), vec![])
.await
}
async fn submit_dealing_chunk(
&self,
chunk: PartialContractDealing,
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::CommitDealingsChunk { chunk, resharing };
self.execute_dkg_contract(fee, req, "dealing chunk commitment".to_string(), vec![])
self.execute_dkg_contract(fee, req, "dealing commitment".to_string(), vec![])
.await
}
@@ -117,10 +94,9 @@ pub trait DkgSigningClient {
resharing: bool,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
let req = DkgExecuteMsg::VerifyVerificationKeyShare {
owner: owner.to_string(),
resharing,
};
// the call to unchecked is fine as we're converting from pre-validated `AccountId`
let owner = Addr::unchecked(owner.to_string());
let req = DkgExecuteMsg::VerifyVerificationKeyShare { owner, resharing };
self.execute_dkg_contract(
fee,
@@ -170,36 +146,28 @@ mod tests {
msg: DkgExecuteMsg,
) {
match msg {
DkgExecuteMsg::InitiateDkg {} => client.initiate_dkg(None).ignore(),
DkgExecuteMsg::RegisterDealer {
bte_key_with_proof,
identity_key,
announce_address,
resharing,
} => client
.register_dealer(
bte_key_with_proof,
identity_key,
announce_address,
resharing,
None,
)
.register_dealer(bte_key_with_proof, announce_address, resharing, None)
.ignore(),
DkgExecuteMsg::CommitDealingsMetadata {
dealing_index,
chunks,
DkgExecuteMsg::CommitDealing {
dealing_bytes,
resharing,
} => client
.submit_dealing_metadata(dealing_index, chunks, resharing, None)
.submit_dealing_bytes(dealing_bytes, resharing, None)
.ignore(),
DkgExecuteMsg::CommitDealingsChunk { chunk, resharing } => {
client.submit_dealing_chunk(chunk, resharing, None).ignore()
}
DkgExecuteMsg::CommitVerificationKeyShare { share, resharing } => client
.submit_verification_key_share(share, resharing, None)
.ignore(),
DkgExecuteMsg::VerifyVerificationKeyShare { owner, resharing } => client
.verify_verification_key_share(&owner.parse().unwrap(), resharing, None)
.verify_verification_key_share(
&owner.into_string().parse().unwrap(),
resharing,
None,
)
.ignore(),
DkgExecuteMsg::SurpassedThreshold {} => client.surpass_threshold(None).ignore(),
DkgExecuteMsg::AdvanceEpochState {} => client.advance_dkg_epoch_state(None).ignore(),
@@ -8,26 +8,26 @@ use std::str::FromStr;
// TODO: all of those could/should be derived via a macro
// query clients
pub mod coconut_bandwidth_query_client;
pub mod dkg_query_client;
pub mod ephemera_query_client;
pub mod group_query_client;
pub mod mixnet_query_client;
pub mod multisig_query_client;
pub mod name_service_query_client;
pub mod sp_directory_query_client;
pub mod vesting_query_client;
mod coconut_bandwidth_query_client;
mod dkg_query_client;
mod ephemera_query_client;
mod group_query_client;
mod mixnet_query_client;
mod multisig_query_client;
mod name_service_query_client;
mod sp_directory_query_client;
mod vesting_query_client;
// signing clients
pub mod coconut_bandwidth_signing_client;
pub mod dkg_signing_client;
pub mod ephemera_signing_client;
pub mod group_signing_client;
pub mod mixnet_signing_client;
pub mod multisig_signing_client;
pub mod name_service_signing_client;
pub mod sp_directory_signing_client;
pub mod vesting_signing_client;
mod coconut_bandwidth_signing_client;
mod dkg_signing_client;
mod ephemera_signing_client;
mod group_signing_client;
mod mixnet_signing_client;
mod multisig_signing_client;
mod name_service_signing_client;
mod sp_directory_signing_client;
mod vesting_signing_client;
// re-export query traits
pub use coconut_bandwidth_query_client::{
@@ -6,8 +6,8 @@ use crate::nyxd::error::NyxdError;
use crate::nyxd::CosmWasmClient;
use async_trait::async_trait;
use cw3::{
ProposalListResponse, ProposalResponse, VoteListResponse, VoteResponse, VoterDetail,
VoterListResponse, VoterResponse,
ProposalListResponse, ProposalResponse, VoteListResponse, VoteResponse, VoterListResponse,
VoterResponse,
};
use cw_utils::ThresholdResponse;
use nym_multisig_contract_common::msg::QueryMsg as MultisigQueryMsg;
@@ -114,26 +114,6 @@ pub trait PagedMultisigQueryClient: MultisigQueryClient {
Ok(proposals)
}
async fn get_all_voters(&self) -> Result<Vec<VoterDetail>, NyxdError> {
let mut voters = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self.list_voters(start_after.take(), None).await?;
let last_voter = paged_response.voters.last().map(|prop| prop.addr.clone());
voters.append(&mut paged_response.voters);
if let Some(start_after_res) = last_voter {
start_after = Some(start_after_res)
} else {
break;
}
}
Ok(voters)
}
}
#[async_trait]
@@ -52,6 +52,10 @@ use wasmtimer::tokio::sleep;
pub const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
pub const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
#[cfg(feature = "http-client")]
#[async_trait]
impl CosmWasmClient for cosmrs::rpc::HttpClient {}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait CosmWasmClient: TendermintRpcClient {
@@ -518,7 +522,3 @@ pub trait CosmWasmClient: TendermintRpcClient {
res.try_into()
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<T> CosmWasmClient for T where T: TendermintRpcClient {}
@@ -425,7 +425,7 @@ where
amount: amount.into_iter().map(Into::into).collect(),
}
.to_any()
.map_err(|_| NyxdError::SerializationError("MsgSend".to_owned()))
.map_err(|_| NyxdError::SerializationError("MsgExecuteContract".to_owned()))
})
.collect::<Result<_, _>>()?;
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::cosmwasm_client::client_traits::SigningCosmWasmClient;
use crate::nyxd::cosmwasm_client::client_traits::{CosmWasmClient, SigningCosmWasmClient};
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Config, GasPrice, Hash, Height};
use crate::rpc::TendermintRpcClient;
@@ -26,7 +26,6 @@ use cosmrs::rpc::{HttpClient, HttpClientUrl};
pub mod client_traits;
mod helpers;
pub mod logs;
pub mod module_traits;
pub mod types;
#[derive(Debug)]
@@ -330,6 +329,14 @@ where
}
}
#[async_trait]
impl<C, S> CosmWasmClient for MaybeSigningClient<C, S>
where
C: TendermintRpcClient + Send + Sync,
S: Send + Sync,
{
}
#[async_trait]
impl<C, S> SigningCosmWasmClient for MaybeSigningClient<C, S>
where
@@ -1,8 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod slashing;
pub mod staking;
pub use staking::query::StakingQueryClient;
// pub use slashing::query
@@ -1,4 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod query;
@@ -1,2 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
@@ -1,8 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod query;
pub use cosmrs::staking::{
QueryHistoricalInfoResponse, QueryValidatorResponse, QueryValidatorsResponse, Validator,
};
@@ -1,78 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::{QueryHistoricalInfoResponse, QueryValidatorResponse, QueryValidatorsResponse};
use crate::nyxd::error::NyxdError;
use crate::nyxd::{CosmWasmClient, PageRequest};
use async_trait::async_trait;
use cosmrs::proto::cosmos::staking::v1beta1::{
QueryHistoricalInfoRequest as ProtoQueryHistoricalInfoRequest,
QueryHistoricalInfoResponse as ProtoQueryHistoricalInfoResponse,
QueryValidatorRequest as ProtoQueryValidatorRequest,
QueryValidatorResponse as ProtoQueryValidatorResponse,
QueryValidatorsRequest as ProtoQueryValidatorsRequest,
QueryValidatorsResponse as ProtoQueryValidatorsResponse,
};
use cosmrs::staking::{QueryHistoricalInfoRequest, QueryValidatorRequest, QueryValidatorsRequest};
use cosmrs::AccountId;
// TODO: change trait restriction from `CosmWasmClient` to `TendermintRpcClient`
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait StakingQueryClient: CosmWasmClient {
async fn historical_info(&self, height: i64) -> Result<QueryHistoricalInfoResponse, NyxdError> {
let path = Some("/cosmos.staking.v1beta1.Query/HistoricalInfo".to_owned());
let req = QueryHistoricalInfoRequest { height };
let res = self
.make_abci_query::<ProtoQueryHistoricalInfoRequest, ProtoQueryHistoricalInfoResponse>(
path,
req.into(),
)
.await?;
Ok(res.try_into()?)
}
async fn validator(
&self,
validator_addr: AccountId,
) -> Result<QueryValidatorResponse, NyxdError> {
let path = Some("/cosmos.staking.v1beta1.Query/Validator".to_owned());
let req = QueryValidatorRequest { validator_addr };
let res = self
.make_abci_query::<ProtoQueryValidatorRequest, ProtoQueryValidatorResponse>(
path,
req.into(),
)
.await?;
Ok(res.try_into()?)
}
async fn validators(
&self,
status: String,
pagination: Option<PageRequest>,
) -> Result<QueryValidatorsResponse, NyxdError> {
let path = Some("/cosmos.staking.v1beta1.Query/Validators".to_owned());
let req = QueryValidatorsRequest { status, pagination };
let res = self
.make_abci_query::<ProtoQueryValidatorsRequest, ProtoQueryValidatorsResponse>(
path,
req.into(),
)
.await?;
Ok(res.try_into()?)
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<T> StakingQueryClient for T where T: CosmWasmClient {}
@@ -1,13 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::nyxd::TxResponse;
pub fn find_tx_attribute(tx: &TxResponse, event_type: &str, attribute_key: &str) -> Option<String> {
let event = tx.tx_result.events.iter().find(|e| e.kind == event_type)?;
let attribute = event
.attributes
.iter()
.find(|attr| attr.key == attribute_key)?;
Some(attribute.value.clone())
}
@@ -29,41 +29,31 @@ use tendermint_rpc::endpoint::*;
use tendermint_rpc::{Error as TendermintRpcError, Order};
use url::Url;
pub use crate::nyxd::{
cosmwasm_client::{
client_traits::{CosmWasmClient, SigningCosmWasmClient},
module_traits::{self, StakingQueryClient},
},
fee::Fee,
};
pub use crate::nyxd::cosmwasm_client::client_traits::{CosmWasmClient, SigningCosmWasmClient};
pub use crate::nyxd::fee::Fee;
pub use crate::rpc::TendermintRpcClient;
pub use coin::Coin;
pub use cosmrs::{
bank::MsgSend,
bip32,
crypto::PublicKey,
query::{PageRequest, PageResponse},
tendermint::{
abci::{response::DeliverTx, types::ExecTxResult, Event, EventAttribute},
block::Height,
hash::{self, Algorithm, Hash},
validator::Info as TendermintValidatorInfo,
Time as TendermintTime,
},
tx::{self, Msg},
AccountId, Any, Coin as CosmosCoin, Denom, Gas,
pub use cosmrs::bank::MsgSend;
pub use cosmrs::tendermint::abci::{
response::DeliverTx, types::ExecTxResult, Event, EventAttribute,
};
pub use cosmrs::tendermint::block::Height;
pub use cosmrs::tendermint::hash::{self, Algorithm, Hash};
pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
pub use cosmrs::tendermint::Time as TendermintTime;
pub use cosmrs::tx::Msg;
pub use cosmrs::tx::{self};
pub use cosmrs::Coin as CosmosCoin;
pub use cosmrs::Gas;
pub use cosmrs::{bip32, AccountId, Denom};
pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use cw2;
pub use cw3;
pub use cw4;
pub use cw_controllers;
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
pub use tendermint_rpc::{
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
query::Query,
Paging, Request, Response, SimpleRequest,
Paging,
};
pub use tendermint_rpc::{Request, Response, SimpleRequest};
#[cfg(feature = "http-client")]
use crate::http_client;
@@ -77,7 +67,6 @@ pub mod contract_traits;
pub mod cosmwasm_client;
pub mod error;
pub mod fee;
pub mod helpers;
#[derive(Debug, Clone)]
pub struct Config {
@@ -103,14 +92,6 @@ impl Config {
}
}
impl TryFrom<NymNetworkDetails> for Config {
type Error = NyxdError;
fn try_from(value: NymNetworkDetails) -> Result<Self, Self::Error> {
Config::try_from_nym_network_details(&value)
}
}
#[derive(Debug)]
pub struct NyxdClient<C, S = NoSigner> {
client: MaybeSigningClient<C, S>,
@@ -742,7 +723,7 @@ where
where
H: Into<Height> + Send,
{
TendermintRpcClient::validators(&self.client, height, paging).await
self.client.validators(height, paging).await
}
async fn latest_consensus_params(
@@ -817,6 +798,14 @@ where
}
}
#[async_trait]
impl<C, S> CosmWasmClient for NyxdClient<C, S>
where
C: TendermintRpcClient + Send + Sync,
S: Send + Sync,
{
}
impl<C, S> OfflineSigner for NyxdClient<C, S>
where
S: OfflineSigner,
-1
View File
@@ -3,7 +3,6 @@ name = "nym-coconut-interface"
version = "0.1.0"
edition = "2021"
description = "Crutch library until there is proper SerDe support for coconut structs"
license.workspace = true
[dependencies]
bs58 = "0.4.0"
+11 -13
View File
@@ -14,21 +14,17 @@ pub use nym_coconut::{
aggregate_signature_shares, aggregate_verification_keys, blind_sign, hash_to_scalar,
prepare_blind_sign, prove_bandwidth_credential, Attribute, Base58, BlindSignRequest,
BlindedSignature, Bytable, CoconutError, KeyPair, Parameters, PrivateAttribute,
PublicAttribute, SecretKey, Signature, SignatureShare, Theta, VerificationKey,
PublicAttribute, Signature, SignatureShare, Theta, VerificationKey,
};
#[derive(Debug, Serialize, Deserialize, Getters, CopyGetters, Clone, PartialEq, Eq)]
pub struct Credential {
#[getset(get = "pub")]
n_params: u32,
#[getset(get = "pub")]
theta: Theta,
voucher_value: u64,
voucher_info: String,
#[getset(get = "pub")]
epoch_id: u64,
}
@@ -68,12 +64,14 @@ impl Credential {
pub fn verify(&self, verification_key: &VerificationKey) -> bool {
let params = Parameters::new(self.n_params).unwrap();
let hashed_value = hash_to_scalar(self.voucher_value.to_string());
let hashed_info = hash_to_scalar(&self.voucher_info);
let public_attributes = &[&hashed_value, &hashed_info];
nym_coconut::verify_credential(&params, verification_key, &self.theta, public_attributes)
let public_attributes = [
self.voucher_value.to_string().as_bytes(),
self.voucher_info.as_bytes(),
]
.iter()
.map(hash_to_scalar)
.collect::<Vec<Attribute>>();
nym_coconut::verify_credential(&params, verification_key, &self.theta, &public_attributes)
}
pub fn as_bytes(&self) -> Vec<u8> {
@@ -182,8 +180,8 @@ mod tests {
&params,
&verification_key,
&signature,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
let credential = Credential::new(4, theta, voucher_value, voucher_info, 42);
-1
View File
@@ -3,7 +3,6 @@ name = "nym-cli-commands"
version = "1.0.0"
authors.workspace = true
edition = "2021"
license.workspace = true
[dependencies]
anyhow = { workspace = true }
@@ -26,10 +26,6 @@ pub struct Args {
}
pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
if args.amount == 0 {
bail!("did not specify credential amount")
}
let loaded = CommonConfigsWrapper::try_load(args.client_config)?;
if let Ok(id) = loaded.try_get_id() {
@@ -6,7 +6,7 @@ use log::{debug, info};
use std::str::FromStr;
use nym_coconut_dkg_common::msg::InstantiateMsg;
use nym_coconut_dkg_common::types::{TimeConfiguration, DEFAULT_DEALINGS};
use nym_coconut_dkg_common::types::TimeConfiguration;
use nym_validator_client::nyxd::AccountId;
#[derive(Debug, Parser)]
@@ -93,7 +93,6 @@ pub async fn generate(args: Args) {
multisig_addr: multisig_addr.to_string(),
time_configuration: Some(time_configuration),
mix_denom,
key_size: DEFAULT_DEALINGS as u32,
};
debug!("instantiate_msg: {:?}", instantiate_msg);
+1 -2
View File
@@ -3,7 +3,6 @@ name = "nym-config"
version = "0.1.0"
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -18,4 +17,4 @@ url = { workspace = true }
nym-network-defaults = { path = "../network-defaults" }
[features]
default = ["dirs"]
default = ["dirs"]
+1 -1
View File
@@ -73,7 +73,7 @@ where
P: AsRef<Path>,
{
let path = path.as_ref();
log::info!("saving config file to {}", path.display());
log::debug!("trying to save config file to {}", path.display());
if let Some(parent) = path.parent() {
create_dir_all(parent)?;
@@ -2,7 +2,6 @@
name = "nym-coconut-bandwidth-contract-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -13,4 +12,4 @@ cw2 = { workspace = true, optional = true }
nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = ["cw2"]
schema = ["cw2"]
@@ -4,9 +4,6 @@
// event types
pub const DEPOSITED_FUNDS_EVENT_TYPE: &str = "deposited-funds";
// a 'wasm-' prefix is added to all cosmwasm events
pub const COSMWASM_DEPOSITED_FUNDS_EVENT_TYPE: &str = "wasm-deposited-funds";
// attributes that are used in multiple places
pub const DEPOSIT_VALUE: &str = "deposit-value";
pub const DEPOSIT_INFO: &str = "deposit-info";
@@ -2,7 +2,6 @@
name = "nym-coconut-dkg-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -10,11 +9,9 @@ license.workspace = true
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw-utils = { workspace = true }
cw2 = { workspace = true }
cw4 = { workspace = true }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = []
schema = []
@@ -1,7 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::{EncodedBTEPublicKeyWithProof, NodeIndex};
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, NodeIndex};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
@@ -9,7 +9,6 @@ use cosmwasm_std::Addr;
pub struct DealerDetails {
pub address: Addr,
pub bte_public_key_with_proof: EncodedBTEPublicKeyWithProof,
pub ed25519_identity: String,
pub announce_address: String,
pub assigned_index: NodeIndex,
}
@@ -65,3 +64,38 @@ impl PagedDealerResponse {
}
}
}
#[cw_serde]
pub struct ContractDealing {
pub dealing: ContractSafeBytes,
pub dealer: Addr,
}
impl ContractDealing {
pub fn new(dealing: ContractSafeBytes, dealer: Addr) -> Self {
ContractDealing { dealing, dealer }
}
}
#[cw_serde]
pub struct PagedDealingsResponse {
pub dealings: Vec<ContractDealing>,
pub per_page: usize,
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
pub start_next_after: Option<Addr>,
}
impl PagedDealingsResponse {
pub fn new(
dealings: Vec<ContractDealing>,
per_page: usize,
start_next_after: Option<Addr>,
) -> Self {
PagedDealingsResponse {
dealings,
per_page,
start_next_after,
}
}
}
@@ -1,284 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::types::{ChunkIndex, DealingIndex, EpochId, PartialContractDealingData};
use contracts_common::dealings::ContractSafeBytes;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use std::collections::{BTreeMap, HashMap};
/// Defines the maximum size of a dealing chunk. Currently set to 2kB
pub const MAX_DEALING_CHUNK_SIZE: usize = 2048;
/// Defines the maximum size of a full dealing.
/// Currently set to 100kB (which is enough for a dealing created for 100 parties)
pub const MAX_DEALING_SIZE: usize = 102400;
pub const MAX_DEALING_CHUNKS: usize = MAX_DEALING_SIZE / MAX_DEALING_CHUNK_SIZE;
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
pub const DEFAULT_DEALINGS: usize = 2 + 2 + 1;
pub fn chunk_dealing(
dealing_index: DealingIndex,
dealing_bytes: Vec<u8>,
chunk_size: usize,
) -> HashMap<ChunkIndex, PartialContractDealing> {
let mut chunks = HashMap::new();
for (chunk_index, chunk) in dealing_bytes.chunks(chunk_size).enumerate() {
let chunk = PartialContractDealing {
dealing_index,
chunk_index: chunk_index as ChunkIndex,
data: ContractSafeBytes(chunk.to_vec()),
};
chunks.insert(chunk_index as ChunkIndex, chunk);
}
chunks
}
#[cw_serde]
#[derive(Copy)]
pub struct DealingChunkInfo {
pub size: usize,
}
impl DealingChunkInfo {
pub fn new(size: usize) -> Self {
DealingChunkInfo { size }
}
pub fn construct(dealing_len: usize, chunk_size: usize) -> Vec<Self> {
let (full_chunks, overflow) = (dealing_len / chunk_size, dealing_len % chunk_size);
let mut chunks = Vec::new();
for _ in 0..full_chunks {
chunks.push(DealingChunkInfo::new(chunk_size));
}
if overflow != 0 {
chunks.push(DealingChunkInfo::new(overflow));
}
chunks
}
}
#[cw_serde]
#[derive(Copy)]
pub struct SubmittedChunk {
pub info: DealingChunkInfo,
pub status: ChunkSubmissionStatus,
}
#[cw_serde]
#[derive(Default, Copy)]
pub struct ChunkSubmissionStatus {
// this field is updated by the contract itself to indicate when this particular chunk has been received
pub submission_height: Option<u64>,
}
impl ChunkSubmissionStatus {
pub fn submitted(&self) -> bool {
self.submission_height.is_some()
}
}
impl From<DealingChunkInfo> for SubmittedChunk {
fn from(value: DealingChunkInfo) -> Self {
SubmittedChunk::new(value)
}
}
impl SubmittedChunk {
pub fn new(info: DealingChunkInfo) -> Self {
SubmittedChunk {
info,
status: Default::default(),
}
}
pub fn submitted(&self) -> bool {
self.status.submitted()
}
}
#[cw_serde]
pub struct DealingMetadata {
pub dealing_index: DealingIndex,
pub submitted_chunks: BTreeMap<ChunkIndex, SubmittedChunk>,
}
impl DealingMetadata {
pub fn new(dealing_index: DealingIndex, chunks: Vec<DealingChunkInfo>) -> Self {
DealingMetadata {
dealing_index,
submitted_chunks: chunks
.into_iter()
.enumerate()
.map(|(id, chunk)| (id as ChunkIndex, chunk.into()))
.collect(),
}
}
pub fn is_complete(&self) -> bool {
self.submitted_chunks.values().all(|c| c.submitted())
}
pub fn total_size(&self) -> usize {
self.submitted_chunks.values().map(|c| c.info.size).sum()
}
pub fn submission_statuses(&self) -> BTreeMap<ChunkIndex, ChunkSubmissionStatus> {
self.submitted_chunks
.iter()
.map(|(id, c)| (*id, c.status))
.collect()
}
}
#[cw_serde]
pub struct PartialContractDealing {
pub dealing_index: DealingIndex,
pub chunk_index: ChunkIndex,
pub data: PartialContractDealingData,
}
impl PartialContractDealing {
pub fn new(
dealing_index: DealingIndex,
chunk_index: ChunkIndex,
data: PartialContractDealingData,
) -> Self {
PartialContractDealing {
dealing_index,
chunk_index,
data,
}
}
}
#[cw_serde]
pub struct DealingMetadataResponse {
pub epoch_id: EpochId,
pub dealer: Addr,
pub dealing_index: DealingIndex,
pub metadata: Option<DealingMetadata>,
}
#[cw_serde]
pub struct DealingChunkResponse {
pub epoch_id: EpochId,
pub dealer: Addr,
pub dealing_index: DealingIndex,
pub chunk_index: ChunkIndex,
pub chunk: Option<PartialContractDealingData>,
}
#[cw_serde]
pub struct DealingChunkStatusResponse {
pub epoch_id: EpochId,
pub dealer: Addr,
pub dealing_index: DealingIndex,
pub chunk_index: ChunkIndex,
pub status: ChunkSubmissionStatus,
}
#[cw_serde]
pub struct DealingStatusResponse {
pub epoch_id: EpochId,
pub dealer: Addr,
pub dealing_index: DealingIndex,
pub status: DealingStatus,
}
#[cw_serde]
pub struct DealingStatus {
pub has_metadata: bool,
pub fully_submitted: bool,
pub chunk_submission_status: BTreeMap<ChunkIndex, ChunkSubmissionStatus>,
}
impl From<Option<DealingMetadata>> for DealingStatus {
fn from(metadata: Option<DealingMetadata>) -> Self {
DealingStatus {
has_metadata: metadata.is_some(),
fully_submitted: metadata
.as_ref()
.map(|m| m.is_complete())
.unwrap_or_default(),
chunk_submission_status: metadata
.map(|m| m.submission_statuses())
.unwrap_or_default(),
}
}
}
#[cw_serde]
pub struct DealerDealingsStatusResponse {
pub epoch_id: EpochId,
pub dealer: Addr,
pub all_dealings_fully_submitted: bool,
pub dealing_submission_status: BTreeMap<DealingIndex, DealingStatus>,
}
impl DealerDealingsStatusResponse {
pub fn full_dealings(&self) -> usize {
self.dealing_submission_status
.values()
.filter(|s| s.fully_submitted)
.count()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chunking_dealings() {
const CHUNK_SIZE: usize = 512;
let test_cases = [
(CHUNK_SIZE - 10, CHUNK_SIZE, 1),
(CHUNK_SIZE, CHUNK_SIZE, 1),
(CHUNK_SIZE + 10, CHUNK_SIZE, 2),
(CHUNK_SIZE * 2, CHUNK_SIZE, 2),
(CHUNK_SIZE * 2 + 1, CHUNK_SIZE, 3),
(CHUNK_SIZE * 10 + 42, CHUNK_SIZE, 11),
];
for (dealing_len, chunk_size, expected_chunks) in test_cases {
let chunks = DealingChunkInfo::construct(dealing_len, chunk_size);
assert_eq!(expected_chunks, chunks.len());
assert_eq!(dealing_len, chunks.iter().map(|c| c.size).sum::<usize>());
let mut expected_last = dealing_len % chunk_size;
if expected_last == 0 {
expected_last = chunk_size;
}
assert_eq!(chunks.last().unwrap().size, expected_last);
}
}
}
@@ -1,8 +1,4 @@
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod dealer;
pub mod dealing;
pub mod event_attributes;
pub mod msg;
pub mod types;
@@ -1,23 +1,16 @@
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::dealing::{DealingChunkInfo, PartialContractDealing};
use crate::types::{
ChunkIndex, DealingIndex, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration,
};
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration};
use crate::verification_key::VerificationKeyShare;
use contracts_common::IdentityKey;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
#[cfg(feature = "schema")]
use crate::{
dealer::{DealerDetailsResponse, PagedDealerResponse},
dealing::{
DealerDealingsStatusResponse, DealingChunkResponse, DealingChunkStatusResponse,
DealingMetadataResponse, DealingStatusResponse,
},
types::{Epoch, InitialReplacementData, State},
verification_key::{PagedVKSharesResponse, VkShareResponse},
dealer::{DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse},
types::{Epoch, InitialReplacementData},
verification_key::PagedVKSharesResponse,
};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
@@ -28,31 +21,18 @@ pub struct InstantiateMsg {
pub multisig_addr: String,
pub time_configuration: Option<TimeConfiguration>,
pub mix_denom: String,
/// Specifies the number of elements in the derived keys
pub key_size: u32,
}
#[cw_serde]
pub enum ExecuteMsg {
// we could have just re-used AdvanceEpochState, but imo an explicit message is better
InitiateDkg {},
RegisterDealer {
bte_key_with_proof: EncodedBTEPublicKeyWithProof,
identity_key: IdentityKey,
announce_address: String,
resharing: bool,
},
CommitDealingsMetadata {
dealing_index: DealingIndex,
chunks: Vec<DealingChunkInfo>,
resharing: bool,
},
CommitDealingsChunk {
chunk: PartialContractDealing,
CommitDealing {
dealing_bytes: ContractSafeBytes,
resharing: bool,
},
@@ -62,7 +42,8 @@ pub enum ExecuteMsg {
},
VerifyVerificationKeyShare {
owner: String,
// TODO: this should be using a String...
owner: Addr,
resharing: bool,
},
@@ -74,9 +55,6 @@ pub enum ExecuteMsg {
#[cw_serde]
#[cfg_attr(feature = "schema", derive(QueryResponses))]
pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(State))]
GetState {},
#[cfg_attr(feature = "schema", returns(Epoch))]
GetCurrentEpochState {},
@@ -101,53 +79,19 @@ pub enum QueryMsg {
start_after: Option<String>,
},
#[cfg_attr(feature = "schema", returns(DealingMetadataResponse))]
GetDealingsMetadata {
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
#[cfg_attr(feature = "schema", returns(PagedDealingsResponse))]
GetDealing {
idx: u64,
limit: Option<u32>,
start_after: Option<String>,
},
#[cfg_attr(feature = "schema", returns(DealerDealingsStatusResponse))]
GetDealerDealingsStatus { epoch_id: EpochId, dealer: String },
#[cfg_attr(feature = "schema", returns(DealingStatusResponse))]
GetDealingStatus {
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
},
#[cfg_attr(feature = "schema", returns(DealingChunkStatusResponse))]
GetDealingChunkStatus {
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
chunk_index: ChunkIndex,
},
#[cfg_attr(feature = "schema", returns(DealingChunkResponse))]
GetDealingChunk {
epoch_id: EpochId,
dealer: String,
dealing_index: DealingIndex,
chunk_index: ChunkIndex,
},
#[cfg_attr(feature = "schema", returns(VkShareResponse))]
GetVerificationKey { epoch_id: EpochId, owner: String },
#[cfg_attr(feature = "schema", returns(PagedVKSharesResponse))]
GetVerificationKeys {
epoch_id: EpochId,
limit: Option<u32>,
start_after: Option<String>,
},
/// Gets the stored contract version information that's required by the CW2 spec interface for migrations.
#[serde(rename = "get_cw2_contract_version")]
#[cfg_attr(feature = "schema", returns(cw2::ContractVersion))]
GetCW2ContractVersion {},
}
#[cw_serde]
@@ -8,18 +8,14 @@ use std::str::FromStr;
pub use crate::dealer::{DealerDetails, PagedDealerResponse};
pub use contracts_common::dealings::ContractSafeBytes;
pub use cosmwasm_std::{Addr, Coin, Timestamp};
pub use cw4::Cw4Contract;
pub type EncodedBTEPublicKeyWithProof = String;
pub type EncodedBTEPublicKeyWithProofRef<'a> = &'a str;
pub type NodeIndex = u64;
pub type EpochId = u64;
pub type DealingIndex = u32;
// we really don't need to hold more data than that (even u8 would have been enough),
// but explicitly make it different type than `DealingIndex` so type system would detect any
// accidental misuses
pub type ChunkIndex = u16;
pub type PartialContractDealingData = ContractSafeBytes;
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
pub const TOTAL_DEALINGS: usize = 2 + 2 + 1;
#[cw_serde]
pub struct InitialReplacementData {
@@ -77,23 +73,13 @@ impl Default for TimeConfiguration {
}
}
#[cw_serde]
pub struct State {
pub mix_denom: String,
pub multisig_addr: Addr,
pub group_addr: Cw4Contract,
/// Specifies the number of elements in the derived keys
pub key_size: u32,
}
#[cw_serde]
#[derive(Copy, Default)]
pub struct Epoch {
pub state: EpochState,
pub epoch_id: EpochId,
pub time_configuration: TimeConfiguration,
pub finish_timestamp: Option<Timestamp>,
pub finish_timestamp: Timestamp,
}
impl Epoch {
@@ -104,40 +90,36 @@ impl Epoch {
current_timestamp: Timestamp,
) -> Self {
let duration = match state {
EpochState::WaitingInitialisation => None,
EpochState::PublicKeySubmission { .. } => {
Some(time_configuration.public_key_submission_time_secs)
}
EpochState::DealingExchange { .. } => {
Some(time_configuration.dealing_exchange_time_secs)
time_configuration.public_key_submission_time_secs
}
EpochState::DealingExchange { .. } => time_configuration.dealing_exchange_time_secs,
EpochState::VerificationKeySubmission { .. } => {
Some(time_configuration.verification_key_submission_time_secs)
time_configuration.verification_key_submission_time_secs
}
EpochState::VerificationKeyValidation { .. } => {
Some(time_configuration.verification_key_validation_time_secs)
time_configuration.verification_key_validation_time_secs
}
EpochState::VerificationKeyFinalization { .. } => {
Some(time_configuration.verification_key_finalization_time_secs)
time_configuration.verification_key_finalization_time_secs
}
EpochState::InProgress => Some(time_configuration.in_progress_time_secs),
EpochState::InProgress => time_configuration.in_progress_time_secs,
};
Epoch {
state,
epoch_id,
time_configuration,
finish_timestamp: duration.map(|d| current_timestamp.plus_seconds(d)),
finish_timestamp: current_timestamp.plus_seconds(duration),
}
}
pub fn final_timestamp_secs(&self) -> Option<u64> {
let mut finish = self.finish_timestamp?.seconds();
pub fn final_timestamp_secs(&self) -> u64 {
let mut finish = self.finish_timestamp.seconds();
let time_configuration = self.time_configuration;
let mut curr_epoch_state = self.state;
while let Some(state) = curr_epoch_state.next() {
curr_epoch_state = state;
let adding = match curr_epoch_state {
EpochState::WaitingInitialisation => return None,
EpochState::PublicKeySubmission { .. } => {
time_configuration.public_key_submission_time_secs
}
@@ -155,13 +137,12 @@ impl Epoch {
};
finish += adding;
}
Some(finish)
finish
}
}
// currently (it is still extremely likely to change, we might be able to get rid of verification key-related complaints),
// the epoch can be in the following states (in order):
// 0. WaitingInitialisation -> the contract has been instantiated, but awaits for the admin to kick off the process (group members might still be getting added)
// 1. PublicKeySubmission -> potential dealers are submitting their BTE and ed25519 public keys to participate in dealing exchange
// 2. DealingExchange -> the actual (off-chain) dealing exchange is happening
// 3. ComplaintSubmission -> receivers submitting evidence of other dealers sending malformed data
@@ -175,7 +156,6 @@ impl Epoch {
#[cw_serde]
#[derive(Copy)]
pub enum EpochState {
WaitingInitialisation,
PublicKeySubmission { resharing: bool },
DealingExchange { resharing: bool },
VerificationKeySubmission { resharing: bool },
@@ -186,28 +166,25 @@ pub enum EpochState {
impl Default for EpochState {
fn default() -> Self {
Self::WaitingInitialisation
Self::PublicKeySubmission { resharing: false }
}
}
impl Display for EpochState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
EpochState::WaitingInitialisation => write!(f, "Waiting for initialisation"),
EpochState::PublicKeySubmission { resharing } => {
write!(f, "PublicKeySubmission (resharing: {resharing})")
}
EpochState::DealingExchange { resharing } => {
write!(f, "DealingExchange (resharing: {resharing})")
write!(f, "PublicKeySubmission with resharing {resharing}")
}
EpochState::DealingExchange { resharing } => write!(f, "DealingExchange {resharing}"),
EpochState::VerificationKeySubmission { resharing } => {
write!(f, "VerificationKeySubmission (resharing: {resharing})")
write!(f, "VerificationKeySubmission with resharing {resharing}")
}
EpochState::VerificationKeyValidation { resharing } => {
write!(f, "VerificationKeyValidation (resharing: {resharing})")
write!(f, "VerificationKeyValidation with resharing {resharing}")
}
EpochState::VerificationKeyFinalization { resharing } => {
write!(f, "VerificationKeyFinalization (resharing: {resharing})")
write!(f, "VerificationKeyFinalization with resharing {resharing}")
}
EpochState::InProgress => write!(f, "InProgress"),
}
@@ -215,13 +192,8 @@ impl Display for EpochState {
}
impl EpochState {
pub fn first() -> Self {
EpochState::PublicKeySubmission { resharing: false }
}
pub fn next(self) -> Option<Self> {
match self {
EpochState::WaitingInitialisation => None,
EpochState::PublicKeySubmission { resharing } => {
Some(EpochState::DealingExchange { resharing })
}
@@ -20,13 +20,6 @@ pub struct ContractVKShare {
pub verified: bool,
}
#[cw_serde]
pub struct VkShareResponse {
pub owner: Addr,
pub epoch_id: EpochId,
pub share: Option<ContractVKShare>,
}
#[cw_serde]
pub struct PagedVKSharesResponse {
pub shares: Vec<ContractVKShare>,
@@ -43,10 +36,7 @@ pub fn to_cosmos_msg(
multisig_addr: String,
expiration_time: Timestamp,
) -> StdResult<CosmosMsg> {
let verify_vk_share_req = ExecuteMsg::VerifyVerificationKeyShare {
owner: owner.to_string(),
resharing,
};
let verify_vk_share_req = ExecuteMsg::VerifyVerificationKeyShare { owner, resharing };
let verify_vk_share_msg = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: coconut_dkg_addr,
msg: to_binary(&verify_vk_share_req)?,
@@ -67,14 +57,7 @@ pub fn to_cosmos_msg(
Ok(msg)
}
// DKG SAFETY:
// each legit verification proposal will only contain a single execute msg,
// if they have more than one, we can safely ignore it
pub fn owner_from_cosmos_msgs(msgs: &[CosmosMsg]) -> Option<String> {
if msgs.len() != 1 {
return None;
}
pub fn owner_from_cosmos_msgs(msgs: &[CosmosMsg]) -> Option<Addr> {
if let Some(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: _,
msg,
@@ -4,14 +4,14 @@
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::ops::Deref;
// some sane upper-bound size on byte sizes
// currently set to 128 bytes
pub const MAX_DISPLAY_SIZE: usize = 128;
// helps to transfer bytes between contract boundary to decrease amount of data sent accross
// after it's put to `Binary`
// TODO: if we are to use this for different types, it might make sense to introduce something like
// CommitmentTypeId field on the below for distinguishing different ones. it would somehow become part of the trait
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, JsonSchema)]
pub struct ContractSafeBytes(pub Vec<u8>);
@@ -23,18 +23,6 @@ impl Deref for ContractSafeBytes {
}
}
impl DerefMut for ContractSafeBytes {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl From<Vec<u8>> for ContractSafeBytes {
fn from(value: Vec<u8>) -> Self {
ContractSafeBytes(value)
}
}
impl Display for ContractSafeBytes {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if !self.0.is_empty() {
@@ -2,7 +2,6 @@
name = "nym-ephemera-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -14,4 +13,4 @@ cw-utils = { workspace = true }
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
[features]
schema = []
schema = []
@@ -2,7 +2,6 @@
name = "nym-group-contract-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -2,7 +2,6 @@
name = "nym-multisig-contract-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -2,7 +2,6 @@
name = "nym-name-service-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -17,4 +16,4 @@ serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
[features]
schema = ["cw2"]
schema = ["cw2"]
@@ -2,7 +2,6 @@
name = "nym-service-provider-directory-common"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -16,4 +15,4 @@ nym-contracts-common = { path = "../contracts-common", version = "0.5.0" }
thiserror = { workspace = true }
[features]
schema = ["cw2"]
schema = ["cw2"]
+3 -4
View File
@@ -2,7 +2,6 @@
name = "nym-credential-storage"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -14,14 +13,14 @@ thiserror = { workspace = true }
tokio = { version = "1.24.1", features = ["sync"]}
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
workspace = true
version = "0.5"
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
workspace = true
version = "1.24.1"
features = [ "rt-multi-thread", "net", "signal", "fs" ]
[build-dependencies]
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
-1
View File
@@ -2,7 +2,6 @@
name = "nym-credential-utils"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+9 -19
View File
@@ -5,9 +5,7 @@ use nym_bandwidth_controller::acquire::state::State;
use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_config::DEFAULT_DATA_DIR;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_validator_client::nyxd::contract_traits::{
dkg_query_client::EpochState, CoconutBandwidthSigningClient, DkgQueryClient,
};
use nym_validator_client::nyxd::contract_traits::{CoconutBandwidthSigningClient, DkgQueryClient};
use nym_validator_client::nyxd::Coin;
use std::path::PathBuf;
use std::process::exit;
@@ -89,29 +87,21 @@ where
.duration_since(SystemTime::UNIX_EPOCH)
.expect("the system clock is set to 01/01/1970 (or earlier)")
.as_secs();
if epoch.state.is_final() {
if let Some(finish_timestamp) = epoch.finish_timestamp {
if current_timestamp_secs + SAFETY_BUFFER_SECS >= finish_timestamp.seconds() {
info!("In the next {} minute(s), a transition will take place in the coconut system. Deposits should be halted in this time for safety reasons.", SAFETY_BUFFER_SECS / 60);
exit(0);
}
if current_timestamp_secs + SAFETY_BUFFER_SECS >= epoch.finish_timestamp.seconds() {
info!("In the next {} minute(s), a transition will take place in the coconut system. Deposits should be halted in this time for safety reasons.", SAFETY_BUFFER_SECS / 60);
exit(0);
}
break;
} else if let Some(final_timestamp) = epoch.final_timestamp_secs() {
} else {
// Use 1 additional second to not start the next iteration immediately and spam get_current_epoch queries
let secs_until_final = final_timestamp.saturating_sub(current_timestamp_secs) + 1;
let secs_until_final = epoch
.final_timestamp_secs()
.saturating_sub(current_timestamp_secs)
+ 1;
info!("Approximately {} seconds until coconut is available. Sleeping until then. You can safely kill the process at any moment.", secs_until_final);
tokio::time::sleep(Duration::from_secs(secs_until_final)).await;
} else if matches!(epoch.state, EpochState::WaitingInitialisation) {
info!("dkg hasn't been initialised yet and it is not known when it will be. Going to check again later");
tokio::time::sleep(Duration::from_secs(60 * 5)).await;
} else {
// this should never be the case since the only case where final timestamp is unknown is when it's waiting for initialisation,
// but let's guard ourselves against future changes
info!("it is unknown when coconut will be come available. Going to check again later");
tokio::time::sleep(Duration::from_secs(60 * 5)).await;
}
}
+2 -4
View File
@@ -2,20 +2,18 @@
name = "nym-credentials"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] }
bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] }
cosmrs = { workspace = true }
thiserror = { workspace = true }
log = { workspace = true }
zeroize = { workspace = true }
# I guess temporarily until we get serde support in coconut up and running
nym-coconut-interface = { path = "../coconut-interface" }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric"] }
nym-crypto = { path = "../crypto", features = ["rand", "asymmetric", "symmetric", "hashing"] }
nym-api-requests = { path = "../../nym-api/nym-api-requests" }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
+51 -93
View File
@@ -13,60 +13,38 @@ use nym_coconut_interface::{
PrivateAttribute, PublicAttribute, Signature, VerificationKey,
};
use nym_crypto::asymmetric::{encryption, identity};
use zeroize::{Zeroize, ZeroizeOnDrop};
use super::utils::prepare_credential_for_spending;
use crate::error::Error;
#[derive(Zeroize, ZeroizeOnDrop)]
pub const PUBLIC_ATTRIBUTES: u32 = 2;
pub const PRIVATE_ATTRIBUTES: u32 = 2;
pub const TOTAL_ATTRIBUTES: u32 = PUBLIC_ATTRIBUTES + PRIVATE_ATTRIBUTES;
pub struct BandwidthVoucher {
// private attributes
/// a random secret value generated by the client used for double-spending detection
// a random secret value generated by the client used for double-spending detection
serial_number: PrivateAttribute,
/// a random secret value generated by the client used to bind multiple credentials together
// a random secret value generated by the client used to bind multiple credentials together
binding_number: PrivateAttribute,
// public atttributes:
/// the plain text value (e.g., bandwidth) encoded in this voucher
// TODO: in another PR change the value from `"1000"` to `"1000unym"`
// the value (e.g., bandwidth) encoded in this voucher
voucher_value: PublicAttribute,
// the plain text value (e.g., bandwidth) encoded in this voucher
voucher_value_plain: String,
/// the plain text information
// a field with public information, e.g., type of voucher, interval etc.
voucher_info: PublicAttribute,
// the plain text information
voucher_info_plain: String,
/// the precomputed value (e.g., bandwidth) encoded in this voucher
_voucher_value_prehashed: PublicAttribute,
/// the precomputed field with public information, e.g., type of voucher, interval etc.
_voucher_info_prehashed: PublicAttribute,
/// the hash of the deposit transaction
#[zeroize(skip)]
// the hash of the deposit transaction
tx_hash: Hash,
/// base58 encoded private key ensuring the depositer requested these attributes
// base58 encoded private key ensuring the depositer requested these attributes
signing_key: identity::PrivateKey,
/// base58 encoded private key ensuring only this client receives the signature share
unused_ed25519: encryption::PrivateKey,
// base58 encoded private key ensuring only this client receives the signature share
encryption_key: encryption::PrivateKey,
pedersen_commitments_openings: Vec<Attribute>,
#[zeroize(skip)]
blind_sign_request: BlindSignRequest,
}
impl BandwidthVoucher {
pub const PUBLIC_ATTRIBUTES: u32 = 2;
pub const PRIVATE_ATTRIBUTES: u32 = 2;
pub const ENCODED_ATTRIBUTES: u32 = 4;
pub fn default_parameters() -> Parameters {
// safety: the unwrap is fine here as Self::ENCODED_ATTRIBUTES is non-zero
Parameters::new(Self::ENCODED_ATTRIBUTES).unwrap()
}
pub fn new(
params: &Parameters,
voucher_value: String,
@@ -79,26 +57,24 @@ impl BandwidthVoucher {
let binding_number = params.random_scalar();
let voucher_value_plain = voucher_value.clone();
let voucher_info_plain = voucher_info.clone();
let _voucher_value_prehashed = hash_to_scalar(voucher_value);
let _voucher_info_prehashed = hash_to_scalar(voucher_info);
let voucher_value = hash_to_scalar(voucher_value.as_bytes());
let voucher_info = hash_to_scalar(voucher_info.as_bytes());
let (pedersen_commitments_openings, blind_sign_request) = prepare_blind_sign(
params,
&[&serial_number, &binding_number],
&[&_voucher_value_prehashed, &_voucher_info_prehashed],
&[serial_number, binding_number],
&[voucher_value, voucher_info],
)
.unwrap();
BandwidthVoucher {
serial_number,
binding_number,
_voucher_value_prehashed,
voucher_value,
voucher_value_plain,
_voucher_info_prehashed,
voucher_info,
voucher_info_plain,
tx_hash,
signing_key,
unused_ed25519: encryption_key,
encryption_key,
pedersen_commitments_openings,
blind_sign_request,
}
@@ -111,7 +87,7 @@ impl BandwidthVoucher {
let voucher_info_plain_b = self.voucher_info_plain.as_bytes();
let tx_hash_b = self.tx_hash.as_bytes();
let signing_key_b = self.signing_key.to_bytes();
let encryption_key_b = self.unused_ed25519.to_bytes();
let encryption_key_b = self.encryption_key.to_bytes();
let blind_sign_request_b = self.blind_sign_request.to_bytes();
let mut ret = Vec::new();
@@ -195,13 +171,13 @@ impl BandwidthVoucher {
bytes[var_length_pointer..var_length_pointer + voucher_value_plain_no].to_vec(),
)
.or_else(utf_err)?;
let _voucher_value_prehashed = hash_to_scalar(&voucher_value_plain);
let voucher_value = hash_to_scalar(&voucher_value_plain);
var_length_pointer += voucher_value_plain_no;
let voucher_info_plain = String::from_utf8(
bytes[var_length_pointer..var_length_pointer + voucher_info_plain_no].to_vec(),
)
.or_else(utf_err)?;
let _voucher_info_prehashed = hash_to_scalar(&voucher_info_plain);
let voucher_info = hash_to_scalar(&voucher_info_plain);
var_length_pointer += voucher_info_plain_no;
let blind_sign_request = BlindSignRequest::from_bytes(
&bytes[var_length_pointer..var_length_pointer + blind_sign_request_no],
@@ -220,43 +196,36 @@ impl BandwidthVoucher {
Ok(Self {
serial_number,
binding_number,
_voucher_value_prehashed,
voucher_value,
voucher_value_plain,
_voucher_info_prehashed,
voucher_info,
voucher_info_plain,
tx_hash,
signing_key,
unused_ed25519: encryption_key,
encryption_key,
pedersen_commitments_openings,
blind_sign_request,
})
}
/// Check if the plain values correspond to the PublicAttributes
pub fn verify_against_plain(values: &[&PublicAttribute], plain_values: &[String]) -> bool {
pub fn verify_against_plain(values: &[PublicAttribute], plain_values: &[String]) -> bool {
values.len() == 2
&& plain_values.len() == 2
&& values[0] == &hash_to_scalar(&plain_values[0])
&& values[1] == &hash_to_scalar(&plain_values[1])
&& values[0] == hash_to_scalar(&plain_values[0])
&& values[1] == hash_to_scalar(&plain_values[1])
}
pub fn tx_hash(&self) -> Hash {
self.tx_hash
pub fn tx_hash(&self) -> &Hash {
&self.tx_hash
}
pub fn get_public_attributes(&self) -> Vec<&PublicAttribute> {
vec![
&self._voucher_value_prehashed,
&self._voucher_info_prehashed,
]
}
pub fn identity_key(&self) -> &identity::PrivateKey {
&self.signing_key
pub fn get_public_attributes(&self) -> Vec<PublicAttribute> {
vec![self.voucher_value, self.voucher_info]
}
pub fn encryption_key(&self) -> &encryption::PrivateKey {
&self.unused_ed25519
&self.encryption_key
}
pub fn pedersen_commitments_openings(&self) -> &Vec<Attribute> {
@@ -278,32 +247,27 @@ impl BandwidthVoucher {
]
}
pub fn get_private_attributes(&self) -> Vec<&PrivateAttribute> {
vec![&self.serial_number, &self.binding_number]
pub fn get_private_attributes(&self) -> Vec<PrivateAttribute> {
vec![self.serial_number, self.binding_number]
}
pub fn signable_plaintext(request: &BlindSignRequest, tx_hash: Hash) -> Vec<u8> {
pub fn sign(&self, request: &BlindSignRequest) -> identity::Signature {
let mut message = request.to_bytes();
message.extend_from_slice(tx_hash.as_bytes());
message
}
pub fn sign(&self) -> identity::Signature {
let message = Self::signable_plaintext(&self.blind_sign_request, self.tx_hash);
self.signing_key.sign(message)
message.extend_from_slice(self.tx_hash.to_string().as_bytes());
self.signing_key.sign(&message)
}
}
pub fn prepare_for_spending(
voucher_value: u64,
voucher_info: String,
serial_number: &PrivateAttribute,
binding_number: &PrivateAttribute,
serial_number: PrivateAttribute,
binding_number: PrivateAttribute,
epoch_id: u64,
signature: &Signature,
verification_key: &VerificationKey,
) -> Result<Credential, Error> {
let params = Parameters::new(BandwidthVoucher::ENCODED_ATTRIBUTES)?;
let params = Parameters::new(TOTAL_ATTRIBUTES)?;
prepare_credential_for_spending(
&params,
@@ -352,30 +316,24 @@ mod test {
let deserialized_voucher = BandwidthVoucher::try_from_bytes(&bytes).unwrap();
assert_eq!(voucher.serial_number, deserialized_voucher.serial_number);
assert_eq!(voucher.binding_number, deserialized_voucher.binding_number);
assert_eq!(voucher.voucher_value, deserialized_voucher.voucher_value);
assert_eq!(
voucher.voucher_value_plain,
deserialized_voucher.voucher_value_plain
);
assert_eq!(voucher.voucher_info, deserialized_voucher.voucher_info);
assert_eq!(
voucher.voucher_info_plain,
deserialized_voucher.voucher_info_plain
);
assert_eq!(
voucher._voucher_value_prehashed,
deserialized_voucher._voucher_value_prehashed
);
assert_eq!(
voucher._voucher_info_prehashed,
deserialized_voucher._voucher_info_prehashed
);
assert_eq!(voucher.tx_hash, deserialized_voucher.tx_hash);
assert_eq!(
voucher.signing_key.to_string(),
deserialized_voucher.signing_key.to_string()
);
assert_eq!(
voucher.unused_ed25519.to_string(),
deserialized_voucher.unused_ed25519.to_string()
voucher.encryption_key.to_string(),
deserialized_voucher.encryption_key.to_string()
);
assert_eq!(
voucher.pedersen_commitments_openings,
@@ -413,11 +371,11 @@ mod test {
]
));
assert!(!BandwidthVoucher::verify_against_plain(
&[voucher.get_public_attributes()[0], &Attribute::one()],
&[voucher.get_public_attributes()[0], Attribute::one()],
&voucher.get_public_attributes_plain()
));
assert!(!BandwidthVoucher::verify_against_plain(
&[&Attribute::one(), voucher.get_public_attributes()[1]],
&[Attribute::one(), voucher.get_public_attributes()[1]],
&voucher.get_public_attributes_plain()
));
assert!(BandwidthVoucher::verify_against_plain(
+1
View File
@@ -2,4 +2,5 @@
// SPDX-License-Identifier: Apache-2.0
pub mod bandwidth;
pub mod params;
pub mod utils;
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_crypto::aes::Aes128;
use nym_crypto::blake3;
use nym_crypto::ctr;
type Aes128Ctr = ctr::Ctr64LE<Aes128>;
/// Hashing algorithm used during hkdf for ephemeral shared key generation per blinded signature
/// response encryption.
pub type NymApiCredentialHkdfAlgorithm = blake3::Hasher;
/// Encryption algorithm used for end-to-end encryption of blinded signature response
pub type NymApiCredentialEncryptionAlgorithm = Aes128Ctr;
+39 -22
View File
@@ -1,14 +1,18 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::coconut::bandwidth::BandwidthVoucher;
use crate::coconut::bandwidth::{BandwidthVoucher, PRIVATE_ATTRIBUTES, PUBLIC_ATTRIBUTES};
use crate::coconut::params::{NymApiCredentialEncryptionAlgorithm, NymApiCredentialHkdfAlgorithm};
use crate::error::Error;
use log::{debug, warn};
use nym_api_requests::coconut::BlindSignRequestBody;
use nym_coconut_interface::{
aggregate_signature_shares, aggregate_verification_keys, prove_bandwidth_credential, Attribute,
Credential, Parameters, Signature, SignatureShare, VerificationKey,
BlindedSignature, Credential, Parameters, Signature, SignatureShare, VerificationKey,
};
use nym_crypto::asymmetric::encryption::PublicKey;
use nym_crypto::shared_key::recompute_shared_key;
use nym_crypto::symmetric::stream_cipher;
use nym_validator_client::client::CoconutApiClient;
pub async fn obtain_aggregate_verification_key(
@@ -32,34 +36,47 @@ pub async fn obtain_aggregate_verification_key(
async fn obtain_partial_credential(
params: &Parameters,
voucher: &BandwidthVoucher,
attributes: &BandwidthVoucher,
client: &nym_validator_client::client::NymApiClient,
validator_vk: &VerificationKey,
) -> Result<Signature, Error> {
let public_attributes_plain = voucher.get_public_attributes_plain();
let blind_sign_request = voucher.blind_sign_request();
let request_signature = voucher.sign();
let public_attributes = attributes.get_public_attributes();
let public_attributes_plain = attributes.get_public_attributes_plain();
let private_attributes = attributes.get_private_attributes();
let blind_sign_request = attributes.blind_sign_request();
let blind_sign_request_body = BlindSignRequestBody::new(
blind_sign_request.clone(),
voucher.tx_hash(),
request_signature,
blind_sign_request,
attributes.tx_hash().to_string(),
attributes.sign(blind_sign_request).to_base58_string(),
&public_attributes,
public_attributes_plain,
(public_attributes.len() + private_attributes.len()) as u32,
);
let response = client.blind_sign(&blind_sign_request_body).await?;
let encrypted_signature = response.encrypted_signature;
let remote_key = PublicKey::from_bytes(&response.remote_key)?;
let blinded_signature = response.blinded_signature;
let encryption_key = recompute_shared_key::<
NymApiCredentialEncryptionAlgorithm,
NymApiCredentialHkdfAlgorithm,
>(&remote_key, attributes.encryption_key());
let zero_iv = stream_cipher::zero_iv::<NymApiCredentialEncryptionAlgorithm>();
let blinded_signature_bytes = stream_cipher::decrypt::<NymApiCredentialEncryptionAlgorithm>(
&encryption_key,
&zero_iv,
&encrypted_signature,
);
let public_attributes = voucher.get_public_attributes();
let private_attributes = voucher.get_private_attributes();
let blinded_signature = BlindedSignature::from_bytes(&blinded_signature_bytes)?;
let unblinded_signature = blinded_signature.unblind_and_verify(
let unblinded_signature = blinded_signature.unblind(
params,
validator_vk,
&private_attributes,
&public_attributes,
&blind_sign_request.get_commitment_hash(),
voucher.pedersen_commitments_openings(),
attributes.pedersen_commitments_openings(),
)?;
Ok(unblinded_signature)
@@ -67,13 +84,16 @@ async fn obtain_partial_credential(
pub async fn obtain_aggregate_signature(
params: &Parameters,
voucher: &BandwidthVoucher,
attributes: &BandwidthVoucher,
coconut_api_clients: &[CoconutApiClient],
threshold: u64,
) -> Result<Signature, Error> {
if coconut_api_clients.is_empty() {
return Err(Error::NoValidatorsAvailable);
}
let public_attributes = attributes.get_public_attributes();
let private_attributes = attributes.get_private_attributes();
let mut shares = Vec::with_capacity(coconut_api_clients.len());
let validators_partial_vks: Vec<_> = coconut_api_clients
.iter()
@@ -94,7 +114,7 @@ pub async fn obtain_aggregate_signature(
match obtain_partial_credential(
params,
voucher,
attributes,
&coconut_api_client.api_client,
&coconut_api_client.verification_key,
)
@@ -116,9 +136,6 @@ pub async fn obtain_aggregate_signature(
return Err(Error::NotEnoughShares);
}
let public_attributes = voucher.get_public_attributes();
let private_attributes = voucher.get_private_attributes();
let mut attributes = Vec::with_capacity(private_attributes.len() + public_attributes.len());
attributes.extend_from_slice(&private_attributes);
attributes.extend_from_slice(&public_attributes);
@@ -133,8 +150,8 @@ pub fn prepare_credential_for_spending(
params: &Parameters,
voucher_value: u64,
voucher_info: String,
serial_number: &Attribute,
binding_number: &Attribute,
serial_number: Attribute,
binding_number: Attribute,
epoch_id: u64,
signature: &Signature,
verification_key: &VerificationKey,
@@ -148,7 +165,7 @@ pub fn prepare_credential_for_spending(
)?;
Ok(Credential::new(
BandwidthVoucher::ENCODED_ATTRIBUTES,
PUBLIC_ATTRIBUTES + PRIVATE_ATTRIBUTES,
theta,
voucher_value,
voucher_info,
@@ -201,17 +201,6 @@ impl<'a> From<&'a PrivateKey> for PublicKey {
}
impl PrivateKey {
#[cfg(feature = "rand")]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let x25519_secret = x25519_dalek::StaticSecret::new(rng);
PrivateKey(x25519_secret)
}
pub fn public_key(&self) -> PublicKey {
self.into()
}
pub fn to_bytes(&self) -> [u8; PRIVATE_KEY_SIZE] {
self.0.to_bytes()
}
+3 -23
View File
@@ -5,14 +5,13 @@ pub use ed25519_dalek::ed25519::signature::Signature as SignatureTrait;
pub use ed25519_dalek::SignatureError;
pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH};
use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair};
#[cfg(feature = "sphinx")]
use nym_sphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use thiserror::Error;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[cfg(feature = "sphinx")]
use nym_sphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
#[cfg(feature = "rand")]
use rand::{CryptoRng, RngCore};
#[cfg(feature = "serde")]
@@ -225,17 +224,6 @@ impl<'a> From<&'a PrivateKey> for PublicKey {
}
impl PrivateKey {
#[cfg(feature = "rand")]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
let ed25519_secret = ed25519_dalek::SecretKey::generate(rng);
PrivateKey(ed25519_secret)
}
pub fn public_key(&self) -> PublicKey {
self.into()
}
pub fn to_bytes(&self) -> [u8; SECRET_KEY_LENGTH] {
self.0.to_bytes()
}
@@ -307,7 +295,7 @@ impl PemStorableKey for PrivateKey {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug)]
pub struct Signature(ed25519_dalek::Signature);
impl Signature {
@@ -331,14 +319,6 @@ impl Signature {
}
}
impl FromStr for Signature {
type Err = Ed25519RecoveryError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Signature::from_base58_string(s)
}
}
#[cfg(feature = "serde")]
impl Serialize for Signature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+3 -4
View File
@@ -3,7 +3,6 @@ name = "nym-dkg"
version = "0.1.0"
edition = "2021"
resolver = "2"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -12,7 +11,7 @@ bitvec = "1.0.0"
# unfortunately until https://github.com/zkcrypto/bls12_381/issues/10 is resolved, we have to rely on the fork
# as we need to be able to serialize Gt so that we could create the lookup table for baby-step-giant-step algorithm
bls12_381 = { workspace = true, default-features = false, features = ["alloc", "pairings", "experimental", "zeroize"] }
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch ="gt-serialisation", default-features = false, features = ["alloc", "pairings", "experimental", "zeroize"] }
nym-contracts-common = { path = "../cosmwasm-smart-contracts/contracts-common", optional = true }
bs58 = "0.4"
@@ -30,11 +29,11 @@ zeroize = { workspace = true, features = ["zeroize_derive"] }
nym-pemstore = { path = "../pemstore" }
[dependencies.group]
workspace = true
version = "0.11"
default-features = false
[dependencies.ff]
workspace = true
version = "0.11"
default-features = false
[dev-dependencies]
+2 -1
View File
@@ -14,7 +14,8 @@ use std::collections::HashMap;
use std::ops::Neg;
use zeroize::Zeroize;
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug)]
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
pub struct Ciphertexts {
pub rr: [G1Projective; NUM_CHUNKS],
pub ss: [G1Projective; NUM_CHUNKS],
+2 -1
View File
@@ -53,7 +53,8 @@ impl PublicKey {
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct PublicKeyWithProof {
pub(crate) key: PublicKey,
pub(crate) proof: ProofOfDiscreteLog,
+2 -1
View File
@@ -67,7 +67,8 @@ impl<'a> Instance<'a> {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug)]
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
pub struct ProofOfChunking {
y0: G1Projective,
bb: Vec<G1Projective>,
+2 -1
View File
@@ -13,7 +13,8 @@ use zeroize::Zeroize;
const DISCRETE_LOG_DOMAIN: &[u8] =
b"NYM_COCONUT_NIDKG_V01_CS01_WITH_BLS12381_XMD:SHA-256_SSWU_RO_PROOF_DISCRETE_LOG";
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct ProofOfDiscreteLog {
pub(crate) rand_commitment: G1Projective,
pub(crate) response: Scalar,
+2 -1
View File
@@ -76,7 +76,8 @@ impl<'a> Instance<'a> {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug)]
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
pub struct ProofOfSecretSharing {
ff: G1Projective,
aa: G2Projective,
+20 -100
View File
@@ -82,7 +82,8 @@ impl RecoveredVerificationKeys {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct Dealing {
pub public_coefficients: PublicCoefficients,
pub ciphertexts: Ciphertexts,
@@ -320,17 +321,9 @@ impl<'a> TryFrom<&'a nym_contracts_common::dealings::ContractSafeBytes> for Deal
}
}
/// Attempt to run the `VkCombine` algorithm to obtain the public master verification key, `VK`
/// alongside shares of the verification key, `shvk_{1}`, `shvk_{2}`, ... `svhk_{n}`, where n is the number of receivers.
///
/// # Arguments
///
/// * `dealings`: map of dealer indices to dealings they generated
/// * `threshold`: explicit threshold value of the associated dealings
/// * `receivers`:map of receiver indices to their public keys
// note: this function assumes all dealings have already been verified
// this assumes all dealings have been verified
pub fn try_recover_verification_keys(
dealings: &BTreeMap<NodeIndex, Dealing>,
dealings: &[Dealing],
threshold: Threshold,
receivers: &BTreeMap<NodeIndex, PublicKey>,
) -> Result<RecoveredVerificationKeys, DkgError> {
@@ -338,31 +331,24 @@ pub fn try_recover_verification_keys(
return Err(DkgError::NoDealingsAvailable);
}
let threshold = threshold as usize;
if dealings.len() < threshold {
return Err(DkgError::NotEnoughDealingsAvailable {
available: dealings.len(),
required: threshold,
});
}
let threshold_usize = threshold as usize;
if !dealings
.values()
.all(|dealing| dealing.public_coefficients.size() == threshold)
.iter()
.all(|dealing| dealing.public_coefficients.size() == threshold_usize)
{
return Err(DkgError::MismatchedDealings);
}
let dealer_indices = dealings.keys().collect::<Vec<_>>();
let indices = receivers.keys().collect::<Vec<_>>();
// Compute A0, ..., A_{t-1}
let mut interpolated_coefficients = Vec::with_capacity(threshold);
for k in 0..threshold {
let mut samples = Vec::with_capacity(dealer_indices.len());
for (dealer_index, dealing) in dealings.iter() {
let mut interpolated_coefficients = Vec::with_capacity(threshold_usize);
for k in 0..threshold_usize {
let mut samples = Vec::with_capacity(indices.len());
for (j, dealing) in dealings.iter().enumerate() {
samples.push((
Scalar::from(*dealer_index),
Scalar::from(*indices[j]),
*dealing.public_coefficients.nth(k),
))
}
@@ -379,7 +365,7 @@ pub fn try_recover_verification_keys(
// shvk_j = A0^{j^0} * A1^{j^1} * ... * A_{t-1}^{j^{t-1}}
let verification_key_shares = receivers
.keys()
.map(|receiver_index| interpolated_coefficients.evaluate_at(&Scalar::from(*receiver_index)))
.map(|index| interpolated_coefficients.evaluate_at(&Scalar::from(*index)))
.collect();
Ok(RecoveredVerificationKeys {
@@ -471,17 +457,14 @@ mod tests {
let dealings = node_indices
.iter()
.map(|&dealer_index| {
(
dealer_index,
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0,
)
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0
})
.collect::<BTreeMap<_, _>>();
.collect::<Vec<_>>();
let mut derived_secrets = Vec::new();
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let shares = dealings
.values()
.iter()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
derived_secrets.push(
@@ -530,12 +513,9 @@ mod tests {
let dealings = node_indices
.iter()
.map(|&dealer_index| {
(
dealer_index,
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0,
)
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0
})
.collect::<BTreeMap<_, _>>();
.collect::<Vec<_>>();
let RecoveredVerificationKeys {
recovered_master,
@@ -551,66 +531,6 @@ mod tests {
.is_ok())
}
#[test]
#[ignore] // expensive test
fn verifying_partial_verification_keys_with_different_dealers_and_receivers() {
let dummy_seed = [42u8; 32];
let mut rng = rand_chacha::ChaCha20Rng::from_seed(dummy_seed);
let params = setup();
let dealer_indices = [1, 2, 3, 8];
let receiver_indices = [3, 4, 5, 6, 7];
let threshold = 3;
let mut receivers = BTreeMap::new();
let mut full_keys = Vec::new();
for index in &receiver_indices {
let (dk, pk) = keygen(&params, &mut rng);
receivers.insert(*index, *pk.public_key());
full_keys.push((dk, pk))
}
let dealings = dealer_indices
.iter()
.map(|&dealer_index| {
(
dealer_index,
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0,
)
})
.collect::<BTreeMap<_, _>>();
let RecoveredVerificationKeys {
recovered_master,
recovered_partials,
} = try_recover_verification_keys(&dealings, threshold, &receivers).unwrap();
let g2 = G2Projective::generator();
let mut derived_secrets = Vec::new();
for (i, (dk, _)) in full_keys.iter().enumerate() {
let shares = dealings
.values()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
let recovered_secret = combine_shares(shares, &dealer_indices).unwrap();
// make sure it matches the associated vk
assert_eq!(recovered_partials[i], g2 * recovered_secret);
derived_secrets.push(recovered_secret)
}
assert!(verify_verification_keys(
&recovered_master,
&recovered_partials,
&receivers,
threshold
)
.is_ok())
}
#[test]
#[ignore] // expensive test
fn dealing_roundtrip() {
+1 -1
View File
@@ -3,7 +3,7 @@
use thiserror::Error;
#[derive(Debug, Error, Clone)]
#[derive(Debug, Error)]
pub enum DkgError {
#[error("Provided set of values contained duplicate coordinate")]
DuplicateCoordinate,
-1
View File
@@ -13,7 +13,6 @@ pub mod dealing;
pub(crate) mod share;
pub(crate) mod utils;
pub use bls12_381::{G2Projective, Scalar};
pub use dealing::*;
pub use share::*;
+36 -51
View File
@@ -52,7 +52,7 @@ fn single_sender() {
.unwrap();
// make sure each share is actually decryptable (even though proofs say they must be, perform this sanity check)
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let _recovered = decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap();
}
@@ -91,13 +91,10 @@ fn full_threshold_secret_sharing() {
let dealings = node_indices
.iter()
.map(|&dealer_index| {
(
dealer_index,
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0,
)
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0
})
.collect::<BTreeMap<_, _>>();
for dealing in dealings.values() {
.collect::<Vec<_>>();
for dealing in dealings.iter() {
dealing
.verify(&params, threshold, &receivers, None)
.unwrap();
@@ -112,9 +109,9 @@ fn full_threshold_secret_sharing() {
let g2 = G2Projective::generator();
let mut derived_secrets = Vec::new();
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let shares = dealings
.values()
.iter()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
@@ -172,12 +169,9 @@ fn full_threshold_secret_resharing() {
let first_dealings = node_indices
.iter()
.map(|&dealer_index| {
(
dealer_index,
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0,
)
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0
})
.collect::<BTreeMap<_, _>>();
.collect::<Vec<_>>();
// recover verification keys
let RecoveredVerificationKeys {
@@ -186,9 +180,9 @@ fn full_threshold_secret_resharing() {
} = try_recover_verification_keys(&first_dealings, threshold, &receivers).unwrap();
let mut derived_secrets = Vec::new();
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let shares = first_dealings
.values()
.iter()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
@@ -209,22 +203,19 @@ fn full_threshold_secret_resharing() {
.iter()
.zip(derived_secrets.iter())
.map(|(&dealer_index, prior_secret)| {
(
Dealing::create(
&mut rng,
&params,
dealer_index,
Dealing::create(
&mut rng,
&params,
dealer_index,
threshold,
&receivers,
Some(*prior_secret),
)
.0,
threshold,
&receivers,
Some(*prior_secret),
)
.0
})
.collect::<BTreeMap<_, _>>();
.collect::<Vec<_>>();
for (reshared_dealing, prior_vk) in resharing_dealings.values().zip(recovered_partials.iter()) {
for (reshared_dealing, prior_vk) in resharing_dealings.iter().zip(recovered_partials.iter()) {
reshared_dealing
.verify(&params, threshold, &receivers, Some(*prior_vk))
.unwrap();
@@ -237,9 +228,9 @@ fn full_threshold_secret_resharing() {
} = try_recover_verification_keys(&resharing_dealings, threshold, &receivers).unwrap();
let mut reshared_secrets = Vec::new();
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let shares = resharing_dealings
.values()
.iter()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
@@ -288,12 +279,9 @@ fn full_threshold_secret_resharing_left_party() {
let first_dealings = node_indices
.iter()
.map(|&dealer_index| {
(
dealer_index,
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0,
)
Dealing::create(&mut rng, &params, dealer_index, threshold, &receivers, None).0
})
.collect::<BTreeMap<_, _>>();
.collect::<Vec<_>>();
// recover verification keys
let RecoveredVerificationKeys {
@@ -302,9 +290,9 @@ fn full_threshold_secret_resharing_left_party() {
} = try_recover_verification_keys(&first_dealings, threshold, &receivers).unwrap();
let mut derived_secrets = Vec::new();
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let shares = first_dealings
.values()
.iter()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
@@ -335,23 +323,20 @@ fn full_threshold_secret_resharing_left_party() {
.iter()
.zip(derived_secrets.iter().take(2))
.map(|(&dealer_index, prior_secret)| {
(
Dealing::create(
&mut rng,
&params,
dealer_index,
Dealing::create(
&mut rng,
&params,
dealer_index,
threshold,
&receivers,
Some(*prior_secret),
)
.0,
threshold,
&receivers,
Some(*prior_secret),
)
.0
})
.collect::<BTreeMap<_, _>>();
.collect::<Vec<_>>();
for (reshared_dealing, prior_vk) in resharing_dealings
.values()
.iter()
.zip(recovered_partials.iter().take(2))
{
reshared_dealing
@@ -366,9 +351,9 @@ fn full_threshold_secret_resharing_left_party() {
} = try_recover_verification_keys(&resharing_dealings, threshold, &receivers).unwrap();
let mut reshared_secrets = Vec::new();
for (i, (ref dk, _)) in full_keys.iter().enumerate() {
for (i, (ref mut dk, _)) in full_keys.iter_mut().enumerate() {
let shares = resharing_dealings
.values()
.iter()
.map(|dealing| decrypt_share(dk, i, &dealing.ciphertexts, None).unwrap())
.collect();
-1
View File
@@ -2,7 +2,6 @@
name = "nym-execute"
version = "0.1.0"
edition = "2021"
license.workspace = true
[lib]
proc-macro = true
-63
View File
@@ -81,15 +81,6 @@ ExitPolicy accept6 *6:119
ExitPolicy accept *4:120
ExitPolicy reject6 [FC00::]/7:*
# Portless
ExitPolicy accept *:0
ExitPolicy accept *4:0
ExitPolicy accept *6:0
ExitPolicy reject *:0
ExitPolicy reject *4:0
ExitPolicy reject *6:0
#ExitPolicy accept *:8080 #and another comment here
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
@@ -193,60 +184,6 @@ ExitPolicy reject *:*
},
);
// ExitPolicy accept *:0
expected.push(
Accept,
AddressPortPattern {
ip_pattern: IpPattern::Star,
ports: PortRange::new_zero(),
},
);
// ExitPolicy accept *4:0
expected.push(
Accept,
AddressPortPattern {
ip_pattern: IpPattern::V4Star,
ports: PortRange::new_zero(),
},
);
// ExitPolicy accept *6:0
expected.push(
Accept,
AddressPortPattern {
ip_pattern: IpPattern::V6Star,
ports: PortRange::new_zero(),
},
);
// ExitPolicy reject *:0
expected.push(
Reject,
AddressPortPattern {
ip_pattern: IpPattern::Star,
ports: PortRange::new_zero(),
},
);
// ExitPolicy reject *4:0
expected.push(
Reject,
AddressPortPattern {
ip_pattern: IpPattern::V4Star,
ports: PortRange::new_zero(),
},
);
// ExitPolicy reject *6:0
expected.push(
Reject,
AddressPortPattern {
ip_pattern: IpPattern::V6Star,
ports: PortRange::new_zero(),
},
);
// ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
expected.push(
Reject,
+14 -37
View File
@@ -264,13 +264,7 @@ mod stringified_ip_pattern {
impl AddressPortPattern {
/// Return true iff this pattern matches a given address and port.
pub fn matches(&self, addr: &IpAddr, port: u16) -> bool {
// For backward compatibility, we treat port 0 as a wildcard until all gateways have
// upgraded, at which point we can add *:0 to the policy list.
if port == 0 {
self.ip_pattern.matches(addr)
} else {
self.ip_pattern.matches(addr) && self.ports.contains(port)
}
self.ip_pattern.matches(addr) && self.ports.contains(port)
}
/// As matches, but accept a SocketAddr.
@@ -401,9 +395,19 @@ fn parse_addr(s: &str) -> Result<IpAddr, PolicyError> {
})
}
/// Helper: try to parse a port making sure it's non-zero
fn parse_port(s: &str) -> Result<u16, PolicyError> {
s.parse::<u16>()
.map_err(|_| PolicyError::InvalidPort { raw: s.to_string() })
let port = s
.parse::<u16>()
.map_err(|_| PolicyError::InvalidPort { raw: s.to_string() })?;
if port == 0 {
Err(PolicyError::InvalidPort {
raw: port.to_string(),
})
} else {
Ok(port)
}
}
impl FromStr for IpPattern {
@@ -490,10 +494,6 @@ impl PortRange {
PortRange::new_unchecked(1, 65535)
}
pub fn new_zero() -> Self {
PortRange { start: 0, end: 0 }
}
/// Create a new PortRange.
///
/// The Portrange contains all ports between `start` and `end` inclusive.
@@ -574,7 +574,6 @@ mod test {
check("marzipan:80");
check("1.2.3.4:90-80");
check("1.2.3.4:0-80");
check("1.2.3.4/100:8888");
check("[1.2.3.4]/16:80");
check("[::1]/130:8888");
@@ -613,22 +612,6 @@ mod test {
check("0.0.0.0/0:*", &["127.0.0.1:80"], &["[f00b::]:80"]);
check("[::]/0:*", &["[f00b::]:80"], &["127.0.0.1:80"]);
check(
"*:0",
&["1.2.3.4:0", "[::1]:0", "9.0.0.0:0"],
&["1.2.3.4:443", "[::1]:500", "9.0.0.0:80", "[::1]:80"],
);
check(
"*4:0",
&["1.2.3.4:0", "9.0.0.0:0"],
&["1.2.3.4:443", "9.0.0.0:80", "[::1]:0", "[::1]:80"],
);
check(
"*6:0",
&["[::1]:0"],
&["[::1]:80", "1.2.3.4:0", "1.2.3.4:443"],
);
}
#[test]
@@ -637,7 +620,6 @@ mod test {
policy.push(AddressPolicyAction::Accept, "*:443".parse()?);
policy.push(AddressPolicyAction::Accept, "[::1]:80".parse()?);
policy.push(AddressPolicyAction::Reject, "*:80".parse()?);
policy.push(AddressPolicyAction::Accept, "*:0".parse()?);
let policy = policy; // drop mut
assert!(policy
@@ -658,9 +640,6 @@ mod test {
assert!(policy
.allows_sockaddr(&"127.0.0.1:66".parse().unwrap())
.is_none());
assert!(policy
.allows_sockaddr(&"127.0.0.1:0".parse().unwrap())
.unwrap());
Ok(())
}
@@ -693,6 +672,7 @@ mod test {
assert_eq!("*".parse::<PortRange>().unwrap(), PortRange::new_all());
assert!("hello".parse::<PortRange>().is_err());
assert!("0".parse::<PortRange>().is_err());
assert!("65536".parse::<PortRange>().is_err());
assert!("65537".parse::<PortRange>().is_err());
assert!("1-2-3".parse::<PortRange>().is_err());
@@ -700,9 +680,6 @@ mod test {
assert!("1-".parse::<PortRange>().is_err());
assert!("-2".parse::<PortRange>().is_err());
assert!("-".parse::<PortRange>().is_err());
assert_eq!("0".parse::<PortRange>().unwrap(), PortRange::new_zero(),);
assert!("0-1".parse::<PortRange>().is_err());
}
#[test]
+1 -2
View File
@@ -2,7 +2,6 @@
name = "ledger"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,4 +10,4 @@ bip32 = "0.5.1"
k256 = { workspace = true }
ledger-transport = "0.10.0"
ledger-transport-hid = "0.10.0"
thiserror = { workspace = true }
thiserror = { workspace = true }
+1 -2
View File
@@ -3,7 +3,6 @@ name = "nym-mixnode-common"
version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -21,7 +20,7 @@ tokio = { version = "1.24.1", features = [
"net",
"io-util",
] }
tokio-util = { workspace = true, features = ["codec"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
url = { workspace = true }
thiserror = { workspace = true }
+3 -3
View File
@@ -108,13 +108,13 @@ impl ConnectionHandler {
let reply_packet = match maybe_echo_packet {
Some(Ok(echo_packet)) => self.handle_echo_packet(echo_packet),
Some(Err(err)) => {
debug!(
error!(
"The socket connection got corrupted with error: {err}. Closing the socket",
);
return;
}
None => {
debug!("The socket connection got terminated by the remote!");
error!("The socket connection got terminated by the remote!");
return;
}
};
@@ -125,7 +125,7 @@ impl ConnectionHandler {
.write_all(reply_packet.to_bytes().as_ref())
.await
{
debug!(
error!(
"Failed to write reply packet back to the sender - {}. Closing the socket on our end",
err
);
+1 -13
View File
@@ -111,7 +111,6 @@ impl NymNetworkDetails {
.with_additional_validator_endpoint(ValidatorDetails::new(
var(var_names::NYXD).expect("nyxd validator not set"),
Some(var(var_names::NYM_API).expect("nym api not set")),
get_optional_env(var_names::NYXD_WEBSOCKET),
))
.with_mixnet_contract(Some(
var(var_names::MIXNET_CONTRACT_ADDRESS).expect("mixnet contract not set"),
@@ -341,9 +340,6 @@ impl DenomDetailsOwned {
pub struct ValidatorDetails {
// it is assumed those values are always valid since they're being provided in our defaults file
pub nyxd_url: String,
//
pub websocket_url: Option<String>,
// Right now api_url is optional as we are not running the api reliably on all validators
// however, later on it should be a mandatory field
pub api_url: Option<String>,
@@ -351,10 +347,9 @@ pub struct ValidatorDetails {
}
impl ValidatorDetails {
pub fn new<S: Into<String>>(nyxd_url: S, api_url: Option<S>, websocket_url: Option<S>) -> Self {
pub fn new<S: Into<String>>(nyxd_url: S, api_url: Option<S>) -> Self {
ValidatorDetails {
nyxd_url: nyxd_url.into(),
websocket_url: websocket_url.map(Into::into),
api_url: api_url.map(Into::into),
}
}
@@ -362,7 +357,6 @@ impl ValidatorDetails {
pub fn new_nyxd_only<S: Into<String>>(nyxd_url: S) -> Self {
ValidatorDetails {
nyxd_url: nyxd_url.into(),
websocket_url: None,
api_url: None,
}
}
@@ -378,12 +372,6 @@ impl ValidatorDetails {
.as_ref()
.map(|url| url.parse().expect("the provided api url is invalid!"))
}
pub fn websocket_url(&self) -> Option<Url> {
self.websocket_url
.as_ref()
.map(|url| url.parse().expect("the provided websocket url is invalid!"))
}
}
fn fix_deprecated_environmental_variables() {
+1 -15
View File
@@ -3,7 +3,6 @@
use crate::var_names;
use crate::{DenomDetails, ValidatorDetails};
use std::str::FromStr;
pub const NETWORK_NAME: &str = "mainnet";
@@ -26,7 +25,6 @@ pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
pub const EXPLORER_API: &str = "https://explorer.nymtech.net/api/";
// I'm making clippy mad on purpose, because that url HAS TO be updated and deployed before merging
@@ -34,11 +32,7 @@ pub const EXIT_POLICY_URL: &str =
"https://nymtech.net/.wellknown/network-requester/exit-policy.txt";
pub(crate) fn validators() -> Vec<ValidatorDetails> {
vec![ValidatorDetails::new(
NYXD_URL,
Some(NYM_API),
Some(NYXD_WS),
)]
vec![ValidatorDetails::new(NYXD_URL, Some(NYM_API))]
}
const DEFAULT_SUFFIX: &str = "_MAINNET_DEFAULT";
@@ -66,12 +60,6 @@ pub fn read_var_if_not_default(var: &str) -> Option<String> {
}
}
pub fn read_parsed_var_if_not_default<T: FromStr>(var: &str) -> Option<Result<T, T::Err>> {
read_var_if_not_default(var)
.as_deref()
.map(FromStr::from_str)
}
pub fn export_to_env() {
set_var_to_default(var_names::CONFIGURED, "true");
set_var_to_default(var_names::NETWORK_NAME, NETWORK_NAME);
@@ -116,7 +104,6 @@ pub fn export_to_env() {
);
set_var_to_default(var_names::NYXD, NYXD_URL);
set_var_to_default(var_names::NYM_API, NYM_API);
set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
set_var_to_default(var_names::EXPLORER_API, EXPLORER_API);
set_var_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL);
}
@@ -165,7 +152,6 @@ pub fn export_to_env_if_not_set() {
);
set_var_conditionally_to_default(var_names::NYXD, NYXD_URL);
set_var_conditionally_to_default(var_names::NYM_API, NYM_API);
set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
set_var_conditionally_to_default(var_names::EXPLORER_API, EXPLORER_API);
set_var_conditionally_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL);
}
-1
View File
@@ -26,7 +26,6 @@ pub const SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS: &str =
pub const NAME_SERVICE_CONTRACT_ADDRESS: &str = "NAME_SERVICE_CONTRACT_ADDRESS";
pub const NYXD: &str = "NYXD";
pub const NYM_API: &str = "NYM_API";
pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
pub const EXPLORER_API: &str = "EXPLORER_API";
pub const EXIT_POLICY_URL: &str = "EXIT_POLICY";
-1
View File
@@ -2,7 +2,6 @@
name = "nym-node-tester-utils"
version = "0.1.0"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -3,7 +3,6 @@ name = "nym-nonexhaustive-delayqueue"
version = "0.1.0"
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+3 -7
View File
@@ -3,12 +3,11 @@ name = "nym-coconut"
version = "0.5.0"
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>", "Ania Piotrowska <ania@nymtech.net>"]
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] }
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", branch ="gt-serialisation", default-features = false, features = ["pairings", "alloc", "experimental"] }
itertools = "0.10"
digest = "0.9"
rand = "0.8"
@@ -17,17 +16,16 @@ serde = { workspace = true }
serde_derive = "1.0"
bs58 = "0.4.0"
sha2 = "0.9"
zeroize = { workspace = true, optional = true }
nym-dkg = { path = "../dkg" }
nym-pemstore = { path = "../pemstore" }
[dependencies.ff]
workspace = true
version = "0.11"
default-features = false
[dependencies.group]
workspace = true
version = "0.11"
default-features = false
[dev-dependencies]
@@ -40,9 +38,7 @@ name = "benchmarks"
harness = false
[features]
key-zeroize = ["zeroize", "bls12_381/zeroize"]
default = []
[target.'cfg(target_env = "wasm32-unknown-unknown")'.dependencies]
getrandom = { version="0.2", features=["js"] }
+14 -14
View File
@@ -7,7 +7,7 @@ use ff::Field;
use group::{Curve, Group};
use nym_coconut::{
aggregate_signature_shares, aggregate_verification_keys, blind_sign, prepare_blind_sign,
prove_bandwidth_credential, random_scalars_refs, setup, ttp_keygen, verify_credential,
prove_bandwidth_credential, setup, ttp_keygen, verify_credential,
verify_partial_blind_signature, Attribute, BlindedSignature, Parameters, Signature,
SignatureShare, VerificationKey,
};
@@ -66,8 +66,8 @@ fn unblind_and_aggregate(
params: &Parameters,
blinded_signatures: &[BlindedSignature],
partial_verification_keys: &[VerificationKey],
private_attributes: &[&Attribute],
public_attributes: &[&Attribute],
private_attributes: &[Attribute],
public_attributes: &[Attribute],
commitment_hash: &G1Projective,
pedersen_commitments_openings: &[Scalar],
verification_key: &VerificationKey,
@@ -78,7 +78,7 @@ fn unblind_and_aggregate(
.zip(partial_verification_keys.iter())
.map(|(signature, partial_verification_key)| {
signature
.unblind_and_verify(
.unblind(
params,
partial_verification_key,
private_attributes,
@@ -171,10 +171,10 @@ fn bench_coconut(c: &mut Criterion) {
let params = setup(case.num_public_attrs + case.num_private_attrs).unwrap();
random_scalars_refs!(public_attributes, params, case.num_public_attrs as usize);
let public_attributes = params.n_random_scalars(case.num_public_attrs as usize);
let serial_number = params.random_scalar();
let binding_number = params.random_scalar();
let private_attributes = vec![&serial_number, &binding_number];
let private_attributes = vec![serial_number, binding_number];
// The prepare blind sign is performed by the user
let (pedersen_commitments_openings, blind_sign_request) =
@@ -213,7 +213,7 @@ fn bench_coconut(c: &mut Criterion) {
b.iter(|| {
blind_sign(
&params,
keypair.secret_key(),
&keypair.secret_key(),
&blind_sign_request,
&public_attributes,
)
@@ -228,7 +228,7 @@ fn bench_coconut(c: &mut Criterion) {
for keypair in coconut_keypairs.iter() {
let blinded_signature = blind_sign(
&params,
keypair.secret_key(),
&keypair.secret_key(),
&blind_sign_request,
&public_attributes,
)
@@ -238,7 +238,7 @@ fn bench_coconut(c: &mut Criterion) {
let verification_keys: Vec<VerificationKey> = coconut_keypairs
.iter()
.map(|keypair| keypair.verification_key().clone())
.map(|keypair| keypair.verification_key())
.collect();
// verify a random partial blind signature
@@ -255,7 +255,7 @@ fn bench_coconut(c: &mut Criterion) {
b.iter(|| {
verify_partial_blind_signature(
&params,
blind_sign_request.get_private_attributes_pedersen_commitments(),
&blind_sign_request,
&public_attributes,
random_blind_signature,
partial_verification_key,
@@ -310,8 +310,8 @@ fn bench_coconut(c: &mut Criterion) {
&params,
&aggr_verification_key,
&aggregated_signature,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
@@ -329,8 +329,8 @@ fn bench_coconut(c: &mut Criterion) {
&params,
&aggr_verification_key,
&aggregated_signature,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap()
})

Some files were not shown because too many files have changed in this diff Show More