@nuggetslife/vc 0.4.1 → 0.4.3

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 (2) hide show
  1. package/package.json +6 -6
  2. package/src/bbs_2023.rs +86 -66
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuggetslife/vc",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "napi": {
@@ -42,10 +42,10 @@
42
42
  },
43
43
  "packageManager": "yarn@4.3.1",
44
44
  "optionalDependencies": {
45
- "@nuggetslife/vc-darwin-arm64": "0.4.1",
46
- "@nuggetslife/vc-linux-arm64-gnu": "0.4.1",
47
- "@nuggetslife/vc-linux-arm64-musl": "0.4.1",
48
- "@nuggetslife/vc-linux-x64-gnu": "0.4.1",
49
- "@nuggetslife/vc-linux-x64-musl": "0.4.1"
45
+ "@nuggetslife/vc-darwin-arm64": "0.4.3",
46
+ "@nuggetslife/vc-linux-arm64-gnu": "0.4.3",
47
+ "@nuggetslife/vc-linux-arm64-musl": "0.4.3",
48
+ "@nuggetslife/vc-linux-x64-gnu": "0.4.3",
49
+ "@nuggetslife/vc-linux-x64-musl": "0.4.3"
50
50
  }
51
51
  }
package/src/bbs_2023.rs CHANGED
@@ -1,4 +1,45 @@
1
+ //! BBS+ 2023 cryptosuite NAPI exports.
2
+ //!
3
+ //! Each export delegates to an async `vc::bbs_2023::*` function via a
4
+ //! **single process-wide tokio runtime** (`bbs_runtime`). Before
5
+ //! v1.14.3 each call constructed a fresh `tokio::runtime::Runtime::new()`
6
+ //! and dropped it on return — that pattern caused a V8 fatal
7
+ //! (`Check failed: node->IsInUse()`) when a vitest / node worker_thread
8
+ //! consumer terminated a worker mid-suite: the per-call runtime's worker
9
+ //! threads were still finishing as V8 began isolate teardown, racing the
10
+ //! NAPI handle lifecycle.
11
+ //!
12
+ //! The shared runtime sidesteps that race — its worker threads outlive
13
+ //! every JS worker isolate, no `Drop`-during-teardown happens, and V8's
14
+ //! handle bookkeeping stays consistent through worker rotation. The
15
+ //! runtime is intentionally never shut down; it lives for the process
16
+ //! lifetime, which matches how every other `pub async fn` in this crate
17
+ //! is scheduled (napi-rs's built-in tokio integration also uses a
18
+ //! single shared runtime — we just couldn't switch these specific
19
+ //! exports to `pub async fn` because the underlying `vc::bbs_2023::*`
20
+ //! futures are not `Send`).
21
+
22
+ use std::sync::OnceLock;
23
+
1
24
  use serde_json::Value;
25
+ use tokio::runtime::Runtime;
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Shared tokio runtime
29
+ // ---------------------------------------------------------------------------
30
+
31
+ fn bbs_runtime() -> napi::Result<&'static Runtime> {
32
+ static RUNTIME: OnceLock<Runtime> = OnceLock::new();
33
+ if let Some(rt) = RUNTIME.get() {
34
+ return Ok(rt);
35
+ }
36
+ let rt = Runtime::new()
37
+ .map_err(|e| napi::Error::from_reason(format!("bbs_2023 runtime init failed: {e}")))?;
38
+ // Race-safe: if another thread also constructed one, the loser's Runtime
39
+ // is dropped here and we return the winner. Cheap because Runtime::new
40
+ // only happens on the first call(s); steady-state is the get() above.
41
+ Ok(RUNTIME.get_or_init(|| rt))
42
+ }
2
43
 
3
44
  // ---------------------------------------------------------------------------
4
45
  // Result types
@@ -6,8 +47,8 @@ use serde_json::Value;
6
47
 
7
48
  #[napi(object)]
8
49
  pub struct Bbs2023VerifyOutput {
9
- pub verified: bool,
10
- pub error: Option<String>,
50
+ pub verified: bool,
51
+ pub error: Option<String>,
11
52
  }
12
53
 
13
54
  // ---------------------------------------------------------------------------
@@ -16,17 +57,12 @@ pub struct Bbs2023VerifyOutput {
16
57
 
17
58
  #[napi(js_name = "bbs2023Sign")]
18
59
  pub fn bbs2023_sign(options: Value) -> napi::Result<Value> {
19
- let sign_opts: vc::bbs_2023::SignOptions = serde_json::from_value(options)
20
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Sign parse options: {e}")))?;
21
-
22
- let rt = tokio::runtime::Runtime::new()
23
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Sign runtime: {e}")))?;
24
-
25
- let result = rt
26
- .block_on(vc::bbs_2023::create_base_proof(sign_opts))
27
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Sign failed: {e}")))?;
60
+ let sign_opts: vc::bbs_2023::SignOptions = serde_json::from_value(options)
61
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023Sign parse options: {e}")))?;
28
62
 
29
- Ok(result)
63
+ bbs_runtime()?
64
+ .block_on(vc::bbs_2023::create_base_proof(sign_opts))
65
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023Sign failed: {e}")))
30
66
  }
31
67
 
32
68
  // ---------------------------------------------------------------------------
@@ -35,17 +71,12 @@ pub fn bbs2023_sign(options: Value) -> napi::Result<Value> {
35
71
 
36
72
  #[napi(js_name = "bbs2023Derive")]
37
73
  pub fn bbs2023_derive(options: Value) -> napi::Result<Value> {
38
- let derive_opts: vc::bbs_2023::DeriveOptions = serde_json::from_value(options)
39
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Derive parse options: {e}")))?;
74
+ let derive_opts: vc::bbs_2023::DeriveOptions = serde_json::from_value(options)
75
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023Derive parse options: {e}")))?;
40
76
 
41
- let rt = tokio::runtime::Runtime::new()
42
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Derive runtime: {e}")))?;
43
-
44
- let result = rt
45
- .block_on(vc::bbs_2023::create_derived_proof(derive_opts))
46
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Derive failed: {e}")))?;
47
-
48
- Ok(result)
77
+ bbs_runtime()?
78
+ .block_on(vc::bbs_2023::create_derived_proof(derive_opts))
79
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023Derive failed: {e}")))
49
80
  }
50
81
 
51
82
  // ---------------------------------------------------------------------------
@@ -54,18 +85,15 @@ pub fn bbs2023_derive(options: Value) -> napi::Result<Value> {
54
85
 
55
86
  #[napi(js_name = "bbs2023HolderCommit")]
56
87
  pub fn bbs2023_holder_commit(options: Value) -> napi::Result<Value> {
57
- let commit_opts: vc::bbs_2023::HolderCommitOptions = serde_json::from_value(options)
58
- .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit parse options: {e}")))?;
88
+ let commit_opts: vc::bbs_2023::HolderCommitOptions = serde_json::from_value(options)
89
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit parse options: {e}")))?;
59
90
 
60
- let rt = tokio::runtime::Runtime::new()
61
- .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit runtime: {e}")))?;
91
+ let result = bbs_runtime()?
92
+ .block_on(vc::bbs_2023::create_holder_commitment(commit_opts))
93
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit failed: {e}")))?;
62
94
 
63
- let result = rt
64
- .block_on(vc::bbs_2023::create_holder_commitment(commit_opts))
65
- .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit failed: {e}")))?;
66
-
67
- serde_json::to_value(&result)
68
- .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit serialize: {e}")))
95
+ serde_json::to_value(&result)
96
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023HolderCommit serialize: {e}")))
69
97
  }
70
98
 
71
99
  // ---------------------------------------------------------------------------
@@ -74,17 +102,12 @@ pub fn bbs2023_holder_commit(options: Value) -> napi::Result<Value> {
74
102
 
75
103
  #[napi(js_name = "bbs2023BlindSign")]
76
104
  pub fn bbs2023_blind_sign(options: Value) -> napi::Result<Value> {
77
- let blind_opts: vc::bbs_2023::BlindSignOptions = serde_json::from_value(options)
78
- .map_err(|e| napi::Error::from_reason(format!("bbs2023BlindSign parse options: {e}")))?;
79
-
80
- let rt = tokio::runtime::Runtime::new()
81
- .map_err(|e| napi::Error::from_reason(format!("bbs2023BlindSign runtime: {e}")))?;
105
+ let blind_opts: vc::bbs_2023::BlindSignOptions = serde_json::from_value(options)
106
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023BlindSign parse options: {e}")))?;
82
107
 
83
- let result = rt
84
- .block_on(vc::bbs_2023::create_blind_base_proof(blind_opts))
85
- .map_err(|e| napi::Error::from_reason(format!("bbs2023BlindSign failed: {e}")))?;
86
-
87
- Ok(result)
108
+ bbs_runtime()?
109
+ .block_on(vc::bbs_2023::create_blind_base_proof(blind_opts))
110
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023BlindSign failed: {e}")))
88
111
  }
89
112
 
90
113
  // ---------------------------------------------------------------------------
@@ -93,30 +116,27 @@ pub fn bbs2023_blind_sign(options: Value) -> napi::Result<Value> {
93
116
 
94
117
  #[napi(js_name = "bbs2023Verify")]
95
118
  pub fn bbs2023_verify(
96
- document: Value,
97
- public_key: Option<String>,
98
- additional_contexts: Option<Value>,
119
+ document: Value,
120
+ public_key: Option<String>,
121
+ additional_contexts: Option<Value>,
99
122
  ) -> napi::Result<Bbs2023VerifyOutput> {
100
- let rt = tokio::runtime::Runtime::new()
101
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Verify runtime: {e}")))?;
102
-
103
- // LR-3 (issue #107 v1.14.1): caller-registered contexts forwarded to
104
- // canonicalize. Accepts an optional JSON map; absence is treated as
105
- // the empty map (bundled-static loader only).
106
- let extras = additional_contexts
107
- .map(|v| {
108
- serde_json::from_value::<std::collections::HashMap<String, Value>>(v).map_err(|e| {
109
- napi::Error::from_reason(format!("bbs2023Verify parse additional_contexts: {e}"))
110
- })
111
- })
112
- .transpose()?;
113
-
114
- let result = rt
115
- .block_on(vc::bbs_2023::verify_proof(document, public_key, extras))
116
- .map_err(|e| napi::Error::from_reason(format!("bbs2023Verify failed: {e}")))?;
117
-
118
- Ok(Bbs2023VerifyOutput {
119
- verified: result.verified,
120
- error: result.error,
123
+ // LR-3 (issue #107 v1.14.1): caller-registered contexts forwarded to
124
+ // canonicalize. Accepts an optional JSON map; absence is treated as
125
+ // the empty map (bundled-static loader only).
126
+ let extras = additional_contexts
127
+ .map(|v| {
128
+ serde_json::from_value::<std::collections::HashMap<String, Value>>(v).map_err(|e| {
129
+ napi::Error::from_reason(format!("bbs2023Verify parse additional_contexts: {e}"))
130
+ })
121
131
  })
132
+ .transpose()?;
133
+
134
+ let result = bbs_runtime()?
135
+ .block_on(vc::bbs_2023::verify_proof(document, public_key, extras))
136
+ .map_err(|e| napi::Error::from_reason(format!("bbs2023Verify failed: {e}")))?;
137
+
138
+ Ok(Bbs2023VerifyOutput {
139
+ verified: result.verified,
140
+ error: result.error,
141
+ })
122
142
  }