From a75d98429a11fcb0c129a55380996a612299917b Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Tue, 16 Jun 2020 17:47:05 +0100 Subject: [PATCH] Update for node release v21 (#14) * Update for node release v21 - Removed `beta` flag no one uses. Maintaining this is too difficult with the difficulty changes. Program will error if that flag is given. This is not necessary for distributed work requests as those include the absolute difficulty - Update threshold to 8x current - Add lower receive threshold - Follow changes to work_validate * Fix incorrectly including "valid" in response if only multiplier was given If **difficulty** is not given then "valid" is not ever included, regardless of multiplier * No redundancy --- README.md | 7 ++++--- src/main.rs | 58 ++++++++++++++++++++++++++--------------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 323eb50..16e6b6b 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ ![Build](https://github.com/nanocurrency/nano-work-server/workflows/Build/badge.svg) -This project is a dedicated work server for [the Nano cryptocurrency](https://nano.org/). +This project is a dedicated work server for [the Nano cryptocurrency](https://nano.org/). See the [documentation](https://docs.nano.org/integration-guides/work-generation/) for details on work generation and the current network difficulty. -It supports the `work_generate`, `work_cancel`, and `work_validate` commands from the Nano RPC. +**nano-work-server** supports the `work_generate`, `work_cancel`, and `work_validate` commands from the Nano RPC. For details on these commands, see [the Nano RPC documentation](https://docs.nano.org/commands/rpc-protocol/). To see available command line options, run `nano-work-server --help`. @@ -47,6 +47,8 @@ cd target/release ## Using +_Note_ difficulty values may be outdated in these examples. + - `work_generate` example: ```json @@ -87,7 +89,6 @@ cd target/release "difficulty": "ffffffd21c3933f4", "multiplier": "1.3946469" } - ``` - `work_cancel` example: diff --git a/src/main.rs b/src/main.rs index 1bf925f..599a263 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,8 +44,8 @@ use time::PreciseTime; use gpu::Gpu; -const LIVE_DIFFICULTY: u64 = 0xffffffc000000000; -const BETA_DIFFICULTY: u64 = 0xfffff00000000000; +const LIVE_DIFFICULTY: u64 = 0xfffffff800000000; +const LIVE_RECEIVE_DIFFICULTY: u64 = 0xfffffe0000000000; fn work_value(root: [u8; 32], work: [u8; 8]) -> u64 { let mut buf = [0u8; 8]; @@ -99,13 +99,12 @@ impl WorkState { #[derive(Clone)] struct RpcService { work_state: Arc<(Mutex, Condvar)>, - base_difficulty: u64, } enum RpcCommand { - WorkGenerate([u8; 32], u64, Option), + WorkGenerate([u8; 32], Option, Option), WorkCancel([u8; 32]), - WorkValidate([u8; 32], [u8; 8], u64, Option), + WorkValidate([u8; 32], [u8; 8], Option, Option), } enum HexJsonError { @@ -148,11 +147,11 @@ impl RpcService { } fn to_multiplier(&self, difficulty: u64) -> f64 { - (self.base_difficulty.wrapping_neg() as f64) / (difficulty.wrapping_neg() as f64) + (LIVE_DIFFICULTY.wrapping_neg() as f64) / (difficulty.wrapping_neg() as f64) } fn from_multiplier(&self, multiplier: f64) -> u64 { - (((self.base_difficulty.wrapping_neg() as f64) / multiplier) as u64).wrapping_neg() + (((LIVE_DIFFICULTY.wrapping_neg() as f64) / multiplier) as u64).wrapping_neg() } fn parse_hex_json(value: &Value, out: &mut [u8], allow_short: bool) -> Result<(), HexJsonError> { @@ -277,7 +276,7 @@ impl RpcService { } Some(action) if action == "work_generate" => Ok(RpcCommand::WorkGenerate( Self::parse_hash_json(&json)?, - Self::parse_difficulty_json(&json)?.unwrap_or(self.base_difficulty), + Self::parse_difficulty_json(&json)?, Self::parse_multiplier_json(&json)?, )), Some(action) if action == "work_cancel" => { @@ -286,7 +285,7 @@ impl RpcService { Some(action) if action == "work_validate" => Ok(RpcCommand::WorkValidate( Self::parse_hash_json(&json)?, Self::parse_work_json(&json)?, - Self::parse_difficulty_json(&json)?.unwrap_or(self.base_difficulty), + Self::parse_difficulty_json(&json)?, Self::parse_multiplier_json(&json)?, )), Some(_) => { @@ -321,7 +320,7 @@ impl RpcService { match command { RpcCommand::WorkGenerate(root, difficulty, multiplier) => { let difficulty = match multiplier { - None => difficulty, + None => difficulty.unwrap_or(LIVE_DIFFICULTY), Some(multiplier) => self.from_multiplier(multiplier) }; Box::new(self.generate_work(root, difficulty).then(move |res| match res { @@ -366,18 +365,27 @@ impl RpcService { } RpcCommand::WorkValidate(root, work, difficulty, multiplier) => { let _ = println!("Validate {}", hex::encode_upper(&root)); - let difficulty = match multiplier { - None => difficulty, + let difficulty_l = match multiplier { + None => difficulty.unwrap_or(LIVE_DIFFICULTY), Some(multiplier) => self.from_multiplier(multiplier) }; - let (valid, result_difficulty) = work_valid(root, work, difficulty); + let (valid, result_difficulty) = work_valid(root, work, difficulty_l); + let (valid_all, _) = work_valid(root, work, LIVE_DIFFICULTY); + let (valid_receive, _) = work_valid(root, work, LIVE_RECEIVE_DIFFICULTY); Box::new(future::ok(( StatusCode::Ok, - json!({ - "valid": if valid { "1" } else { "0" }, - "difficulty": format!("{:x}", result_difficulty), - "multiplier": format!("{}", self.to_multiplier(result_difficulty)), - }), + { + let mut result = json!({ + "valid_all": if valid_all { "1" } else { "0" }, + "valid_receive": if valid_receive { "1" } else { "0" }, + "difficulty": format!("{:x}", result_difficulty), + "multiplier": format!("{}", self.to_multiplier(result_difficulty)), + }); + if difficulty.is_some() { + result.as_object_mut().unwrap().insert(String::from("valid"), json!(if valid {"1"} else {"0"})); + } + result + }, ))) } } @@ -453,19 +461,12 @@ fn main() { .value_name("N") .help("The GPU local work size. Increasing it may increase performance. For advanced users only."), ) - .arg( - clap::Arg::with_name("beta") - .long("beta") - .help("Generate work for the beta network. Modifies the base threshold for given multipliers or requests without a custom difficulty"), - ) .arg( clap::Arg::with_name("shuffle") .long("shuffle") .help("Pick a random request from the queue instead of the oldest. Increases efficiency when using multiple work servers") ) .get_matches(); - let beta = args.is_present("beta"); - let base_difficulty = if beta {BETA_DIFFICULTY} else {LIVE_DIFFICULTY}; let random_mode = args.is_present("shuffle"); let listen_addr = args.value_of("listen_address") .unwrap() @@ -664,14 +665,11 @@ fn main() { let server = Http::new() .bind(&listen_addr, move || { Ok(RpcService { - work_state: work_state.clone(), - base_difficulty + work_state: work_state.clone() }) }) .expect("Failed to bind server"); - println!("Configured for the {} network with threshold {:x}", - if beta {"beta"} else {"live"}, - base_difficulty); + println!("Configured for the live network with threshold {:x}", LIVE_DIFFICULTY); println!("Ready to receive requests on {}", listen_addr); server.run().expect("Error running server"); }