nano-rspow-python 0.13.0__tar.gz → 0.16.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/Cargo.lock +12 -5
  2. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/Cargo.toml +1 -1
  3. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/PKG-INFO +15 -2
  4. {nano_rspow_python-0.13.0/nano-rspow-python → nano_rspow_python-0.16.0}/README.md +13 -0
  5. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/Cargo.toml +1 -1
  6. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/README.md +4 -1
  7. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0/nano-rspow-python}/README.md +13 -0
  8. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/nano_rspow.pyi +8 -0
  9. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/src/lib.rs +117 -0
  10. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/pyproject.toml +4 -1
  11. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/benches/pow_benchmark.rs +0 -0
  12. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/cpu.rs +0 -0
  13. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/difficulty.rs +0 -0
  14. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/lib.rs +0 -0
  15. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/opencl_backend/mod.rs +0 -0
  16. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/opencl_backend/pow.cl +0 -0
  17. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/thresholds.rs +0 -0
  18. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/types.rs +0 -0
  19. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/wgpu_backend/mod.rs +0 -0
  20. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/wgpu_backend/pow.wgsl +0 -0
  21. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow/src/wgpu_shared.rs +0 -0
  22. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/Cargo.toml +0 -0
  23. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/build.rs +0 -0
  24. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/tests/test_pow.py +0 -0
  25. {nano_rspow_python-0.13.0 → nano_rspow_python-0.16.0}/nano-rspow-python/uv.lock +0 -0
@@ -757,7 +757,7 @@ dependencies = [
757
757
 
758
758
  [[package]]
759
759
  name = "nano-rspow"
760
- version = "0.13.0"
760
+ version = "0.16.0"
761
761
  dependencies = [
762
762
  "blake2b_simd",
763
763
  "bytemuck",
@@ -773,7 +773,7 @@ dependencies = [
773
773
 
774
774
  [[package]]
775
775
  name = "nano-rspow-cli"
776
- version = "0.13.0"
776
+ version = "0.16.0"
777
777
  dependencies = [
778
778
  "clap",
779
779
  "hex",
@@ -783,9 +783,16 @@ dependencies = [
783
783
  "tiny_http",
784
784
  ]
785
785
 
786
+ [[package]]
787
+ name = "nano-rspow-ffi"
788
+ version = "0.16.0"
789
+ dependencies = [
790
+ "nano-rspow",
791
+ ]
792
+
786
793
  [[package]]
787
794
  name = "nano-rspow-node"
788
- version = "0.13.0"
795
+ version = "0.16.0"
789
796
  dependencies = [
790
797
  "hex",
791
798
  "nano-rspow",
@@ -797,7 +804,7 @@ dependencies = [
797
804
 
798
805
  [[package]]
799
806
  name = "nano-rspow-python"
800
- version = "0.13.0"
807
+ version = "0.16.0"
801
808
  dependencies = [
802
809
  "hex",
803
810
  "nano-rspow",
@@ -806,7 +813,7 @@ dependencies = [
806
813
 
807
814
  [[package]]
808
815
  name = "nano-rspow-web"
809
- version = "0.13.0"
816
+ version = "0.16.0"
810
817
  dependencies = [
811
818
  "bytemuck",
812
819
  "getrandom",
@@ -3,7 +3,7 @@ members = ["nano-rspow", "nano-rspow-python"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.13.0"
6
+ version = "0.16.0"
7
7
  edition = "2024"
8
8
  license = "MIT"
9
9
  repository = "https://github.com/CasualSecurityInc/nano-rspow"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nano-rspow-python
3
- Version: 0.13.0
3
+ Version: 0.16.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Python :: 3.9
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
13
13
  Classifier: Programming Language :: Rust
14
14
  Classifier: Topic :: Security :: Cryptography
15
15
  Summary: Hybrid CPU/GPU Nano (XNO) Proof of Work library — Python bindings.
16
- Keywords: nano,xno,proof-of-work,blake2b,gpu
16
+ Keywords: nano,xno,nanocurrency,proof-of-work,blake2b
17
17
  Author-email: Conny Brunnkvist <cbrunnkvist@gmail.com>
18
18
  License-Expression: MIT
19
19
  Requires-Python: >=3.9
@@ -32,6 +32,19 @@ Native Nano (XNO) proof-of-work bindings for Python. The extension selects an av
32
32
  pip install nano-rspow-python
33
33
  ```
34
34
 
35
+ The package also installs a minimal streaming executable named
36
+ `nano-rspow-python`. It accepts no options except `--help` and uses the same
37
+ line protocol as `nano-rspow generate --stream`:
38
+
39
+ ```text
40
+ <hash_hex>[:0x<threshold_hex>]
41
+ <hash_hex>:0x<threshold_hex>:<work_hex>
42
+ ```
43
+
44
+ `nano-rspow` remains the full-featured CLI provided by the Rust
45
+ `nano-rspow-cli` crate; this Python package intentionally exposes only the
46
+ `nano-rspow-python` entrypoint.
47
+
35
48
  ## Usage
36
49
 
37
50
  ```python
@@ -8,6 +8,19 @@ Native Nano (XNO) proof-of-work bindings for Python. The extension selects an av
8
8
  pip install nano-rspow-python
9
9
  ```
10
10
 
11
+ The package also installs a minimal streaming executable named
12
+ `nano-rspow-python`. It accepts no options except `--help` and uses the same
13
+ line protocol as `nano-rspow generate --stream`:
14
+
15
+ ```text
16
+ <hash_hex>[:0x<threshold_hex>]
17
+ <hash_hex>:0x<threshold_hex>:<work_hex>
18
+ ```
19
+
20
+ `nano-rspow` remains the full-featured CLI provided by the Rust
21
+ `nano-rspow-cli` crate; this Python package intentionally exposes only the
22
+ `nano-rspow-python` entrypoint.
23
+
11
24
  ## Usage
12
25
 
13
26
  ```python
@@ -6,7 +6,7 @@ repository.workspace = true
6
6
  version.workspace = true
7
7
  readme = "README.md"
8
8
  description = "Hybrid CPU/GPU Nano (XNO) Proof of Work library — Rust core, cross-platform."
9
- keywords = ["nano", "xno", "proof-of-work", "blake2b", "gpu"]
9
+ keywords = ["nano", "xno", "nanocurrency", "proof-of-work", "blake2b"]
10
10
  categories = ["cryptography", "hardware-support"]
11
11
 
12
12
  [features]
@@ -57,8 +57,9 @@ Below is the directory mapping for each target, along with their primary release
57
57
  | **Rust (Core)** | [crate API documentation](nano-rspow/src/lib.rs) | [GitHub Releases](https://github.com/CasualSecurityInc/nano-rspow/releases) |
58
58
  | **Node.js & TS** | [nano-rspow-node README](https://github.com/CasualSecurityInc/nano-rspow/blob/HEAD/nano-rspow-node/README.md) | [Public NPM package](https://www.npmjs.com/package/nano-rspow-node) |
59
59
  | **Python** | [nano-rspow-python README](nano-rspow-python/README.md) | [PyPI (pip)](https://pypi.org/project/nano-rspow-python/) |
60
+ | **Go** | [nano-rspow-go README](nano-rspow-go/README.md) | Go module source checkout |
60
61
  | **Web (WASM / WebGPU)** | [nano-rspow-web/README.md](nano-rspow-web/README.md) | [Public NPM package](https://www.npmjs.com/package/nano-rspow-web) + [🎛️ Demo](https://csi.ninzin.net/nano-rspow/) |
61
- | **CLI Tool** | [nano-rspow-cli README](nano-rspow-cli/README.md) | [crates.io](https://crates.io/crates/nano-rspow-cli) · [GitHub Releases](https://github.com/CasualSecurityInc/nano-rspow/releases) |
62
+ | **CLI Tool** | [nano-rspow-cli README](nano-rspow-cli/README.md) | The only full-featured `nano-rspow` executable: [crates.io](https://crates.io/crates/nano-rspow-cli) · [GitHub Releases](https://github.com/CasualSecurityInc/nano-rspow/releases) |
62
63
 
63
64
  ---
64
65
 
@@ -70,7 +71,9 @@ This monorepo is organized into specialized workspaces to deliver native perform
70
71
  .
71
72
  ├── .cargo/ # Target-specific build configurations and cargo aliases
72
73
  ├── nano-rspow/ # Core Rust library containing cryptographic Blake2b logic & backends
74
+ ├── nano-rspow-ffi/ # C ABI used by the Go bindings
73
75
  ├── nano-rspow-cli/ # Standalone CLI binary for hardware benchmarking & generation
76
+ ├── nano-rspow-go/ # Go module and nano-rspow-go streaming CLI
74
77
  ├── nano-rspow-node/ # High-performance Node.js & TypeScript native bindings (N-API)
75
78
  ├── nano-rspow-python/ # Native PyO3 bindings for Python environments
76
79
  └── nano-rspow-web/ # Web/WASM target crate & self-contained HTML benchmarking dashboard
@@ -8,6 +8,19 @@ Native Nano (XNO) proof-of-work bindings for Python. The extension selects an av
8
8
  pip install nano-rspow-python
9
9
  ```
10
10
 
11
+ The package also installs a minimal streaming executable named
12
+ `nano-rspow-python`. It accepts no options except `--help` and uses the same
13
+ line protocol as `nano-rspow generate --stream`:
14
+
15
+ ```text
16
+ <hash_hex>[:0x<threshold_hex>]
17
+ <hash_hex>:0x<threshold_hex>:<work_hex>
18
+ ```
19
+
20
+ `nano-rspow` remains the full-featured CLI provided by the Rust
21
+ `nano-rspow-cli` crate; this Python package intentionally exposes only the
22
+ `nano-rspow-python` entrypoint.
23
+
11
24
  ## Usage
12
25
 
13
26
  ```python
@@ -63,6 +63,10 @@ def generate_work(hash_hex: str, work_type: WorkType) -> WorkResult:
63
63
  """
64
64
  ...
65
65
 
66
+ def generate_work_with_threshold(hash_hex: str, threshold_hex: str) -> WorkResult:
67
+ """Generate valid Proof of Work for an arbitrary hexadecimal threshold."""
68
+ ...
69
+
66
70
  def validate_work(hash_hex: str, work_hex: str, work_type: WorkType) -> bool:
67
71
  """Validate a work nonce against a hash and threshold.
68
72
 
@@ -101,6 +105,10 @@ def backend_name() -> str:
101
105
  """
102
106
  ...
103
107
 
108
+ def cli_main() -> int:
109
+ """Run the minimal line-buffered nano-rspow-python CLI."""
110
+ ...
111
+
104
112
  class thresholds:
105
113
  """Nano PoW threshold constants for all network epochs.
106
114
 
@@ -29,6 +29,7 @@ use pyo3::exceptions::PyValueError;
29
29
  use pyo3::prelude::*;
30
30
 
31
31
  use ::nano_rspow::{WorkGenerator, difficulty, thresholds};
32
+ use std::io::{BufRead, Write};
32
33
  use std::sync::OnceLock;
33
34
 
34
35
  // ---------------------------------------------------------------------------
@@ -187,6 +188,35 @@ fn generate_work(py: Python<'_>, hash_hex: &str, work_type: WorkType) -> PyResul
187
188
  }
188
189
  }
189
190
 
191
+ /// Generate valid Proof of Work for an arbitrary hexadecimal threshold.
192
+ #[pyfunction]
193
+ fn generate_work_with_threshold(
194
+ py: Python<'_>,
195
+ hash_hex: &str,
196
+ threshold_hex: &str,
197
+ ) -> PyResult<WorkResult> {
198
+ let hash = parse_hash(hash_hex)?;
199
+ let threshold = u64::from_str_radix(
200
+ threshold_hex.trim().trim_start_matches("0x"),
201
+ 16,
202
+ )
203
+ .map_err(|e| PyValueError::new_err(format!("Invalid threshold hex: {e}")))?;
204
+ let generator = get_generator();
205
+
206
+ let result = py.detach(move || generator.generate(&hash, threshold));
207
+
208
+ match result {
209
+ Some(r) => Ok(WorkResult {
210
+ nonce: r.nonce,
211
+ difficulty: r.difficulty,
212
+ threshold: r.threshold,
213
+ }),
214
+ None => Err(pyo3::exceptions::PyRuntimeError::new_err(
215
+ "Work generation failed or was cancelled",
216
+ )),
217
+ }
218
+ }
219
+
190
220
  /// Validate a work nonce against a hash and threshold.
191
221
  ///
192
222
  /// Args:
@@ -242,6 +272,91 @@ fn backend_name() -> &'static str {
242
272
  get_generator().backend_name()
243
273
  }
244
274
 
275
+ const CLI_HELP: &str = "nano-rspow-python generates Nano proof of work from stdin.\n\nUsage:\n nano-rspow-python [--help]\n\nWith no arguments, read one request per line and write one result per line.\nEmpty lines are ignored. The only accepted argument is --help.\n\nInput:\n <hash_hex>\n <hash_hex>:<threshold_hex>\n\nThe optional threshold must use a 0x prefix. Without one, the current\nepoch-2 send/change threshold is used.\n\nOutput:\n <hash_hex>:0x<threshold_hex>:<work_hex>\n";
276
+
277
+ fn parse_cli_request(line: &str) -> Result<(String, [u8; 32], u64), String> {
278
+ let parts: Vec<&str> = line.split(':').collect();
279
+ if parts.len() > 2 {
280
+ return Err("request must be <hash_hex> or <hash_hex>:<threshold_hex>".to_owned());
281
+ }
282
+
283
+ let hash_text = parts[0].trim().to_owned();
284
+ let hash = parse_hash(&hash_text).map_err(|error| error.to_string())?;
285
+ let threshold = if let Some(threshold_text) = parts.get(1).map(|part| part.trim()) {
286
+ if !threshold_text.starts_with("0x") {
287
+ return Err(format!(
288
+ "threshold {threshold_text:?} must start with 0x"
289
+ ));
290
+ }
291
+ u64::from_str_radix(&threshold_text[2..], 16)
292
+ .map_err(|error| format!("invalid threshold {threshold_text:?}: {error}"))?
293
+ } else {
294
+ thresholds::EPOCH2_SEND
295
+ };
296
+
297
+ Ok((hash_text, hash, threshold))
298
+ }
299
+
300
+ /// Run the minimal line-buffered CLI shipped as `nano-rspow-python`.
301
+ #[pyfunction]
302
+ fn cli_main(py: Python<'_>) -> PyResult<i32> {
303
+ let sys = py.import("sys")?;
304
+ let args: Vec<String> = sys
305
+ .getattr("argv")?
306
+ .extract::<Vec<String>>()?
307
+ .into_iter()
308
+ .skip(1)
309
+ .collect();
310
+ if args == ["--help"] {
311
+ print!("{CLI_HELP}");
312
+ return Ok(0);
313
+ }
314
+ if !args.is_empty() {
315
+ eprintln!("error: only --help is supported");
316
+ eprint!("{CLI_HELP}");
317
+ return Ok(2);
318
+ }
319
+
320
+ let generator = get_generator();
321
+ let stdin = std::io::stdin();
322
+ let mut stdout = std::io::BufWriter::new(std::io::stdout());
323
+ for line_result in stdin.lock().lines() {
324
+ let line = line_result.map_err(|error| {
325
+ pyo3::exceptions::PyRuntimeError::new_err(format!("Error reading input: {error}"))
326
+ })?;
327
+ let line = line.trim();
328
+ if line.is_empty() {
329
+ continue;
330
+ }
331
+
332
+ let (hash_text, hash, threshold) = match parse_cli_request(line) {
333
+ Ok(request) => request,
334
+ Err(error) => {
335
+ eprintln!("Error parsing request {line:?}: {error}");
336
+ continue;
337
+ }
338
+ };
339
+
340
+ let result = py.detach(move || generator.generate(&hash, threshold));
341
+ let Some(result) = result else {
342
+ eprintln!("Error generating work for {hash_text}: generation failed");
343
+ continue;
344
+ };
345
+ writeln!(
346
+ stdout,
347
+ "{hash_text}:0x{threshold:016x}:{:016x}",
348
+ result.nonce
349
+ )
350
+ .map_err(|error| {
351
+ pyo3::exceptions::PyRuntimeError::new_err(format!("Error writing result: {error}"))
352
+ })?;
353
+ stdout.flush().map_err(|error| {
354
+ pyo3::exceptions::PyRuntimeError::new_err(format!("Error flushing result: {error}"))
355
+ })?;
356
+ }
357
+ Ok(0)
358
+ }
359
+
245
360
  // ---------------------------------------------------------------------------
246
361
  // Threshold constants submodule
247
362
  // ---------------------------------------------------------------------------
@@ -277,9 +392,11 @@ fn nano_rspow(m: &Bound<'_, PyModule>) -> PyResult<()> {
277
392
  m.add_class::<WorkType>()?;
278
393
  m.add_class::<WorkResult>()?;
279
394
  m.add_function(wrap_pyfunction!(generate_work, m)?)?;
395
+ m.add_function(wrap_pyfunction!(generate_work_with_threshold, m)?)?;
280
396
  m.add_function(wrap_pyfunction!(validate_work, m)?)?;
281
397
  m.add_function(wrap_pyfunction!(compute_difficulty, m)?)?;
282
398
  m.add_function(wrap_pyfunction!(backend_name, m)?)?;
399
+ m.add_function(wrap_pyfunction!(cli_main, m)?)?;
283
400
  register_thresholds(m)?;
284
401
  Ok(())
285
402
  }
@@ -12,7 +12,7 @@ license = "MIT"
12
12
  authors = [
13
13
  { name = "Conny Brunnkvist", email = "cbrunnkvist@gmail.com" },
14
14
  ]
15
- keywords = ["nano", "xno", "proof-of-work", "blake2b", "gpu"]
15
+ keywords = ["nano", "xno", "nanocurrency", "proof-of-work", "blake2b"]
16
16
  classifiers = [
17
17
  "Programming Language :: Python :: 3",
18
18
  "Programming Language :: Python :: 3 :: Only",
@@ -32,6 +32,9 @@ Homepage = "https://github.com/CasualSecurityInc/nano-rspow"
32
32
  Repository = "https://github.com/CasualSecurityInc/nano-rspow"
33
33
  Issues = "https://github.com/CasualSecurityInc/nano-rspow/issues"
34
34
 
35
+ [project.scripts]
36
+ nano-rspow-python = "nano_rspow:cli_main"
37
+
35
38
  [dependency-groups]
36
39
  test = [
37
40
  "maturin>=1.5",