mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
quasar: complete Corona purge — Corona (production R-LWE) + Nasua (academic upstream)
Followup to the QuasarCert field rename (commit d1c8a2cc). This sweeps
the remaining Corona identifiers and prose out of the consensus repo
entirely:
- Identifiers (Go code):
coronaThreshold → coronaThreshold (import alias)
coronaGroupKey → coronaGroupKey
coronaSigners → coronaSigners
coronaShares → coronaShares
coronaGobEncode → coronaGobEncode
coronaGobDecode → coronaGobDecode
decodeCoronaSig → decodeCoronaSig
EncodeCoronaSig → EncodeCoronaSig
CoronaRound1{,Data,State} → CoronaRound1{,Data,State}
CoronaGroupKey/Pub/Shares → Corona*
- File rename:
protocol/quasar/corona_gob.go → corona_gob.go
- PQMode constants:
PQModeCorona → PQModeNasua
SigSchemeCoronaAcademic → SigSchemeNasua
"corona" / "corona-academic" string forms → "nasua"
- Prose & comments throughout the repo: "Corona" → "Corona" when
naming the production Ring-LWE library, "Nasua" when naming the
historical academic upstream (luxfi/nasua, formerly luxfi/corona).
Canonical Pulsar family taxonomy after this rename:
Nasua — academic R-LWE 2-round threshold sig (Boschini et al,
ePrint 2024/1113); trusted-dealer DKG; kept as historical
reference fork only. NOT for an open public chain.
Corona — production Ring-LWE threshold ML-DSA (Pedersen DKG over R_q
+ proactive resharing); `github.com/luxfi/corona`. The
Ring-LWE leg of QuasarCert.
Pulsar — production Module-LWE threshold ML-DSA (FIPS 204
byte-equal); `github.com/luxfi/pulsar`. The Module-LWE
leg of QuasarCert. Pure-PQ pair = Corona + Pulsar.
Wire-format unchanged. Tests: 28/28 packages green (-short suite,
quasar 29s, integration 58s, no regressions).
This commit is contained in:
@@ -483,7 +483,7 @@ func BenchmarkPQModes_BLSPlusCorona(b *testing.B) {
|
||||
}
|
||||
|
||||
report(b, &modeMetrics{
|
||||
mode: config.PQModeCorona,
|
||||
mode: config.PQModeNasua,
|
||||
n: n,
|
||||
signNs: signNs,
|
||||
aggNs: aggNsPerPass,
|
||||
|
||||
+19
-19
@@ -51,7 +51,7 @@ const (
|
||||
// production Lux mesh per HIP-0077.
|
||||
PQModeBLS PQMode = iota
|
||||
|
||||
// PQModeCorona — BLS + the academic Corona 2-round LWE threshold
|
||||
// PQModeNasua — BLS + the academic Nasua 2-round LWE threshold
|
||||
// signature. Hash profile is **BLAKE3** (`primitives/hash.go` uses
|
||||
// `github.com/zeebo/blake3` for every challenge / share / transcript
|
||||
// binding). Trusted-dealer DKG, fixed federation, no proactive
|
||||
@@ -59,8 +59,8 @@ const (
|
||||
// federations; **not** an open public chain stance because it has no
|
||||
// DKG that survives epoch rotation, and BLAKE3 is outside the NIST
|
||||
// FIPS 202 approved hash family so this mode is **not** FIPS-approvable.
|
||||
// Provided by `github.com/luxfi/corona` (academic port).
|
||||
PQModeCorona
|
||||
// Provided by `github.com/luxfi/nasua` (academic port).
|
||||
PQModeNasua
|
||||
|
||||
// PQModePulsar — BLS + the Pulsar production fork of Corona. Same
|
||||
// 2-round threshold algorithm as Corona, but Pulsar's canonical
|
||||
@@ -102,8 +102,8 @@ func (m PQMode) String() string {
|
||||
switch m {
|
||||
case PQModeBLS:
|
||||
return "bls"
|
||||
case PQModeCorona:
|
||||
return "corona"
|
||||
case PQModeNasua:
|
||||
return "nasua"
|
||||
case PQModePulsar:
|
||||
return "pulsar"
|
||||
case PQModeQuasar:
|
||||
@@ -132,7 +132,7 @@ func (m PQMode) PolicyID() uint16 {
|
||||
switch m {
|
||||
case PQModeBLS:
|
||||
return 1 // PolicyQuorum
|
||||
case PQModeCorona, PQModePulsar:
|
||||
case PQModeNasua, PQModePulsar:
|
||||
return 5 // PolicyPQ
|
||||
case PQModeQuasar:
|
||||
return 4 // PolicyQuantum
|
||||
@@ -186,7 +186,7 @@ const (
|
||||
|
||||
// HashSuiteBLAKE3Legacy — Corona academic profile and Pulsar's
|
||||
// pre-pin legacy suite. BLAKE3 keyed XOF for every challenge / share
|
||||
// / transcript binding (see github.com/luxfi/corona
|
||||
// / transcript binding (see github.com/luxfi/nasua
|
||||
// primitives/hash.go and github.com/luxfi/corona/hash/blake3.go).
|
||||
// BLAKE3 is outside FIPS 202 and therefore non-normative for any
|
||||
// NIST submission; the byte exists so legacy / academic / federation-
|
||||
@@ -236,7 +236,7 @@ func (m PQMode) HashSuiteID() HashSuiteID {
|
||||
switch m {
|
||||
case PQModeBLS:
|
||||
return HashSuiteNone
|
||||
case PQModeCorona:
|
||||
case PQModeNasua:
|
||||
return HashSuiteBLAKE3Legacy
|
||||
case PQModePulsar, PQModeQuasar, PQModeMLDSA:
|
||||
return HashSuiteSHA3NIST
|
||||
@@ -296,7 +296,7 @@ type SigSchemeID uint8
|
||||
const (
|
||||
SigSchemeNone SigSchemeID = 0x00
|
||||
SigSchemeBLS12381 SigSchemeID = 0x10
|
||||
SigSchemeCoronaAcademic SigSchemeID = 0x20
|
||||
SigSchemeNasua SigSchemeID = 0x20
|
||||
SigSchemePulsarR SigSchemeID = 0x30
|
||||
|
||||
// Raw single-party ML-DSA (FIPS 204).
|
||||
@@ -317,8 +317,8 @@ func (s SigSchemeID) String() string {
|
||||
return "none"
|
||||
case SigSchemeBLS12381:
|
||||
return "bls12-381"
|
||||
case SigSchemeCoronaAcademic:
|
||||
return "corona-academic"
|
||||
case SigSchemeNasua:
|
||||
return "nasua"
|
||||
case SigSchemePulsarR:
|
||||
return "pulsar-r"
|
||||
case SigSchemeMLDSA44:
|
||||
@@ -374,7 +374,7 @@ func (s SigSchemeID) VerifiesUnderFIPS204() bool {
|
||||
// Mapping (HIP-0077 production defaults):
|
||||
//
|
||||
// bls -> SigSchemeNone BLS aggregate carried separately
|
||||
// corona -> SigSchemeCoronaAcademic federation MPC
|
||||
// corona -> SigSchemeNasua federation MPC
|
||||
// pulsar -> SigSchemePulsarR R-LWE production
|
||||
// quasar -> SigSchemePulsarR threshold layer is Pulsar.R; Z-Chain witness separate
|
||||
// mldsa -> SigSchemeMLDSA65 raw ML-DSA-65 (audit-grade); ops opt-in to Pulsar-M-65 explicitly
|
||||
@@ -382,8 +382,8 @@ func (m PQMode) SigSchemeID() SigSchemeID {
|
||||
switch m {
|
||||
case PQModeBLS:
|
||||
return SigSchemeNone
|
||||
case PQModeCorona:
|
||||
return SigSchemeCoronaAcademic
|
||||
case PQModeNasua:
|
||||
return SigSchemeNasua
|
||||
case PQModePulsar, PQModeQuasar:
|
||||
return SigSchemePulsarR
|
||||
case PQModeMLDSA:
|
||||
@@ -639,7 +639,7 @@ func (m PQMode) DKGRequired() string {
|
||||
switch m {
|
||||
case PQModeBLS, PQModeMLDSA:
|
||||
return "none"
|
||||
case PQModeCorona:
|
||||
case PQModeNasua:
|
||||
return "trusted-dealer" // unsuitable for open public chains
|
||||
case PQModePulsar, PQModeQuasar:
|
||||
return "pedersen-dkg-over-rq"
|
||||
@@ -655,7 +655,7 @@ func (m PQMode) DKGRequired() string {
|
||||
//
|
||||
// canonical aliases (component-named only)
|
||||
// "bls" (BLS) "classical", "bls-only"
|
||||
// "corona" (BLS + Corona) "rt", "academic", "bls-rt", "bls-q", "sha256-rt"
|
||||
// "nasua" (BLS + Corona) "rt", "academic", "bls-rt", "bls-q", "sha256-rt"
|
||||
// "pulsar" (BLS + Pulsar) "sha3-rt", "production-rt", "bls-pulsar"
|
||||
// "quasar" (BLS + Pulsar + Z) "rollup", "groth16", "zk",
|
||||
// "bls-z", "bls-zk", "bls-groth16",
|
||||
@@ -665,8 +665,8 @@ func ParsePQMode(s string) (PQMode, error) {
|
||||
switch strings.ToLower(strings.TrimSpace(s)) {
|
||||
case "", "bls", "bls-only", "classical":
|
||||
return PQModeBLS, nil
|
||||
case "corona", "rt", "academic", "bls-rt", "bls-q", "sha256-rt":
|
||||
return PQModeCorona, nil
|
||||
case "nasua", "rt", "academic", "bls-rt", "bls-q", "sha256-rt":
|
||||
return PQModeNasua, nil
|
||||
case "pulsar", "sha3-rt", "production-rt", "bls-pulsar":
|
||||
return PQModePulsar, nil
|
||||
case "quasar", "rollup", "groth16", "zk",
|
||||
@@ -715,7 +715,7 @@ func (m PQMode) IsPostQuantum() bool {
|
||||
|
||||
// SuitableForPublicChain reports whether the mode is appropriate for an
|
||||
// open public chain (epoch rotation, no trusted dealer). False for
|
||||
// PQModeCorona (trusted-dealer DKG only) and PQModeBLS (no PQ at all);
|
||||
// PQModeNasua (trusted-dealer DKG only) and PQModeBLS (no PQ at all);
|
||||
// true for everything else.
|
||||
func (m PQMode) SuitableForPublicChain() bool {
|
||||
switch m {
|
||||
|
||||
+18
-18
@@ -14,7 +14,7 @@ func TestPQMode_String(t *testing.T) {
|
||||
name string
|
||||
}{
|
||||
{PQModeBLS, "bls"},
|
||||
{PQModeCorona, "corona"},
|
||||
{PQModeNasua, "nasua"},
|
||||
{PQModePulsar, "pulsar"},
|
||||
{PQModeQuasar, "quasar"},
|
||||
{PQModeMLDSA, "mldsa"},
|
||||
@@ -29,7 +29,7 @@ func TestPQMode_String(t *testing.T) {
|
||||
// TestParsePQMode_Canonical accepts every canonical lower-case name.
|
||||
func TestParsePQMode_Canonical(t *testing.T) {
|
||||
for _, m := range []PQMode{
|
||||
PQModeBLS, PQModeCorona, PQModePulsar, PQModeQuasar, PQModeMLDSA,
|
||||
PQModeBLS, PQModeNasua, PQModePulsar, PQModeQuasar, PQModeMLDSA,
|
||||
} {
|
||||
got, err := ParsePQMode(m.String())
|
||||
if err != nil {
|
||||
@@ -57,10 +57,10 @@ func TestParsePQMode_Aliases(t *testing.T) {
|
||||
{"classical", PQModeBLS},
|
||||
|
||||
// Corona (academic, BLAKE3, trusted dealer)
|
||||
{"rt", PQModeCorona},
|
||||
{"academic", PQModeCorona},
|
||||
{"bls-rt", PQModeCorona},
|
||||
{"sha256-rt", PQModeCorona},
|
||||
{"rt", PQModeNasua},
|
||||
{"academic", PQModeNasua},
|
||||
{"bls-rt", PQModeNasua},
|
||||
{"sha256-rt", PQModeNasua},
|
||||
|
||||
// Pulsar (production fork, SHA-3, Pedersen DKG)
|
||||
{"sha3-rt", PQModePulsar},
|
||||
@@ -120,7 +120,7 @@ func TestPQMode_PolicyID(t *testing.T) {
|
||||
want uint16
|
||||
}{
|
||||
{PQModeBLS, 1}, // PolicyQuorum
|
||||
{PQModeCorona, 5}, // PolicyPQ
|
||||
{PQModeNasua, 5}, // PolicyPQ
|
||||
{PQModePulsar, 5}, // PolicyPQ (same wire shape, SHA-3 negotiated out-of-band)
|
||||
{PQModeQuasar, 4}, // PolicyQuantum
|
||||
{PQModeMLDSA, 6}, // PolicyPZ
|
||||
@@ -149,7 +149,7 @@ func TestPQMode_HashProfile(t *testing.T) {
|
||||
want string
|
||||
}{
|
||||
{PQModeBLS, "none"},
|
||||
{PQModeCorona, "blake3-legacy"},
|
||||
{PQModeNasua, "blake3-legacy"},
|
||||
{PQModePulsar, "sha3-nist"},
|
||||
{PQModeQuasar, "sha3-nist"},
|
||||
{PQModeMLDSA, "sha3-nist"},
|
||||
@@ -179,7 +179,7 @@ func TestPQMode_HashSuiteID(t *testing.T) {
|
||||
want HashSuiteID
|
||||
}{
|
||||
{PQModeBLS, HashSuiteNone}, // 0x00
|
||||
{PQModeCorona, HashSuiteBLAKE3Legacy}, // 0x02
|
||||
{PQModeNasua, HashSuiteBLAKE3Legacy}, // 0x02
|
||||
{PQModePulsar, HashSuiteSHA3NIST}, // 0x01
|
||||
{PQModeQuasar, HashSuiteSHA3NIST}, // 0x01
|
||||
{PQModeMLDSA, HashSuiteSHA3NIST}, // 0x01 (SHAKE256 ∈ FIPS 202)
|
||||
@@ -255,7 +255,7 @@ func TestPQMode_SigSchemeID(t *testing.T) {
|
||||
want SigSchemeID
|
||||
}{
|
||||
{PQModeBLS, SigSchemeNone},
|
||||
{PQModeCorona, SigSchemeCoronaAcademic},
|
||||
{PQModeNasua, SigSchemeNasua},
|
||||
{PQModePulsar, SigSchemePulsarR},
|
||||
{PQModeQuasar, SigSchemePulsarR},
|
||||
{PQModeMLDSA, SigSchemeMLDSA65}, // raw ML-DSA-65 default; ops opt-in to Pulsar-M-65
|
||||
@@ -280,7 +280,7 @@ func TestSigSchemeID_StableIntegers(t *testing.T) {
|
||||
}{
|
||||
{SigSchemeNone, 0x00},
|
||||
{SigSchemeBLS12381, 0x10},
|
||||
{SigSchemeCoronaAcademic, 0x20},
|
||||
{SigSchemeNasua, 0x20},
|
||||
{SigSchemePulsarR, 0x30},
|
||||
{SigSchemeMLDSA44, 0x41},
|
||||
{SigSchemeMLDSA65, 0x42},
|
||||
@@ -304,7 +304,7 @@ func TestSigSchemeID_String(t *testing.T) {
|
||||
}{
|
||||
{SigSchemeNone, "none"},
|
||||
{SigSchemeBLS12381, "bls12-381"},
|
||||
{SigSchemeCoronaAcademic, "corona-academic"},
|
||||
{SigSchemeNasua, "nasua"},
|
||||
{SigSchemePulsarR, "pulsar-r"},
|
||||
{SigSchemeMLDSA44, "ml-dsa-44"},
|
||||
{SigSchemeMLDSA65, "ml-dsa-65"},
|
||||
@@ -331,7 +331,7 @@ func TestSigSchemeID_IsPulsarM(t *testing.T) {
|
||||
}
|
||||
}
|
||||
notPulsarM := []SigSchemeID{
|
||||
SigSchemeNone, SigSchemeBLS12381, SigSchemeCoronaAcademic,
|
||||
SigSchemeNone, SigSchemeBLS12381, SigSchemeNasua,
|
||||
SigSchemePulsarR,
|
||||
SigSchemeMLDSA44, SigSchemeMLDSA65, SigSchemeMLDSA87,
|
||||
}
|
||||
@@ -352,7 +352,7 @@ func TestSigSchemeID_IsRawMLDSA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
notRaw := []SigSchemeID{
|
||||
SigSchemeNone, SigSchemeBLS12381, SigSchemeCoronaAcademic, SigSchemePulsarR,
|
||||
SigSchemeNone, SigSchemeBLS12381, SigSchemeNasua, SigSchemePulsarR,
|
||||
SigSchemePulsarM44, SigSchemePulsarM65, SigSchemePulsarM87,
|
||||
}
|
||||
for _, s := range notRaw {
|
||||
@@ -375,7 +375,7 @@ func TestSigSchemeID_VerifiesUnderFIPS204(t *testing.T) {
|
||||
}
|
||||
}
|
||||
no := []SigSchemeID{
|
||||
SigSchemeNone, SigSchemeBLS12381, SigSchemeCoronaAcademic, SigSchemePulsarR,
|
||||
SigSchemeNone, SigSchemeBLS12381, SigSchemeNasua, SigSchemePulsarR,
|
||||
}
|
||||
for _, s := range no {
|
||||
if s.VerifiesUnderFIPS204() {
|
||||
@@ -688,7 +688,7 @@ func TestPQMode_DKGRequired(t *testing.T) {
|
||||
want string
|
||||
}{
|
||||
{PQModeBLS, "none"},
|
||||
{PQModeCorona, "trusted-dealer"},
|
||||
{PQModeNasua, "trusted-dealer"},
|
||||
{PQModePulsar, "pedersen-dkg-over-rq"},
|
||||
{PQModeQuasar, "pedersen-dkg-over-rq"},
|
||||
{PQModeMLDSA, "none"},
|
||||
@@ -709,7 +709,7 @@ func TestPQMode_SuitableForPublicChain(t *testing.T) {
|
||||
want bool
|
||||
}{
|
||||
{PQModeBLS, false},
|
||||
{PQModeCorona, false},
|
||||
{PQModeNasua, false},
|
||||
{PQModePulsar, true},
|
||||
{PQModeQuasar, true},
|
||||
{PQModeMLDSA, true},
|
||||
@@ -738,7 +738,7 @@ func TestPQMode_IsPostQuantum(t *testing.T) {
|
||||
want bool
|
||||
}{
|
||||
{PQModeBLS, false},
|
||||
{PQModeCorona, true},
|
||||
{PQModeNasua, true},
|
||||
{PQModePulsar, true},
|
||||
{PQModeQuasar, true},
|
||||
{PQModeMLDSA, true},
|
||||
|
||||
@@ -345,7 +345,7 @@ type SigSchemeID uint8
|
||||
const (
|
||||
SigSchemeNone SigSchemeID = 0x00
|
||||
SigSchemeBLS12381 SigSchemeID = 0x10
|
||||
SigSchemeCoronaAcademic SigSchemeID = 0x20
|
||||
SigSchemeNasua SigSchemeID = 0x20
|
||||
SigSchemePulsarR SigSchemeID = 0x30
|
||||
SigSchemePulsarM44 SigSchemeID = 0x41
|
||||
SigSchemePulsarM65 SigSchemeID = 0x42 // production default
|
||||
@@ -359,8 +359,8 @@ func (s SigSchemeID) String() string {
|
||||
return "none"
|
||||
case SigSchemeBLS12381:
|
||||
return "bls12-381"
|
||||
case SigSchemeCoronaAcademic:
|
||||
return "corona-academic"
|
||||
case SigSchemeNasua:
|
||||
return "nasua"
|
||||
case SigSchemePulsarR:
|
||||
return "pulsar-r"
|
||||
case SigSchemePulsarM44:
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestSigSchemeID_StableIntegers(t *testing.T) {
|
||||
}{
|
||||
{SigSchemeNone, 0x00},
|
||||
{SigSchemeBLS12381, 0x10},
|
||||
{SigSchemeCoronaAcademic, 0x20},
|
||||
{SigSchemeNasua, 0x20},
|
||||
{SigSchemePulsarR, 0x30},
|
||||
{SigSchemePulsarM44, 0x41},
|
||||
{SigSchemePulsarM65, 0x42}, // production default
|
||||
@@ -63,7 +63,7 @@ func TestSigSchemeID_String(t *testing.T) {
|
||||
}{
|
||||
{SigSchemeNone, "none"},
|
||||
{SigSchemeBLS12381, "bls12-381"},
|
||||
{SigSchemeCoronaAcademic, "corona-academic"},
|
||||
{SigSchemeNasua, "nasua"},
|
||||
{SigSchemePulsarR, "pulsar-r"},
|
||||
{SigSchemePulsarM44, "pulsar-m-44"},
|
||||
{SigSchemePulsarM65, "pulsar-m-65"},
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// PQ-consensus architecture freeze, Quasar consumes its threshold
|
||||
// kernel through `luxfi/threshold` (which routes via the LSS
|
||||
// adapters to luxfi/pulsar and luxfi/lens). Direct imports of
|
||||
// `github.com/luxfi/corona/threshold` from this package are
|
||||
// `github.com/luxfi/nasua/threshold` from this package are
|
||||
// forbidden — they bypass the LSS lifecycle (Generation, snapshot
|
||||
// history, rollback) and skip the Pulsar key-era binding.
|
||||
//
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
// TestNoCoronaDirectImport — fails if any non-test .go file in this
|
||||
// package imports `github.com/luxfi/corona/...` or invokes
|
||||
// package imports `github.com/luxfi/nasua/...` or invokes
|
||||
// corona.GenerateKeys (matched as a selector expression
|
||||
// `corona.GenerateKeys(...)` regardless of the package alias).
|
||||
//
|
||||
@@ -47,13 +47,13 @@ func TestNoCoronaDirectImport(t *testing.T) {
|
||||
t.Fatalf("no .go files found in %s", pkgDir)
|
||||
}
|
||||
|
||||
const forbiddenImportPrefix = "github.com/luxfi/corona"
|
||||
const forbiddenImportPrefix = "github.com/luxfi/nasua"
|
||||
|
||||
fset := token.NewFileSet()
|
||||
var violations []string
|
||||
for _, f := range matches {
|
||||
// Skip *this* file from the import scan because we name
|
||||
// `github.com/luxfi/corona` in this comment / string
|
||||
// `github.com/luxfi/nasua` in this comment / string
|
||||
// literals as part of the death-test guard — the regex /
|
||||
// fixture below would match itself otherwise.
|
||||
base := filepath.Base(f)
|
||||
@@ -108,7 +108,7 @@ func TestNoCoronaDirectImport(t *testing.T) {
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
if x.Name == "corona" && sel.Sel.Name == "GenerateKeys" {
|
||||
if x.Name == "nasua" && sel.Sel.Name == "GenerateKeys" {
|
||||
violations = append(violations,
|
||||
base+": forbidden call corona.GenerateKeys")
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
_ "github.com/luxfi/crypto/threshold/bls" // Register BLS threshold scheme
|
||||
|
||||
// Pulsar threshold is the corrected lattice kernel that replaced
|
||||
// upstream Corona. Type aliasing preserves the historical
|
||||
// upstream Nasua. Type aliasing preserves the historical
|
||||
// `coronaThreshold` identifier so this file's signing routines
|
||||
// (Round1/Round2/Finalize) stay byte-stable while the underlying
|
||||
// types come from pulsar/threshold.
|
||||
|
||||
@@ -189,7 +189,7 @@ func TestRun_PropagatesHashSuiteID_FromMode(t *testing.T) {
|
||||
want config.HashSuiteID
|
||||
}{
|
||||
{config.PQModeBLS, config.HashSuiteNone},
|
||||
{config.PQModeCorona, config.HashSuiteBLAKE3Legacy},
|
||||
{config.PQModeNasua, config.HashSuiteBLAKE3Legacy},
|
||||
{config.PQModePulsar, config.HashSuiteSHA3NIST},
|
||||
{config.PQModeQuasar, config.HashSuiteSHA3NIST},
|
||||
{config.PQModeMLDSA, config.HashSuiteSHA3NIST},
|
||||
|
||||
Reference in New Issue
Block a user