Feature/include nymd client in gateway (#1398)

* Reinclude custom validators in coconut

* Check mnemonic validity early

* Include nymd client in coconut verifier

and simplify the erc20 bridge part
This commit is contained in:
Bogdan-Ștefan Neacşu
2022-06-23 12:28:40 +03:00
committed by GitHub
parent 6b07f31a87
commit ae88e25300
7 changed files with 69 additions and 60 deletions
+7 -11
View File
@@ -43,6 +43,10 @@ pub struct Init {
#[clap(long)]
validator_apis: Option<String>,
/// Comma separated list of endpoints of the validator
#[clap(long)]
validators: Option<String>,
/// Cosmos wallet mnemonic needed for double spending protection
#[clap(long)]
mnemonic: Option<String>,
@@ -64,11 +68,6 @@ pub struct Init {
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
#[clap(long)]
statistics_service_url: Option<String>,
/// Comma separated list of endpoints of the validator
#[cfg(all(feature = "eth", not(feature = "coconut")))]
#[clap(long)]
validators: Option<String>,
}
impl From<Init> for OverrideConfig {
@@ -81,6 +80,7 @@ impl From<Init> for OverrideConfig {
datastore: init_config.datastore,
announce_host: init_config.announce_host,
validator_apis: init_config.validator_apis,
validators: init_config.validators,
mnemonic: init_config.mnemonic,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
@@ -91,9 +91,6 @@ impl From<Init> for OverrideConfig {
enabled_statistics: init_config.enabled_statistics,
statistics_service_url: init_config.statistics_service_url,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
validators: init_config.validators,
}
}
}
@@ -174,15 +171,14 @@ mod tests {
announce_host: Some("foo-announce-host".to_string()),
datastore: Some("foo-datastore".to_string()),
validator_apis: None,
mnemonic: Some("a b c".to_string()),
validators: None,
mnemonic: None,
statistics_service_url: None,
enabled_statistics: None,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
enabled_credentials_mode: None,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
eth_endpoint: "".to_string(),
#[cfg(all(feature = "eth", not(feature = "coconut")))]
validators: None,
};
let config = Config::new(&args.id);
+9 -9
View File
@@ -1,7 +1,7 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::process;
use std::{process, str::FromStr};
use crate::{config::Config, Cli};
use clap::Subcommand;
@@ -17,9 +17,6 @@ pub(crate) mod upgrade;
#[cfg(all(not(feature = "eth"), not(feature = "coconut")))]
const DEFAULT_ETH_ENDPOINT: &str = "https://rinkeby.infura.io/v3/00000000000000000000000000000000";
#[cfg(all(not(feature = "eth"), not(feature = "coconut")))]
const DEFAULT_VALIDATOR_ENDPOINT: &str = "http://localhost:26657";
#[derive(Subcommand)]
pub(crate) enum Commands {
/// Initialise the gateway
@@ -49,6 +46,7 @@ pub(crate) struct OverrideConfig {
enabled_statistics: Option<bool>,
statistics_service_url: Option<String>,
validator_apis: Option<String>,
validators: Option<String>,
mnemonic: Option<String>,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
@@ -56,9 +54,6 @@ pub(crate) struct OverrideConfig {
#[cfg(all(feature = "eth", not(feature = "coconut")))]
eth_endpoint: Option<String>,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
validators: Option<String>,
}
pub(crate) async fn execute(args: Cli) {
@@ -120,6 +115,10 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
config = config.with_custom_validator_apis(parse_validators(&raw_validators));
}
if let Some(raw_validators) = args.validators {
config = config.with_custom_validator_nymd(parse_validators(&raw_validators));
}
if let Some(wallet_address) = args.wallet_address {
let trimmed = wallet_address.trim();
validate_bech32_address_or_exit(trimmed);
@@ -131,12 +130,13 @@ pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Confi
}
if let Some(cosmos_mnemonic) = args.mnemonic {
config = config.with_cosmos_mnemonic(cosmos_mnemonic);
config = config.with_cosmos_mnemonic(
bip39::Mnemonic::from_str(&cosmos_mnemonic).expect("Provided mnemonic is invalid"),
);
}
#[cfg(all(not(feature = "eth"), not(feature = "coconut")))]
{
config = config.with_custom_validator_nymd(parse_validators(DEFAULT_VALIDATOR_ENDPOINT));
config = config.with_eth_endpoint(String::from(DEFAULT_ETH_ENDPOINT));
}
+5 -8
View File
@@ -43,6 +43,10 @@ pub struct Run {
#[clap(long)]
validator_apis: Option<String>,
/// Comma separated list of endpoints of the validator
#[clap(long)]
validators: Option<String>,
/// Cosmos wallet mnemonic
#[clap(long)]
mnemonic: Option<String>,
@@ -64,11 +68,6 @@ pub struct Run {
/// URL where a statistics aggregator is running. The default value is a Nym aggregator server
#[clap(long)]
statistics_service_url: Option<String>,
/// Comma separated list of endpoints of the validator
#[cfg(all(feature = "eth", not(feature = "coconut")))]
#[clap(long)]
validators: Option<String>,
}
impl From<Run> for OverrideConfig {
@@ -81,6 +80,7 @@ impl From<Run> for OverrideConfig {
datastore: run_config.datastore,
announce_host: run_config.announce_host,
validator_apis: run_config.validator_apis,
validators: run_config.validators,
mnemonic: run_config.mnemonic,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
@@ -91,9 +91,6 @@ impl From<Run> for OverrideConfig {
enabled_statistics: run_config.enabled_statistics,
statistics_service_url: run_config.statistics_service_url,
#[cfg(all(feature = "eth", not(feature = "coconut")))]
validators: run_config.validators,
}
}
}
+5 -8
View File
@@ -8,6 +8,7 @@ use log::error;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;
use url::Url;
@@ -142,13 +143,12 @@ impl Config {
self
}
#[cfg(not(feature = "coconut"))]
pub fn with_custom_validator_nymd(mut self, validator_nymd_urls: Vec<Url>) -> Self {
self.gateway.validator_nymd_urls = validator_nymd_urls;
self
}
pub fn with_cosmos_mnemonic(mut self, cosmos_mnemonic: String) -> Self {
pub fn with_cosmos_mnemonic(mut self, cosmos_mnemonic: bip39::Mnemonic) -> Self {
self.gateway.cosmos_mnemonic = cosmos_mnemonic;
self
}
@@ -249,12 +249,11 @@ impl Config {
self.gateway.validator_api_urls.clone()
}
#[cfg(not(feature = "coconut"))]
pub fn get_validator_nymd_endpoints(&self) -> Vec<Url> {
self.gateway.validator_nymd_urls.clone()
}
pub fn _get_cosmos_mnemonic(&self) -> String {
pub fn get_cosmos_mnemonic(&self) -> bip39::Mnemonic {
self.gateway.cosmos_mnemonic.clone()
}
@@ -367,11 +366,10 @@ pub struct Gateway {
validator_api_urls: Vec<Url>,
/// Addresses to validators which the node uses to check for double spending of ERC20 tokens.
#[cfg(not(feature = "coconut"))]
validator_nymd_urls: Vec<Url>,
/// Mnemonic of a cosmos wallet used in checking for double spending.
cosmos_mnemonic: String,
cosmos_mnemonic: bip39::Mnemonic,
/// nym_home_directory specifies absolute path to the home nym gateways directory.
/// It is expected to use default value and hence .toml file should not redefine this field.
@@ -426,9 +424,8 @@ impl Default for Gateway {
enabled_statistics: false,
statistics_service_url: default_statistics_service_url(),
validator_api_urls: default_api_endpoints(),
#[cfg(not(feature = "coconut"))]
validator_nymd_urls: default_nymd_endpoints(),
cosmos_mnemonic: "exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day".to_string(),
cosmos_mnemonic: bip39::Mnemonic::from_str("exact antique hybrid width raise anchor puzzle degree fee quit long crack net vague hip despair write put useless civil mechanic broom music day").unwrap(),
nym_root_directory: Config::default_root_directory(),
persistent_storage: Default::default(),
wallet_address: "nymXXXXXXXX".to_string(),
@@ -2,17 +2,26 @@
// SPDX-License-Identifier: Apache-2.0
use coconut_interface::VerificationKey;
use validator_client::ApiClient;
use validator_client::{
nymd::{NymdClient, SigningNymdClient},
ApiClient,
};
pub struct CoconutVerifier {
api_clients: Vec<ApiClient>,
_nymd_client: NymdClient<SigningNymdClient>,
aggregated_verification_key: VerificationKey,
}
impl CoconutVerifier {
pub fn new(api_clients: Vec<ApiClient>, aggregated_verification_key: VerificationKey) -> Self {
pub fn new(
api_clients: Vec<ApiClient>,
_nymd_client: NymdClient<SigningNymdClient>,
aggregated_verification_key: VerificationKey,
) -> Self {
CoconutVerifier {
api_clients,
_nymd_client,
aggregated_verification_key,
}
}
@@ -21,6 +30,10 @@ impl CoconutVerifier {
&self.api_clients
}
pub fn _nymd_client(&self) -> &NymdClient<SigningNymdClient> {
&self._nymd_client
}
pub fn aggregated_verification_key(&self) -> &VerificationKey {
&self.aggregated_verification_key
}
@@ -1,12 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use bip39::core::str::FromStr;
use bip39::Mnemonic;
use config::defaults::DEFAULT_NETWORK;
use rand::seq::SliceRandom;
use rand::thread_rng;
use url::Url;
use std::str::FromStr;
use web3::contract::tokens::Detokenize;
use web3::contract::{Contract, Error};
use web3::ethabi::Token;
@@ -31,17 +26,9 @@ pub(crate) struct ERC20Bridge {
}
impl ERC20Bridge {
pub fn new(eth_endpoint: String, nymd_urls: Vec<Url>, cosmos_mnemonic: String) -> Self {
pub fn new(eth_endpoint: String, nymd_client: NymdClient<SigningNymdClient>) -> Self {
let transport = Http::new(&eth_endpoint).expect("Invalid Ethereum endpoint");
let web3 = Web3::new(transport);
let nymd_url = nymd_urls
.choose(&mut thread_rng())
.expect("The list of validators is empty");
let mnemonic =
Mnemonic::from_str(&cosmos_mnemonic).expect("Invalid Cosmos mnemonic provided");
let nymd_client =
NymdClient::connect_with_mnemonic(DEFAULT_NETWORK, nymd_url.as_ref(), mnemonic, None)
.expect("Could not create nymd client");
ERC20Bridge {
contract: eth_contract(web3.clone()),
+26 -7
View File
@@ -9,6 +9,7 @@ use crate::node::client_handling::websocket;
use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler;
use crate::node::statistics::collector::GatewayStatisticsCollector;
use crate::node::storage::Storage;
use config::defaults::DEFAULT_NETWORK;
use crypto::asymmetric::{encryption, identity};
use log::*;
use mixnet_client::forwarder::{MixForwardingSender, PacketForwarder};
@@ -239,6 +240,23 @@ where
validator_client::ApiClient::new(validator_api.clone())
}
fn random_nymd_client(
&self,
) -> validator_client::nymd::NymdClient<validator_client::nymd::SigningNymdClient> {
let endpoints = self.config.get_validator_nymd_endpoints();
let validator_nymd = endpoints
.choose(&mut thread_rng())
.expect("The list of validators is empty");
validator_client::nymd::NymdClient::connect_with_mnemonic(
DEFAULT_NETWORK,
validator_nymd.as_ref(),
self.config.get_cosmos_mnemonic(),
None,
)
.expect("Could not connect with mnemonic")
}
#[cfg(feature = "coconut")]
fn all_api_clients(&self) -> Vec<validator_client::ApiClient> {
self.config
@@ -288,16 +306,17 @@ where
obtain_aggregate_verification_key(&self.config.get_validator_api_endpoints())
.await
.expect("failed to contact validators to obtain their verification keys");
let nymd_client = self.random_nymd_client();
#[cfg(feature = "coconut")]
let coconut_verifier =
CoconutVerifier::new(self.all_api_clients(), validators_verification_key);
let coconut_verifier = CoconutVerifier::new(
self.all_api_clients(),
nymd_client,
validators_verification_key,
);
#[cfg(not(feature = "coconut"))]
let erc20_bridge = ERC20Bridge::new(
self.config.get_eth_endpoint(),
self.config.get_validator_nymd_endpoints(),
self.config._get_cosmos_mnemonic(),
);
let erc20_bridge = ERC20Bridge::new(self.config.get_eth_endpoint(), nymd_client);
let mix_forwarding_channel = self.start_packet_forwarder();