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
209 changed files with 2285 additions and 10498 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
-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
+87 -36
View File
@@ -987,13 +987,27 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]]
name = "bls12_381"
version = "0.8.0"
source = "git+https://github.com/jstuczyn/bls12_381?branch=feature/gt-serialization-0.8.0#c4543fde7d02efea6ecfcf22e14476ddb516b483"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397"
dependencies = [
"digest 0.9.0",
"ff 0.13.0",
"group 0.13.0",
"pairing",
"ff 0.10.1",
"group 0.10.0",
"pairing 0.20.0",
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "bls12_381"
version = "0.6.0"
source = "git+https://github.com/jstuczyn/bls12_381?branch=gt-serialisation#10fb6f700bfda17c8475af3bfd31e3fec15f2278"
dependencies = [
"digest 0.9.0",
"ff 0.11.1",
"group 0.11.0",
"pairing 0.21.0",
"rand_core 0.6.4",
"subtle 2.4.1",
"zeroize",
@@ -3016,6 +3030,26 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "ff"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f"
dependencies = [
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "ff"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924"
dependencies = [
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "ff"
version = "0.12.1"
@@ -3032,7 +3066,6 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
dependencies = [
"bitvec",
"rand_core 0.6.4",
"subtle 2.4.1",
]
@@ -3486,6 +3519,30 @@ dependencies = [
"web-sys",
]
[[package]]
name = "group"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912"
dependencies = [
"byteorder",
"ff 0.10.1",
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "group"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
dependencies = [
"byteorder",
"ff 0.11.1",
"rand_core 0.6.4",
"subtle 2.4.1",
]
[[package]]
name = "group"
version = "0.12.1"
@@ -4229,15 +4286,6 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.9"
@@ -5889,7 +5937,6 @@ dependencies = [
"futures-util",
"getset",
"humantime-serde",
"itertools 0.12.0",
"lazy_static",
"log",
"nym-api-requests",
@@ -5954,12 +6001,10 @@ dependencies = [
"cosmwasm-std",
"getset",
"nym-coconut-interface",
"nym-crypto",
"nym-mixnet-contract-common",
"nym-node-requests",
"schemars",
"serde",
"tendermint",
"ts-rs",
]
@@ -5977,7 +6022,6 @@ dependencies = [
"rand 0.7.3",
"thiserror",
"url",
"zeroize",
]
[[package]]
@@ -6213,14 +6257,14 @@ dependencies = [
name = "nym-coconut"
version = "0.5.0"
dependencies = [
"bls12_381",
"bls12_381 0.6.0",
"bs58 0.4.0",
"criterion",
"digest 0.9.0",
"doc-comment",
"ff 0.13.0",
"ff 0.11.1",
"getrandom 0.2.10",
"group 0.13.0",
"group 0.11.0",
"itertools 0.10.5",
"nym-dkg",
"nym-pemstore",
@@ -6230,7 +6274,6 @@ dependencies = [
"serde_derive",
"sha2 0.9.9",
"thiserror",
"zeroize",
]
[[package]]
@@ -6321,7 +6364,7 @@ dependencies = [
name = "nym-credentials"
version = "0.1.0"
dependencies = [
"bls12_381",
"bls12_381 0.5.0",
"cosmrs",
"log",
"nym-api-requests",
@@ -6330,7 +6373,6 @@ dependencies = [
"nym-validator-client",
"rand 0.7.3",
"thiserror",
"zeroize",
]
[[package]]
@@ -6364,11 +6406,11 @@ name = "nym-dkg"
version = "0.1.0"
dependencies = [
"bitvec",
"bls12_381",
"bls12_381 0.6.0",
"bs58 0.4.0",
"criterion",
"ff 0.13.0",
"group 0.13.0",
"ff 0.11.1",
"group 0.11.0",
"lazy_static",
"nym-contracts-common",
"nym-pemstore",
@@ -7840,11 +7882,20 @@ dependencies = [
[[package]]
name = "pairing"
version = "0.23.0"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f"
checksum = "7de9d09263c9966e8196fe0380c9dbbc7ea114b5cf371ba29004bc1f9c6db7f3"
dependencies = [
"group 0.13.0",
"group 0.10.0",
]
[[package]]
name = "pairing"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2e415e349a3006dd7d9482cdab1c980a845bed1377777d768cb693a44540b42"
dependencies = [
"group 0.11.0",
]
[[package]]
@@ -9739,9 +9790,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.108"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
@@ -10963,16 +11014,16 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.10"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
dependencies = [
"bytes",
"futures-core",
"futures-io",
"futures-sink",
"futures-util",
"hashbrown 0.14.1",
"hashbrown 0.12.3",
"pin-project-lite 0.2.13",
"slab",
"tokio",
+1 -11
View File
@@ -162,8 +162,7 @@ serde_json = "1.0.91"
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 }
@@ -173,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"
@@ -201,7 +192,6 @@ cw-controllers = { version = "=1.1.0" }
bip32 = "0.5.1"
cosmrs = "=0.15.0"
tendermint-rpc = "0.34" # same version as used by cosmrs
tendermint = "0.34" # same version as used by cosmrs
prost = "0.12"
# wasm-related dependencies
-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
@@ -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"] }
-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
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
@@ -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
@@ -5,12 +5,8 @@ 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};
use nym_api_requests::coconut::models::{
EpochCredentialsResponse, IssuedCredentialResponse, IssuedCredentialsResponse,
};
use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, CredentialsRequestBody, VerifyCredentialBody,
VerifyCredentialResponse,
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_api_requests::models::{
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
@@ -19,7 +15,6 @@ use nym_api_requests::models::{
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
StakeSaturationResponse, UptimeResponse,
};
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;
@@ -404,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";
@@ -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,
@@ -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]
@@ -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())
}
@@ -47,10 +47,6 @@ 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},
@@ -71,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 {
-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"
+10 -12
View File
@@ -21,14 +21,10 @@ pub use nym_coconut::{
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() {
+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"]
@@ -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
@@ -15,4 +14,4 @@ contracts-common = { path = "../contracts-common", package = "nym-contracts-comm
nym-multisig-contract-common = { path = "../multisig-contract" }
[features]
schema = []
schema = []
@@ -174,19 +174,17 @@ impl Display for EpochState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
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"),
}
@@ -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"]
-1
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
-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
+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]
-1
View File
@@ -2,7 +2,6 @@
name = "nym-execute"
version = "0.1.0"
edition = "2021"
license.workspace = true
[lib]
proc-macro = true
+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
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"] }
+13 -13
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
@@ -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()
})
+13 -34
View File
@@ -34,10 +34,7 @@ impl TryFrom<&[u8]> for Ciphertext {
)));
}
// safety: we just checked for the length so the unwraps are fine
#[allow(clippy::unwrap_used)]
let c1_bytes: &[u8; 48] = &bytes[..48].try_into().unwrap();
#[allow(clippy::unwrap_used)]
let c2_bytes: &[u8; 48] = &bytes[48..].try_into().unwrap();
let c1 = try_deserialize_g1_projective(
@@ -115,16 +112,7 @@ impl Bytable for PrivateKey {
}
fn try_from_byte_slice(slice: &[u8]) -> Result<Self> {
let received = slice.len();
let Ok(arr) = slice.try_into() else {
return Err(CoconutError::UnexpectedArrayLength {
typ: "elgamal::PrivateKey".to_string(),
received,
expected: 32,
});
};
PrivateKey::from_bytes(arr)
PrivateKey::from_bytes(slice.try_into().unwrap())
}
}
@@ -157,36 +145,21 @@ impl PublicKey {
}
pub fn to_bytes(&self) -> [u8; 48] {
self.0.to_affine().to_compressed()
self.to_byte_vec().try_into().unwrap()
}
pub fn from_bytes(bytes: &[u8; 48]) -> Result<PublicKey> {
try_deserialize_g1_projective(
bytes,
CoconutError::Deserialization(
"Failed to deserialize compressed ElGamal public key".to_string(),
),
)
.map(PublicKey)
Ok(PublicKey::try_from(bytes.to_vec().as_slice()).unwrap())
}
}
impl Bytable for PublicKey {
fn to_byte_vec(&self) -> Vec<u8> {
self.to_bytes().into()
self.0.to_affine().to_compressed().into()
}
fn try_from_byte_slice(slice: &[u8]) -> Result<Self> {
let received = slice.len();
let Ok(arr) = slice.try_into() else {
return Err(CoconutError::UnexpectedArrayLength {
typ: "elgamal::PublicKey".to_string(),
received,
expected: 48,
});
};
PublicKey::from_bytes(arr)
Ok(PublicKey::from_bytes(slice.try_into().unwrap()).unwrap())
}
}
@@ -194,7 +167,13 @@ impl TryFrom<&[u8]> for PublicKey {
type Error = CoconutError;
fn try_from(slice: &[u8]) -> Result<PublicKey> {
PublicKey::try_from_byte_slice(slice)
try_deserialize_g1_projective(
slice.try_into().unwrap(),
CoconutError::Deserialization(
"Failed to deserialize compressed ElGamal public key".to_string(),
),
)
.map(PublicKey)
}
}
@@ -246,7 +225,7 @@ pub fn elgamal_keygen(params: &Parameters) -> ElGamalKeyPair {
pub fn compute_attribute_encryption(
params: &Parameters,
private_attributes: &[&Attribute],
private_attributes: &[Attribute],
pub_key: &PublicKey,
commitment_hash: G1Projective,
) -> (Vec<Ciphertext>, Vec<EphemeralKey>) {
-16
View File
@@ -50,20 +50,4 @@ pub enum CoconutError {
modulus: usize,
object: String,
},
#[error("received an array of unexpected size for deserialization of {typ}. got {received} but expected {expected}")]
UnexpectedArrayLength {
typ: String,
received: usize,
expected: usize,
},
#[error("failed to decode the base58 representation: {0}")]
Base58DecodingFailure(#[from] bs58::decode::Error),
#[error("failed to deserialize scalar from the received bytes - it might not have been canonically encoded")]
ScalarDeserializationFailure,
#[error("failed to deserialize G1Projective point from the received bytes - it might not have been canonically encoded")]
G1ProjectiveDeserializationFailure,
}
+17 -4
View File
@@ -1,9 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
use std::convert::TryInto;
use bls12_381::Scalar;
pub use crate::traits::Bytable;
pub use elgamal::elgamal_keygen;
pub use elgamal::ElGamalKeyPair;
pub use elgamal::PublicKey;
@@ -28,7 +30,6 @@ pub use scheme::BlindedSignature;
pub use scheme::Signature;
pub use scheme::SignatureShare;
pub use traits::Base58;
pub use traits::Bytable;
pub use utils::hash_to_scalar;
pub mod elgamal;
@@ -40,6 +41,18 @@ pub mod tests;
mod traits;
mod utils;
pub type Attribute = bls12_381::Scalar;
pub type Attribute = Scalar;
pub type PrivateAttribute = Attribute;
pub type PublicAttribute = Attribute;
impl Bytable for Attribute {
fn to_byte_vec(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
fn try_from_byte_slice(slice: &[u8]) -> Result<Self, CoconutError> {
Ok(Attribute::from_bytes(slice.try_into().unwrap()).unwrap())
}
}
impl Base58 for Attribute {}
+26 -38
View File
@@ -91,8 +91,8 @@ impl ProofCmCs {
commitment_opening: &Scalar,
commitments: &[G1Projective],
pedersen_commitments_openings: &[Scalar],
private_attributes: &[&Attribute],
public_attributes: &[&Attribute],
private_attributes: &[Attribute],
public_attributes: &[Attribute],
) -> Self {
// note: this is only called from `prepare_blind_sign` that already checks
// whether private attributes are non-empty and whether we don't have too many
@@ -162,8 +162,11 @@ impl ProofCmCs {
&challenge,
&pedersen_commitments_openings.iter().collect::<Vec<_>>(),
);
let response_attributes =
produce_responses(&witness_attributes, &challenge, private_attributes);
let response_attributes = produce_responses(
&witness_attributes,
&challenge,
&private_attributes.iter().collect::<Vec<_>>(),
);
ProofCmCs {
challenge,
@@ -178,7 +181,7 @@ impl ProofCmCs {
params: &Parameters,
commitment: &G1Projective,
commitments: &[G1Projective],
public_attributes: &[&Attribute],
public_attributes: &[Attribute],
) -> bool {
if self.response_attributes.len() != commitments.len() {
return false;
@@ -200,7 +203,7 @@ impl ProofCmCs {
- public_attributes
.iter()
.zip(params.gen_hs().iter().skip(self.response_attributes.len()))
.map(|(&pub_attr, hs)| hs * pub_attr)
.map(|(pub_attr, hs)| hs * pub_attr)
.sum::<G1Projective>())
* self.challenge
+ g1 * self.response_opening
@@ -277,12 +280,8 @@ impl ProofCmCs {
}
let mut idx = 0;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let challenge_bytes = bytes[idx..idx + 32].try_into().unwrap();
idx += 32;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let response_opening_bytes = bytes[idx..idx + 32].try_into().unwrap();
idx += 32;
@@ -298,8 +297,6 @@ impl ProofCmCs {
),
)?;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let ro_len = u64::from_le_bytes(bytes[idx..idx + 8].try_into().unwrap());
idx += 8;
if bytes[idx..].len() < ro_len as usize * 32 + 8 {
@@ -316,8 +313,6 @@ impl ProofCmCs {
CoconutError::Deserialization("Failed to deserialize openings response".to_string()),
)?;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let rm_len = u64::from_le_bytes(bytes[ro_end..ro_end + 8].try_into().unwrap());
let response_attributes = try_deserialize_scalar_vec(
rm_len,
@@ -467,7 +462,7 @@ impl ProofKappaZeta {
pub(crate) fn from_bytes(bytes: &[u8]) -> Result<Self> {
// at the very minimum there must be a single attribute being proven
if bytes.len() != 128 {
if bytes.len() < 32 * 4 || (bytes.len()) % 32 != 0 {
return Err(CoconutError::DeserializationInvalidLength {
actual: bytes.len(),
modulus_target: bytes.len(),
@@ -477,32 +472,24 @@ impl ProofKappaZeta {
});
}
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let challenge_bytes = bytes[..32].try_into().unwrap();
let challenge = try_deserialize_scalar(
&challenge_bytes,
CoconutError::Deserialization("Failed to deserialize challenge".to_string()),
)?;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let serial_number_bytes = &bytes[32..64].try_into().unwrap();
let response_serial_number = try_deserialize_scalar(
serial_number_bytes,
CoconutError::Deserialization("failed to deserialize the serial number".to_string()),
)?;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let binding_number_bytes = &bytes[64..96].try_into().unwrap();
let response_binding_number = try_deserialize_scalar(
binding_number_bytes,
CoconutError::Deserialization("failed to deserialize the binding number".to_string()),
)?;
// safety: bound checked + constant offset
#[allow(clippy::unwrap_used)]
let blinder_bytes = bytes[96..].try_into().unwrap();
let response_blinder = try_deserialize_scalar(
&blinder_bytes,
@@ -525,13 +512,14 @@ impl ProofKappaZeta {
#[cfg(test)]
mod tests {
use super::*;
use group::Group;
use rand::thread_rng;
use crate::scheme::keygen::keygen;
use crate::scheme::setup::setup;
use crate::scheme::verification::{compute_kappa, compute_zeta};
use crate::tests::helpers::random_scalars_refs;
use group::Group;
use rand::thread_rng;
use super::*;
#[test]
fn proof_cm_cs_bytes_roundtrip() {
@@ -542,7 +530,7 @@ mod tests {
let r = params.random_scalar();
let cms: [G1Projective; 1] = [G1Projective::random(&mut rng)];
let rs = params.n_random_scalars(1);
random_scalars_refs!(private_attributes, params, 1);
let private_attributes = params.n_random_scalars(1);
// 0 public 1 private
let pi_s = ProofCmCs::construct(&params, &cm, &r, &cms, &rs, &private_attributes, &[]);
@@ -558,7 +546,7 @@ mod tests {
G1Projective::random(&mut rng),
];
let rs = params.n_random_scalars(2);
random_scalars_refs!(private_attributes, params, 2);
let private_attributes = params.n_random_scalars(2);
// 0 public 2 privates
let pi_s = ProofCmCs::construct(&params, &cm, &r, &cms, &rs, &private_attributes, &[]);
@@ -574,20 +562,20 @@ mod tests {
let keypair = keygen(&params);
// we don't care about 'correctness' of the proof. only whether we can correctly recover it from bytes
let serial_number = &params.random_scalar();
let binding_number = &params.random_scalar();
let serial_number = params.random_scalar();
let binding_number = params.random_scalar();
let private_attributes = vec![serial_number, binding_number];
let r = params.random_scalar();
let kappa = compute_kappa(&params, keypair.verification_key(), &private_attributes, r);
let kappa = compute_kappa(&params, &keypair.verification_key(), &private_attributes, r);
let zeta = compute_zeta(&params, serial_number);
// 0 public 2 private
let pi_v = ProofKappaZeta::construct(
&params,
keypair.verification_key(),
serial_number,
binding_number,
&keypair.verification_key(),
&serial_number,
&binding_number,
&r,
&kappa,
&zeta,
@@ -604,9 +592,9 @@ mod tests {
let pi_v = ProofKappaZeta::construct(
&params,
keypair.verification_key(),
serial_number,
binding_number,
&keypair.verification_key(),
&serial_number,
&binding_number,
&r,
&kappa,
&zeta,
+15 -35
View File
@@ -83,7 +83,7 @@ pub fn aggregate_verification_keys(
pub fn aggregate_signatures(
params: &Parameters,
verification_key: &VerificationKey,
attributes: &[&Attribute],
attributes: &[Attribute],
signatures: &[PartialSignature],
indices: Option<&[SignerIndex]>,
) -> Result<Signature> {
@@ -100,7 +100,7 @@ pub fn aggregate_signatures(
let tmp = attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(&attr, beta_i)| beta_i * attr)
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
if !check_bilinear_pairing(
@@ -119,7 +119,7 @@ pub fn aggregate_signatures(
pub fn aggregate_signature_shares(
params: &Parameters,
verification_key: &VerificationKey,
attributes: &[&Attribute],
attributes: &[Attribute],
shares: &[SignatureShare],
) -> Result<Signature> {
let (signatures, indices): (Vec<_>, Vec<_>) = shares
@@ -138,13 +138,13 @@ pub fn aggregate_signature_shares(
#[cfg(test)]
mod tests {
use bls12_381::G1Projective;
use group::Group;
use crate::scheme::issuance::sign;
use crate::scheme::keygen::ttp_keygen;
use crate::scheme::setup::Parameters;
use crate::scheme::verification::verify;
use crate::tests::helpers::random_scalars_refs;
use bls12_381::G1Projective;
use group::Group;
use super::*;
@@ -155,7 +155,7 @@ mod tests {
let vks = keypairs
.into_iter()
.map(|keypair| keypair.verification_key().clone())
.map(|keypair| keypair.verification_key())
.collect::<Vec<_>>();
let aggr_vk1 = aggregate_verification_keys(&vks[..3], Some(&[1, 2, 3])).unwrap();
@@ -212,18 +212,13 @@ mod tests {
#[test]
fn signature_aggregation_works_for_any_subset_of_signatures() {
let mut params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let attributes = params.n_random_scalars(2);
let keypairs = ttp_keygen(&params, 3, 5).unwrap();
let (sks, vks): (Vec<_>, Vec<_>) = keypairs
.into_iter()
.map(|keypair| {
(
keypair.secret_key().clone(),
keypair.verification_key().clone(),
)
})
.map(|keypair| (keypair.secret_key(), keypair.verification_key()))
.unzip();
let sigs = sks
@@ -317,17 +312,12 @@ mod tests {
fn signature_aggregation_doesnt_work_for_empty_set_of_signatures() {
let signatures: Vec<Signature> = vec![];
let params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let attributes = params.n_random_scalars(2);
let keypairs = ttp_keygen(&params, 3, 5).unwrap();
let (_, vks): (Vec<_>, Vec<_>) = keypairs
.into_iter()
.map(|keypair| {
(
keypair.secret_key().clone(),
keypair.verification_key().clone(),
)
})
.map(|keypair| (keypair.secret_key(), keypair.verification_key()))
.unzip();
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
@@ -340,16 +330,11 @@ mod tests {
fn signature_aggregation_doesnt_work_if_indices_have_invalid_length() {
let signatures = vec![random_signature()];
let params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let attributes = params.n_random_scalars(2);
let keypairs = ttp_keygen(&params, 3, 5).unwrap();
let (_, vks): (Vec<_>, Vec<_>) = keypairs
.into_iter()
.map(|keypair| {
(
keypair.secret_key().clone(),
keypair.verification_key().clone(),
)
})
.map(|keypair| (keypair.secret_key(), keypair.verification_key()))
.unzip();
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
@@ -371,16 +356,11 @@ mod tests {
fn signature_aggregation_doesnt_work_for_non_unique_indices() {
let signatures = vec![random_signature(), random_signature()];
let params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let attributes = params.n_random_scalars(2);
let keypairs = ttp_keygen(&params, 3, 5).unwrap();
let (_, vks): (Vec<_>, Vec<_>) = keypairs
.into_iter()
.map(|keypair| {
(
keypair.secret_key().clone(),
keypair.verification_key().clone(),
)
})
.map(|keypair| (keypair.secret_key(), keypair.verification_key()))
.unzip();
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
@@ -25,8 +25,6 @@ impl TryFrom<&[u8]> for BlindedSerialNumber {
));
}
// safety: we've just made a check for 96 bytes
#[allow(clippy::unwrap_used)]
let inner = try_deserialize_g2_projective(
&bytes.try_into().unwrap(),
CoconutError::Deserialization(
+33 -51
View File
@@ -54,8 +54,6 @@ impl TryFrom<&[u8]> for BlindSignRequest {
let commitment_bytes_len = 48;
let commitment_hash_bytes_len = 48;
// safety: we made bound check and we're using constant offest
#[allow(clippy::unwrap_used)]
let cm_bytes = bytes[..j + commitment_bytes_len].try_into().unwrap();
let commitment = try_deserialize_g1_projective(
&cm_bytes,
@@ -65,8 +63,6 @@ impl TryFrom<&[u8]> for BlindSignRequest {
)?;
j += commitment_bytes_len;
// safety: we made bound check and we're using constant offest
#[allow(clippy::unwrap_used)]
let cm_hash_bytes = bytes[j..j + commitment_hash_bytes_len].try_into().unwrap();
let commitment_hash = try_deserialize_g1_projective(
&cm_hash_bytes,
@@ -76,8 +72,6 @@ impl TryFrom<&[u8]> for BlindSignRequest {
)?;
j += commitment_hash_bytes_len;
// safety: we made bound check and we're using constant offest
#[allow(clippy::unwrap_used)]
let c_len = u64::from_le_bytes(bytes[j..j + 8].try_into().unwrap());
j += 8;
if bytes[j..].len() < c_len as usize * 48 {
@@ -92,14 +86,6 @@ impl TryFrom<&[u8]> for BlindSignRequest {
let start = j + i * 48;
let end = start + 48;
if bytes.len() < end {
return Err(CoconutError::Deserialization(
"Failed to deserialize compressed commitment".to_string(),
));
}
// safety: we made bound check and we're using constant offest
#[allow(clippy::unwrap_used)]
let private_attributes_commitment_bytes = bytes[start..end].try_into().unwrap();
let private_attributes_commitment = try_deserialize_g1_projective(
&private_attributes_commitment_bytes,
@@ -151,7 +137,7 @@ impl Bytable for BlindSignRequest {
impl Base58 for BlindSignRequest {}
impl BlindSignRequest {
fn verify_proof(&self, params: &Parameters, public_attributes: &[&Attribute]) -> bool {
fn verify_proof(&self, params: &Parameters, public_attributes: &[Attribute]) -> bool {
self.pi_s.verify(
params,
&self.commitment,
@@ -164,8 +150,8 @@ impl BlindSignRequest {
self.commitment_hash
}
pub fn get_private_attributes_pedersen_commitments(&self) -> &[G1Projective] {
&self.private_attributes_commitments
pub fn get_private_attributes_pedersen_commitments(&self) -> Vec<G1Projective> {
self.private_attributes_commitments.clone()
}
pub fn to_bytes(&self) -> Vec<u8> {
@@ -175,16 +161,12 @@ impl BlindSignRequest {
pub fn from_bytes(bytes: &[u8]) -> Result<BlindSignRequest> {
BlindSignRequest::try_from(bytes)
}
pub fn num_private_attributes(&self) -> usize {
self.private_attributes_commitments.len()
}
}
pub fn compute_attributes_commitment(
params: &Parameters,
private_attributes: &[&Attribute],
public_attributes: &[&Attribute],
private_attributes: &[Attribute],
public_attributes: &[Attribute],
hs: &[G1Affine],
) -> (Scalar, G1Projective) {
let commitment_opening = params.random_scalar();
@@ -205,7 +187,7 @@ pub fn compute_attributes_commitment(
pub fn compute_pedersen_commitments_for_private_attributes(
params: &Parameters,
private_attributes: &[&Attribute],
private_attributes: &[Attribute],
h: &G1Projective,
) -> (Vec<Scalar>, Vec<G1Projective>) {
// Generate openings for Pedersen commitment for each private attribute
@@ -215,13 +197,13 @@ pub fn compute_pedersen_commitments_for_private_attributes(
let pedersen_commitments = commitments_openings
.iter()
.zip(private_attributes.iter())
.map(|(o_j, &m_j)| params.gen1() * o_j + h * m_j)
.map(|(o_j, m_j)| params.gen1() * o_j + h * m_j)
.collect::<Vec<_>>();
(commitments_openings, pedersen_commitments)
}
pub fn compute_hash(commitment: G1Projective, public_attributes: &[&Attribute]) -> G1Projective {
pub fn compute_hash(commitment: G1Projective, public_attributes: &[Attribute]) -> G1Projective {
let mut buff = Vec::new();
buff.extend_from_slice(commitment.to_bytes().as_ref());
for attr in public_attributes {
@@ -233,8 +215,8 @@ pub fn compute_hash(commitment: G1Projective, public_attributes: &[&Attribute])
/// Builds cryptographic material required for blind sign.
pub fn prepare_blind_sign(
params: &Parameters,
private_attributes: &[&Attribute],
public_attributes: &[&Attribute],
private_attributes: &[Attribute],
public_attributes: &[Attribute],
) -> Result<(Vec<Scalar>, BlindSignRequest)> {
if private_attributes.is_empty() {
return Err(CoconutError::Issuance(
@@ -289,7 +271,7 @@ pub fn blind_sign(
params: &Parameters,
signing_secret_key: &SecretKey,
blind_sign_request: &BlindSignRequest,
public_attributes: &[&Attribute],
public_attributes: &[Attribute],
) -> Result<BlindedSignature> {
let num_private = blind_sign_request.private_attributes_commitments.len();
let hs = params.gen_hs();
@@ -322,7 +304,7 @@ pub fn blind_sign(
let signed_public = h * public_attributes
.iter()
.zip(signing_secret_key.ys.iter().skip(num_private))
.map(|(&attr, yi)| attr * yi)
.map(|(attr, yi)| attr * yi)
.sum::<Scalar>();
// h ^ x + c[0] ^ y[0] + ... c[m] ^ y[m] + h ^ (pub_m[0] * y[m + 1] + ... + pub_m[n] * y[m + n])
@@ -363,7 +345,7 @@ pub fn blind_sign(
pub fn verify_partial_blind_signature(
params: &Parameters,
blind_sign_request: &BlindSignRequest,
public_attributes: &[&Attribute],
public_attributes: &[Attribute],
blind_sig: &BlindedSignature,
partial_verification_key: &VerificationKey,
) -> bool {
@@ -401,7 +383,7 @@ pub fn verify_partial_blind_signature(
}
// for each public attribute, add (s^pub_j, beta_{priv + j}) to the miller terms
for (&pub_attr, beta_g2) in public_attributes.iter().zip(
for (pub_attr, beta_g2) in public_attributes.iter().zip(
partial_verification_key
.beta_g2
.iter()
@@ -433,7 +415,7 @@ pub fn verify_partial_blind_signature(
pub fn sign(
params: &mut Parameters,
secret_key: &SecretKey,
public_attributes: &[&Attribute],
public_attributes: &[Attribute],
) -> Result<Signature> {
if public_attributes.len() > secret_key.ys.len() {
return Err(CoconutError::IssuanceMaxAttributes {
@@ -447,7 +429,7 @@ pub fn sign(
// (the python implementation hashes string representation of all attributes onto the curve,
// but I think the same can be achieved by just summing the attributes thus avoiding the unnecessary
// transformation. If I'm wrong, please correct me.)
let attributes_sum = public_attributes.iter().copied().sum::<Scalar>();
let attributes_sum = public_attributes.iter().sum::<Scalar>();
let h = hash_g1((params.gen1() * attributes_sum).to_bytes());
// x + m0 * y0 + m1 * y1 + ... mn * yn
@@ -455,7 +437,7 @@ pub fn sign(
+ public_attributes
.iter()
.zip(secret_key.ys.iter())
.map(|(&m_i, y_i)| m_i * y_i)
.map(|(m_i, y_i)| m_i * y_i)
.sum::<Scalar>();
let sig2 = h * exponent;
@@ -466,14 +448,13 @@ pub fn sign(
mod tests {
use super::*;
use crate::scheme::keygen::keygen;
use crate::tests::helpers::random_scalars_refs;
#[test]
fn blind_sign_request_bytes_roundtrip() {
// 0 public and 1 private attribute
let params = Parameters::new(1).unwrap();
random_scalars_refs!(private_attributes, params, 1);
random_scalars_refs!(public_attributes, params, 0);
let private_attributes = params.n_random_scalars(1);
let public_attributes = params.n_random_scalars(0);
let (_commitments_openings, lambda) =
prepare_blind_sign(&params, &private_attributes, &public_attributes).unwrap();
@@ -486,8 +467,8 @@ mod tests {
// 2 public and 2 private attributes
let params = Parameters::new(4).unwrap();
random_scalars_refs!(private_attributes, params, 2);
random_scalars_refs!(public_attributes, params, 2);
let private_attributes = params.n_random_scalars(2);
let public_attributes = params.n_random_scalars(2);
let (_commitments_openings, lambda) =
prepare_blind_sign(&params, &private_attributes, &public_attributes).unwrap();
@@ -502,8 +483,8 @@ mod tests {
#[test]
fn successful_verify_partial_blind_signature() {
let params = Parameters::new(4).unwrap();
random_scalars_refs!(private_attributes, params, 2);
random_scalars_refs!(public_attributes, params, 2);
let private_attributes = params.n_random_scalars(2);
let public_attributes = params.n_random_scalars(2);
let (_commitments_openings, request) =
prepare_blind_sign(&params, &private_attributes, &public_attributes).unwrap();
@@ -511,7 +492,7 @@ mod tests {
let validator_keypair = keygen(&params);
let blind_sig = blind_sign(
&params,
validator_keypair.secret_key(),
&validator_keypair.secret_key(),
&request,
&public_attributes,
)
@@ -522,35 +503,36 @@ mod tests {
&request,
&public_attributes,
&blind_sig,
validator_keypair.verification_key()
&validator_keypair.verification_key()
));
}
#[test]
fn successful_verify_partial_blind_signature_no_public_attributes() {
let params = Parameters::new(4).unwrap();
random_scalars_refs!(private_attributes, params, 2);
let private_attributes = params.n_random_scalars(2);
let (_commitments_openings, request) =
prepare_blind_sign(&params, &private_attributes, &[]).unwrap();
let validator_keypair = keygen(&params);
let blind_sig = blind_sign(&params, validator_keypair.secret_key(), &request, &[]).unwrap();
let blind_sig =
blind_sign(&params, &validator_keypair.secret_key(), &request, &[]).unwrap();
assert!(verify_partial_blind_signature(
&params,
&request,
&[],
&blind_sig,
validator_keypair.verification_key()
&validator_keypair.verification_key()
));
}
#[test]
fn fail_verify_partial_blind_signature_with_wrong_key() {
let params = Parameters::new(4).unwrap();
random_scalars_refs!(private_attributes, params, 2);
random_scalars_refs!(public_attributes, params, 2);
let private_attributes = params.n_random_scalars(2);
let public_attributes = params.n_random_scalars(2);
let (_commitments_openings, request) =
prepare_blind_sign(&params, &private_attributes, &public_attributes).unwrap();
@@ -559,7 +541,7 @@ mod tests {
let validator2_keypair = keygen(&params);
let blind_sig = blind_sign(
&params,
validator_keypair.secret_key(),
&validator_keypair.secret_key(),
&request,
&public_attributes,
)
@@ -571,7 +553,7 @@ mod tests {
&request,
&public_attributes,
&blind_sig,
validator2_keypair.verification_key()
&validator2_keypair.verification_key()
),);
}
}
+7 -36
View File
@@ -23,12 +23,8 @@ use crate::utils::{
};
use crate::Base58;
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq, Eq, Clone))]
#[cfg_attr(
feature = "key-zeroize",
derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop)
)]
#[derive(Debug, Clone)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct SecretKey {
pub(crate) x: Scalar,
pub(crate) ys: Vec<Scalar>,
@@ -66,9 +62,7 @@ impl TryFrom<&[u8]> for SecretKey {
}
// this conversion will not fail as we are taking the same length of data
#[allow(clippy::unwrap_used)]
let x_bytes: [u8; 32] = bytes[..32].try_into().unwrap();
#[allow(clippy::unwrap_used)]
let ys_len = u64::from_le_bytes(bytes[32..40].try_into().unwrap());
let actual_ys_len = (bytes.len() - 40) / 32;
@@ -103,10 +97,6 @@ impl SecretKey {
(self.x, self.ys.clone())
}
pub fn size(&self) -> usize {
self.ys.len()
}
/// Derive verification key using this secret key.
pub fn verification_key(&self, params: &Parameters) -> VerificationKey {
let g1 = params.gen1();
@@ -151,10 +141,6 @@ impl Base58 for SecretKey {}
// TODO: perhaps change points to affine representation
// to make verification slightly more efficient?
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(
feature = "key-zeroize",
derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop)
)]
pub struct VerificationKey {
// TODO add gen2 as per the paper or imply it from the fact library is using bls381?
pub(crate) alpha: G2Projective,
@@ -194,9 +180,7 @@ impl TryFrom<&[u8]> for VerificationKey {
}
// this conversion will not fail as we are taking the same length of data
#[allow(clippy::unwrap_used)]
let alpha_bytes: [u8; 96] = bytes[..96].try_into().unwrap();
#[allow(clippy::unwrap_used)]
let betas_len = u64::from_le_bytes(bytes[96..104].try_into().unwrap());
let actual_betas_len = (bytes.len() - 104) / (96 + 48);
@@ -220,8 +204,6 @@ impl TryFrom<&[u8]> for VerificationKey {
for i in 0..betas_len {
let start = (104 + i * 48) as usize;
let end = start + 48;
// we're using a constant 48 byte offset (which is the size of G1 compressed) so unwrap is fine
#[allow(clippy::unwrap_used)]
let beta_i_bytes = bytes[start..end].try_into().unwrap();
let beta_i = try_deserialize_g1_projective(
&beta_i_bytes,
@@ -238,8 +220,6 @@ impl TryFrom<&[u8]> for VerificationKey {
for i in 0..betas_len {
let start = (beta_g1_end + i * 96) as usize;
let end = start + 96;
// we're using a constant 96 byte offset (which is the size of G2 compressed) so unwrap is fine
#[allow(clippy::unwrap_used)]
let beta_i_bytes = bytes[start..end].try_into().unwrap();
let beta_i = try_deserialize_g2_projective(
&beta_i_bytes,
@@ -412,11 +392,7 @@ impl Bytable for VerificationKey {
impl Base58 for VerificationKey {}
#[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(PartialEq, Eq, Clone))]
#[cfg_attr(
feature = "key-zeroize",
derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop)
)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct KeyPair {
secret_key: SecretKey,
verification_key: VerificationKey,
@@ -453,12 +429,12 @@ impl KeyPair {
}
}
pub fn secret_key(&self) -> &SecretKey {
&self.secret_key
pub fn secret_key(&self) -> SecretKey {
self.secret_key.clone()
}
pub fn verification_key(&self) -> &VerificationKey {
&self.verification_key
pub fn verification_key(&self) -> VerificationKey {
self.verification_key.clone()
}
pub fn to_bytes(&self) -> Vec<u8> {
@@ -512,8 +488,6 @@ impl TryFrom<&[u8]> for KeyPair {
});
}
// safety: we made bound check and we're using constant offest
#[allow(clippy::unwrap_used)]
let secret_key_len =
u64::from_le_bytes(bytes[header_len..header_len + 8].try_into().unwrap()) as usize;
let secret_key_start = header_len + 8;
@@ -529,8 +503,6 @@ impl TryFrom<&[u8]> for KeyPair {
});
}
// safety: we made bound check
#[allow(clippy::unwrap_used)]
let verification_key_len = u64::from_le_bytes(
bytes[secret_key_start + secret_key_len..secret_key_start + secret_key_len + 8]
.try_into()
@@ -543,7 +515,6 @@ impl TryFrom<&[u8]> for KeyPair {
)?;
let consumed_bytes = verification_key_start + verification_key_len;
let index = if consumed_bytes < bytes.len() && [consumed_bytes..].len() == 8 {
#[allow(clippy::unwrap_used)]
Some(u64::from_le_bytes(
bytes[consumed_bytes..consumed_bytes + 8]
.try_into()
+97 -143
View File
@@ -44,10 +44,7 @@ impl TryFrom<&[u8]> for Signature {
)));
}
// safety: we just checked for the length so the unwraps are fine
#[allow(clippy::expect_used)]
let sig1_bytes: &[u8; 48] = &bytes[..48].try_into().expect("Slice size != 48");
#[allow(clippy::expect_used)]
let sig2_bytes: &[u8; 48] = &bytes[48..].try_into().expect("Slice size != 48");
let sig1 = try_deserialize_g1_projective(
@@ -91,45 +88,6 @@ impl Signature {
pub fn from_bytes(bytes: &[u8]) -> Result<Signature> {
Signature::try_from(bytes)
}
pub fn verify(
&self,
params: &Parameters,
partial_verification_key: &VerificationKey,
private_attributes: &[&Attribute],
public_attributes: &[&Attribute],
commitment_hash: &G1Projective,
) -> Result<()> {
// Verify the commitment hash
if !(commitment_hash == &self.0) {
return Err(CoconutError::Verification(
"Verification of commitment hash from signature failed".to_string(),
));
}
let alpha = partial_verification_key.alpha;
let signed_attributes = private_attributes
.iter()
.chain(public_attributes.iter())
.zip(partial_verification_key.beta_g2.iter())
.map(|(&attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
// Verify the signature share
if !check_bilinear_pairing(
&self.0.to_affine(),
&G2Prepared::from((alpha + signed_attributes).to_affine()),
&self.1.to_affine(),
params.prepared_miller_g2(),
) {
return Err(CoconutError::Unblind(
"Verification of signature share failed".to_string(),
));
}
Ok(())
}
}
impl Bytable for Signature {
@@ -144,7 +102,8 @@ impl Bytable for Signature {
impl Base58 for Signature {}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub struct BlindedSignature(G1Projective, G1Projective);
impl Bytable for BlindedSignature {
@@ -170,10 +129,7 @@ impl TryFrom<&[u8]> for BlindedSignature {
)));
}
// safety: we just checked for the length so the unwraps are fine
#[allow(clippy::expect_used)]
let h_bytes: &[u8; 48] = &bytes[..48].try_into().expect("Slice size != 48");
#[allow(clippy::expect_used)]
let sig_bytes: &[u8; 48] = &bytes[48..].try_into().expect("Slice size != 48");
let h = try_deserialize_g1_projective(
@@ -192,12 +148,24 @@ impl TryFrom<&[u8]> for BlindedSignature {
impl BlindedSignature {
pub fn unblind(
&self,
params: &Parameters,
partial_verification_key: &VerificationKey,
private_attributes: &[Attribute],
public_attributes: &[Attribute],
commitment_hash: &G1Projective,
pedersen_commitments_openings: &[Scalar],
) -> Result<Signature> {
// parse the signature
let h = &self.0;
let c = &self.1;
// Verify the commitment hash
if !(commitment_hash == h) {
return Err(CoconutError::Unblind(
"Verification of commitment hash from signature failed".to_string(),
));
}
let blinding_removers = partial_verification_key
.beta_g1
.iter()
@@ -207,27 +175,28 @@ impl BlindedSignature {
let unblinded_c = c - blinding_removers;
Ok(Signature(*h, unblinded_c))
}
let alpha = partial_verification_key.alpha;
pub fn unblind_and_verify(
&self,
params: &Parameters,
partial_verification_key: &VerificationKey,
private_attributes: &[&Attribute],
public_attributes: &[&Attribute],
commitment_hash: &G1Projective,
pedersen_commitments_openings: &[Scalar],
) -> Result<Signature> {
let unblinded = self.unblind(partial_verification_key, pedersen_commitments_openings)?;
unblinded.verify(
params,
partial_verification_key,
private_attributes,
public_attributes,
commitment_hash,
)?;
Ok(unblinded)
let signed_attributes = private_attributes
.iter()
.chain(public_attributes.iter())
.zip(partial_verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
// Verify the signature share
if !check_bilinear_pairing(
&h.to_affine(),
&G2Prepared::from((alpha + signed_attributes).to_affine()),
&unblinded_c.to_affine(),
params.prepared_miller_g2(),
) {
return Err(CoconutError::Unblind(
"Verification of signature share failed".to_string(),
));
}
Ok(Signature(*h, unblinded_c))
}
pub fn to_bytes(&self) -> [u8; 96] {
@@ -268,25 +237,25 @@ impl SignatureShare {
#[cfg(test)]
mod tests {
use super::*;
use crate::hash_to_scalar;
use crate::scheme::aggregation::{aggregate_signatures, aggregate_verification_keys};
use crate::scheme::issuance::{blind_sign, compute_hash, prepare_blind_sign, sign};
use crate::scheme::keygen::{keygen, ttp_keygen};
use crate::scheme::verification::{prove_bandwidth_credential, verify, verify_credential};
use crate::tests::helpers::random_scalars_refs;
use super::*;
#[test]
fn unblind_returns_error_if_integrity_check_on_commitment_hash_fails() {
let params = Parameters::new(2).unwrap();
random_scalars_refs!(private_attributes, params, 2);
let private_attributes = params.n_random_scalars(2_usize);
let (_commitments_openings, lambda) =
prepare_blind_sign(&params, &private_attributes, &[]).unwrap();
let keypair1 = keygen(&params);
let sig1 = blind_sign(&params, keypair1.secret_key(), &lambda, &[]).unwrap();
let sig1 = blind_sign(&params, &keypair1.secret_key(), &lambda, &[]).unwrap();
let wrong_commitment_opening = params.random_scalar();
let wrong_commitment = params.gen1() * wrong_commitment_opening;
@@ -294,9 +263,9 @@ mod tests {
let wrong_commitments_openings = params.n_random_scalars(private_attributes.len());
assert!(sig1
.unblind_and_verify(
.unblind(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&private_attributes,
&[],
&fake_commitment_hash,
@@ -308,23 +277,20 @@ mod tests {
#[test]
fn unblind_returns_error_if_signature_verification_fails() {
let params = Parameters::new(2).unwrap();
let p = [hash_to_scalar("Attribute1"), hash_to_scalar("Attribute2")];
let private_attributes = vec![&p[0], &p[1]];
let p2 = [hash_to_scalar("Attribute3"), hash_to_scalar("Attribute4")];
let private_attributes2 = vec![&p2[0], &p2[1]];
let private_attributes = vec![hash_to_scalar("Attribute1"), hash_to_scalar("Attribute2")];
let private_attributes2 = vec![hash_to_scalar("Attribute3"), hash_to_scalar("Attribute4")];
let (commitments_openings, lambda) =
prepare_blind_sign(&params, &private_attributes, &[]).unwrap();
let keypair1 = keygen(&params);
let sig1 = blind_sign(&params, keypair1.secret_key(), &lambda, &[]).unwrap();
let sig1 = blind_sign(&params, &keypair1.secret_key(), &lambda, &[]).unwrap();
assert!(sig1
.unblind_and_verify(
.unblind(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&private_attributes2,
&[],
&lambda.get_commitment_hash(),
@@ -338,7 +304,7 @@ mod tests {
let params = Parameters::new(2).unwrap();
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];
let keypair1 = keygen(&params);
let keypair2 = keygen(&params);
@@ -346,11 +312,11 @@ mod tests {
let (commitments_openings, lambda) =
prepare_blind_sign(&params, &private_attributes, &[]).unwrap();
let sig1 = blind_sign(&params, keypair1.secret_key(), &lambda, &[])
let sig1 = blind_sign(&params, &keypair1.secret_key(), &lambda, &[])
.unwrap()
.unblind_and_verify(
.unblind(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&private_attributes,
&[],
&lambda.get_commitment_hash(),
@@ -358,11 +324,11 @@ mod tests {
)
.unwrap();
let sig2 = blind_sign(&params, keypair2.secret_key(), &lambda, &[])
let sig2 = blind_sign(&params, &keypair2.secret_key(), &lambda, &[])
.unwrap()
.unblind_and_verify(
.unblind(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&private_attributes,
&[],
&lambda.get_commitment_hash(),
@@ -372,39 +338,39 @@ mod tests {
let theta1 = prove_bandwidth_credential(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&sig1,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
let theta2 = prove_bandwidth_credential(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&sig2,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
assert!(verify_credential(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&theta1,
&[],
));
assert!(verify_credential(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&theta2,
&[],
));
assert!(!verify_credential(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&theta2,
&[],
));
@@ -413,30 +379,30 @@ mod tests {
#[test]
fn verification_on_two_public_attributes() {
let mut params = Parameters::new(2).unwrap();
random_scalars_refs!(attributes, params, 2);
let attributes = params.n_random_scalars(2);
let keypair1 = keygen(&params);
let keypair2 = keygen(&params);
let sig1 = sign(&mut params, keypair1.secret_key(), &attributes).unwrap();
let sig2 = sign(&mut params, keypair2.secret_key(), &attributes).unwrap();
let sig1 = sign(&mut params, &keypair1.secret_key(), &attributes).unwrap();
let sig2 = sign(&mut params, &keypair2.secret_key(), &attributes).unwrap();
assert!(verify(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&attributes,
&sig1,
));
assert!(!verify(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&attributes,
&sig1,
));
assert!(!verify(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&attributes,
&sig2,
));
@@ -445,11 +411,10 @@ mod tests {
#[test]
fn verification_on_two_public_and_two_private_attributes() {
let params = Parameters::new(4).unwrap();
random_scalars_refs!(public_attributes, params, 2);
let public_attributes = params.n_random_scalars(2);
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];
let keypair1 = keygen(&params);
let keypair2 = keygen(&params);
@@ -457,11 +422,11 @@ mod tests {
let (commitments_openings, lambda) =
prepare_blind_sign(&params, &private_attributes, &public_attributes).unwrap();
let sig1 = blind_sign(&params, keypair1.secret_key(), &lambda, &public_attributes)
let sig1 = blind_sign(&params, &keypair1.secret_key(), &lambda, &public_attributes)
.unwrap()
.unblind_and_verify(
.unblind(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&private_attributes,
&public_attributes,
&lambda.get_commitment_hash(),
@@ -469,11 +434,11 @@ mod tests {
)
.unwrap();
let sig2 = blind_sign(&params, keypair2.secret_key(), &lambda, &public_attributes)
let sig2 = blind_sign(&params, &keypair2.secret_key(), &lambda, &public_attributes)
.unwrap()
.unblind_and_verify(
.unblind(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&private_attributes,
&public_attributes,
&lambda.get_commitment_hash(),
@@ -483,39 +448,39 @@ mod tests {
let theta1 = prove_bandwidth_credential(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&sig1,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
let theta2 = prove_bandwidth_credential(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&sig2,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
assert!(verify_credential(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&theta1,
&public_attributes,
));
assert!(verify_credential(
&params,
keypair2.verification_key(),
&keypair2.verification_key(),
&theta2,
&public_attributes,
));
assert!(!verify_credential(
&params,
keypair1.verification_key(),
&keypair1.verification_key(),
&theta2,
&public_attributes,
));
@@ -524,11 +489,10 @@ mod tests {
#[test]
fn verification_on_two_public_and_two_private_attributes_from_two_signers() {
let params = Parameters::new(4).unwrap();
random_scalars_refs!(public_attributes, params, 2);
let public_attributes = params.n_random_scalars(2);
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];
let keypairs = ttp_keygen(&params, 2, 3).unwrap();
@@ -538,11 +502,11 @@ mod tests {
let sigs = keypairs
.iter()
.map(|keypair| {
blind_sign(&params, keypair.secret_key(), &lambda, &public_attributes)
blind_sign(&params, &keypair.secret_key(), &lambda, &public_attributes)
.unwrap()
.unblind_and_verify(
.unblind(
&params,
keypair.verification_key(),
&keypair.verification_key(),
&private_attributes,
&public_attributes,
&lambda.get_commitment_hash(),
@@ -554,7 +518,7 @@ mod tests {
let vks = keypairs
.into_iter()
.map(|keypair| keypair.verification_key().clone())
.map(|keypair| keypair.verification_key())
.collect::<Vec<_>>();
let mut attributes = Vec::with_capacity(private_attributes.len() + public_attributes.len());
@@ -566,14 +530,9 @@ mod tests {
aggregate_signatures(&params, &aggr_vk, &attributes, &sigs[..2], Some(&[1, 2]))
.unwrap();
let theta = prove_bandwidth_credential(
&params,
&aggr_vk,
&aggr_sig,
&serial_number,
&binding_number,
)
.unwrap();
let theta =
prove_bandwidth_credential(&params, &aggr_vk, &aggr_sig, serial_number, binding_number)
.unwrap();
assert!(verify_credential(
&params,
@@ -588,14 +547,9 @@ mod tests {
aggregate_signatures(&params, &aggr_vk, &attributes, &sigs[1..], Some(&[2, 3]))
.unwrap();
let theta = prove_bandwidth_credential(
&params,
&aggr_vk,
&aggr_sig,
&serial_number,
&binding_number,
)
.unwrap();
let theta =
prove_bandwidth_credential(&params, &aggr_vk, &aggr_sig, serial_number, binding_number)
.unwrap();
assert!(verify_credential(
&params,
+18 -26
View File
@@ -43,8 +43,6 @@ impl TryFrom<&[u8]> for Theta {
));
}
// safety: we just checked for the length so the unwraps are fine
#[allow(clippy::unwrap_used)]
let blinded_message_bytes = bytes[..96].try_into().unwrap();
let blinded_message = try_deserialize_g2_projective(
&blinded_message_bytes,
@@ -53,8 +51,6 @@ impl TryFrom<&[u8]> for Theta {
),
)?;
// safety: we just checked for the length so the unwraps are fine
#[allow(clippy::unwrap_used)]
let blinded_serial_number_bytes = bytes[96..192].try_into().unwrap();
let blinded_serial_number = try_deserialize_g2_projective(
&blinded_serial_number_bytes,
@@ -134,7 +130,7 @@ impl Base58 for Theta {}
pub fn compute_kappa(
params: &Parameters,
verification_key: &VerificationKey,
private_attributes: &[&Attribute],
private_attributes: &[Attribute],
blinding_factor: Scalar,
) -> G2Projective {
params.gen2() * blinding_factor
@@ -142,11 +138,11 @@ pub fn compute_kappa(
+ private_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(&priv_attr, beta_i)| beta_i * priv_attr)
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
}
pub fn compute_zeta(params: &Parameters, serial_number: &Attribute) -> G2Projective {
pub fn compute_zeta(params: &Parameters, serial_number: Attribute) -> G2Projective {
params.gen2() * serial_number
}
@@ -154,8 +150,8 @@ pub fn prove_bandwidth_credential(
params: &Parameters,
verification_key: &VerificationKey,
signature: &Signature,
serial_number: &Attribute,
binding_number: &Attribute,
serial_number: Attribute,
binding_number: Attribute,
) -> Result<Theta> {
if verification_key.beta_g2.len() < 2 {
return Err(
@@ -175,7 +171,7 @@ pub fn prove_bandwidth_credential(
// Thus, we need kappa which allows us to verify sigma'. In particular,
// kappa is computed on m as input, but thanks to the use or random value r,
// it does not reveal any information about m.
let private_attributes = [serial_number, binding_number];
let private_attributes = vec![serial_number, binding_number];
let blinded_message = compute_kappa(
params,
verification_key,
@@ -189,8 +185,8 @@ pub fn prove_bandwidth_credential(
let pi_v = ProofKappaZeta::construct(
params,
verification_key,
serial_number,
binding_number,
&serial_number,
&binding_number,
&sign_blinding_factor,
&blinded_message,
&blinded_serial_number,
@@ -225,10 +221,7 @@ pub fn check_vk_pairing(
if values_len == 0 || values_len - 1 != vk.beta_g1.len() || values_len - 1 != vk.beta_g2.len() {
return false;
}
// safety: we made an explicit check for if the length of the slice is 0, thus unwrap here is fine
#[allow(clippy::unwrap_used)]
if &vk.alpha != *dkg_values.last().as_ref().unwrap() {
if vk.alpha != *dkg_values.last().unwrap() {
return false;
}
if dkg_values
@@ -256,7 +249,7 @@ pub fn verify_credential(
params: &Parameters,
verification_key: &VerificationKey,
theta: &Theta,
public_attributes: &[&Attribute],
public_attributes: &[Attribute],
) -> bool {
if public_attributes.len() + theta.pi_v.private_attributes_len()
> verification_key.beta_g2.len()
@@ -279,7 +272,7 @@ pub fn verify_credential(
.iter()
.skip(theta.pi_v.private_attributes_len()),
)
.map(|(&pub_attr, beta_i)| beta_i * pub_attr)
.map(|(pub_attr, beta_i)| beta_i * pub_attr)
.sum::<G2Projective>();
theta.blinded_message + signed_public_attributes
@@ -298,14 +291,14 @@ pub fn verify_credential(
pub fn verify(
params: &Parameters,
verification_key: &VerificationKey,
public_attributes: &[&Attribute],
public_attributes: &[Attribute],
sig: &Signature,
) -> bool {
let kappa = (verification_key.alpha
+ public_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(&m_i, b_i)| b_i * m_i)
.map(|(m_i, b_i)| b_i * m_i)
.sum::<G2Projective>())
.to_affine();
@@ -327,11 +320,10 @@ mod tests {
#[test]
fn vk_pairing() {
let params = setup(2).unwrap();
let keypair = keygen(&params);
let vk = keypair.verification_key();
let vk = keygen(&params).verification_key();
let mut dkg_values = vk.beta_g2.clone();
dkg_values.push(vk.alpha);
assert!(check_vk_pairing(&params, &dkg_values, vk));
assert!(check_vk_pairing(&params, &dkg_values, &vk));
}
#[test]
@@ -348,10 +340,10 @@ mod tests {
let theta = prove_bandwidth_credential(
&params,
keypair.verification_key(),
&keypair.verification_key(),
&signature,
&serial_number,
&binding_number,
serial_number,
binding_number,
)
.unwrap();
+4 -5
View File
@@ -1,7 +1,6 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::random_scalars_refs;
use crate::tests::helpers::tests::generate_dkg_keys;
use crate::{
aggregate_verification_keys, setup, tests::helpers::*, ttp_keygen, verify_credential,
@@ -13,14 +12,14 @@ fn keygen() -> Result<(), CoconutError> {
let params = setup(5)?;
let node_indices = vec![15u64, 248, 33521];
random_scalars_refs!(public_attributes, params, 2);
let public_attributes = params.n_random_scalars(2);
// generate_keys
let coconut_keypairs = ttp_keygen(&params, 2, 3)?;
let verification_keys: Vec<VerificationKey> = coconut_keypairs
.iter()
.map(|keypair| keypair.verification_key().clone())
.map(|keypair| keypair.verification_key())
.collect();
// aggregate verification keys
@@ -51,14 +50,14 @@ fn dkg() -> Result<(), CoconutError> {
let params = setup(5)?;
let node_indices = vec![15u64, 248, 33521];
random_scalars_refs!(public_attributes, params, 2);
let public_attributes = params.n_random_scalars(2);
// generate_keys
let coconut_keypairs = generate_dkg_keys(5, &node_indices);
let verification_keys: Vec<VerificationKey> = coconut_keypairs
.iter()
.map(|keypair| keypair.verification_key().clone())
.map(|keypair| keypair.verification_key())
.collect();
// aggregate verification keys
+7 -22
View File
@@ -5,17 +5,15 @@ use crate::*;
use itertools::izip;
use std::fmt::Debug;
// unwraps are fine in the test code
#[allow(clippy::unwrap_used)]
pub fn theta_from_keys_and_attributes(
params: &Parameters,
coconut_keypairs: &Vec<KeyPair>,
indices: &[scheme::SignerIndex],
public_attributes: &[&PublicAttribute],
public_attributes: &Vec<PublicAttribute>,
) -> Result<Theta, CoconutError> {
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];
// generate commitment
let (commitments_openings, blind_sign_request) =
@@ -23,7 +21,7 @@ pub fn theta_from_keys_and_attributes(
let verification_keys: Vec<VerificationKey> = coconut_keypairs
.iter()
.map(|keypair| keypair.verification_key().clone())
.map(|keypair| keypair.verification_key())
.collect();
// aggregate verification keys
@@ -35,7 +33,7 @@ pub fn theta_from_keys_and_attributes(
for keypair in coconut_keypairs {
let blinded_signature = blind_sign(
params,
keypair.secret_key(),
&keypair.secret_key(),
&blind_sign_request,
public_attributes,
)?;
@@ -51,7 +49,7 @@ pub fn theta_from_keys_and_attributes(
.map(|(idx, s, vk)| {
(
*idx,
s.unblind_and_verify(
s.unblind(
params,
vk,
&private_attributes,
@@ -83,15 +81,13 @@ pub fn theta_from_keys_and_attributes(
params,
&verification_key,
&signature,
&serial_number,
&binding_number,
serial_number,
binding_number,
)?;
Ok(theta)
}
// unwraps are fine in the test code
#[allow(clippy::unwrap_used)]
pub fn transpose_matrix<T: Debug>(matrix: Vec<Vec<T>>) -> Vec<Vec<T>> {
if matrix.is_empty() {
return vec![];
@@ -170,14 +166,3 @@ pub mod tests {
.collect()
}
}
#[macro_export]
macro_rules! random_scalars_refs {
( $x: ident, $params: expr, $n: expr ) => {
let _vec = $params.n_random_scalars($n);
#[allow(clippy::map_identity)]
let $x = _vec.iter().collect::<Vec<_>>();
};
}
pub use random_scalars_refs;
+1 -68
View File
@@ -1,13 +1,4 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
use crate::CoconutError;
use bls12_381::{G1Affine, G1Projective, Scalar};
use group::GroupEncoding;
use std::convert::TryInto;
pub trait Bytable
where
@@ -23,67 +14,9 @@ where
Self: Bytable,
{
fn try_from_bs58<S: AsRef<str>>(x: S) -> Result<Self, CoconutError> {
let bs58_decoded = &bs58::decode(x.as_ref()).into_vec()?;
Self::try_from_byte_slice(bs58_decoded)
Self::try_from_byte_slice(&bs58::decode(x.as_ref()).into_vec().unwrap())
}
fn to_bs58(&self) -> String {
bs58::encode(self.to_byte_vec()).into_string()
}
}
impl Bytable for Scalar {
fn to_byte_vec(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
fn try_from_byte_slice(slice: &[u8]) -> Result<Self, CoconutError> {
let received = slice.len();
let Ok(arr) = slice.try_into() else {
return Err(CoconutError::UnexpectedArrayLength {
typ: "Scalar".to_string(),
received,
expected: 32,
});
};
let maybe_scalar = Scalar::from_bytes(arr);
if maybe_scalar.is_none().into() {
Err(CoconutError::ScalarDeserializationFailure)
} else {
// safety: this unwrap is fine as we've just checked the element is not none
#[allow(clippy::unwrap_used)]
Ok(maybe_scalar.unwrap())
}
}
}
impl Base58 for Scalar {}
impl Bytable for G1Projective {
fn to_byte_vec(&self) -> Vec<u8> {
self.to_bytes().as_ref().to_vec()
}
fn try_from_byte_slice(slice: &[u8]) -> Result<Self, CoconutError> {
let received = slice.len();
let arr: Result<[u8; 48], _> = slice.try_into();
let Ok(bytes) = arr else {
return Err(CoconutError::UnexpectedArrayLength {
typ: "G1Projective".to_string(),
received,
expected: 48,
});
};
let maybe_g1 = G1Affine::from_compressed(&bytes);
if maybe_g1.is_none().into() {
Err(CoconutError::G1ProjectiveDeserializationFailure)
} else {
// safety: this unwrap is fine as we've just checked the element is not none
#[allow(clippy::unwrap_used)]
Ok(maybe_g1.unwrap().into())
}
}
}
impl Base58 for G1Projective {}
-3
View File
@@ -34,7 +34,6 @@ impl Polynomial {
// just return the last term of the polynomial
} else if x.is_zero().into() {
// we checked that coefficients are not empty so unwrap here is fine
#[allow(clippy::unwrap_used)]
*self.coefficients.first().unwrap()
} else {
self.coefficients
@@ -149,8 +148,6 @@ pub(crate) fn try_deserialize_scalar_vec(
let mut out = Vec::with_capacity(expected_len as usize);
for i in 0..expected_len as usize {
// we just checked we have exactly the amount of bytes we need and thus the unwrap is fine
#[allow(clippy::unwrap_used)]
let s_bytes = bytes[i * 32..(i + 1) * 32].try_into().unwrap();
let s = match Into::<Option<Scalar>>::into(Scalar::from_bytes(&s_bytes)) {
None => return Err(err),
+1 -1
View File
@@ -9,7 +9,7 @@ repository = { workspace = true }
[dependencies]
bytes = "1.0"
tokio-util = { workspace = true, features = ["codec"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
thiserror = { workspace = true }
nym-sphinx-types = { path = "../types", features = ["sphinx", "outfox"] }
-1
View File
@@ -2,7 +2,6 @@
name = "nym-socks5-client-core"
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
-1
View File
@@ -3,7 +3,6 @@ name = "nym-ordered-buffer"
version = "0.1.0"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
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,14 +3,13 @@ name = "nym-socks5-proxy-helpers"
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]
bytes = "1.0"
tokio = { workspace = true, features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] }
tokio-util = { workspace = true, features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use
tokio = { version = "1.24.1", features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] }
tokio-util = { version = "0.7.4", features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use
# their `read_buf` [from the util crate] replacement rather than having to rethink/reimplement `AvailableReader` with the new AsyncRead trait definition.
# In the long run, the dependency should probably get removed in favour of pure-tokio implementation, but for time being it's fine.
futures = { workspace = true }
-1
View File
@@ -3,7 +3,6 @@ name = "nym-socks5-requests"
version = "0.1.0"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
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 @@
name = "nym-statistics-common"
version = "1.0.1"
edition = "2021"
license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+1 -2
View File
@@ -2,7 +2,6 @@
name = "nym-store-cipher"
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
@@ -21,4 +20,4 @@ getrandom = { version = "0.2", features = ["js"] }
[features]
default = []
json = ["serde_json"]
json = ["serde_json"]
+3 -3
View File
@@ -494,13 +494,13 @@ impl Drop for TaskClient {
fn drop(&mut self) {
if !self.mode.should_signal_on_drop() {
self.log(
Level::Trace,
"the task client is getting dropped but inststructed to not signal: this is expected during client shutdown",
Level::Debug,
"the task client is getting dropped: this is expected during client shutdown",
);
return;
} else {
self.log(
Level::Debug,
Level::Info,
"the task client is getting dropped: this is expected during client shutdown",
);
}
-1
View File
@@ -5,7 +5,6 @@ description = "Nym common types"
authors.workspace = true
edition = "2021"
rust-version = "1.58"
license.workspace = true
[dependencies]
base64 = "0.21.4"
+1 -2
View File
@@ -3,7 +3,6 @@ name = "wasm-storage"
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 @@ indexed_db_futures = { version = " 0.3.0"}
thiserror = { workspace = true }
nym-store-cipher = { path = "../../store-cipher", features = ["json"] }
wasm-utils = { path = "../utils", default-features = false }
wasm-utils = { path = "../utils", default-features = false }
-1
View File
@@ -3,7 +3,6 @@ name = "wasm-utils"
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
+85 -4
View File
@@ -10,19 +10,22 @@ use crate::dealings::transactions::try_commit_dealings;
use crate::epoch_state::queries::{
query_current_epoch, query_current_epoch_threshold, query_initial_dealers,
};
use crate::epoch_state::storage::CURRENT_EPOCH;
use crate::epoch_state::storage::{CURRENT_EPOCH, THRESHOLD};
use crate::epoch_state::transactions::{advance_epoch_state, try_surpassed_threshold};
use crate::error::ContractError;
use crate::state::{State, MULTISIG, STATE};
use crate::verification_key_shares::queries::query_vk_shares_paged;
use crate::verification_key_shares::storage::vk_shares;
use crate::verification_key_shares::transactions::try_commit_verification_key_share;
use crate::verification_key_shares::transactions::try_verify_verification_key_share;
use cosmwasm_std::{
entry_point, to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
entry_point, to_binary, Addr, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response,
Timestamp,
};
use cw4::Cw4Contract;
use nym_coconut_dkg_common::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use nym_coconut_dkg_common::types::{Epoch, EpochState};
use nym_coconut_dkg_common::types::{Epoch, EpochId, EpochState, TimeConfiguration};
use nym_coconut_dkg_common::verification_key::ContractVKShare;
/// Instantiate the contract.
///
@@ -127,7 +130,85 @@ pub fn query(deps: Deps<'_>, _env: Env, msg: QueryMsg) -> Result<QueryResponse,
}
#[entry_point]
pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
pub fn migrate(deps: DepsMut<'_>, env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
CURRENT_EPOCH.save(
deps.storage,
&Epoch {
state: EpochState::InProgress,
epoch_id: 0,
time_configuration: TimeConfiguration {
public_key_submission_time_secs: 999999,
dealing_exchange_time_secs: 999999,
verification_key_submission_time_secs: 999999,
verification_key_validation_time_secs: 999999,
verification_key_finalization_time_secs: 999999,
in_progress_time_secs: 999999,
},
finish_timestamp: env.block.time.plus_days(10000),
},
)?;
let apis = [
"https://qa-nym-api-coconut1.qa.nymte.ch/api",
"https://qa-nym-api-coconut2.qa.nymte.ch/api",
"https://qa-nym-api-coconut3.qa.nymte.ch/api",
"https://qa-nym-api-coconut-6.qa.nymte.ch/api",
"https://qa-nym-api-coconut-7.qa.nymte.ch/api",
"https://qa-nym-api-coconut-8.qa.nymte.ch/api",
"https://qa-nym-api-coconut-9.qa.nymte.ch/api",
"https://qa-nym-api-coconut-10.qa.nymte.ch/api",
"https://qa-nym-api-coconut-11.qa.nymte.ch/api",
"https://qa-nym-api-coconut-12.qa.nymte.ch/api",
];
let addresses = [
Addr::unchecked("n1e6wkf0x2l4qt45uwkft9t7fs3ka02rsmft5jjn"),
Addr::unchecked("n190f6rwtcpfgx3y84af6eapg54suehd4nzq4sh3"),
Addr::unchecked("n1c7nu7wncuru09eg2m8429d5ff6umytet993xmf"),
Addr::unchecked("n144fypmxc9jrdk28qrjlptpqn7h077f30vvvdjf"),
Addr::unchecked("n15rmhp3psrnlcgp8tsa9y528ppwt0vvwuazfa4a"),
Addr::unchecked("n18dy35dtsg7ycyp7g9pvlj29ksmjpu9h6tznxdl"),
Addr::unchecked("n17usrtqe6ypvn3r4v05sspu3ufs30uykc7euwne"),
Addr::unchecked("n1efpvtu5x7x4v293pc42a2fwkf265lnh05r023z"),
Addr::unchecked("n15k2zadxm7m3wyfyx7g2uk2tctmmp43syxuqmdf"),
Addr::unchecked("n1k4w8pp62htn0tdmrsv3gh9kzrap4tpalw8eqd7"),
];
let keys = [
"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",
];
for (i, ((address, api), key)) in addresses
.iter()
.zip(apis.iter())
.zip(keys.iter())
.enumerate()
{
let share = ContractVKShare {
share: key.to_string(),
announce_address: api.to_string(),
node_index: (i + 1) as u64,
owner: address.clone(),
epoch_id: 0,
verified: true,
};
vk_shares().save(deps.storage, (address, 0), &share)?;
}
THRESHOLD.save(deps.storage, &7)?;
Ok(Default::default())
}
+9 -17
View File
@@ -104,16 +104,8 @@ unlicensed = "deny"
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
allow = [
"MIT",
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"0BSD",
"MPL-2.0",
"CC0-1.0",
"Unicode-DFS-2016",
"OpenSSL",
#"MIT",
#"Apache-2.0",
]
# List of explicitly disallowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
@@ -151,22 +143,22 @@ exceptions = [
# Some crates don't have (easily) machine readable licensing information,
# adding a clarification entry for it allows you to manually specify the
# licensing information
[[licenses.clarify]]
#[[licenses.clarify]]
# The name of the crate the clarification applies to
name = "ring"
#name = "ring"
# The optional version constraint for the crate
version = "*"
#version = "*"
# The SPDX expression for the license requirements of the crate
expression = "MIT AND ISC AND OpenSSL"
#expression = "MIT AND ISC AND OpenSSL"
# One or more files in the crate's source used as the "source of truth" for
# the license expression. If the contents match, the clarification will be used
# when running the license check, otherwise the clarification will be ignored
# and the crate will be checked normally, which may produce warnings or errors
# depending on the rest of your configuration
license-files = [
#license-files = [
# Each entry is a crate relative path, and the (opaque) hash of its contents
{ path = "LICENSE", hash = 0xbd0eed23 }
]
#{ path = "LICENSE", hash = 0xbd0eed23 }
#]
[licenses.private]
# If true, ignores workspace crates that aren't published, or are only
+6 -7
View File
@@ -51,7 +51,7 @@
- [Querying the Chain](tutorials/cosmos-service/querying.md)
- [Typescript](tutorials/typescript.md)
- [Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md)
- [[DEPRECATED] Simple Service Provider](tutorials/simple-service-provider/simple-service-provider.md)
- [Tutorial Overview](tutorials/simple-service-provider/overview.md)
- [Preparing Your User Client Environment](tutorials/simple-service-provider/preparating-env.md)
- [Building Your User Client](tutorials/simple-service-provider/user-client.md)
@@ -59,12 +59,11 @@
- [Building Your Service Provider](tutorials/simple-service-provider/service-provider.md)
- [Sending a Message Through the Mixnet](tutorials/simple-service-provider/sending-message.md)
[//]: # (TODO make generic )
[//]: # (# Shipyard Builders Hackathon 2023 )
[//]: # (- [General Info & Resources]&#40;shipyard/general.md&#41;)
[//]: # (- [Hackathon Challenges]&#40;shipyard/challenges-overview.md&#41;)
[//]: # (- [A Note on Infrastructure]&#40;shipyard/infra.md&#41;)
[//]: # (- [Submission Guidelines]&#40;shipyard/guidelines.md&#41;)
# Shipyard Builders Hackathon 2023
- [General Info & Resources](shipyard/general.md)
- [Hackathon Challenges](shipyard/challenges-overview.md)
- [A Note on Infrastructure](shipyard/infra.md)
- [Submission Guidelines](shipyard/guidelines.md)
# Events
@@ -26,7 +26,7 @@ Since this is the file where client creation and message parsing are handled, th
Below this are the chain-related `const` variables. These have been hardcoded for this demo.
```rust
pub const DEFAULT_VALIDATOR_RPC: &str = "https://rpc.sandbox.nymtech.net";
pub const DEFAULT_VALIDATOR_RPC: &str = "https://sandbox-validator1.nymtech.net";
pub const DEFAULT_DENOM: &str = "unym";
pub const DEFAULT_PREFIX: &str = "n";
```
@@ -28,7 +28,7 @@ COCONUT_DKG_CONTRACT_ADDRESS="nymt1gwk6muhmzeuxje7df7rjvqwl2vex0kj4t2hwuzmyx5k62
GROUP_CONTRACT_ADDRESS="nymt14ry36mwauycz08v8ndcujghxz4hmua5epxcn0mamlr3suqe0l2qsqx5ya2"
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYXD="https://rpc.sandbox.nymtech.net"
NYXD="https://sandbox-validator1.nymtech.net"
NYM_API="https://sandbox-validator1-api.nymtech.net/api"
```
@@ -44,7 +44,7 @@ Next, you init the nym-client with the enabled credentials mode set to true:
Using the new credentials binary, purchase some credentials for the client. The recovery directory is a directory where the credentials will be temporarily stored in case the request fails.
```./credential --config-env-file <path-to>sandbox.env run --client-home-directory <path-to-the-client-config> --nyxd-url https://rpc.sandbox.nymtech.net --mnemonic "<mnemonic of the account created above>" --amount 50 --recovery-dir <a-path> ```
```./credential --config-env-file <path-to>sandbox.env run --client-home-directory <path-to-the-client-config> --nyxd-url https://sandbox-validator1.nymtech.net --mnemonic "<mnemonic of the account created above>" --amount 50 --recovery-dir <a-path> ```
You can redeem this now by running the nym-client, in enabled credentials mode:
@@ -62,7 +62,7 @@ Now time to init the socks5 client:
Purchase credentials for this now too:
`./credential --config-env-file <path-to>sandbox.env run --client-home-directory <path-to-socks5-config> --nyxd-url https://rpc.sandbox.nymtech.net --mnemonic "<any valid sandbox mnemonic>" --amount 100 --recovery-dir <a-path>`
`./credential --config-env-file <path-to>sandbox.env run --client-home-directory <path-to-socks5-config> --nyxd-url https://sandbox-validator1.nymtech.net --mnemonic "<any valid sandbox mnemonic>" --amount 100 --recovery-dir <a-path>`
Run the socks5 client:
@@ -61,8 +61,7 @@ Quite a bit of stuff gets built. The key working parts are:
* [network requester](../nodes/network-requester.md): `nym-network-requester`
* [nym-cli tool](../tools/nym-cli.md): `nym-cli`
* [nym-api](https://nymtech.net/operators/nodes/nym-api.html): `nym-api`
[//]: # (* [nymvisor]&#40;https://nymtech.net/operators/nodes/nymvisor-upgrade.html&#41;: `nymvisor`)
* [nymvisor](https://nymtech.net/operators/nodes/nymvisor-upgrade.html): `nymvisor`
The repository also contains Typescript applications which aren't built in this process. These can be built by following the instructions on their respective docs pages.
* [Nym Wallet](../wallet/desktop-wallet.md)
+2 -2
View File
@@ -4,9 +4,9 @@ This is Nym's technical documentation, containing information and setup guides a
If you are new to Nym and want to learn about the Mixnet, explore kickstart options and demos, learn how to integrate with the network, and follow developer tutorials check out the [Developer Portal](https://nymtech.net/developers/) where you can find also our [FAQ section](https://nymtech.net/developers/faq/general-faq.html).
If you are looking for information and setup guides for the various pieces of Nym Mixnet infrastructure (Mix Nodes, Gateways and Network Requesters) and Nyx blockchain validators see the [Operators Guides](https://nymtech.net/operators) book.
If you are looking for information and setup guides for the various pieces of Nym Mixnet infrastructure (Mix Nodes, Gateways and Network Requesters) and Nyx blockchain validators see the **new [Operators Guides](https://nymtech.net/operators)** book.
If you're specifically looking for TypeScript/JavaScript related information such as SDKs to build your own tools, step-by-step tutorials, live playgrounds and more - check out the [TS SDK Handbook](https://sdk.nymtech.net/).
If you're specifically looking for TypeScript/JavaScript related information such as SDKs to build your own tools, step-by-step tutorials, live playgrounds and more - make sure to check out the **new [TS SDK Handbook](https://sdk.nymtech.net/)** !
## Popular pages
**Network Architecture:**
+1 -2
View File
@@ -20,8 +20,7 @@
- [Nym API Setup](nodes/nym-api.md)
- [Maintenance](nodes/maintenance.md)
- [Manual Node Upgrade](nodes/manual-upgrade.md)
[//]: # ( - [Automatic Node Upgrade: Nymvisor Setup and Usage]&#40;nodes/nymvisor-upgrade.md&#41;)
- [Automatic Node Upgrade: Nymvisor Setup and Usage](nodes/nymvisor-upgrade.md)
- [Troubleshooting](nodes/troubleshooting.md)
# FAQ
@@ -62,8 +62,7 @@ Quite a bit of stuff gets built. The key working parts are:
* [network requester](../nodes/network-requester-setup.md): `nym-network-requester`
* [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.html): `nym-cli`
* [nym-api](../nodes/nym-api.md): `nym-api`
[//]: # (* [nymvisor]&#40;../nodes/nymvisor-upgrade.md&#41;: `nymvisor`)
* [nymvisor](../nodes/nymvisor-upgrade.md): `nymvisor`
The repository also contains Typescript applications which aren't built in this process. These can be built by following the instructions on their respective docs pages.
* [Nym Wallet](https://nymtech.net/docs/wallet/desktop-wallet.html)
@@ -25,14 +25,14 @@ These steps are for an operator who is setting up a [Gateway](gateway-setup.md)
1. New flags will need to be added to the `init` and `run` command. The `--host` option should be replaced with these flags:
- `--listening-address`: The IP address which is used for receiving sphinx packets and listening to client data.
- `--public-ips`: A comma separated list of IPs that are announced to the `nym-api`. In the most cases `--public-ips` **is the address used for bonding.**
- `--listening-address`: The IP address which is used for receiving sphinx packets and listening to client data.
- `--public-ips`: A comma separated list of IPs that are announced to the `nym-api`. In the most cases `--public-ips` **is the address used for bonding.**
```sh
--listening-address 0.0.0.0 --public-ips "$(curl -4 https://ifconfig.me)"
```
- `--hostname` (optional): This flag is required if the operator wishes to run WSS. It can be something like `mainnet-gateway2.nymtech.net`.
- `--hostname` (optional): This flag is required if the operator wishes to run WSS. It can be something like `mainnet-gateway2.nymtech.net`.
2. Make sure to enable all necessary [ports](maintenance.md#configure-your-firewall) on the Gateway:
@@ -42,7 +42,7 @@ sudo ufw allow 1789,1790,8000,9000,9001,22/tcp, 9001/tcp
The Gateway will then be accessible on something like: *http://85.159.211.99:8080/api/v1/swagger/index.html*
Are you seeing something like: *this node attempted to announce an invalid public address: 0.0.0.0.*?
Are you seeing something like: *this node attempted to announce an invalid public address: 0.0.0.0.*?
Please modify `[host.public_ips]` section of your config file stored as `~/.nym/gateways/<ID>/config/config.toml`.
@@ -92,7 +92,7 @@ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo
apt update
apt install caddy
systemctl enable caddy.service
systemctl enable caddy.service
cd /etc/caddy
@@ -102,7 +102,7 @@ if [ -f Caddyfile ]; then
rm -f Caddyfile
fi
cat <<EOF >> Caddyfile
cat <<EOF >> Caddyfile
${host}:${port_value} {
@websockets {
header Connection *Upgrade*
@@ -191,9 +191,9 @@ nohup ./<NODE> run --id <YOUR_ID> # where `<YOUR_ID>` is the id you set during t
#### tmux
One way is to use `tmux` shell on top of your current VPS terminal. Tmux is a terminal multiplexer, it allows you to create several terminal windows and panes from a single terminal. Processes started in `tmux` keep running after closing the terminal as long as the given `tmux` window was not terminated.
One way is to use `tmux` shell on top of your current VPS terminal. Tmux is a terminal multiplexer, it allows you to create several terminal windows and panes from a single terminal. Processes started in `tmux` keep running after closing the terminal as long as the given `tmux` window was not terminated.
Use the following command to get `tmux`.
Use the following command to get `tmux`.
Platform|Install Command
---|---
@@ -204,15 +204,15 @@ RHEL or CentOS|`yum install tmux`
macOS (using Homebrew|`brew install tmux`
macOS (using MacPorts)|`port install tmux`
openSUSE|`zypper install tmux`
In case it didn't work for your distribution, see how to build `tmux` from [version control](https://github.com/tmux/tmux#from-version-control).
In case it didn't work for your distribution, see how to build `tmux` from [version control](https://github.com/tmux/tmux#from-version-control).
**Running tmux**
Now you have installed tmux on your VPS, let's run a Mix Node on tmux, which allows you to detach your terminal and let your `<NODE>` run on its own on the VPS.
* Pause your `<NODE>`
* Start tmux with the command
* Start tmux with the command
```sh
tmux
```
@@ -230,7 +230,7 @@ tmux attach-session
#### systemd
To automate with `systemd` use this init service file and follow the steps below.
To automate with `systemd` use this init service file and follow the steps below.
##### For Mix Node
@@ -327,18 +327,18 @@ Change the `<PATH>` in `ExecStart` to point at your `<NODE>` binary (`nym-mixnod
Example: If you have built nym in the `$HOME` directory on your server, your username is `jetpanther`, and node `<ID>` is `puma`, then the `ExecStart` line (command) in the script located in `/etc/systemd/system/nym-mixnode.service` for Nym Mixnode might look like this:
`ExecStart=/home/jetpanther/nym/target/release/nym-mixnode run --id puma`.
`ExecStart=/home/jetpanther/nym/target/release/nym-mixnode run --id puma`.
Basically, you want the full `/<PATH>/<TO>/nym-mixnode run --id <WHATEVER-YOUR-NODE-ID-IS>`. If you are unsure about your `/<PATH>/<TO>/<NODE>`, then `cd` to your directory where you run your `<NODE>` from and run `pwd` command which returns the full path for you.
Once done, save the script and follow these steps:
```sh
systemctl daemon-reload
systemctl daemon-reload
# to pickup the new unit file
```
Enable the newly created service:
Enable the newly created service:
```sh
# for Mix Node
@@ -350,7 +350,7 @@ systemctl enable nym-gateway.service
# for Network Requester
systemctl enable nym-network-requester.service
# for Nymvisor
# for Nymvisor
systemctl enable nymvisor.service
```
@@ -367,7 +367,7 @@ service nym-gateway start
service nym-network-requester.service
# for Nymvisor
service nymvisor.service start
service nymvisor.service start
```
This will cause your `<NODE>` to start at system boot time. If you restart your machine, your `<NODE>` will come back up automatically.
@@ -427,7 +427,7 @@ systemctl start nymd # to actually start the service
journalctl -f -u nymd # to monitor system logs showing the service start
```
##### For Nym API
##### For Nym API
Below is a `systemd` unit file to place at `/etc/systemd/system/nym-api.service` to automate your API instance:
@@ -535,7 +535,7 @@ In case you chose tmux option for Mix Node automation, see your `ulimit` list by
ulimit -a
# watch for the output line -n
-n: file descriptors 1024
-n: file descriptors 1024
```
You can change it either by running a command:
@@ -582,14 +582,14 @@ scp -r -3 <SOURCE_USER_NAME>@<SOURCE_HOST_ADDRESS>:~/.nym/mixnodes/<YOUR_ID> <TA
```
* Re-run init (remember that init doesn't overwrite existing keys) to generate a config with the new listening address etc.
* Change the node smart contract info via the wallet interface. Otherwise the keys will point to the old IP address in the smart contract, and the node will not be able to be connected, and it will fail up-time checks.
* Re-run the node from the new location.
* Re-run the node from the new location.
## Virtual IPs and hosting via Google & AWS
For true internet decentralization we encourage operators to use diverse VPS providers instead of the largest companies offering such services. If for some reasons you have already running AWS or Google and want to setup a `<NODE>` there, please read the following.
On some services (AWS, Google, etc) the machine's available bind address is not the same as the public IP address. In this case, bind `--host` to the local machine address returned by `$(curl -4 https://ifconfig.me)`, but that may not the public IP address to bond your `<NODE>` in the wallet.
On some services (AWS, Google, etc) the machine's available bind address is not the same as the public IP address. In this case, bind `--host` to the local machine address returned by `$(curl -4 https://ifconfig.me)`, but that may not the public IP address to bond your `<NODE>` in the wallet.
You can run `ifconfig` command. For example, on a Google machine, you may see the following output:
@@ -601,7 +601,7 @@ ens4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1460
The `ens4` interface has the IP `10.126.5.7`. But this isn't the public IP of the machine, it's the IP of the machine on Google's internal network. Google uses virtual routing, so the public IP of this machine is something else, maybe `36.68.243.18`.
To find the right IP configuration, contact your VPS provider for support to find the right public IP and use it to bond your `<NODE>` with the `nym-api` via Nym wallet.
To find the right IP configuration, contact your VPS provider for support to find the right public IP and use it to bond your `<NODE>` with the `nym-api` via Nym wallet.
On self-hosted machine it's a bit more tricky. In that case as an operator you must be sure that your ISP allows for public IPv4 and IPv6 and then it may be a bit of playing around to find the right configuration. One way may be to bind your binary with the `--host` flag to local address `127.0.0.1` and run `echo "$(curl -4 https://ifconfig.me)"` to get a public address which you use to bond your Mix Node to `nym-api` via Nym wallet.
@@ -650,7 +650,7 @@ Query Response:
### Validator: Installing and configuring nginx for HTTPS
#### Setup
[Nginx](https://www.nginx.com/resources/glossary/nginx) is an open source software used for operating high-performance web servers. It allows us to set up reverse proxying on our validator server to improve performance and security.
[Nginx](https://www.nginx.com/resources/glossary/nginx/#:~:text=NGINX%20is%20open%20source%20software,%2C%20media%20streaming%2C%20and%20more.&text=In%20addition%20to%20its%20HTTP,%2C%20TCP%2C%20and%20UDP%20servers.) is an open source software used for operating high-performance web servers. It allows us to set up reverse proxying on our validator server to improve performance and security.
Install `nginx` and allow the 'Nginx Full' rule in your firewall:
@@ -678,16 +678,15 @@ Which should return:
└─2380 nginx: worker process
```
#### Full Node Configuration
#### Configuration
Proxying various full node services through port 80 can then be done by creating a file with the following at `/etc/nginx/sites-enabled/nyxd-webrequests.conf`:
Proxying your validator's port `26657` to nginx port `80` can then be done by creating a file with the following at `/etc/nginx/conf.d/validator.conf`:
```sh
### To expose RPC server
server {
listen 80;
listen [::]:80;
server_name "<rpc.nyx.yourdomain.tld>";
server_name "domain_name";
location / {
proxy_pass http://127.0.0.1:26657;
@@ -696,58 +695,20 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
### To expose Cosmos API server
server {
server_name "<api.nyx.yourdomain.tld>";
location / {
proxy_pass http://127.0.0.1:1317;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
}
}
### To expose GRPC endpoint
server {
server_name "<grpc.nyx.yourdomain.tld>";
location / {
grpc_pass 127.0.0.1:9090;
}
}
```
#### nym-api Configuration
```sh
### To expose nym-api webserver
server {
listen 80;
listen [::]:80;
server_name "<nym-api.nyx.yourdomain.tld>";
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
Followed by:
```sh
sudo apt install certbot nginx python3
certbot --nginx -m <you@yourdomain.com> --agree-tos
certbot --nginx -d nym-validator.yourdomain.com -m you@yourdomain.com --agree-tos --noninteractive --redirect
```
```admonish caution title=""
If using a VPS running Ubuntu 20: replace `certbot nginx python3` with `python3-certbot-nginx`
```
These commands will get you an https encrypted nginx proxy in front of the various endpoints.
These commands will get you an https encrypted nginx proxy in front of the API.
### Configuring Prometheus metrics (optional)
@@ -834,3 +795,6 @@ All validator-specific port configuration can be found in `$HOME/.nymd/config/co
| 1317 | REST API server endpoint |
| 26656 | Listen for incoming peer connections |
| 26660 | Listen for Prometheus connections |
+23 -41
View File
@@ -1,48 +1,33 @@
# Nym API Setup
[//]: # (> The nym-api binary was built in the [building nym]&#40;../binaries/building-nym.md&#41; section. If you haven't yet built Nym and want to run the code, go there first. You can build just the API with `cargo build --release --bin nym-api`.)
[//]: # (> The Nym API binary was built in the [building nym]&#40;../binaries/building-nym.md&#41; section. If you haven't yet built Nym and want to run the code, go there first. You can build just the API with `cargo build --release --bin nym-api`.)
[//]: # ()
> The `nym-api` binary will be released in the immediate future - we're releasing this document beforehand so that Validators have information as soon as possible and get an idea of what to expect. This doc will be expanded over time as we release the API binary itself as well as start enabling functionality.
>
> You can build the API with `cargo build --release --bin nym-api`.
> The `nym-api` binary should be coming out in the next release - we're releasing this document beforehand so that Validators have information as soon as possible and get an idea of what to expect. This doc will be expanded over time as we release the API binary itself as well as start enabling functionality.
> Any syntax in `<>` brackets is a user's unique variable. Exchange with a corresponding name without the `<>` brackets.
## What is the Nym API?
The Nym API is a binary that will be operated by the Nyx validator set. This binary can be run in several different modes, and has two main bits of functionality:
* network monitoring (calculating the routing score of Mixnet nodes)
The Nym API is a binary that will be operated by some or all of the Nyx Blockchain Validator set. This binary can be run in several different modes, and has two main bits of functionality:
* network monitoring (calculating the routing score of Mixnet nodes)
* generation and validation of [zk-Nyms](https://blog.nymtech.net/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a), our implementation of the Coconut Selective Disclosure Credential Scheme.
This is important for both the proper decentralisation of the network uptime calculation and, more pressingly, enabling the NymVPN to utilise privacy preserving payments.
This is important for both the proper decentralisation of the network uptime calculation and, more pressingly, enabling the NymVPN to utilise privacy preserving payments.
The process of enabling these different aspects of the system will take time. At the moment, Nym API operators will only have to run the binary in a minimal 'caching' mode in order to get used to maintaining an additional process running alongside a full node.
The process of enabling these different aspects of the system will take time. Operators of the Nym API binary for the moment will only have to run the binary in a minimal 'caching' mode in order to get used to maintaining an additional process running alongside their Validator.
```admonish warning
It is highly recommended to run `nym-api` alongside a full node since you will be exposing HTTP port(s) to the Internet. We also observed degradation in p2p and block signing operations when `nym-api` was run alongside a signing validator.
```
### Rewards
Operators of Nym API instances will be rewarded for performing the extra work of taking part in credential generation. These rewards will be calculated **separately** from rewards for block production.
### Rewards
Operators of Nym API will be rewarded for performing the extra work of taking part in credential generation. These rewards will be calculated **separately** from rewards for block production.
Rewards for credential signing will be calculated hourly, with API operators receiving a proportional amount of the reward pool (333NYM per hour / 237600NYM per month) according to the % of credentials they have signed.
Rewards for credential signing will be calculated hourly, with API operators receiving a proportional amount of the reward pool (333NYM per hour / 237,600 NYM per month), proportional to the percentage of credentials they have signed.
### (Coming Soon) Machine Specs
We are working on load testing currently in order to get good specs for a full node + Nym API setup. Bear in mind that credential signing is primarily CPU-bound.
### (Coming Soon) Machine Specs
We are working on load testing currently in order to get good specs for a Validator + Nym API setup. Bear in mind that credential signing is primarily CPU-bound.
### (Coming Soon) Credential Generation
Validators that take part in the DKG ceremony will become part of the 'quorum' generating and verifying zk-Nym credentials. These will initially be used for private proof of payment for NymVPN (see our blogposts [here](https://blog.nymtech.net/nymvpn-an-invitation-for-privacy-experts-and-enthusiasts-63644139d09d) and [here](https://blog.nymtech.net/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a) for more on this), and in the future will be expanded into more general usecases such as [offline ecash](https://arxiv.org/abs/2303.08221).
Validators that take part in the DKG ceremony (more details on this soon) will become part of the quorum generating and verifying zk-Nym credentials. These will initially be used for private proof of payment for NymVPN (see our blogposts [here](https://blog.nymtech.net/nymvpn-an-invitation-for-privacy-experts-and-enthusiasts-63644139d09d) and [here](https://blog.nymtech.net/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a) for more on this), and in the future will be expanded into more general usecases such as [offline ecash](https://arxiv.org/abs/2303.08221).
The DKG ceremony will be used to create a subset of existing validators - referred to as the quorum. As outlined above, they will be the ones taking part in the generation and verification of zk-Nym credentials. The size of the 'minimum viable quorum' is 10 - we are aiming for a larger number than this for the initial quorum in order to have some redundancy in the case of a Validator dropping or going offline.
We will be releasing more detailed step-by-step documentation for involved validators nearer to the ceremony itself, but at a high level it will involve:
* the deployment and initialisation of [`group`](https://github.com/nymtech/nym/tree/develop/contracts/multisig/cw4-group) and [`multisig`](https://github.com/nymtech/nym/tree/develop/contracts/multisig) contracts by Nym. Validators that are members of the `group` contract are the only ones that will be able to take part in the ceremony.
* the deployment and initialisation of an instance of the [DKG contract](https://github.com/nymtech/nym/tree/develop/contracts/coconut-dkg) by Nym.
* Validators will update their `nym-api` configs with the address of the deployed contracts. They will also stop running their API instance in caching only mode, instead switching over run with the `--enabled-credentials-mode`.
* From the perspective of operators, this is all they have to do. Under the hood, each `nym-api` instance will then take part in several rounds of key submission, verification, and derivation. This will continue until quorum is acheived. More information on this will be released closer to the time of the ceremony.
**We will be communicating individually with members of the existing Validator set who have expressed interest in joining the quorum concerning the timing and specifics of the ceremony**.
## Current version
## Current version
```
<!-- cmdrun ../../../../target/release/nym-api --version | grep "Build Version" | cut -b 21-26 -->
```
@@ -69,31 +54,31 @@ You can also check the various arguments required for individual commands with:
./nym-api <COMMAND> --help
```
### Initialising your Nym API Instance
Initialise your API instance with:
### Initialising your Nym API Instance
Initialise your API instance with:
```
./nym-api init
```
You can optionally pass a local identifier for this instance with the `--id` flag. Otherwise the ID of your instance defaults to `default`.
You can optionally pass a local identifier for this instance with the `--instance` flag. Otherwise the ID of your instance defaults to `default`.
### Running your Nym API Instance
The API binary currently defaults to running in caching mode. You can run your API with:
### Running your Nym API Instance
The API binary currently defaults to running in caching mode. You can run your API with:
```
./nym-api run
```
By default the API will be trying to query a running `nyxd` process (either a validator or RPC node) on `localhost:26657`. This value can be modified either via the `--nyxd-validator ` flag on `run`:
By default the API will be trying to query a running `nyxd` process (either a validator or RPC node) on `localhost:26657`. This value can be modified either via the `--nyxd-validator ` flag on `run`:
```
./nym-api run --nyxd-validator https://rpc.nymtech.net:443
./nym-api run --nyxd-validator https://rpc.nymtech.net:443
```
> You can also change the value of `local_validator` in the config file found by default in `$HOME/.nym/nym-api/<ID>/config/config.toml`.
This process is quite noisy, but informative:
This process is quite noisy, but informative:
~~~admonish example collapsible=true title="Console output"
```
@@ -175,8 +160,5 @@ Starting nym api...
```
~~~
## Automation
## Automation
You will most likely want to automate your validator restarting if your server reboots. Checkout the [maintenance page](./maintenance.md) for an example `service` file.
## Exposing web endpoint using HTTPS
It is recommended to expose the webserver over HTTPS by using a webserver like Nginx. An example configuration for configuring Nginx is listed [on the maintenance page](maintenance.md#nym-api-configuration)
@@ -216,7 +216,7 @@ You can use the following command to download them for the correct network:
wget -O $HOME/.nyxd/config/genesis.json https://nymtech.net/genesis/genesis.json
# Sandbox testnet
curl https://rpc.sandbox.nymtech.net/snapshots/genesis.json | jq '.result.genesis' > $HOME/.nyxd/config/genesis.json
wget -O $HOME/.nyxd/config/genesis.json https://sandbox-validator1.nymtech.net/snapshots/genesis.json | jq '.result.genesis'
```
### `config.toml` configuration
@@ -232,7 +232,7 @@ laddr = "tcp://0.0.0.0:26656"
```
# Sandbox testnet
cors_allowed_origins = ["*"]
persistent_peers = "26f7782aff699457c8e6dd9a845e5054c9b0707e@:3.72.19.120:26656"
persistent_peers = "26f7782aff699457c8e6dd9a845e5054c9b0707e@sandbox-validator1.nymtech.net:26666"
laddr = "tcp://0.0.0.0:26656"
```
@@ -254,7 +254,7 @@ And if you wish to add a human-readable moniker to your node:
Finally, if you plan on using [Cockpit](https://cockpit-project.org/documentation.html) on your server, change the `grpc` port from `9090` as this is the port used by Cockpit.
### `app.toml` configuration
In the file `$HOME/.nyxd/config/app.toml`, set the following values:
In the file `$HOME/nyxd/config/app.toml`, set the following values:
```
# Mainnet
@@ -264,6 +264,7 @@ minimum-gas-prices = "0.025unym,0.025unyx"
```
# Sandbox Testnet
minimum-gas-prices = "0.025unym,0.025unyx"
enable = true` in the `[api]` section to get the API server running
```
### Setting up your validator's admin user
@@ -303,31 +304,6 @@ File at /path/to/genesis.json is a valid genesis file
> If this test did not pass, check that you have replaced the contents of `/<PATH-TO>/.nyxd/config/genesis.json` with that of the correct genesis file.
### Setting up nyxd as full node (non-signing)
```admonish danger title=""
Skip this section if you're planning to run a validator node to join network consensus. To ensure security & maximum availability of validators, do not expose additional services to the Internet
```
Unlike signing validators, full nodes do not propose / sign blocks. A full node is typically used for indexing blocks produced on the chain and for exposing web interfaces such as RPC, API and gRPC endpoints required for external applications/services to interact with the blockchain.
By default, API server is disabled and RPC/gRPC servers listen to the loopback address only. In a production setup, it is recommended to use a webserver such as Nginx or caddy to proxy requests to the endpoints as required.
To enable Cosmos REST API, you can enable it in `$HOME/.nyxd/config/app.toml` like :
```
[api]
# Enable defines if the API server should be enabled. Toggle this to `true`
enable = true
# Swagger defines if swagger documentation should automatically be registered.
# You can also expose swagger documentation by toggling the below configuration to true
swagger = true
```
For more information on enabling access to various endpoints via Nginx, refer to the [example configuration here](./maintenance.md#setup)
### Open firewall ports
Before starting the validator, we will need to open the firewall ports:
@@ -343,9 +319,6 @@ sudo ufw enable
# 22 : Default SSH port
sudo ufw allow 26656,26660,22
## !! FOR FULL NODES ONLY !! - exposing Nginx for serving web requests
sudo ufw allow 80,443
# to check everything worked
sudo ufw status
```
@@ -373,7 +346,7 @@ sudo apt install snapd -y
sudo snap install lz4
# download the snapshot
wget -O nyxd-sandbox-snapshot-data.tar.lz4 https://rpc.sandbox.nymtech.net/snapshots/nyxd-sandbox-snapshot-data.tar.lz4
wget -O nyxd-sandbox-snapshot-data.tar.lz4 https://sandbox-validator1.nymtech.net/snapshots/nyxd-sandbox-snapshot-data.tar.lz4
# reset your validator state
nyxd tendermint unsafe-reset-all
@@ -385,8 +358,10 @@ lz4 -c -d nyxd-sandbox-snapshot-data.tar.lz4 | tar -x -C $HOME/.nyxd
You can then restart `nyxd` - it should start syncing from a block > 2000000.
### Joining Consensus
```admonish info title=""
You can skip this section if you are planning to run a full-node. This step will make your node a signing validator which joins network consensus
```admonish caution title=""
When joining consensus, make sure that you do not disrupt (or worse - halt) the network by coming in with a disproportionately large amount of staked tokens.
Please initially stake a small amount of tokens compared to existing validators, then delegate to yourself in tranches over time.
```
Once your validator has synced and you have received tokens, you can join consensus and produce blocks.
@@ -423,7 +398,7 @@ nyxd tx staking create-validator
--gas-adjustment=1.15
--gas-prices=0.025unyx
--from=<"KEYRING_NAME">
--node https://rpc.sandbox.nymtech.net:443
--node https://sandbox-validator1.nymtech.net:443
```
You'll need Nyx tokens on mainnet / sandbox to perform the above tasks.
@@ -498,15 +473,11 @@ To upgrade your validator, follow the steps on the [maintenance page](./maintena
#### Common reasons for your validator being jailed
Your validator will be jailed if your node:
- misses _`x`_ amount of blocks in _`y`_ interval, where _`x`_ and _`y`_ are parameters set by chain governance
- performs double signing (two conflicting signatures on the same block using the same key)
The most common reason for your validator being jailed is that your validator is out of memory because of bloated syslogs.
Double signing is a serious infraction. If a node double signs, all the delegators to the node (including self-delegation) will be slashed by 5%. Additionally, the node will be permanently jailed and removed from consensus (called _tombstoning_)
Running the command `df -H` will return the size of the various partitions of your VPS.
One of the most common reason for your validator being jailed is that your validator is out of memory because of bloated syslogs.
Running the command `df -H` will return the size of the various partitions of your VPS. If the partition with blockchain data is almost full, try pruning the blockchain data or expanding the storage size.
If the `/dev/sda` partition is almost full, try pruning some of the `.gz` syslog archives and restart your validator process.
### Day 2 operations with your validator
+1 -1
View File
@@ -23,5 +23,5 @@ SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1ps5yutd7sufwg058qd7ac7ldnlazsvmhzq
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
EXPLORER_API=https://sandbox-explorer.nymtech.net/api
NYXD="https://rpc.sandbox.nymtech.net"
NYXD="https://sandbox-validator1.nymtech.net"
NYM_API="https://sandbox-nym-api1.nymtech.net/api"
+1 -1
View File
@@ -47,7 +47,7 @@ serde_json = "1.0.91"
thiserror = { workspace = true }
tokio = { version = "1", features = ["macros", "net","rt-multi-thread"] }
tokio-tungstenite = { workspace = true }
tokio-util = { workspace = true, features = ["full"] }
tokio-util = { version = "0.7.4", features = ["full"] }
toml = "0.7.0"
unsigned-varint = "0.7.1"
utoipa = { workspace = true, features = ["actix_extras"] }
+1 -1
View File
@@ -22,7 +22,7 @@ NAME_SERVICE_CONTRACT_ADDRESS=n12ne7qtmdwd0j03t9t5es8md66wq4e5xg9neladrsag8fx3y8
SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS=n1ps5yutd7sufwg058qd7ac7ldnlazsvmhzqwucsfxmm445d70u8asqxpur4
STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0"
NYXD="https://rpc.sandbox.nymtech.net"
NYXD="https://sandbox-validator1.nymtech.net"
NYM_API="https://sandbox-nym-api1.nymtech.net/api"
GEOIP_DB_PATH=geo_ip/GeoLite2-City.mmdb
-1
View File
@@ -2,7 +2,6 @@
name = "explorer-api"
version = "1.1.32"
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-explorer-api-requests"
version = "0.1.0"
edition = "2021"
license.workspace = true
[dependencies]
nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common" }
-1
View File
@@ -2,7 +2,6 @@
name = "nym-explorer-client"
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
+1 -1
View File
@@ -3,7 +3,7 @@
EXPLORER_API_URL=https://sandbox-explorer.nymtech.net/api/v1
NYM_API_URL=https://sandbox-nym-api1.nymtech.net
VALIDATOR_URL=https://rpc.sandbox.nymtech.net
VALIDATOR_URL=https://sandbox-validator1.nymtech.net
BIG_DIPPER_URL=https://sandbox-blocks.nymtech.net
CURRENCY_DENOM=unym
CURRENCY_STAKING_DENOM=unyx
+2 -2
View File
@@ -3,7 +3,7 @@
[package]
name = "nym-gateway"
license = "GPL-3.0"
license = "GPL-3"
version = "1.1.32"
authors = [
"Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
@@ -53,7 +53,7 @@ tokio = { workspace = true, features = [
] }
tokio-stream = { version = "0.1.11", features = ["fs"] }
tokio-tungstenite = { version = "0.20.1" }
tokio-util = { workspace = true, features = ["codec"] }
tokio-util = { version = "0.7.4", features = ["codec"] }
url = { workspace = true, features = ["serde"] }
zeroize = { workspace = true }

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