diff --git a/common/client-libs/validator-client/src/models/gateway.rs b/common/client-libs/validator-client/src/models/gateway.rs index 91330bfd01f..cd98b4899f4 100644 --- a/common/client-libs/validator-client/src/models/gateway.rs +++ b/common/client-libs/validator-client/src/models/gateway.rs @@ -55,6 +55,7 @@ impl GatewayRegistrationInfo { sphinx_key: String, version: String, location: String, + incentives_address: Option, ) -> Self { GatewayRegistrationInfo { node_info: NodeInfo { @@ -63,6 +64,7 @@ impl GatewayRegistrationInfo { sphinx_key, version, location, + incentives_address: incentives_address.unwrap_or_else(|| "".to_string()), }, clients_host, } diff --git a/common/client-libs/validator-client/src/models/mixnode.rs b/common/client-libs/validator-client/src/models/mixnode.rs index 071d0aea574..8a471db9bb6 100644 --- a/common/client-libs/validator-client/src/models/mixnode.rs +++ b/common/client-libs/validator-client/src/models/mixnode.rs @@ -55,6 +55,7 @@ impl MixRegistrationInfo { version: String, location: String, layer: u64, + incentives_address: Option, ) -> Self { MixRegistrationInfo { node_info: NodeInfo { @@ -63,6 +64,7 @@ impl MixRegistrationInfo { sphinx_key, version, location, + incentives_address: incentives_address.unwrap_or_else(|| "".to_string()), }, layer, } diff --git a/common/client-libs/validator-client/src/models/node.rs b/common/client-libs/validator-client/src/models/node.rs index 0e6912a5644..cfbdd82546e 100644 --- a/common/client-libs/validator-client/src/models/node.rs +++ b/common/client-libs/validator-client/src/models/node.rs @@ -22,4 +22,5 @@ pub(crate) struct NodeInfo { pub(crate) sphinx_key: String, pub(crate) version: String, pub(crate) location: String, + pub(crate) incentives_address: String, } diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index f73af09924d..245d340fa15 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -103,6 +103,12 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { .help("REST endpoint of the validator the node is registering presence with") .takes_value(true), ) + .arg( + Arg::with_name("incentives-address") + .long("incentives-address") + .help("Optional, if participating in the incentives program, payment address") + .takes_value(true), + ) } fn show_incentives_url() { diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index ce9f9eeb9d6..88cf63087e4 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -102,5 +102,9 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi config = config.with_location(location); } + if let Some(incentives_address) = matches.value_of("incentives-address") { + config = config.with_incentives_address(incentives_address); + } + config } diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 16c092c4ec6..900ca0c34cc 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -139,6 +139,18 @@ where deserializer.deserialize_any(DurationVisitor) } +fn deserialize_option_string<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + if s.is_empty() { + Ok(None) + } else { + Ok(Some(s)) + } +} + pub fn missing_string_value() -> String { MISSING_VALUE.to_string() } @@ -380,6 +392,11 @@ impl Config { self } + pub fn with_incentives_address>(mut self, incentives_address: S) -> Self { + self.gateway.incentives_address = Some(incentives_address.into()); + self + } + // getters pub fn get_config_file_save_location(&self) -> PathBuf { self.config_directory().join(Self::config_file_name()) @@ -464,6 +481,10 @@ impl Config { pub fn get_version(&self) -> &str { &self.gateway.version } + + pub fn get_incentives_address(&self) -> Option { + self.gateway.incentives_address.clone() + } } #[derive(Debug, Deserialize, PartialEq, Serialize)] @@ -500,6 +521,10 @@ pub struct Gateway { /// 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. nym_root_directory: PathBuf, + + /// Optional, if participating in the incentives program, payment address. + #[serde(deserialize_with = "deserialize_option_string")] + incentives_address: Option, } impl Gateway { @@ -536,6 +561,7 @@ impl Default for Gateway { public_sphinx_key_file: Default::default(), validator_rest_url: DEFAULT_VALIDATOR_REST_ENDPOINT.to_string(), nym_root_directory: Config::default_root_directory(), + incentives_address: None, } } } diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index 3ba36fe6c91..a66b5ef7823 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -48,6 +48,9 @@ private_sphinx_key_file = '{{ gateway.private_sphinx_key_file }}' # Path to file containing public sphinx key. public_sphinx_key_file = '{{ gateway.public_sphinx_key_file }}' +# Optional, if participating in the incentives program, payment address. +incentives_address = '{{ gateway.incentives_address }}' + # Validator server to which the node will be reporting their presence data. validator_rest_url = '{{ gateway.validator_rest_url }}' diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index d17957d20a3..c0e2a459ad6 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -194,6 +194,7 @@ impl Gateway { self.encryption_keys.public_key().to_base58_string(), self.config.get_version().to_string(), self.config.get_location(), + self.config.get_incentives_address() ).await { error!("failed to register with the validator - {:?}", err); return diff --git a/gateway/src/node/presence.rs b/gateway/src/node/presence.rs index 66991d1cbbc..6b67222a88b 100644 --- a/gateway/src/node/presence.rs +++ b/gateway/src/node/presence.rs @@ -25,6 +25,7 @@ pub(crate) async fn register_with_validator( sphinx_key: String, version: String, location: String, + incentives_address: Option, ) -> Result<(), ValidatorClientError> { let config = validator_client::Config::new(validator_endpoint); let validator_client = validator_client::Client::new(config); @@ -36,6 +37,7 @@ pub(crate) async fn register_with_validator( sphinx_key, version, location, + incentives_address, ); validator_client.register_gateway(registration_info).await diff --git a/mixnode/src/commands/init.rs b/mixnode/src/commands/init.rs index bbef492965a..a74cb5a26f1 100644 --- a/mixnode/src/commands/init.rs +++ b/mixnode/src/commands/init.rs @@ -82,6 +82,12 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { .help("Server to which the node is sending all metrics data") .takes_value(true), ) + .arg( + Arg::with_name("incentives-address") + .long("incentives-address") + .help("Optional, if participating in the incentives program, payment address") + .takes_value(true), + ) } fn show_incentives_url() { diff --git a/mixnode/src/commands/mod.rs b/mixnode/src/commands/mod.rs index 00bfa24968c..d170240fb31 100644 --- a/mixnode/src/commands/mod.rs +++ b/mixnode/src/commands/mod.rs @@ -77,5 +77,9 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches) -> Confi config = config.with_location(location); } + if let Some(incentives_address) = matches.value_of("incentives-address") { + config = config.with_incentives_address(incentives_address); + } + config } diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index 5fb44bfbb65..06d78270a1e 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -131,6 +131,18 @@ where deserializer.deserialize_any(DurationVisitor) } +fn deserialize_option_string<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + if s.is_empty() { + Ok(None) + } else { + Ok(Some(s)) + } +} + pub fn missing_string_value>() -> T { MISSING_VALUE.to_string().into() } @@ -270,6 +282,11 @@ impl Config { self } + pub fn with_incentives_address>(mut self, incentives_address: S) -> Self { + self.mixnode.incentives_address = Some(incentives_address.into()); + self + } + // getters pub fn get_config_file_save_location(&self) -> PathBuf { self.config_directory().join(Self::config_file_name()) @@ -343,6 +360,10 @@ impl Config { &self.mixnode.version } + pub fn get_incentives_address(&self) -> Option { + self.mixnode.incentives_address.clone() + } + // upgrade-specific pub(crate) fn set_default_identity_keypair_paths(&mut self) { self.mixnode.private_identity_key_file = @@ -406,6 +427,10 @@ pub struct MixNode { /// nym_home_directory specifies absolute path to the home nym MixNodes directory. /// It is expected to use default value and hence .toml file should not redefine this field. nym_root_directory: PathBuf, + + /// Optional, if participating in the incentives program, payment address. + #[serde(deserialize_with = "deserialize_option_string")] + incentives_address: Option, } impl MixNode { @@ -448,6 +473,7 @@ impl Default for MixNode { validator_rest_url: DEFAULT_VALIDATOR_REST_ENDPOINT.to_string(), metrics_server_url: DEFAULT_METRICS_SERVER.to_string(), nym_root_directory: Config::default_root_directory(), + incentives_address: None, } } } diff --git a/mixnode/src/config/template.rs b/mixnode/src/config/template.rs index 941dffa4b7e..15b480a1690 100644 --- a/mixnode/src/config/template.rs +++ b/mixnode/src/config/template.rs @@ -54,6 +54,9 @@ private_sphinx_key_file = '{{ mixnode.private_sphinx_key_file }}' # Path to file containing public sphinx key. public_sphinx_key_file = '{{ mixnode.public_sphinx_key_file }}' +# Optional, if participating in the incentives program, payment address. +incentives_address = '{{ mixnode.incentives_address }}' + ##### additional mixnode config options ##### # Optional address announced to the directory server for the clients to connect to. diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 7b06b28a4f0..bd0ec27a26f 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -152,6 +152,7 @@ impl MixNode { self.config.get_version().to_string(), self.config.get_location(), self.config.get_layer(), + self.config.get_incentives_address(), ).await { error!("failed to register with the validator - {:?}", err); return diff --git a/mixnode/src/node/presence.rs b/mixnode/src/node/presence.rs index 262223bcd60..a7d0f62eb83 100644 --- a/mixnode/src/node/presence.rs +++ b/mixnode/src/node/presence.rs @@ -25,12 +25,20 @@ pub(crate) async fn register_with_validator( version: String, location: String, layer: u64, + incentives_address: Option, ) -> Result<(), ValidatorClientError> { let config = validator_client::Config::new(validator_endpoint); let validator_client = validator_client::Client::new(config); - let registration_info = - MixRegistrationInfo::new(mix_host, identity_key, sphinx_key, version, location, layer); + let registration_info = MixRegistrationInfo::new( + mix_host, + identity_key, + sphinx_key, + version, + location, + layer, + incentives_address, + ); validator_client.register_mix(registration_info).await }