LightRiderInc commited on
Commit
dfdb85f
·
verified ·
1 Parent(s): 907314b

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +45 -45
  2. app.py +5 -2
  3. lr_entropy_api.py +10 -1
README.md CHANGED
@@ -1,45 +1,45 @@
1
- ---
2
- title: Light Rider Quantum Entropy
3
- emoji: ⚛️
4
- colorFrom: red
5
- colorTo: yellow
6
- sdk: gradio
7
- sdk_version: 6.30.0
8
- app_file: app.py
9
- pinned: false
10
- license: apache-2.0
11
- short_description: Entropy from named quantum sources, with signed receipts
12
- ---
13
-
14
- # Light Rider Quantum Entropy
15
-
16
- Draw random bytes from **named quantum sources** (quantum random number generators
17
- and quantum processors). Every draw comes with a **receipt signed by the Light Rider
18
- Entropy Management Service (EMS)**: it records which source produced the bytes, how
19
- they were health-checked and when. The app verifies the receipt's Ed25519 signature
20
- against EMS's published key and shows the result.
21
-
22
- This is an alternative entropy source with verifiable provenance. It is not a claim
23
- that quantum randomness is better than a good classical generator. If a source can't
24
- serve, you'll see why. Nothing is ever substituted, and nothing is generated locally.
25
-
26
- ## Use it from your code
27
-
28
- ```python
29
- import lightrider as lr # pip install lightrider (1.6.0+), export LR_API_KEY=lr_live_...
30
- r = lr.entropy.get(32, source="anu_aws_001") # or sources=["anu_aws_001", "cisco_qrng_001"]
31
- print(r.hex, r.request_id, r.sources)
32
- assert lr.entropy.verify(r.receipt)
33
- seed = lr.entropy.seed(64) # int seed for numpy / torch
34
- ```
35
-
36
- Get your Light Rider API key from Light Rider Cloud (Settings → API Keys). It is a
37
- full-access account key: keep it out of public code and store it as a Space secret.
38
-
39
- ## Space configuration
40
-
41
- Secrets: `LR_API_KEY` (demo account key), `LR_ENTROPY_BASE_URL`, and
42
- `LR_VERCEL_BYPASS` (only while pointing at a protected preview deployment).
43
-
44
- Optional variables: `DEMO_PER_VISITOR_DAILY` (default 5), `DEMO_GLOBAL_DAILY`
45
- (default 200), `LR_PUBLIC_SITE_URL`, `LR_CLOUD_KEYS_URL`.
 
1
+ ---
2
+ title: Light Rider Quantum Entropy
3
+ emoji: ⚛️
4
+ colorFrom: red
5
+ colorTo: yellow
6
+ sdk: gradio
7
+ sdk_version: 6.30.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: apache-2.0
11
+ short_description: Entropy from named quantum sources, with signed receipts
12
+ ---
13
+
14
+ # Light Rider Quantum Entropy
15
+
16
+ Draw random bytes from **named quantum sources** (quantum random number generators
17
+ and quantum processors). Every draw comes with a **receipt signed by the Light Rider
18
+ Entropy Management Service (EMS)**: it records which source produced the bytes, how
19
+ they were health-checked and when. The app verifies the receipt's Ed25519 signature
20
+ against EMS's published key and shows the result.
21
+
22
+ This is an alternative entropy source with verifiable provenance. It is not a claim
23
+ that quantum randomness is better than a good classical generator. If a source can't
24
+ serve, you'll see why. Nothing is ever substituted, and nothing is generated locally.
25
+
26
+ ## Use it from your code
27
+
28
+ ```python
29
+ import lightrider as lr # pip install lightrider (1.6.0+), export LR_API_KEY=lr_live_...
30
+ r = lr.entropy.get(16, source="anu") # or sources=["anu", "cisco"]
31
+ print(r.hex, r.request_id, r.sources)
32
+ assert lr.entropy.verify(r.receipt)
33
+ seed = lr.entropy.seed(64) # int seed for numpy / torch
34
+ ```
35
+
36
+ Get your Light Rider API key from Light Rider Cloud (Settings → API Keys). It is a
37
+ full-access account key: keep it out of public code and store it as a Space secret.
38
+
39
+ ## Space configuration
40
+
41
+ Secrets: `LR_API_KEY` (demo account key), `LR_ENTROPY_BASE_URL`, and
42
+ `LR_VERCEL_BYPASS` (only while pointing at a protected preview deployment).
43
+
44
+ Optional variables: `DEMO_PER_VISITOR_DAILY` (default 5), `DEMO_GLOBAL_DAILY`
45
+ (default 200), `LR_PUBLIC_SITE_URL`, `LR_CLOUD_KEYS_URL`.
app.py CHANGED
@@ -115,7 +115,8 @@ def visitor_id(request: gr.Request | None) -> str:
115
 
116
  def _label(s: lre.Source) -> str:
117
  state = f"{s.bytes_available:,} B on hand" if s.ready else "out of entropy, refill pending"
118
- return f"{s.name} · {s.type} · {state}"
 
119
 
120
 
121
  def load_sources():
@@ -251,12 +252,14 @@ export LR_API_KEY=lr_live_... # your Light Rider API key
251
  ```python
252
  import lightrider as lr
253
 
254
- r = lr.entropy.get(32, source="anu_aws_001") # or sources=["anu_aws_001", "cisco_qrng_001"]
255
  print(r.hex, r.request_id, r.sources)
256
  assert lr.entropy.verify(r.receipt) # Ed25519 against EMS's published key
257
  seed = lr.entropy.seed(64) # int seed for numpy / torch
258
  ```
259
 
 
 
260
  - **Get your key:** [Light Rider Cloud → API Keys]({CLOUD_KEYS_URL}). It is your account's full-access key, so keep it
261
  out of public code and Spaces (store it as a Space secret).
262
  - **Docs and the HTTP API:** [{PUBLIC_SITE}/developers]({PUBLIC_SITE}/developers)
 
115
 
116
  def _label(s: lre.Source) -> str:
117
  state = f"{s.bytes_available:,} B on hand" if s.ready else "out of entropy, refill pending"
118
+ name = f"{s.name} ({s.alias})" if s.alias else s.name
119
+ return f"{name} · {s.type} · {state}"
120
 
121
 
122
  def load_sources():
 
252
  ```python
253
  import lightrider as lr
254
 
255
+ r = lr.entropy.get(16, source="anu") # or sources=["anu", "cisco"]
256
  print(r.hex, r.request_id, r.sources)
257
  assert lr.entropy.verify(r.receipt) # Ed25519 against EMS's published key
258
  seed = lr.entropy.seed(64) # int seed for numpy / torch
259
  ```
260
 
261
+ - **Sources** by short name: `anu`, `cisco`, `qispace`, `rigetti`, `iqm`, `iqm-qec` (or the full id);
262
+ `lr.entropy.sources()` lists what's ready now. Receipts always record the full id.
263
  - **Get your key:** [Light Rider Cloud → API Keys]({CLOUD_KEYS_URL}). It is your account's full-access key, so keep it
264
  out of public code and Spaces (store it as a Space secret).
265
  - **Docs and the HTTP API:** [{PUBLIC_SITE}/developers]({PUBLIC_SITE}/developers)
lr_entropy_api.py CHANGED
@@ -10,7 +10,7 @@ Quantum entropy with signed provenance, billed to your Light Rider credits:
10
 
11
  import lightrider as lr
12
 
13
- r = lr.entropy.get(32, source="anu_aws_001") # LR_API_KEY in the environment
14
  r.data, r.hex, r.request_id # the bytes and their receipt id
15
  lr.entropy.verify(r.receipt) # True: EMS signed exactly this
16
 
@@ -209,6 +209,8 @@ class Source:
209
  max_single_draw_bytes: int
210
  custom_pool_selectable: bool
211
  custom_pool_reason: str | None
 
 
212
  raw: dict = field(repr=False, default_factory=dict)
213
 
214
  @property
@@ -358,6 +360,7 @@ class EntropyAPI:
358
  max_single_draw_bytes=int(s.get("max_single_draw_bytes", 0)),
359
  custom_pool_selectable=bool((s.get("custom_pool") or {}).get("selectable", False)),
360
  custom_pool_reason=(s.get("custom_pool") or {}).get("reason"),
 
361
  raw=s,
362
  )
363
  for s in body.get("sources", [])
@@ -374,6 +377,12 @@ class EntropyAPI:
374
  """Draw ``n_bytes`` (1-4096) from one source (``source=``) or a custom
375
  pool of 2-8 sources (``sources=[...]``).
376
 
 
 
 
 
 
 
377
  With neither, uses ``default_source`` / ``LR_ENTROPY_SOURCE``, else the
378
  first source that is ready right now (the receipt says which).
379
  Raises :class:`SourceEmptyError` rather than ever substituting.
 
10
 
11
  import lightrider as lr
12
 
13
+ r = lr.entropy.get(16, source="anu") # LR_API_KEY in the environment
14
  r.data, r.hex, r.request_id # the bytes and their receipt id
15
  lr.entropy.verify(r.receipt) # True: EMS signed exactly this
16
 
 
209
  max_single_draw_bytes: int
210
  custom_pool_selectable: bool
211
  custom_pool_reason: str | None
212
+ #: Short name usable as ``source=`` / in ``sources=`` (e.g. ``"anu"``).
213
+ alias: str | None = None
214
  raw: dict = field(repr=False, default_factory=dict)
215
 
216
  @property
 
360
  max_single_draw_bytes=int(s.get("max_single_draw_bytes", 0)),
361
  custom_pool_selectable=bool((s.get("custom_pool") or {}).get("selectable", False)),
362
  custom_pool_reason=(s.get("custom_pool") or {}).get("reason"),
363
+ alias=s.get("alias"),
364
  raw=s,
365
  )
366
  for s in body.get("sources", [])
 
377
  """Draw ``n_bytes`` (1-4096) from one source (``source=``) or a custom
378
  pool of 2-8 sources (``sources=[...]``).
379
 
380
+ Name sources by alias (``"anu"``, ``"cisco"``, ...; see
381
+ :meth:`sources`) or full id (``"anu_aws_001"``). Names are passed to
382
+ the service as given and resolved there, so new sources need no SDK
383
+ update; an unknown name raises :class:`InvalidRequestError` listing
384
+ the valid ones. Receipts always carry the full id.
385
+
386
  With neither, uses ``default_source`` / ``LR_ENTROPY_SOURCE``, else the
387
  first source that is ready right now (the receipt says which).
388
  Raises :class:`SourceEmptyError` rather than ever substituting.