cryptovalid-opencore 0.23.0__py3-none-any.whl
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.
- cldma_confidential.py +255 -0
- committed_attestation.py +487 -0
- conformance.py +90 -0
- cryptovalid_acta.py +1081 -0
- cryptovalid_aps.py +236 -0
- cryptovalid_cedulon.py +461 -0
- cryptovalid_checkpoint.py +511 -0
- cryptovalid_cose_receipts.py +223 -0
- cryptovalid_heterogeneous.py +146 -0
- cryptovalid_ingest.py +606 -0
- cryptovalid_jws.py +154 -0
- cryptovalid_kms.py +920 -0
- cryptovalid_lotl.py +361 -0
- cryptovalid_mcp.py +321 -0
- cryptovalid_merkle.py +207 -0
- cryptovalid_monitor.py +245 -0
- cryptovalid_opencore-0.23.0.dist-info/METADATA +257 -0
- cryptovalid_opencore-0.23.0.dist-info/RECORD +49 -0
- cryptovalid_opencore-0.23.0.dist-info/WHEEL +5 -0
- cryptovalid_opencore-0.23.0.dist-info/entry_points.txt +2 -0
- cryptovalid_opencore-0.23.0.dist-info/licenses/LICENSE +661 -0
- cryptovalid_opencore-0.23.0.dist-info/licenses/NOTICE +45 -0
- cryptovalid_opencore-0.23.0.dist-info/top_level.txt +42 -0
- cryptovalid_pruning_probe.py +126 -0
- cryptovalid_qeas.py +163 -0
- cryptovalid_reanchor.py +107 -0
- cryptovalid_receipt.py +565 -0
- cryptovalid_report.py +467 -0
- cryptovalid_scitt.py +382 -0
- cryptovalid_solana.py +271 -0
- cryptovalid_tip.py +396 -0
- cryptovalid_tsa.py +576 -0
- cryptovalid_vaara_receipt.py +193 -0
- cryptovalid_witness.py +773 -0
- cryptovalid_worm.py +167 -0
- dora_incident.py +218 -0
- ed25519_order.py +111 -0
- eidas_ledger_check.py +290 -0
- evidence_pack.py +654 -0
- fundcert_canonical.py +780 -0
- fundcert_crosssource.py +100 -0
- microfinance.py +205 -0
- mutation_runner.py +187 -0
- pedersen_commit.py +152 -0
- refresh_regulatory.py +114 -0
- signer.py +480 -0
- tx_evidence.py +238 -0
- verifier.py +981 -0
- verify_evidence.py +375 -0
cldma_confidential.py
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
# Copyright (C) 2026 Roberto Locatelli
|
|
3
|
+
"""
|
|
4
|
+
cldma_confidential — PROPOSTA FUTURA additiva: attestazione CLDMA con contributi CONFIDENZIALI.
|
|
5
|
+
|
|
6
|
+
Status: EXPERIMENTAL. Outside the maintained core of cryptovalid-opencore (README, "Core and experimental
|
|
7
|
+
modules"): kept, installed and tested, no new scope is added here.
|
|
8
|
+
|
|
9
|
+
ADDITIVO PER COSTRUZIONE (ordine Roberto 2026-08-22): NON modifica `committed_attestation` ne'
|
|
10
|
+
`pedersen_commit` — li IMPORTA e li COMPONE. Il sistema CLDMA esistente resta identico e funzionante;
|
|
11
|
+
questo e' un layer opt-in, una proposta seria per il post-2030 (auditabilita' privacy-preserving CBDC/RWA),
|
|
12
|
+
non un cambio del prodotto attuale.
|
|
13
|
+
|
|
14
|
+
IDEA: invece dei totali in chiaro di CLDMA, ogni contributo per-record (num_i, den_i della metrica) e'
|
|
15
|
+
impegnato con Pedersen (hiding). La radice Merkle (hash, PQ-safe) lega TUTTI gli impegni -> tamper-evidence;
|
|
16
|
+
la somma OMOMORFICA degli impegni da' i totali impegnati -> il ratio si prova sui totali senza rivelare i
|
|
17
|
+
singoli record. Apertura selettiva del solo TOTALE al regolatore.
|
|
18
|
+
|
|
19
|
+
DIVISIONE ONESTA DEL LAVORO (honest-scope):
|
|
20
|
+
- CONFIDENZIALITA' dei valori per-record: Pedersen hiding = INFO-TEORICO (quantum-safe).
|
|
21
|
+
- TAMPER-EVIDENCE / integrita' di QUALI impegni sono attestati: hash-Merkle = PQ-safe (come CLDMA).
|
|
22
|
+
- BINDING valore<->impegno: DL, NON quantum-safe (un quantistico riapre un impegno). Percio' la garanzia
|
|
23
|
+
forte di integrita' resta hash-based; Pedersen aggiunge PRIVACY. Per l'integrita' PQ a lungo termine si
|
|
24
|
+
compone con un rinnovo hash-based (RFC 4998). NON e' ZK completa.
|
|
25
|
+
- ⚠ LIMITE DI SOUNDNESS DIMOSTRATO (2026-08-22): senza prova di RANGE lo schema NON e' sound contro un
|
|
26
|
+
prover MALEVOLO. Attacco (verificato nel banco): impegnare num_i = q-k ("-k" mod q) SGONFIA il numeratore
|
|
27
|
+
netto (es. reale 100000 + fake (q-100000) => somma = 0 mod q), e l'apertura del solo TOTALE non lo coglie
|
|
28
|
+
(il netto sembra valido). Ogni c_num_i e' un impegno valido, la radice regge => verify_confidential PASSA.
|
|
29
|
+
E' esattamente il motivo per cui esistono le prove di RANGE (Bulletproofs). CONSEGUENZA ONESTA: questo modulo
|
|
30
|
+
e' una PROPOSTA/DIMOSTRAZIONE di PRIVACY, sound solo contro prover ONESTO-ma-curioso; per la sound-ness contro
|
|
31
|
+
prover malevolo serve il layer di range proof (Bulletproofs, pesante, NON arrangiato a mano) O l'apertura
|
|
32
|
+
completa al regolatore (che pero' annulla la privacy). NON spacciarlo per attestazione confidenziale sicura.
|
|
33
|
+
- prova di RANGE in ZK (num_i<=den_i, e non-negativita', senza rivelarli) = layer Bulletproofs -> NON incluso.
|
|
34
|
+
- COMPLETEZZA/TRONCAMENTO (review council 2026-08-22): la radice e' AUTO-REFERENZIALE (verify la ricomputa
|
|
35
|
+
dalle stesse foglie di `att`) -> un prover che tronca/riordina puo' ricomputare la radice e passare. Percio'
|
|
36
|
+
la radice DEVE essere ANCORATA ESTERNAMENTE al momento dell'attestazione (ledger CLDMA / RFC3161 TSA /
|
|
37
|
+
Solana) perche' completezza e non-troncamento contino. Mitigato in parte: indice nella foglia (anti-riordino)
|
|
38
|
+
+ n legato alla radice (cattura n incoerente). La completezza piena resta fuori schema (come CLDMA E4).
|
|
39
|
+
- MITIGAZIONE del range SENZA Bulletproofs (council) -- IMPLEMENTATA: SPOT-CHECK a campione
|
|
40
|
+
(`challenge_indices`/`open_challenged`/`verify_challenged`): il regolatore sfida k foglie (indici da beacon
|
|
41
|
+
= hash(root||nonce) DOPO l'attestazione), il prover le apre, si controlla 0<=num<=den<=MAX_SANE. Coglie il
|
|
42
|
+
-k (q-k >> den) e l'overflow con detection PROBABILISTICA 1-(1-f)^k. Alza la soundness da ZERO a
|
|
43
|
+
probabilistica restando STDLIB e senza ZK. Rivela solo le foglie campionate (privacy ridotta sul campione).
|
|
44
|
+
NB: verifica il RANGE dei contributi; la CLASSIFICAZIONE onesta (che num/den seguano la definizione della
|
|
45
|
+
metrica sul record) richiederebbe di aprire anche il RECORD sfidato (come la challenge piena di CLDMA) = piu'
|
|
46
|
+
privacy spesa -> layer ulteriore, qui non incluso. Le prove di RANGE in ZK (Bulletproofs) restano l'alternativa
|
|
47
|
+
pesante e a zero-privacy-cost, ma NON stdlib e MAI a mano.
|
|
48
|
+
- La guardia `if num<0 raise` in build e' solo HONEST-PATH: un prover malevolo pubblica il dict `att`
|
|
49
|
+
direttamente, non passa da build -> NON e' una difesa (lo dice il council). verify_total_opening ora e'
|
|
50
|
+
SELF-CONTAINED (ricomputa i totali dalle foglie e verifica la radice: non si fida del campo pubblicato).
|
|
51
|
+
|
|
52
|
+
Stdlib puro (riusa gli helper di committed_attestation + pedersen_commit).
|
|
53
|
+
"""
|
|
54
|
+
from __future__ import annotations
|
|
55
|
+
|
|
56
|
+
import sys as _sys_0203
|
|
57
|
+
if __name__ == "__main__": # 0.20.3: run as a command, never write the bytecode cache: CPython 3.9 and 3.11 write
|
|
58
|
+
_sys_0203.dont_write_bytecode = True # a .pyc with one raw write; cut by a file size limit, every later run died (13/10/2026)
|
|
59
|
+
_L0210 = type(__loader__) # 0.21.0: a .pyc already cut (CPython 3.9/3.11 installed one) is compiled from the source
|
|
60
|
+
if _L0210.__name__ == "SourceFileLoader": # instead of failing every later run (EOFError: marshal data too short)
|
|
61
|
+
def _get_code_0210(self, fullname, _get_code=_L0210.get_code):
|
|
62
|
+
try:
|
|
63
|
+
return _get_code(self, fullname)
|
|
64
|
+
except (EOFError, ValueError):
|
|
65
|
+
path = self.get_filename(fullname)
|
|
66
|
+
return self.source_to_code(self.get_data(path), path)
|
|
67
|
+
_L0210.get_code = _get_code_0210
|
|
68
|
+
from typing import Dict, List, Tuple
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
import committed_attestation as _C
|
|
72
|
+
import pedersen_commit as _P
|
|
73
|
+
except ImportError: # importato come opencore.*
|
|
74
|
+
from opencore import committed_attestation as _C
|
|
75
|
+
from opencore import pedersen_commit as _P
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _merkle_root(leaf_hashes: List[str]) -> str:
|
|
79
|
+
"""Radice Merkle hash-only (PQ-safe) sui leaf_hash. Nodo dispari promosso (come CLDMA)."""
|
|
80
|
+
if not leaf_hashes:
|
|
81
|
+
raise ValueError("nessuna foglia")
|
|
82
|
+
cur = list(leaf_hashes)
|
|
83
|
+
while len(cur) > 1:
|
|
84
|
+
nxt = []
|
|
85
|
+
for j in range(0, len(cur), 2):
|
|
86
|
+
if j + 1 < len(cur):
|
|
87
|
+
nxt.append(_C._h(_C._enc("N", cur[j], cur[j + 1])))
|
|
88
|
+
else:
|
|
89
|
+
nxt.append(cur[j])
|
|
90
|
+
cur = nxt
|
|
91
|
+
return cur[0]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _leaf_hash(index: int, record_commit: str, c_num: int, c_den: int) -> str:
|
|
95
|
+
# lega INDICE (anti-riordino, council 2026-08-22) + impegno del record ai suoi impegni di valore -> radice
|
|
96
|
+
return _C._h(_C._enc("CL", index, record_commit, str(c_num), str(c_den)))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _bound_root(inner_root: str, metric_id: str, as_of: str, n: int) -> str:
|
|
100
|
+
# lega metadati + n alla radice pubblicata (come CLDMA _bind_meta). NB: NON prova la COMPLETEZZA da
|
|
101
|
+
# sola (un prover che tronca ricomputa anche n e la radice) -> la radice VA ANCORATA ESTERNAMENTE.
|
|
102
|
+
return _C._h(_C._enc("CLDMA-CONF-1", metric_id, as_of, n, inner_root))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def build_confidential(records: List[Dict], master_salt: str, spec: "_C.MetricSpec",
|
|
106
|
+
as_of: str) -> Tuple[Dict, Dict]:
|
|
107
|
+
"""Costruisce l'attestazione confidenziale. Ritorna (attestation_pubblica, secret_per_il_prover).
|
|
108
|
+
- attestation: radice + per-foglia {record_commit, c_num, c_den} + totali impegnati (nessun valore/record).
|
|
109
|
+
- secret: i randomizer e i valori, che il prover custodisce per aprire il TOTALE al regolatore."""
|
|
110
|
+
leaves_pub, leaf_hashes = [], []
|
|
111
|
+
c_nums, c_dens = [], []
|
|
112
|
+
r_nums, r_dens, nums, dens = [], [], [], []
|
|
113
|
+
for i, rec in enumerate(records):
|
|
114
|
+
num, den = spec.num_of(rec), spec.den_of(rec)
|
|
115
|
+
if num < 0 or den < 0:
|
|
116
|
+
raise ValueError(f"contributo negativo al record {i}")
|
|
117
|
+
salt = _C.leaf_salt(master_salt, i)
|
|
118
|
+
record_commit = _C._h(_C._enc("commit", salt, _C.canonical_record(rec)))
|
|
119
|
+
c_num, r_num = _P.commit(num)
|
|
120
|
+
c_den, r_den = _P.commit(den)
|
|
121
|
+
leaves_pub.append({"record_commit": record_commit, "c_num": c_num, "c_den": c_den})
|
|
122
|
+
leaf_hashes.append(_leaf_hash(i, record_commit, c_num, c_den))
|
|
123
|
+
c_nums.append(c_num); c_dens.append(c_den)
|
|
124
|
+
r_nums.append(r_num); r_dens.append(r_den); nums.append(num); dens.append(den)
|
|
125
|
+
root = _bound_root(_merkle_root(leaf_hashes), spec.metric_id, as_of, len(records))
|
|
126
|
+
C_num_total = _P.add(*c_nums)
|
|
127
|
+
C_den_total = _P.add(*c_dens)
|
|
128
|
+
att = {
|
|
129
|
+
"scheme": "CLDMA-CONFIDENTIAL-1", "metric_id": spec.metric_id, "as_of": as_of,
|
|
130
|
+
"n_records": len(records), "root": root, "leaves": leaves_pub,
|
|
131
|
+
"C_num_total": C_num_total, "C_den_total": C_den_total,
|
|
132
|
+
"num_le_den": getattr(spec, "num_le_den", True),
|
|
133
|
+
}
|
|
134
|
+
secret = {"nums": nums, "dens": dens, "r_nums": r_nums, "r_dens": r_dens}
|
|
135
|
+
return att, secret
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def verify_confidential(att: Dict) -> Dict:
|
|
139
|
+
"""Chiunque, SENZA i record: (1) la radice Merkle si ricostruisce dalle foglie pubblicate
|
|
140
|
+
(tamper-evidence); (2) la somma OMOMORFICA degli impegni per-foglia == totali impegnati pubblicati.
|
|
141
|
+
Prova che i totali impegnati derivano ESATTAMENTE dagli impegni legati alla radice, senza aprirli."""
|
|
142
|
+
reasons: List[str] = []
|
|
143
|
+
leaves = att.get("leaves", [])
|
|
144
|
+
if not leaves:
|
|
145
|
+
return {"ok": False, "reasons": ["nessuna foglia"]}
|
|
146
|
+
if len(leaves) != att.get("n_records"):
|
|
147
|
+
reasons.append(f"n_records dichiarato ({att.get('n_records')}) != foglie ({len(leaves)})")
|
|
148
|
+
lh = [_leaf_hash(i, l["record_commit"], l["c_num"], l["c_den"]) for i, l in enumerate(leaves)]
|
|
149
|
+
root = _bound_root(_merkle_root(lh), att["metric_id"], att["as_of"], len(leaves))
|
|
150
|
+
if root != att["root"]:
|
|
151
|
+
reasons.append("radice non combacia (foglie/impegni/ordine/metadati manomessi). NB: la radice va "
|
|
152
|
+
"ANCORATA ESTERNAMENTE per contare la completezza/troncamento")
|
|
153
|
+
if _P.add(*[l["c_num"] for l in leaves]) != att["C_num_total"]:
|
|
154
|
+
reasons.append("somma omomorfica numeratore != C_num_total")
|
|
155
|
+
if _P.add(*[l["c_den"] for l in leaves]) != att["C_den_total"]:
|
|
156
|
+
reasons.append("somma omomorfica denominatore != C_den_total")
|
|
157
|
+
return {"ok": not reasons, "reasons": reasons, "n": len(leaves)}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def open_totals(att: Dict, secret: Dict) -> Dict:
|
|
161
|
+
"""Il prover apre SOLO i totali (per il regolatore): num_total, den_total e i randomizer sommati.
|
|
162
|
+
Non rivela i singoli record ne' i singoli contributi."""
|
|
163
|
+
num_total = sum(secret["nums"]) % _P.Q
|
|
164
|
+
den_total = sum(secret["dens"]) % _P.Q
|
|
165
|
+
r_num_total = sum(secret["r_nums"]) % _P.Q
|
|
166
|
+
r_den_total = sum(secret["r_dens"]) % _P.Q
|
|
167
|
+
return {"num_total": num_total, "den_total": den_total,
|
|
168
|
+
"r_num_total": r_num_total, "r_den_total": r_den_total}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def verify_total_opening(att: Dict, opening: Dict) -> Dict:
|
|
172
|
+
"""Il regolatore: i totali impegnati aprono ai totali dichiarati, e il ratio e' calcolabile.
|
|
173
|
+
SELF-CONTAINED (fix council 2026-08-22): ricomputa C_num_total/C_den_total DALLE FOGLIE (non si fida del
|
|
174
|
+
campo pubblicato) e prima verifica la coerenza foglie<->radice, cosi' non dipende dall'ordine di chiamata.
|
|
175
|
+
num<=den controllato SUI TOTALI aperti se la metrica e' limitata (guardia che sa fallire)."""
|
|
176
|
+
reasons: List[str] = []
|
|
177
|
+
vc = verify_confidential(att)
|
|
178
|
+
if not vc["ok"]:
|
|
179
|
+
return {"ok": False, "reasons": ["attestazione non coerente: " + "; ".join(vc["reasons"])]}
|
|
180
|
+
C_num = _P.add(*[l["c_num"] for l in att["leaves"]]) # ricomputato dalle foglie legate alla radice
|
|
181
|
+
C_den = _P.add(*[l["c_den"] for l in att["leaves"]])
|
|
182
|
+
if not _P.open_commit(C_num, opening["num_total"], opening["r_num_total"]):
|
|
183
|
+
reasons.append("C_num_total (ricomputato dalle foglie) non apre al num_total dichiarato")
|
|
184
|
+
if not _P.open_commit(C_den, opening["den_total"], opening["r_den_total"]):
|
|
185
|
+
reasons.append("C_den_total (ricomputato dalle foglie) non apre al den_total dichiarato")
|
|
186
|
+
if att.get("num_le_den") and not reasons and opening["num_total"] > opening["den_total"]:
|
|
187
|
+
reasons.append(f"ratio IMPOSSIBILE: num_total {opening['num_total']} > den_total {opening['den_total']}")
|
|
188
|
+
ratio = None
|
|
189
|
+
if not reasons and opening["den_total"]:
|
|
190
|
+
ratio = opening["num_total"] / opening["den_total"]
|
|
191
|
+
return {"ok": not reasons, "reasons": reasons, "ratio": ratio}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# --------------------------------------------------------------------------- #
|
|
195
|
+
# MITIGAZIONE onesta del range SENZA Bulletproofs: SPOT-CHECK a campione (council 2026-08-22)
|
|
196
|
+
# Alza la soundness da ZERO a PROBABILISTICA (detection = 1-(1-f)^k) restando stdlib e senza ZK.
|
|
197
|
+
# Riusa la challenge di CLDMA (indici da beacon pubblico = hash(root||nonce)). NON e' zero-knowledge:
|
|
198
|
+
# rivela i contributi delle SOLE foglie campionate (privacy ridotta sul campione, non azzerata).
|
|
199
|
+
# --------------------------------------------------------------------------- #
|
|
200
|
+
MAX_SANE = 10 ** 18 # limite di sanita' dichiarato (unita' minori): oltre = fuori range (coglie q-k e overflow)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def challenge_indices(att: Dict, nonce: str, k: int) -> List[int]:
|
|
204
|
+
"""k indici da sfidare, deterministici da (radice, nonce). REQUISITO (CLDMA E2): il `nonce` DEVE venire
|
|
205
|
+
dal VERIFICATORE/beacon DOPO l'attestazione, altrimenti il prover lo macina per evitare le foglie barate."""
|
|
206
|
+
return _C.challenge(att["root"], nonce, k, att["n_records"])
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def open_challenged(att: Dict, secret: Dict, indices: List[int]) -> List[Dict]:
|
|
210
|
+
"""Il prover apre SOLO le foglie sfidate (valore + randomizer), non tutte."""
|
|
211
|
+
return [{"index": i, "num": secret["nums"][i], "r_num": secret["r_nums"][i],
|
|
212
|
+
"den": secret["dens"][i], "r_den": secret["r_dens"][i]} for i in indices]
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def verify_challenged(att: Dict, opened: List[Dict]) -> Dict:
|
|
216
|
+
"""Per ogni foglia sfidata: (a) l'apertura combacia con l'impegno pubblicato; (b) RANGE:
|
|
217
|
+
0 <= num <= den <= MAX_SANE (non-negativita' + bound + sanita') -> coglie il -k (q-k e' enorme > den) e
|
|
218
|
+
l'overflow. Se una foglia barata e' campionata, FALLISCE. Honest-scope: detection PROBABILISTICA."""
|
|
219
|
+
reasons: List[str] = []
|
|
220
|
+
if not opened:
|
|
221
|
+
return {"ok": False, "reasons": ["nessuna foglia aperta (challenge vuoto) = assurance nulla"]}
|
|
222
|
+
for o in opened:
|
|
223
|
+
i = o["index"]
|
|
224
|
+
leaf = att["leaves"][i]
|
|
225
|
+
if not _P.open_commit(leaf["c_num"], o["num"], o["r_num"]):
|
|
226
|
+
reasons.append(f"foglia {i}: c_num non apre al valore dichiarato")
|
|
227
|
+
if not _P.open_commit(leaf["c_den"], o["den"], o["r_den"]):
|
|
228
|
+
reasons.append(f"foglia {i}: c_den non apre al valore dichiarato")
|
|
229
|
+
if not (0 <= o["num"] <= o["den"] <= MAX_SANE):
|
|
230
|
+
reasons.append(f"foglia {i}: FUORI RANGE (num={o['num']}, den={o['den']}) -> contributo "
|
|
231
|
+
f"negativo/overflow (attacco -k) o valore assurdo")
|
|
232
|
+
return {"ok": not reasons, "reasons": reasons, "n_checked": len(opened)}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def detection_probability(fraction_bad: float, k: int) -> float:
|
|
236
|
+
"""P(almeno una sfida colpisce una foglia barata) = 1-(1-f)^k. Honest-scope dello spot-check."""
|
|
237
|
+
return _C.detection_probability(fraction_bad, k)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _demo() -> int:
|
|
241
|
+
led = [{"principal_outstanding": "1000.00", "days_overdue": "0", "status": "active"},
|
|
242
|
+
{"principal_outstanding": "500.00", "days_overdue": "45", "status": "active"}]
|
|
243
|
+
att, secret = build_confidential(led, "salt", _C.SPEC_PAR30, "2026-08-22")
|
|
244
|
+
emit("verify_confidential:", verify_confidential(att)["ok"])
|
|
245
|
+
op = open_totals(att, secret)
|
|
246
|
+
emit("verify_total_opening:", verify_total_opening(att, op))
|
|
247
|
+
return 0
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
if __name__ == "__main__": # a demo: its two lines go through the same writer (exit 74 when not written whole)
|
|
251
|
+
try: # 0.20.3: the one writer of every command (verifier.py): an outcome is written whole, or exit 74
|
|
252
|
+
from verifier import emit, receipt_cli
|
|
253
|
+
except ImportError: # python3 -m opencore.<module> from the parent directory
|
|
254
|
+
from opencore.verifier import emit, receipt_cli
|
|
255
|
+
raise SystemExit(receipt_cli(_demo)())
|