pulsar: drop -M qualifier everywhere — Pulsar (M-LWE) is the family name

Symmetric with Corona's parallel rename (PULSAR-* -> CORONA-* in
luxfi/corona). The -M was the M-LWE qualifier from when Pulsar-M and
Pulsar-R were sibling constructions; Pulsar-R shipped as Corona, so
the -M qualifier is dead weight across the family.

Changes:
  - spec/pulsar.tex: prose + tag strings PULSAR-M-* -> PULSAR-*
  - ref/go: all "Pulsar-M" string literals -> "Pulsar" in mode names,
    KAT message prefixes, and beacon strings (PULSAR-M-RESHARE-BEACON
    -> PULSAR-RESHARE-BEACON, etc.)
  - vectors/{sign,keygen,verify,threshold-sign,dkg}.json: regenerated
    from genkat with new mode strings

Preserved (different scope):
  - Go package directory name `pkg/pulsarm/` (renaming the dir is a
    Go module break for any importer; punted to a separate cleanup)
  - luxcpp/crypto/pulsar/ path references in comments (separate repo)

All 9 test packages pass: pulsarm (KAT replay, large e2e, reshare,
shamir, types) + the rest.
This commit is contained in:
2026-05-13 14:21:45 -07:00
parent ea0d8cb32c
commit d7dc75411e
29 changed files with 227 additions and 227 deletions
+5 -5
View File
@@ -2,7 +2,7 @@
// See the file LICENSE for licensing terms.
// genkat is the canonical KAT (Known Answer Test) generator for
// Pulsar-M. It produces the JSON vector files committed under
// Pulsar. It produces the JSON vector files committed under
// vectors/ — keygen, sign, verify, threshold-sign, dkg.
//
// Re-running genkat on a clean checkout MUST produce byte-identical
@@ -155,7 +155,7 @@ func main() {
var seed [pm.SeedSize]byte
_, _ = seedReader.Read(seed[:])
sk, _ := pm.KeyFromSeed(params, seed)
msg := []byte(fmt.Sprintf("Pulsar-M KAT message %s #%d", mode.String(), i))
msg := []byte(fmt.Sprintf("Pulsar KAT message %s #%d", mode.String(), i))
sig, err := pm.Sign(params, sk, msg, nil, false, nil)
if err != nil {
fail(err)
@@ -181,7 +181,7 @@ func main() {
var seed [pm.SeedSize]byte
_, _ = seedReader.Read(seed[:])
sk, _ := pm.KeyFromSeed(params, seed)
msg := []byte(fmt.Sprintf("Pulsar-M Verify KAT %s", mode.String()))
msg := []byte(fmt.Sprintf("Pulsar Verify KAT %s", mode.String()))
sig, _ := pm.Sign(params, sk, msg, nil, false, nil)
verifyKATs = append(verifyKATs, VerifyKAT{
Mode: mode.String(),
@@ -213,7 +213,7 @@ func main() {
params := pm.MustParamsFor(mode)
committee := makeKATCommittee(tc.N)
pub, shares, _ := runKATDKG(params, committee, tc.T, mode)
msg := []byte(fmt.Sprintf("Pulsar-M Threshold KAT %s n=%d t=%d", mode.String(), tc.N, tc.T))
msg := []byte(fmt.Sprintf("Pulsar Threshold KAT %s n=%d t=%d", mode.String(), tc.N, tc.T))
quorum := make([]pm.NodeID, tc.T)
for i := 0; i < tc.T; i++ {
quorum[i] = shares[i].NodeID
@@ -306,7 +306,7 @@ func runKATDKG(params *pm.Params, committee []pm.NodeID, threshold int, mode pm.
sessions := make([]*pm.DKGSession, n)
for i := range sessions {
// Deterministic per-party seed.
seedTag := append([]byte("PULSAR-M-DKG-KAT-V1"), []byte{byte(mode), byte(n), byte(threshold), byte(i)}...)
seedTag := append([]byte("PULSAR-DKG-KAT-V1"), []byte{byte(mode), byte(n), byte(threshold), byte(i)}...)
rng := newDetReader(seedTag)
s, _ := pm.NewDKGSession(params, committee, threshold, committee[i], rng)
sessions[i] = s
+1 -1
View File
@@ -10,7 +10,7 @@ package pulsarm
// complaints; a quorum of distinct accusers against the same accused
// is a disqualification event.
//
// pulsar-m.tex §4.5 enumerates the complaint taxonomy. This file
// pulsar.tex §4.5 enumerates the complaint taxonomy. This file
// gives the canonical wire format and the verification routines that
// any third party (chain validator, audit observer, slashing module)
// uses to check a complaint is well-formed.
+1 -1
View File
@@ -23,7 +23,7 @@ package pulsarm
//
// which is binding under collision resistance and hiding under
// uniformity of blind_i. The v0.2 path replaces this with R_q^k
// Pedersen per pulsar-m.tex §3.2 + §4.1 to obtain the same
// Pedersen per pulsar.tex §3.2 + §4.1 to obtain the same
// guarantees under M-LWE hardness (a stronger PQ-safe binding
// argument). Both targets are Class N4-eligible.
//
+1 -1
View File
@@ -255,7 +255,7 @@ func (r *detReader) Read(p []byte) (int, error) {
if r.off >= len(r.buf) {
// Generate a new chunk.
input := append(append([]byte{}, r.seed...), byte(r.off>>16), byte(r.off>>8), byte(r.off))
r.buf = cshake256(input, 4096, "PULSAR-M-TESTRAND-V1")
r.buf = cshake256(input, 4096, "PULSAR-TESTRAND-V1")
r.off = 0
}
copied := copy(p[n:], r.buf[r.off:])
+2 -2
View File
@@ -1,8 +1,8 @@
// Package pulsarm is the reference implementation of Pulsar-M, a threshold
// Package pulsarm is the reference implementation of Pulsar, a threshold
// implementation of NIST FIPS 204 ML-DSA targeting NIST MPTC Class N1
// (signing) + N4 (ML keygen / DKG).
//
// The headline claim of Pulsar-M is output interchangeability with FIPS 204:
// The headline claim of Pulsar is output interchangeability with FIPS 204:
// a signature produced by an n-of-t threshold ceremony verifies under
// unmodified FIPS 204 ML-DSA.Verify(pk, message, signature). See
// spec/nist-mptc-category.tex for the formal claim and its scope.
+3 -3
View File
@@ -233,11 +233,11 @@ func TestKAT_DKG_Replay(t *testing.T) {
func modeFromString(s string) Mode {
switch s {
case "Pulsar-M-44":
case "Pulsar-44":
return ModeP44
case "Pulsar-M-65":
case "Pulsar-65":
return ModeP65
case "Pulsar-M-87":
case "Pulsar-87":
return ModeP87
default:
return ModeUnspecified
+2 -2
View File
@@ -31,7 +31,7 @@ var (
ErrInvalidPriv = errors.New("pulsarm: invalid private-key length")
)
// GenerateKey produces a fresh single-party Pulsar-M key pair. The
// GenerateKey produces a fresh single-party Pulsar key pair. The
// generated key is a FIPS 204 ML-DSA key pair: the public key
// verifies under unmodified mldsa{44,65,87}.Verify.
//
@@ -52,7 +52,7 @@ func GenerateKey(params *Params, rng io.Reader) (*PrivateKey, error) {
return KeyFromSeed(params, seed)
}
// KeyFromSeed deterministically derives a Pulsar-M key pair from a
// KeyFromSeed deterministically derives a Pulsar key pair from a
// 32-byte seed. This is the canonical seed-based keygen path used by
// every KAT and by the DKG aggregation step.
//
+3 -3
View File
@@ -108,7 +108,7 @@ func TestLarge_E2E_DKG_ThresholdSign_Verify(t *testing.T) {
sessionID := [16]byte{'S', 'E', 'S', 'S'}
attempt := uint32(0)
message := []byte("pulsar-m large e2e roundtrip on quasar (3,2) profile")
message := []byte("pulsar large e2e roundtrip on quasar (3,2) profile")
signers := make([]*LargeThresholdSigner, tc.t)
for i := 0; i < tc.t; i++ {
@@ -152,7 +152,7 @@ func TestLarge_E2E_DKG_ThresholdSign_Verify(t *testing.T) {
// ---- FIPS 204 ML-DSA.Verify ----
if err := Verify(params, groupPK, message, sig); err != nil {
t.Fatalf("FIPS 204 ML-DSA.Verify on Pulsar-M output: %v", err)
t.Fatalf("FIPS 204 ML-DSA.Verify on Pulsar output: %v", err)
}
})
}
@@ -342,7 +342,7 @@ func TestLarge_Reshare_E2E(t *testing.T) {
newCommittee[i][3] = 'N'
}
const newThresh = 3
beacon := []byte("PULSAR-M-RESHARE-BEACON-2026")
beacon := []byte("PULSAR-RESHARE-BEACON-2026")
// Build reshare sessions for parties in (oldCommittee ∪ newCommittee).
// In this test the two committees are disjoint, so old parties only
+3 -3
View File
@@ -11,13 +11,13 @@ package pulsarm
// above TargetCommitteeSize = 1 111 111. This is the canonical
// extreme committee size for Lux's continental-scale validator set
// roadmap; the underlying GF(q) field supports up to q - 1 =
// 8 380 416 parties but pulsar-m's reference implementation pins
// 8 380 416 parties but pulsar's reference implementation pins
// the cap an order of magnitude below for over-provisioning,
// joining-without-reshare slack, and grow-without-fork.
//
// Architectural note. Production Lux consensus does NOT run one
// Pulsar-M ceremony over 1.1 M parties. It runs the small-committee
// GF(257) Pulsar-M at (T, N) = (2, 3) per sortitioned group, with
// Pulsar ceremony over 1.1 M parties. It runs the small-committee
// GF(257) Pulsar at (T, N) = (2, 3) per sortitioned group, with
// ~366k groups in parallel and a Z-Chain Groth16 roll-up. See
// spec/system-model.tex section "Committee selection and rollup".
// The Large* types in this file are for the alternative deployment
+3 -3
View File
@@ -5,10 +5,10 @@ package pulsarm
// largeshamir.go -- the public, large-committee Shamir surface.
//
// At committee sizes above GF(257)'s cap (n > 256), the Pulsar-M
// At committee sizes above GF(257)'s cap (n > 256), the Pulsar
// reference implementation switches to byte-wise Shamir over the
// FIPS 204 prime q = 8 380 417. This file exposes a clean Field-
// agnostic surface, so a chain integrator can drive Pulsar-M at
// agnostic surface, so a chain integrator can drive Pulsar at
// committees ranging from 2 parties (a multisig) all the way to
// TargetCommitteeSize = 1 111 111 (the canonical "extreme committee"
// target for Lux's continental-scale validator set roadmap) with a
@@ -23,7 +23,7 @@ package pulsarm
import "errors"
// LargeShareWire is the public wire form of one large-committee
// Pulsar-M share. Bytes are the big-endian uint32 lanes of the
// Pulsar share. Bytes are the big-endian uint32 lanes of the
// per-byte share, identical to shamirShareQ.Y.
type LargeShareWire [shareWireSizeQ]byte
+17 -17
View File
@@ -5,12 +5,12 @@ package pulsarm
import "errors"
// params.go — concrete parameter sets for Pulsar-M and the canonical
// params.go — concrete parameter sets for Pulsar and the canonical
// Mode -> Params resolution. The parameters mirror FIPS 204 ML-DSA's
// three security levels per pulsar-m.tex §5 (parameters.tex).
// three security levels per pulsar.tex §5 (parameters.tex).
// Mode identifies which FIPS 204 parameter set a Pulsar-M instance
// targets. The Pulsar-M family inherits FIPS 204's three NIST PQ
// Mode identifies which FIPS 204 parameter set a Pulsar instance
// targets. The Pulsar family inherits FIPS 204's three NIST PQ
// security categories.
type Mode uint8
@@ -38,18 +38,18 @@ const (
func (m Mode) String() string {
switch m {
case ModeP44:
return "Pulsar-M-44"
return "Pulsar-44"
case ModeP65:
return "Pulsar-M-65"
return "Pulsar-65"
case ModeP87:
return "Pulsar-M-87"
return "Pulsar-87"
default:
return "Pulsar-M-unspecified"
return "Pulsar-unspecified"
}
}
// Params captures the concrete parameters of a Pulsar-M instance.
// The values are derived from FIPS 204 §4 Table 1 (and pulsar-m.tex
// Params captures the concrete parameters of a Pulsar instance.
// The values are derived from FIPS 204 §4 Table 1 (and pulsar.tex
// §5 parameters.tex).
type Params struct {
Mode Mode
@@ -68,7 +68,7 @@ type Params struct {
PrivateKeySize int
SignatureSize int
// Pulsar-M-specific. ShamirPrime is the prime over which seed-byte
// Pulsar-specific. ShamirPrime is the prime over which seed-byte
// Shamir shares are computed. We use 8380417 (the FIPS 204 q): it
// is prime, fits two bytes plus three bits, and gives a uniform
// distribution on per-byte share values modulo the same prime that
@@ -83,12 +83,12 @@ type Params struct {
}
// SeedSize is the byte length of an ML-DSA key seed across all
// parameter sets. The Pulsar-M threshold layer Shamir-shares this
// parameter sets. The Pulsar threshold layer Shamir-shares this
// seed across the committee.
const SeedSize = 32
// TargetCommitteeSize is the canonical "extreme committee" size used
// in spec/pulsar-m.tex section "Large committees" and in the bench
// in spec/pulsar.tex section "Large committees" and in the bench
// harness. It exercises the GF(q) Shamir path at 1 111 111 signers —
// over four orders of magnitude beyond the GF(257) cap of 256.
//
@@ -102,7 +102,7 @@ const SeedSize = 32
// remains a single uint32 lane (mod q is ≤ 23 bits). One Lagrange
// multiplication needs at most 46 bits of intermediate width, so
// uint64 accumulators suffice everywhere — uint128 / uint256 are not
// required for Pulsar-M's core arithmetic. (Wider widths are
// required for Pulsar's core arithmetic. (Wider widths are
// reserved for the SNARK side of Z-Chain, which operates over
// ~254-bit prime-order fields.)
const TargetCommitteeSize = 1_111_111
@@ -113,7 +113,7 @@ const TargetCommitteeSize = 1_111_111
// cloudflare/circl's mldsa{44,65,87} package constants verbatim — they
// are the canonical FIPS 204 wire sizes.
// ParamsP44 is the Pulsar-M-44 parameter set.
// ParamsP44 is the Pulsar-44 parameter set.
var ParamsP44 = &Params{
Mode: ModeP44,
K: 4,
@@ -130,7 +130,7 @@ var ParamsP44 = &Params{
MaxRestart: 256,
}
// ParamsP65 is the Pulsar-M-65 parameter set (production target).
// ParamsP65 is the Pulsar-65 parameter set (production target).
var ParamsP65 = &Params{
Mode: ModeP65,
K: 6,
@@ -147,7 +147,7 @@ var ParamsP65 = &Params{
MaxRestart: 256,
}
// ParamsP87 is the Pulsar-M-87 parameter set.
// ParamsP87 is the Pulsar-87 parameter set.
var ParamsP87 = &Params{
Mode: ModeP87,
K: 8,
+1 -1
View File
@@ -188,7 +188,7 @@ func TestPrecompile_E2E_LargeCombine_FIPS204_VerifyCtx(t *testing.T) {
// ---- Threshold sign ----
quorum := committee[:threshold]
msg := []byte("pulsar-m large threshold -> precompile ctx -> FIPS 204")
msg := []byte("pulsar large threshold -> precompile ctx -> FIPS 204")
var sid [16]byte
copy(sid[:], "precompile-lg-01")
attempt := uint32(0)
+3 -3
View File
@@ -12,12 +12,12 @@ package pulsarm
// terms are pre-multiplied by the old-committee Lagrange coefficients
// (so the sum of fresh polynomials evaluates to the master secret at
// x=0 by construction). Beacon-randomised quorum selection per
// pulsar-m.tex §4.4 mitigates mobile-adversary corruption-set
// pulsar.tex §4.4 mitigates mobile-adversary corruption-set
// gaming.
//
// v0.1 instantiation: the reshare quorum is the FIRST k members of
// the old committee in canonical order, with k = threshold(old).
// The beacon-randomised selection in pulsar-m.tex §4.4 is implemented
// The beacon-randomised selection in pulsar.tex §4.4 is implemented
// as a configurable knob (BeaconQuorum) — pass the beacon bytes and
// the routine permutes the old committee deterministically before
// selecting the first k. Without a beacon, the deterministic
@@ -384,7 +384,7 @@ func (s *ReshareSession) Round3(round1 []*DKGRound1Msg, round2 []*DKGRound2Msg)
//
// If beacon is non-nil, the old committee is permuted by sorting
// under cSHAKE256(committee_root || beacon) — this is the
// beacon-randomised selection of pulsar-m.tex §4.4. Without a beacon,
// beacon-randomised selection of pulsar.tex §4.4. Without a beacon,
// the canonical-order first-k selection is used.
func selectReshareQuorum(oldSorted []NodeID, oldThreshold int, beacon []byte) []NodeID {
if beacon == nil {
+16 -16
View File
@@ -5,25 +5,25 @@ package pulsarm
// round.go -- Wave-driven metastable threshold signing.
//
// For validator pools above the GF(257) Pulsar-M cap of n=256, the
// canonical Lux deployment does NOT run one large Pulsar-M ceremony.
// It runs Pulsar-M (3, 2) at the per-Lux-round committee level. Each
// For validator pools above the GF(257) Pulsar cap of n=256, the
// canonical Lux deployment does NOT run one large Pulsar ceremony.
// It runs Pulsar (3, 2) at the per-Lux-round committee level. Each
// Lux round (one Wave Tick) samples K validators via prism.Cut, the
// K members emit Pulsar-M Round-1 commits over the value under vote,
// Wave decides agreement (alpha-of-K), Pulsar-M Round-2 reveals are
// K members emit Pulsar Round-1 commits over the value under vote,
// Wave decides agreement (alpha-of-K), Pulsar Round-2 reveals are
// collected, and after Focus.Tracker reaches the beta-confidence
// threshold the accumulator combines all collected (3, 2) signatures
// into a single FIPS 204 ML-DSA proof via the P3Q STARK rollup at
// the Z-Chain layer.
//
// The result: a 1.1M-validator pool reaches finality with constant
// per-Lux-round cost (K=3 Pulsar-M ceremonies in flight) and
// per-Lux-round cost (K=3 Pulsar ceremonies in flight) and
// constant final-certificate size (one P3Q proof).
//
// This file provides the helper primitives that the
// consensus/protocol/quasar Wave-driver calls during each Lux round.
// The Wave / Focus / Cut wiring itself lives in
// consensus/protocol/quasar/wave_signer.go (out of pulsar-m's scope).
// consensus/protocol/quasar/wave_signer.go (out of pulsar's scope).
import (
"encoding/binary"
@@ -32,7 +32,7 @@ import (
// RoundContext is the per-Lux-round binding context. Each Wave Tick
// produces a fresh context whose bytes are committed into every
// Pulsar-M transcript-hash so cross-round Round-1 commits cannot be
// Pulsar transcript-hash so cross-round Round-1 commits cannot be
// replayed against a different Wave round.
type RoundContext struct {
// Epoch is the validator-set epoch identifier (e.g. block height
@@ -64,8 +64,8 @@ func (c RoundContext) Encode() []byte {
return out
}
// RoundSessionID derives a deterministic per-Lux-round Pulsar-M
// SessionID from a RoundContext. The session-id binds the Pulsar-M
// RoundSessionID derives a deterministic per-Lux-round Pulsar
// SessionID from a RoundContext. The session-id binds the Pulsar
// per-round PRNG (PULSAR-SIGN-PRNG-V1 customisation tag in
// transcript.go) to the unique (epoch, round, item, committee) tuple,
// closing the CRIT-1 replay vector that del Pino-Niot's PRNGKeyForRound
@@ -79,7 +79,7 @@ func RoundSessionID(ctx RoundContext) [16]byte {
// RoundCommitteeRoot returns the canonical 32-byte digest of a
// Wave-sampled K-committee (sorted ascending NodeID). Both the
// per-round Pulsar-M transcript and the Wave protocol's per-round
// per-round Pulsar transcript and the Wave protocol's per-round
// commitments bind to this digest.
func RoundCommitteeRoot(committee []NodeID) [32]byte {
sorted := make([]NodeID, len(committee))
@@ -97,7 +97,7 @@ func RoundCommitteeRoot(committee []NodeID) [32]byte {
return transcriptHash32(tagDKGCommit, parts...)
}
// RoundSigShare is the per-validator Pulsar-M signature contribution
// RoundSigShare is the per-validator Pulsar signature contribution
// emitted in one Lux round. It rides alongside the validator's Wave
// preference vote on the Photon wire. The aggregator at the Quasar
// layer collects β rounds worth of these, passes them to LargeCombine
@@ -107,23 +107,23 @@ func RoundCommitteeRoot(committee []NodeID) [32]byte {
type RoundSigShare struct {
// Context binds the share to its Lux round.
Context RoundContext
// Round1 is the per-round Pulsar-M Round-1 commit message.
// Round1 is the per-round Pulsar Round-1 commit message.
Round1 *Round1Message
// Round2 is the per-round Pulsar-M Round-2 reveal message.
// Round2 is the per-round Pulsar Round-2 reveal message.
// Filled in after the Wave alpha-of-K agreement check passes.
Round2 *Round2Message
}
// RoundQuorumPolicy bundles the (alpha, beta) parameters Wave uses to
// drive Lux-round agreement. These are exposed here so the
// consensus-layer Wave-driver can synchronise them with the Pulsar-M
// consensus-layer Wave-driver can synchronise them with the Pulsar
// combiner's expectations.
//
// alpha is the within-Lux-round agreement threshold (yes-votes among
// K samples that count this round as "successful"). beta is the
// number of consecutive successful Lux rounds before the Focus
// tracker fires "decided" -- at which point the aggregator combines
// β·alpha Pulsar-M shares into one FIPS 204 signature.
// β·alpha Pulsar shares into one FIPS 204 signature.
type RoundQuorumPolicy struct {
K int
Alpha int
+4 -4
View File
@@ -42,7 +42,7 @@ func TestRoundContext_Encode_Deterministic(t *testing.T) {
// TestRoundSessionID_PerRoundDistinct verifies that two consecutive
// Lux rounds get distinct session IDs even when item + committee
// match -- so the Pulsar-M PRNG is forced to re-seed every round
// match -- so the Pulsar PRNG is forced to re-seed every round
// (the CRIT-1 cross-round replay defense from del Pino-Niot).
func TestRoundSessionID_PerRoundDistinct(t *testing.T) {
ctxR1 := RoundContext{Epoch: 7, Round: 1, Item: [32]byte{0x11}, CommitteeRoot: [32]byte{0x22}}
@@ -68,12 +68,12 @@ func TestRoundCommitteeRoot_OrderIndependent(t *testing.T) {
// signing test. It simulates:
// 1. Validator pool of 100 (beyond GF(257) cap not needed; tests math).
// 2. β = 4 consecutive Lux rounds.
// 3. Each Lux round: prism.Cut.Sample(K=3) → Pulsar-M (3,2) sign.
// 3. Each Lux round: prism.Cut.Sample(K=3) → Pulsar (3,2) sign.
// 4. After β rounds: 4 separate FIPS 204 ML-DSA signatures, each
// valid under the per-round group pubkey produced by per-round
// DKG.
//
// This validates the per-Lux-round Pulsar-M math without requiring
// This validates the per-Lux-round Pulsar math without requiring
// the Wave / Focus / Cut wiring (those live in consensus). The
// test asserts that each per-Lux-round signature verifies under
// unmodified FIPS 204 ML-DSA.Verify.
@@ -147,7 +147,7 @@ func TestRound_E2E_BetaRounds_Pulsar_M(t *testing.T) {
}
groupPK := outs[0].GroupPubkey
// Per-round Pulsar-M (3,2) threshold sign on the same item.
// Per-round Pulsar (3,2) threshold sign on the same item.
quorum := committee[:T]
myShares := make(map[NodeID]*KeyShare)
for i := 0; i < T; i++ {
+1 -1
View File
@@ -16,7 +16,7 @@ package pulsarm
// each share is 32 × uint16 = 64 bytes, regardless of the FIPS 204
// parameter set. Sharing over GF(8380417) is on the v0.2 path that
// integrates with the Lagrange-linearity sign mode of
// pulsar-m.tex §4.2 (where shares must align with R_q^k arithmetic).
// pulsar.tex §4.2 (where shares must align with R_q^k arithmetic).
//
// All arithmetic is constant-time mod p via the small-prime modular
// inverse table seeded at package init.
+2 -2
View File
@@ -7,7 +7,7 @@ package pulsarm
// q = 8380417 is the FIPS 204 ML-DSA prime. This is the wide-field
// counterpart to shamir.go's GF(257) and unlocks committee sizes up
// to q-1 = 8 380 416 parties, with comfortable margin for the N >
// 10 000 large-committee regime documented in spec/pulsar-m.tex
// 10 000 large-committee regime documented in spec/pulsar.tex
// section "Large committees (N > 256)".
//
// Layout choice. Each per-byte share value is a uniform draw in
@@ -26,7 +26,7 @@ package pulsarm
// the same (t-1)-out-of-n information-theoretic privacy as the GF(257)
// path. The choice of q matches the ring modulus, which removes one
// distinct prime from the audit footprint: every modular arithmetic
// operation in Pulsar-M is now mod q.
// operation in Pulsar is now mod q.
import (
"encoding/binary"
+1 -1
View File
@@ -17,7 +17,7 @@ func TestSignVerify_RoundTrip_AllModes(t *testing.T) {
if err != nil {
t.Fatal(err)
}
msg := []byte("Pulsar-M round-trip test message — Class N1 sanity")
msg := []byte("Pulsar round-trip test message — Class N1 sanity")
sig, err := Sign(params, sk, msg, nil, true, rand.Reader)
if err != nil {
t.Fatalf("Sign: %v", err)
+3 -3
View File
@@ -25,7 +25,7 @@ package pulsarm
// FIPS 204 mldsa.SignTo. Returns the resulting signature.
//
// The 2-round commit-and-reveal pattern with MACs is the structural
// pulsar-m.tex §4.2 form. The reconstruction-aggregator path collapses
// pulsar.tex §4.2 form. The reconstruction-aggregator path collapses
// the Lagrange-linearity-of-z computation of §4.2 into a single FIPS
// 204 Sign call after share Lagrange reconstruction. This trade is
// documented in BLOCKERS.md; the v0.2 path implements
@@ -57,7 +57,7 @@ var (
// A ThresholdSigner is single-use: one (sid, attempt) pair per
// instance. The protocol-layer driver allocates a fresh signer for
// each rejection-restart attempt (the FIPS 204 restart counter is
// the Attempt field; see pulsar-m.tex §6.2 for the cross-restart
// the Attempt field; see pulsar.tex §6.2 for the cross-restart
// state discipline).
type ThresholdSigner struct {
Params *Params
@@ -90,7 +90,7 @@ type ThresholdSigner struct {
// peerNodeID, group-pubkey) — a non-secret value sufficient for
// the v0.1 commit-and-reveal binding. v0.2 (production) replaces
// this with per-session ephemeral keys exchanged at the
// preprocessing phase per pulsar-m.tex §6.2.
// preprocessing phase per pulsar.tex §6.2.
MACKeys map[NodeID][32]byte
// rng is the entropy source for per-round mask r_i.
+7 -7
View File
@@ -4,18 +4,18 @@
package pulsarm
// transcript.go — FIPS 202 / SP 800-185 transcript primitives used by
// every Pulsar-M protocol round.
// every Pulsar protocol round.
//
// All hashing in Pulsar-M routes through this file. Direct use of
// All hashing in Pulsar routes through this file. Direct use of
// stdlib hashes anywhere else in the package is a CI failure per
// pulsar-m.tex §6.1 (DD-002 hash family) and CONTRIBUTING.md.
// pulsar.tex §6.1 (DD-002 hash family) and CONTRIBUTING.md.
//
// The two primitives we vend are:
//
// - cSHAKE256(K, X, L, S) — FIPS 202 §6.3 + SP 800-185 §3
// - KMAC256 (K, X, L, S) — SP 800-185 §4
//
// All Pulsar-M customisation strings live in this file as named
// All Pulsar customisation strings live in this file as named
// constants so that the audit footprint of the hash layer is one
// file. Rotating a tag invalidates every test vector pinned at that
// tag — bumping a tag is a deliberate, audited move.
@@ -27,7 +27,7 @@ import (
)
// Customisation tags for cSHAKE256/KMAC256. These match
// pulsar-m.tex §3 table "purpose -> SP 800-185 customisation tag"
// pulsar.tex §3 table "purpose -> SP 800-185 customisation tag"
// byte-for-byte.
const (
tagDKGCommit = "PULSAR-DKG-COMMIT-V1"
@@ -47,8 +47,8 @@ const (
)
// functionName is the SP 800-185 cSHAKE function-name parameter.
// All Pulsar-M cSHAKE calls pin N to "Pulsar" so that an integrator
// who mistakenly fed Pulsar-M cSHAKE bytes into a non-Pulsar-M cSHAKE
// All Pulsar cSHAKE calls pin N to "Pulsar" so that an integrator
// who mistakenly fed Pulsar cSHAKE bytes into a non-Pulsar cSHAKE
// engine would get a deterministic mismatch.
const functionName = "Pulsar"
+8 -8
View File
@@ -69,8 +69,8 @@ func TestSP800_185_BytepadAligned(t *testing.T) {
}
func TestCSHAKE256_Deterministic(t *testing.T) {
a := cshake256([]byte("test"), 32, "PULSAR-M-TEST")
b := cshake256([]byte("test"), 32, "PULSAR-M-TEST")
a := cshake256([]byte("test"), 32, "PULSAR-TEST")
b := cshake256([]byte("test"), 32, "PULSAR-TEST")
if !bytes.Equal(a, b) {
t.Fatalf("cSHAKE256 not deterministic")
}
@@ -83,26 +83,26 @@ func TestCSHAKE256_Deterministic(t *testing.T) {
func TestKMAC256_Deterministic(t *testing.T) {
key := []byte("a-key-32-bytes-long-for-kmac256-")
a := kmac256(key, []byte("test"), 32, "PULSAR-M-TEST")
b := kmac256(key, []byte("test"), 32, "PULSAR-M-TEST")
a := kmac256(key, []byte("test"), 32, "PULSAR-TEST")
b := kmac256(key, []byte("test"), 32, "PULSAR-TEST")
if !bytes.Equal(a, b) {
t.Fatalf("KMAC256 not deterministic")
}
// Different key → different output.
c := kmac256([]byte("b-key-32-bytes-long-for-kmac256-"), []byte("test"), 32, "PULSAR-M-TEST")
c := kmac256([]byte("b-key-32-bytes-long-for-kmac256-"), []byte("test"), 32, "PULSAR-TEST")
if bytes.Equal(a, c) {
t.Fatalf("KMAC256 key has no effect")
}
}
func TestTranscriptHash_Stable(t *testing.T) {
a := transcriptHash("PULSAR-M-TEST", []byte("a"), []byte("b"), []byte("c"))
b := transcriptHash("PULSAR-M-TEST", []byte("a"), []byte("b"), []byte("c"))
a := transcriptHash("PULSAR-TEST", []byte("a"), []byte("b"), []byte("c"))
b := transcriptHash("PULSAR-TEST", []byte("a"), []byte("b"), []byte("c"))
if a != b {
t.Fatalf("transcriptHash not stable")
}
// Reordering parts must give different output.
c := transcriptHash("PULSAR-M-TEST", []byte("a"), []byte("c"), []byte("b"))
c := transcriptHash("PULSAR-TEST", []byte("a"), []byte("c"), []byte("b"))
if a == c {
t.Fatalf("transcriptHash insensitive to part order")
}
+15 -15
View File
@@ -3,12 +3,12 @@
package pulsarm
// types.go — public data types used across the Pulsar-M reference
// types.go — public data types used across the Pulsar reference
// implementation. The wire layout of every wire-bound type freezes at
// the encoding-freeze gate (DD-008); until then, on-the-wire bytes are
// stable per-test-vector but not stable across patch releases.
// NodeID is the canonical party identifier used in all Pulsar-M
// NodeID is the canonical party identifier used in all Pulsar
// protocols. The 32-byte width matches the Lux validator-ID format and
// is wide enough to host an arbitrary external identifier (for example
// a Hanzo IAM subject hash). Index 0 is forbidden because the Shamir
@@ -16,7 +16,7 @@ package pulsarm
// nominal index 0 is rejected by params validation.
type NodeID [32]byte
// Field identifies which Shamir base field a Pulsar-M instance uses.
// Field identifies which Shamir base field a Pulsar instance uses.
// The choice is committee-size driven: GF(257) (FieldGF257) has the
// smallest wire footprint and is preferred for committees of at most
// 256 parties; GF(q) (FieldGFq) supports committees up to q − 1 =
@@ -84,7 +84,7 @@ func resolveField(want Field, n int) (Field, error) {
// exactly what cloudflare/circl's mldsa{44,65,87}.PublicKey.Pack emits
// — i.e. a single contiguous (ρ, t1) concatenation per FIPS 204 §5.1.
//
// The headline Class N1 claim of Pulsar-M is that a Pulsar-M
// The headline Class N1 claim of Pulsar is that a Pulsar
// signature against this PublicKey verifies under unmodified
// FIPS 204 ML-DSA.Verify (see Verify in verify.go).
type PublicKey struct {
@@ -129,9 +129,9 @@ type KeyShare struct {
// Signature is a FIPS 204 ML-DSA signature in its standard byte
// layout. The triple (c̃, z, h) is concatenated exactly per
// FIPS 204 §7.2 (Algorithm 28 sigEncode); no Pulsar-M envelope is
// FIPS 204 §7.2 (Algorithm 28 sigEncode); no Pulsar envelope is
// applied. A relying party that can verify ML-DSA can verify a
// Pulsar-M Signature with no code change.
// Pulsar Signature with no code change.
type Signature struct {
Mode Mode
Bytes []byte
@@ -139,16 +139,16 @@ type Signature struct {
// Round1Message is the broadcast emitted by ThresholdSigner.Round1.
//
// The protocol structure follows pulsar-m.tex §4.2 Algorithm "Sign
// The protocol structure follows pulsar.tex §4.2 Algorithm "Sign
// Round 1": commit + MAC the per-party w̄_i. The full bar-w is sent
// alongside the digest at round 2 — the digest's role is binding under
// MAC, not concealment. See pulsar-m.tex §4.2 Remark "Round-1
// MAC, not concealment. See pulsar.tex §4.2 Remark "Round-1
// commit-digest binding".
type Round1Message struct {
NodeID NodeID
SessionID [16]byte // sid uniqueness; see pulsar-m.tex §6.2
SessionID [16]byte // sid uniqueness; see pulsar.tex §6.2
Attempt uint32 // rejection-restart counter κ
Commit [32]byte // D_i = cSHAKE(w̄_i || τ_1) per pulsar-m.tex §4.2
Commit [32]byte // D_i = cSHAKE(w̄_i || τ_1) per pulsar.tex §4.2
MACs map[NodeID][32]byte // KMAC256(K_{i,j}, D_i || τ_1)
}
@@ -174,7 +174,7 @@ type Round2Message struct {
// the seed encrypted under the round transcript hash; the
// aggregator collects t shares, reconstructs the seed, and emits
// a single FIPS 204 signature. The Lagrange-linearity path of
// pulsar-m.tex §4.2 Algorithm "Sign Round 2" produces (z_i, r_i)
// pulsar.tex §4.2 Algorithm "Sign Round 2" produces (z_i, r_i)
// here directly; it is on the v0.2 critical path.
PartialSig []byte
}
@@ -209,7 +209,7 @@ type DKGShareEnvelope struct {
// DKGRound2Msg is the broadcast emitted by DKGSession.Round2: the
// per-party Pedersen-commit digest (the Round-1.5 cross-party
// equivocation gate of pulsar-m.tex §4.1).
// equivocation gate of pulsar.tex §4.1).
type DKGRound2Msg struct {
NodeID NodeID
Digest [32]byte // cSHAKE256(commits) per PULSAR-DKG-COMMIT-V1
@@ -233,9 +233,9 @@ type DKGOutput struct {
}
// AbortEvidence is a signed complaint emitted by an honest party when
// it detects deviation. The Pulsar-M protocol family commits to
// it detects deviation. The Pulsar protocol family commits to
// identifiable abort: every detected deviation produces verifiable
// evidence suitable for slashing. See pulsar-m.tex §4.5 for the
// evidence suitable for slashing. See pulsar.tex §4.5 for the
// taxonomy of complaints.
type AbortEvidence struct {
Kind ComplaintKind
@@ -256,7 +256,7 @@ type ComplaintKind uint8
const (
// ComplaintEquivocation: a dealer broadcast distinct commit vectors
// to distinct recipients. Evidence: two commits and the signed
// broadcasts from the accused. See pulsar-m.tex §4.5.
// broadcasts from the accused. See pulsar.tex §4.5.
ComplaintEquivocation ComplaintKind = 1
// ComplaintBadDelivery: the private (share, blind) delivered to the
+6 -6
View File
@@ -7,13 +7,13 @@ package pulsarm
//
// This file is the Class N1 manifesto in code: Verify literally
// dispatches to mldsa{44,65,87}.Verify from cloudflare/circl, which
// is the FIPS 204 §6.3 verifier verbatim. No Pulsar-M-specific
// is the FIPS 204 §6.3 verifier verbatim. No Pulsar-specific
// logic; no threshold-specific extension fields; no envelope. A
// signature produced by ThresholdSign (threshold.go) flows through
// the SAME Verify code path as a single-party Sign output.
//
// Per pulsar-m.tex §4.3 and spec/nist-mptc-category.tex, this is the
// load-bearing property of the entire Pulsar-M family: anything that
// Per pulsar.tex §4.3 and spec/nist-mptc-category.tex, this is the
// load-bearing property of the entire Pulsar family: anything that
// changes Verify breaks Class N1 output interchangeability.
import (
@@ -25,7 +25,7 @@ import (
)
// Verification errors. Returning a typed error rather than a panic
// is mandated by pulsar-m.tex §6.1 (DD-007: no panic in the verify
// is mandated by pulsar.tex §6.1 (DD-007: no panic in the verify
// path) and CONTRIBUTING.md.
var (
// ErrInvalidSignature is returned when the signature does not
@@ -49,7 +49,7 @@ var (
)
// Verify is the canonical consensus-consumer entry point for
// Pulsar-M signature verification.
// Pulsar signature verification.
//
// Returns nil if the signature is valid under FIPS 204 ML-DSA.Verify;
// a typed error otherwise. Never panics: caller code in the consensus
@@ -65,7 +65,7 @@ var (
// Class N1 manifesto: this function MUST remain a thin dispatch over
// the FIPS 204 verifier. Adding logic here breaks output
// interchangeability with single-party FIPS 204 — the whole point
// of the Pulsar-M.M variant.
// of the Pulsar.M variant.
func Verify(params *Params, groupPubkey *PublicKey, message []byte, sig *Signature) error {
return VerifyCtx(params, groupPubkey, message, nil, sig)
}
+25 -25
View File
@@ -279,18 +279,18 @@ string. The canonical customisation tags used by Pulsar are:
\toprule
purpose & SP~800-185 customisation tag \\
\midrule
DKG commit-digest (Round~1.5) & \texttt{PULSAR-M-DKG-COMMIT-V1} \\
DKG transcript hash & \texttt{PULSAR-M-DKG-TRANSCRIPT-V1} \\
Sign Round-1 transcript (sid hash $H_1$) & \texttt{PULSAR-M-SIGN-R1-V1} \\
DKG commit-digest (Round~1.5) & \texttt{PULSAR-DKG-COMMIT-V1} \\
DKG transcript hash & \texttt{PULSAR-DKG-TRANSCRIPT-V1} \\
Sign Round-1 transcript (sid hash $H_1$) & \texttt{PULSAR-SIGN-R1-V1} \\
Sign Round-2 challenge (FIPS~204 $\tilde c$) & FIPS~204 inner SHAKE-256 \\
Sign per-party PRNG (round-keyed) & \texttt{PULSAR-M-SIGN-PRNG-V1} \\
Sign PRF for mask cancellation & \texttt{PULSAR-M-SIGN-PRF-V1} \\
Reshare commit digest & \texttt{PULSAR-M-RESHARE-COMMIT-V1} \\
Reshare transcript & \texttt{PULSAR-M-RESHARE-TRANSCRIPT-V1} \\
Reshare beacon binding & \texttt{PULSAR-M-RESHARE-BEACON-V1} \\
Sign per-party PRNG (round-keyed) & \texttt{PULSAR-SIGN-PRNG-V1} \\
Sign PRF for mask cancellation & \texttt{PULSAR-SIGN-PRF-V1} \\
Reshare commit digest & \texttt{PULSAR-RESHARE-COMMIT-V1} \\
Reshare transcript & \texttt{PULSAR-RESHARE-TRANSCRIPT-V1} \\
Reshare beacon binding & \texttt{PULSAR-RESHARE-BEACON-V1} \\
Public matrix $\mathbf{A}$ derivation & FIPS~204 \texttt{ExpandA} (no change) \\
Public matrix $\mathbf{B}$ derivation & \texttt{PULSAR-M-EXPANDB-V1} \\
Complaint signing transcript & \texttt{PULSAR-M-COMPLAINT-V1} \\
Public matrix $\mathbf{B}$ derivation & \texttt{PULSAR-EXPANDB-V1} \\
Complaint signing transcript & \texttt{PULSAR-COMPLAINT-V1} \\
\bottomrule
\end{tabular}
\end{center}
@@ -456,8 +456,8 @@ $\mathbf{A}$ is derived exactly as in FIPS~204 via
\texttt{ExpandA} (FIPS~204~\S7.1): \(\mathbf{A} = \texttt{ExpandA}(\rho)\),
$\rho \in \{0,1\}^{256}$ a public seed. $\mathbf{B}$ is derived from
a separate nothing-up-my-sleeve seed
$\rho_B = \cSHAKE(\text{empty}, 256, \text{`Pulsar-M'},
\text{`PULSAR-M-EXPANDB-V1'}\,)$. The two derivations are
$\rho_B = \cSHAKE(\text{empty}, 256, \text{`Pulsar'},
\text{`PULSAR-EXPANDB-V1'}\,)$. The two derivations are
domain-separated so that $\mathbf{A}$ and $\mathbf{B}$ are independent
even with shared randomness, satisfying the independence
requirement of \Cref{thm:pedersen-hiding}.
@@ -597,8 +597,8 @@ with $\mathbf{r}_{i,k} \gets \chi_\eta^\ell$ for each $k$.
\paragraph{Round 1.5 (cross-party commitment consistency).}
Each party broadcasts the commit digest
\[
H_i = \cSHAKE(\,\text{empty},\,256,\,\text{`Pulsar-M'},\,
\text{`PULSAR-M-DKG-COMMIT-V1'}\,||\,\mathit{encode}(\{\mathbf{C}_{i,k}\}_{k=0}^{t-1})\,).
H_i = \cSHAKE(\,\text{empty},\,256,\,\text{`Pulsar'},\,
\text{`PULSAR-DKG-COMMIT-V1'}\,||\,\mathit{encode}(\{\mathbf{C}_{i,k}\}_{k=0}^{t-1})\,).
\]
Parties compare digests received from every sender across the cohort.
Mismatch $\Rightarrow$ equivocation: the sender broadcast distinct
@@ -712,14 +712,14 @@ quorum $T$, party-pair PRF keys $\{K_{i,j}\}_{j \in T \setminus \{i\}}$,
message hash $\mu$.
\State $\tau_1 \gets (\mathit{sid}, \kappa, T, i, \mathit{pk}, \mu)$
\Comment{Round-1 transcript binding}
\State $\text{seed}_i \gets \KMAC(K_i^{\mathrm{prng}},\,\tau_1,\,256,\,\text{`PULSAR-M-SIGN-PRNG-V1'})$
\State $\text{seed}_i \gets \KMAC(K_i^{\mathrm{prng}},\,\tau_1,\,256,\,\text{`PULSAR-SIGN-PRNG-V1'})$
\Comment{Per-round PRNG seed (\S\ref{sec:impl-rejection-restart})}
\State Sample $\mathbf{y}_i \gets U_{\gamma_1}^\ell$ from the PRNG keyed by $\text{seed}_i$
\State Compute commit $\mathbf{w}_i = \mathbf{A} \mathbf{y}_i \in \Rq^k$
\State Compute high-bits commit $\bar{\mathbf{w}}_i = \HighBits(\mathbf{w}_i,\,2\gamma_2)$
\State Compute commit digest $D_i = \cSHAKE(\bar{\mathbf{w}}_i,\,256,\,\text{`Pulsar-M'},\,\text{`PULSAR-M-SIGN-R1-V1'} \| \tau_1)$
\State Compute commit digest $D_i = \cSHAKE(\bar{\mathbf{w}}_i,\,256,\,\text{`Pulsar'},\,\text{`PULSAR-SIGN-R1-V1'} \| \tau_1)$
\State \textbf{For each} $j \in T \setminus \{i\}$ \textbf{do}
$\;\mathrm{MAC}_{i \to j} \gets \KMAC(K_{i,j},\,D_i \| \tau_1,\,256,\,\text{`PULSAR-M-SIGN-R1-MAC-V1'})$
$\;\mathrm{MAC}_{i \to j} \gets \KMAC(K_{i,j},\,D_i \| \tau_1,\,256,\,\text{`PULSAR-SIGN-R1-MAC-V1'})$
\State \textbf{Broadcast:} $(D_i, \{\mathrm{MAC}_{i \to j}\}_{j \in T \setminus \{i\}})$
\end{algorithmic}
\end{algorithm}
@@ -730,7 +730,7 @@ $\;\mathrm{MAC}_{i \to j} \gets \KMAC(K_{i,j},\,D_i \| \tau_1,\,256,\,\text{`PUL
\begin{algorithmic}[1]
\State \textbf{Input:} the received $\{D_j\}_{j \in T}$ and corresponding MACs, plus all Round-1 state from party $i$.
\State Verify every MAC received from each $j$ against the locally-known $K_{i,j}$. Abort with $\textsc{ComplaintMACFailure}(j)$ on mismatch.
\State Compute the aggregated commit hash $\bar D = \cSHAKE(\text{empty},\,256,\,\text{`Pulsar-M'},\,\text{`PULSAR-M-SIGN-R2-V1'} \,\|\, D_1 \| D_2 \| \cdots \| D_n)$
\State Compute the aggregated commit hash $\bar D = \cSHAKE(\text{empty},\,256,\,\text{`Pulsar'},\,\text{`PULSAR-SIGN-R2-V1'} \,\|\, D_1 \| D_2 \| \cdots \| D_n)$
\State Recover the aggregated $\bar{\mathbf{w}} = \HighBits(\sum_{j \in T} \mathbf{w}_j,\,2\gamma_2)$ by summing per-party Round-1 commits (each party transmits its raw $\bar{\mathbf{w}}_i$ alongside the commit digest in Round~2 for verification --- the digest's role is binding under MAC, not concealment).
\State Compute the FIPS~204 challenge $\tilde c \gets \SHAKE(\mu \,\|\, \bar{\mathbf{w}},\,2\lambda)$ and expand to $c \in \Rq$ via $c = \texttt{SampleInBall}(\tilde c)$.
\State Compute the Lagrange coefficient $\lambda_i^T \in \Zq$ for party $i$ in the quorum $T$.
@@ -864,8 +864,8 @@ chain's randomness beacon $\beta_e$ for epoch $e$:
\;=\;
\bigl\{\text{the } t_{\mathrm{old}} \text{ smallest-ID members of }
\mathcal{O}\text{ in the permutation induced by }
\cSHAKE(\beta_e, 256\cdot|\mathcal{O}|, \text{`Pulsar-M'},
\text{`PULSAR-M-RESHARE-BEACON-V1'})\bigr\}.
\cSHAKE(\beta_e, 256\cdot|\mathcal{O}|, \text{`Pulsar'},
\text{`PULSAR-RESHARE-BEACON-V1'})\bigr\}.
\]
The beacon $\beta_e$ must be unpredictable in advance to the
adversary; the Lux consensus randomness layer (Quasar) provides this
@@ -1123,7 +1123,7 @@ within them are not.
\paragraph{Common conventions.}
\begin{itemize}[leftmargin=*, itemsep=0pt]
\item Every wire message starts with a fixed-length version tag:
$(\text{`PULSAR-M-1'}, \text{kind\_byte}, \text{epoch\_u32})$.
$(\text{`PULSAR-1'}, \text{kind\_byte}, \text{epoch\_u32})$.
Tag length: TBD at freeze.
\item Lengths are big-endian unsigned. Length-prefixed for every
variable-size field.
@@ -1177,7 +1177,7 @@ Length-pinned per kind.
\paragraph{Activation certificate.}
A FIPS~204 ML-DSA signature on the reshare transcript hash under the
unchanged $\mathit{pk}$. The hash is bound under the
\texttt{PULSAR-M-RESHARE-TRANSCRIPT-V1} customisation tag.
\texttt{PULSAR-RESHARE-TRANSCRIPT-V1} customisation tag.
\paragraph{Open at freeze.}
Outstanding decisions for the encoding freeze:
@@ -1281,11 +1281,11 @@ attempt counter. The per-attempt PRNG seed is derived as:
\KMAC(\,K_i^{\mathrm{prng}},\,
(\mathit{sid}, \kappa, T, i, \mathit{pk}, \mu),\,
256,\,
\text{`PULSAR-M-SIGN-PRNG-V1'}\,),
\text{`PULSAR-SIGN-PRNG-V1'}\,),
\]
where $K_i^{\mathrm{prng}}$ is a per-party PRNG key derived at DKG
time from $\mathbf{s}_i$ via $\cSHAKE$ with the customisation tag
\texttt{`PULSAR-M-SIGN-PRNGKEY-V1'}. Both $\mathit{sid}$ and $\kappa$
\texttt{`PULSAR-SIGN-PRNGKEY-V1'}. Both $\mathit{sid}$ and $\kappa$
are bound into the seed.
\item \textbf{Across quorums on the same $\mathit{sid}$} (distinct
$T$). If two distinct quorums coordinate on the same $\mathit{sid}$
@@ -1570,7 +1570,7 @@ $(k, \ell)$ & module dimensions, FIPS~204 dependent \\
$(\eta, \tau, \gamma_1, \gamma_2, \omega, \beta, d, \lambda)$ & FIPS~204 parameter set \\
$(n, t)$ & threshold parameters, $n \ge 2t-1$ \\
$\mathbf{A} \in \Rq^{k \times \ell}$ & public matrix, derived from $\rho$ via FIPS~204 \texttt{ExpandA} \\
$\mathbf{B} \in \Rq^{k \times \ell}$ & Pedersen blinding matrix, derived via \texttt{PULSAR-M-EXPANDB-V1} \\
$\mathbf{B} \in \Rq^{k \times \ell}$ & Pedersen blinding matrix, derived via \texttt{PULSAR-EXPANDB-V1} \\
$\mathbf{s}_1 \in \Rq^\ell$ & master secret, $\chi_\eta$-distributed \\
$\mathbf{u} \in \Rq^\ell$ & Pedersen blinding, $\chi_\eta$-distributed \\
$\mathbf{s}_2 \in \Rq^k$ & FIPS~204 noise, $= \mathbf{B}\mathbf{u}$ in Pulsar \\
+24 -24
View File
@@ -1,6 +1,6 @@
[
{
"mode": "Pulsar-M-65",
"mode": "Pulsar-65",
"n": 3,
"t": 2,
"committee": [
@@ -8,16 +8,16 @@
"0200000000000000000000000000000000000000000000000000000000000000",
"0300000000000000000000000000000000000000000000000000000000000000"
],
"public_key": "dabd708d295eb716d57ed7ce17f3a3048cd39b433eb6c9e5b00bb889fd5135fe1bf33bb3b146b77343810fe83b023a84d95ae02e786157ec7e821cec941f82b7209a01cab329911f214228c958a1258e8176684c951e413c2714e6d98482fa87bd27194ff9bac5220f3ef1ed3ca795246b9dd0d11dfff30b3f2054b0d9f66bd3c82049d55cdbf8ef72275fb1da34c77e05ca8cf59e52f086610dae671c092768bb1e6958a6dc17c24864bedafc294de1c172ae4cf751964d1dae00cb5f125431ce56a0a7bdf6a36a0dea8590a91853baff6d95a57da2e3fc1edbf8c00ffe9e285ba66c60da27f143d2d3137f66efb8f0429b4abc9f47a905acfb15cbf768010969d53d36e72cb5adc840cbef48561b4cda3b5a610ecc88b7074413510fad72da7811f418c0eb4afeddc765945dd46331876b1b753dc99d5d8a6ccb41e87f420121539b1b9e9c650b09f303a6856e8a1ea49e68d0f166f208f78a0a5e964be963a1cefa4ad3a3c736dd73996fa46220ac0227f299cd5e250c6202405093ffe676f2470fb50acc4f5a208f4180e4aa25a1fe9a53ccebe274cfbba1bd906e013328bd8e7bae335dceecadc52c1be53a3d2c29530398e4e8309440a70ddd6f14b14ba85af438ede821b0a50983bed0c174adf0ea359b4b10c4b235ce1a76017795b207250e57c60393c13e3d7dea13601c3c6926f210185c6371f8c7504939d52713cfc712eac1e18306c6995854dccbbc737f05a1ef532649a5c52b682d27ba7340c4efec891d798b1e5f42de12f50c25fe1e1881e2a30d2c986ae05efc149079e82012b47cb908c3f50afe268d6cbe0919e32945e3c021927dca3d313b2f040c27f55c15a4577f593233ce474a6f429fdd3ebd521678053a018f9705c8a8025fe1b1605a1c2758a429cd81fd1d3a59e95a2e724d9e0983c0e260ec384bd9a18bad97712799e416c57319273fbc91086d41cafa4822842649dccb1ed75f927a2363ec59f3a7405af13b7aa629178840f6c2d233171cc5ba124424ebc867564261d217639faf9397e5ad9aee7cf019aac2e62c8d49fdf2ad8c2c857da51ded638ff4f5c6383d396a231dc6510dd8a2a887802f6235bbefef0ac7cfd8c6c684972aa0540389185af8afedd411b21946a11b236391781dc7d9cb55ae3434294b87b52e8ab3f4afd12391471299f05f41f50b54a55f5ccfa29acf9ff41cbd00a4a1a2af100a077d83e7847f9cd9a2088c46a675fc69dc38d0391721ab6fc216e0dc88618464da029cc0a7041e3e0e0e7d311a337e0970cf25be69346cc7fe2ba340d14ae1a7452f9ad6fe72103b7afe8acbb249682ba68a82e62e1eb21f4257f3b2a46e686d4ec10a853828555861617ca0c85cc7eb43a93c7d090788858eb4a5ca20df43c009508c0b02be10568a7071bf22f3f6a27d9b4ccd8d22ecc7d6839542dbac63d40dff0a9abe24fd2ac107e3f47742561e3a10f663805c1277064dbd86a50d8d502181ec4e8e24cb9621c4bae67b2491c675db917592d01f6bf2411df76d24acb04043d8f6ef8164772be8bbae73faf7db2979c52b5771af83578ac2b3649180a294fca44a35e12f2d85f8dc48d222258d6aa389f7e3367310441b299a5680b602fa05aedcac313802d046ab0043a70635a74ec090f55b0210c5f50fc169f3886cf8cec44feb8506b31a7161a9c39787bbc5621bf7b7c4bc88a8c40ae70709dae4924445787af2a5c72b13889a21c95006e6061ea15173c1d70690b5d5ec040e760fad860ce003ee3ecca766631ce0c40cac221b1258d0086e4e22f032c11a6e5fd079df7dc0e25c2b8a6336f47c19adda07aeee166affa8903326311a9051ce72219cd1587b0c6ff8822705b50eef3f26c4516d264f9e5824f9a599641e4c7d06deaada4710ca9a0a7c49eadb2484d2512b3d4d6cc79012586b8b7a8479c91070468e045e776084dff11f93eeec254a466fe4e864affd8548999b2d6458333f035f02fd1f2d22589ec95627ca337d0f4735e2ef28a7858474effb5d70b7caebd54f32cbb53436a74e60c5942f2c83c545dda7c2248b23f69a0f9a8b99fd534f6d837a09a770765e86a3330cf94332a5fbb19a9cfc5f41e8f4c9408bb83e4d75ed64b9bc6f55816c850a603c27fb8ecb212aff52cea02edc763e029fc1a2bb13c5dc74b5fe7f74965f9e1c1961de662c28a7bebd9a8bf668e931e909e23f722bc746cee879d6ab90e19915012fcd8b8d91992c72207ea1f2bb5afbe455f45fcddfa287474fec733efc216fff5ce11b316044043dc3197d66ecb6eace9776f2713f8764699d32fea76eada266e8c2ef7808f9effb8cb4280b73e075c4790d4aec8643bf34e00dd68568eccce3a6399dfa6dc0fbb54c1c73b67dabb05e8ac009a87791d1092215a720e70e6bcbb50bc1d66f59ebc2325695930c55ffd9f1c01bec867e7dd392d74d59de31414f8083ff9d21d2543133d60095e64303b86e3ee56cc9077831ffdcd44cab3477320e14f96e0e6a072699c331d6cdc663c381b8541bb4efeff8279836ee13e1ab09e56b6363832d48d4bb9f483d797b2055e883965c16acaf9bb00f2fe9b0fd764d5758f94108a80c47bf735253f07ae810a8799a8ac0c489392aa3057a37171809e42241730960904d8cda92b10e45c49485130aa2f3cd315dd6725509010c0c3dfcbfef1a2b64931a7b98e602bdc8e3e74a6a5b3eae7f2d3ee5609ebf3f1d0473bed5af4fbe8e8b42c7f93d542cad2a952e9c7d",
"transcript_hash": "6a00d5ad4e362645ae96b676eafa5508935aa8a7d07492aa4852e8abd259b35e0bb9305eb6db93c0a386aaf08a2c0c0e",
"public_key": "d1054a700acd3109e44304aa67d39745f9d47ec74c1bd2ea74270ef172d8edabe571f7b2a6e4726aaed17c31f91f544b97cab0dba366edbb77577bf5990531e59159590de7f3b7f496f23519523b1e123d3631271e5557def85e6ff461eee45f7ee4d69dbb413e518a3aabecfdaf4177b2f8515de045cf28794017ea0979ae3bad204eb92b26921fed52481d7c628aaef9fb839eaf13d61db57518ea4dcd5602d18a2889e9d1a5b073fe83b17b0e5942aa34ab89f97b96b954e11be19d9b2ecae7e505bc1a6f907e28a139ac45869d4065996ddb415b0e45565cb306e61b2b083652b9fe39cc359ccdb68ebf5f1b3ddc382dc01ccf93912016cca9f95be4ce3a5cb51728875364d93bb650eb592e5b482cfb5e07295b96e4ff5337caac2ceb31f363d950a3ef6d42516c03399b09635660909c6708d5de037d4640bfb30fdfa1f666aa7a52f9d4553a43c9be7bcf3fc15dfd16bb68edebf145875c15cad444457ed0fe33f98fa459cc448b85fb13139ddb0ff085c834b5c1961cdae632cae559b87c7c9dc45277fb64b501c5fe6004f5cc9284b8889aa72dcf5935e42fa01e3e34ccdb0e49c3c4353d5ef1589e4239c9e7825655839e5bb5022bc170aa31256879464c7de439984981549c625970f154f91e46ed4bcc6a636ebf73d1eb23d358d130f77935d5e3cd6537881b4ba141ae4618fa90f834a2f40c8def2e679fb59569a48b71209a0821090a333060419224fd67e3e42f9d4bb976edaf71e2c50fbf866e0616130fab2184775452af5ae98679c9a605e5dce8673c80682adeea8bd10a4a8e585e9b5026e16c60ecd41ed7bc4a8fe0d31d9efa8605c0b854d30badb4b0cb0e900f688fd28e15e0fd6b4ec09903bb1ea0d094cd5da51263d94dd9d6fa0a53fd52a7be6a1fd5a51da4192eaa020dba2d2eb4d8ec5d238ce16877f5de309ba4e0471d98bcf1ab92652707881786c28ca09882072afb95a36ffd8e02de7b4d5f6e5b6ca85ff70313fbe5c46bc0895f78063903449b083fb8f44bb1b3c6ae36232f2f31a01995fdeb1116c71a30f1799f4f124a7f67f3b13e9c335d79f7e558f94b1c1e4ac89616fc73180eb887453a953d06eb41aae1bdf10bad0ffac607553bd5a9f8f151e255a399462e2f79785dfa1b80d56d1127cf9859dca52b99f51a5ca5d2535946d5fc6f526adc920b9c6c775669ea14231046d7351d3d64d3f42f8af751914393acda67ddd6f852cb0c5988d4f45ec5e71c346d353aaca8da5cf41d96391d4690684d934ff5a2144e2d058751b84a0dec73611a647bcb3e8b5e6c6d52bcead72f6279ef18a0f5bc7117a5a78221947eee438cafa194635064eeb49b27c1bcfc4c4ea5a270c105c0383420bf359e0a10e74a85249c24ecc3aceaa170de70a7a38023e8340f302ef1f4c00e0fe990186e87b233fa778f16ae314aa5b6b030e1efe05511f14f543c1c9e0ffbee7454b912d0c205e73db416052247e29f5347e723d59887c6952ea273de2aa29ab2d83a2ad7d740a199b68bde5a4c8dde1dc5fcee85e38a2cd6e32fe7fb4d9c4378a4f939620794671d6fe4781e923e66f2e16262e262b8f78a3b74f14b89fd1ecd5a5a8c190c62f4dc0fe3e3cefbf5021328ab93d1a7b28e00d79b112a1630d33afcb48be731f759f1d3ec23ff25d8ed888754b248e4d7232d689e41c8ae480ced59a248a71b5a1153a8c072909d1664d684ef4dfe1f1202f275f1a78abb7c75e2a703850960b65b01178e79343d739bcf5a455dee241398cd5c2aebd6b7d9fd85442ebad24e0b60e14cdd702c230b3ee16e7d7652f4811ee40af4f3098df46d3b362ee1e051bb91964ae0b1037db63226f4d183b678ffdcb7ce4f538e1ecbce7314d6d34b6ed1c45e08a6a2601f4961635ebd3b6216cc46a81e2cbfc71836c67eaa6e14addd822887563dcf55ca727cb390413bc2ec6d3fcf31c134f07c4b15caf0e4141e66d35b7e8a3fe807a8b58c56ddecd0a4563dc877d6af8773f7887eae5840ea579b8cbcad18af5b1d7b109660a0c564aab8d9c349a4d18bca21c49b6a45e8b851b033ed54eca805893076dc3e5b50faf3f4a6d1ad34510955fbeafeccd332b2b9db5633428af7dcfdb50c87681099074964a7b0ed0986717f8f8abd12dbc6f5f2bd611c04ab646d6edaa9b9c90b30e5610a68ef0642ac7015c1b6f5c92c3a931c637f86883b99df2a1a3531907fbeaff11a8b08a22dab44463adde0115d8d72bd23ec8f2a6a92e5977edc44b57221f3f45d0f6a8aec07f0e8a7aeabd20bdbcae1b12b09e26d4940892154820f419f57ec596ccfb99361beac57a1578c429035077f226b41713cc286db837b164ebd19c45e2ef2faa77c1a57ecbfdeb33af289bfc0579cda72e699770dcab9208fad7d7e3d99c703af79b195f394f9755c587145e6018d04784d1a8b00e50502b61b70ff6d8803cf5ba4c88c428b9bfaa9388da816b94b4f2297ca741f2a4148d18a2b19478cc86c5a414fe82de534b4b6d70c5df8b84693e321197043f029a037d4a16151a9430c28f0afa90c4a18f4458e1924ac6e3cffafb0fb5b7af3641c976abe2bc2f2e4a3e4d58a74d3121e4d6bbba4e08e7082820682c3152109ca9081b13c76a6b4ac2cfb648e38521c1cb1c4c8ed8f50db35be5532b0638ba661aa719f1dd6d7a63bdd84a9d5531ad3c1a786ba1bc1f35c3f7b2ae744bb822be74f8ab1061ea7b8372fd72c02924aac8fbb5ea803e7725e36e7d4a8a63d80",
"transcript_hash": "d44e7629d194b80cd4656068f0e79d8e60778ffdee0964732461c09a5ee54128890c04eb2662cb5d87dc2a0cb2844fd6",
"shares": [
"0085006a005c00ca00cf004300e4001e0002000c009a00c300af002100b6005800e400e1000a001900d3005500490074008700c9009d001600ca010000ab0097",
"00da0045009e00ae00330004003600fb00590095004900720057002800d6003400b700b500ec0035008e001a001000b50073000f00e3001100ac005e00e70048",
"002e002000e00092009800c6008900d700b0001d00f900210100002f00f60010008a008900cd0051004900e000d800f6005f00560028000c008e00bd002200fa"
"003900b000d100c2001000bc000c00e800d100270072001b0021003c00bc0023001f006300f200c700d9003800a5005100960023006900c70006004c00c100ff",
"00160005006c000100c700e300680010000c007c00f60060005e000400f60081001f00b800aa00cf006a000c00fd00a400d000d0001d000c00dd009d0004006f",
"00f4005b00070041007d000900c40039004800d1007900a5009b00cd002f00df001f000c006200d700fc00e1005400f70009007c00d2005200b300ee004800e0"
]
},
{
"mode": "Pulsar-M-65",
"mode": "Pulsar-65",
"n": 5,
"t": 3,
"committee": [
@@ -27,18 +27,18 @@
"0400000000000000000000000000000000000000000000000000000000000000",
"0500000000000000000000000000000000000000000000000000000000000000"
],
"public_key": "8e7491cb9ac1860de3fd8c7a4f2864dc7c6f9293acefa09498efda1b77475163563640bebafc7f0791ed090b85e61ea10fcf86e189c91c5d1714da1c828aa76930d55cc64c3e81c7c6a42672352e9de817cc929933d22bfcca70047631e33ded8da2c0efabd0adea3dd1f6d2857d5e75e41615041ace238034660ee188ce8eee01618bba6b1e0d1c2ecf788ab62593726fc102854e36a3e6e0a9d02f45271ff400b4fc93a8f1cd4eabed9bb1ee823582227b3f13dca9b51a42658504f0b8443238fb8c0e48866f9b65639e5756597443dee39f006758339db7b9b6f8a3b3f36399350711dee148ac0f3c07fb4358c41ef34f32f9954ad16f269c063bb6ea28e0e42c15b442a9569bef5fec38172c3c93e0ff6c2093c4ba068b386b778d0f54aabbc13d078e04bdcbce3264e93f79a8fb01cbba488971a6d139437e2a21c09c1fd8198f6288d64fb8c27611d125c8712abb46a8bc46aa08fd8b39801c9135c143e384dc1c860e02bace607691a49c7f4394cd25d9f415b40000e8d9dd0793dd29fadae3fedc7a303906a8c7e8d36dc108721379bf21c5a48d8695153ced3d54a77458bc10c98ec899fe9a41d2c251b270293d11e5c9cb97fe446d32e1631640856b483d6f824bfd0e7d66625074c0c253d9e070861895e25333ac7ddd18c5ab942e25e87afe22b7ea7ce52b1c44002a92bf6f5ab40954316f4492dda7472c6b54d757ce865f85f5726f8b836465e4fdefac7697e62a5de7e63ca90e9c0a77a2be7c16b1d8d62e4f66dff6643e226b2d1026499946f4d728cd50f2b9265f777ebac79afdb8036bf49207ef048a3910f43e5f998a4035f279bf4a6b6b498be2dc50bab77083bfa3e3cdb8f4d3b1bf83881b5a217d1d9e5e06d4318696500d2fb37530d1172c5f884b6e3e32f9acc2623748186644a053d2951d6320e82177b85742b7f54066a1f3e9e97a5d073387a3636faf04ef5d1d7f1f49213452aa260b3cf632305eadab51757b6028272d7dd49d8e0b8ef3d6722956c78666f7cb123c72c172437344dc7aec4da73739151f5b5e295d708a31f1c4d3b38e69887665e79dfa88dc137a3483af9131a11626bbd100076da1a5b27352795c09a5e38ac57634a119f3fad6b25f8f51b2f35055faa1d5ee546d4b698f34a0df17d93c745d2b85a1e36b5c092898e4d4ddd3b24bfe0b036ccb559094db1813b86d13234b37cb0a2ba767104c344c2a1df8368368f31686ed943f5fc556b53f3d2ea8825dd9d8188f74fcdf1c81d476d147a8367b2e9faacba2dd611cbdf42a9b8af5a2604e9f980190f1b75ddb9c61695355dd1fe40a15403c7427c88fafb14294013707c315b6b686d4a50688095329e67e2d4d47f0e3d61c40a300b5c8384a53150605e6bc49e306958cd7d6deaf1a0be10fc014d767434e1f40235631881ae1b8a98f2cdb1148762eab50758f5b4ffe0bc22e0d34b976624c6ae7de364e03a350a57dfa77049da8b8b3a0ef121e07bf2d6a330f6d1e36bd51fb71f877bf1dcec86f8ae868939e21afd435de9faef298ff0877825004a3594c95244a29b8936e0dc3c84c79e488c678075104097b4c8fce7af42543faf1922058d552ded72c7b8f4c797d05893b146661ced29b67a5f7b27947600258fcf501041102723da0abaa02ed22273da5605bc4a9289cdf3159c286d0343acd4f122297f6af131871df46dce542b39a6ed7cbbc98a57ca6931e71bc7cbf3d7635b1a1fceffe91ba114e2782d7d6cedd6e34118f014478e0621e6071af31665a655b3f0c6576503f1e966bdbedafeba52268e2dc33c5a047acdcf1320789ee9cad609f81740c3f1f08e60a9a348e5cb5b09ed03ea21856e63ab78eda0a82adb87f1301c9c451ab673c1e9ea8c37c619325a2a953496c2ad3d7d870248599a7cdb244e8494e20864720111c793f56a2031bf43f6db661d6872b236ff7274a6648e0d62294be14e042b40d6a8fbd36517741dda5d56be16e645202f0b2083c0ab79dec5c228af9a58642fc6c1f6fd78081ea387b0940f32508fca44957d8d314f8de635229f45c767fa41211dcc46219cc07a907c8070b849283f9a21bbc525eb51c88d15b876b11f54c1ccd54670f799b9496d5f1fa83de2a6ce8182a94a89754d8f04fdd15884a3bb8036adede9b9e25a2b20b68cf23d071fca9f19859187128a3d4771bfd2448267b5540ba760810717ef01447996e80cc9c718755a58c6fccd896d7397f32caaca1d1cfcde73496dbde4fc8059faa2f8d5acb0870a2441ded733e7f34307c53c7409cfe0181e34d703864859d2c3ccf501c385fc7c2ad19e612bfde1f584f63bdde9836c6d301134216e760e464582cb216e30591b1066f76d8ee7daaba0654c6c6b35ff88f1a6d966c411b807421f72042bcaad02611514b5e6910a1c570a733d9b71df048e27e8802f2693f11e46070072b0aa27bd4c3657bab49be92e43155c2af7edfbbdf64867e2106bb86cc47d540e4e74daa84eafa43bb7cae5e76815504d870b3ad26e311eaab5a7e116adce7573a06b23ee7e2b20793cd53b9db948d5936ecd4170a78db85bc628a2333e56322749ae70e88fe294addafd74ed7ab32d4f48913a581294cdf9ac9c8405a5345c8cacf0817ee157093831aa4589a4e249db5b494cb77d8899f5a1d8d78443296c838fec682518a5586ea5e94d199f5b6c1205272b69e621926e5695ba83ce027de02b556473f24fef4709876d08c8c5f18c89f6838cd9cae12",
"transcript_hash": "7146f5df910b17db791f5553b0a2c0d9f3b633b29bef0264d174de727b4123b65cd76753f5f88845518b80a6d590af7d",
"public_key": "c44773280a55df79134b7f4a37b75f9d2a77f3520ae82f172d1896a21d14384f92a5b26969a618abc71afe1fef312800253712494001d7b6720764bc8d37b824748315acd11f5834a29883794697b16542465bc7efd357311798d3184eb69907cf154ace7d1c077702438af8e7af954a265041f3618a40e6fd19db7a47e07a4ad6c83b5a179002baf9adb386737b8e6dd746377f815d0486ecc3b5ba79feb4d9412e1cb07afaa3406066cda8bb9f086c60a496b5f84013d4ec3a9adaf86823a4dba479570f99d2a71163b0a7026dac26b5d372da234288f19536614417ad47a96fdc7faf9a950ad0a46c650a4ecc008ae29132246ddd1a34ba4f30ccdcc1283e35467ad30d1fc3bd25d329aba5c03779ffc646c792065378b03b60b5a6c52cb3ba66c2b62a4989cc00f0cde737ffa61aaa09abaee0c26946472a0ac2335a6bab5d7f0880ca771d9cc0045b9151f0a7d90d9489fce8fe1d89224869757ac9f3eda94a0084df52af21af5ee109dbe75f84ef6c52e07a459b99675b09dfee9fb1437178cb27e4a711d15ecbb69293f135667deda7790a5b8848f6b5cbc5ad90e53b97787218170ac29745201c1cc24af9a17c4474bc894cbcaf18d09d982bc0ef38703c6ffb74526ac1dec8b31badcd80c4188ca72e592822d7dc19555fa7a534d3d83bb1666646220a0f8adfbd79ed1b69a9e741bac6511e093d55916a48a638b72faa9063b131aedce418ad555d1a4971d49d81e6da718a079525b93a8aaa3b4097ca16f3f2de9b2fe89c1e66db9c2e3bc2021d8f924dc1ff651bac61736943cdb04f9d9835acdf93faba04850daf4baf33fd549acfda52539ca5903a5cd6f102bbb020cab7f882b2a269cc1fd43f60c4a9b2f2426920ffab35d8609c7209f975030ec92060b84ddfd01875d13aa5063d0baa9d20ff83506acd5726884d88c080f3d29e45dafec62d6174c07ead83596654eea0341d1942d518b8b7c12f669a4007b49d533ba1afc966ef3024e8ee633a65d5a7b45978a3f0ab30e30331418307fe75e64a9777c249e337c88e3bbad11ccfe22365a3ac9acf2f07f2aa603f783465b4f2e217f138d91cdbccd1a5045dbf78b55597629003fcdfffb79c283127e46afb9e8db4c4e545f63411f3752dfd5311948c9fdfb1c2e96b6fcfb31d4ecb5e3991b7865fcf3c72aa45d4b405971566616accb22788a8d9288aabf64bb606d5ae45ddf3c0dfe52212bb177341ca6202babac26cc12e8c9fc4dff7dcfe2e6b000a91acc1c59e6718e1503c097c2480fb5176fe3af5d59930b8ef04260780595ad11658db1f5c2455f6a2990354f1cbdda024ffc0ef854d477b038ee9d3c7b34773e9779aefb19bbd8e68e6030816f7292d2f888d5d27697cd7c75fc24ab77a7444f6dc72d4574de159184a904509595a7525d2d9e905bce9471bf15359f761cb7eaaea588bcd18c1bcbdfd0db7c188232dc19b6949a3796cc1a99e581a159f8bd8dfd9e51fa9062d9d6c2b1792ce66585e693e92ea87c7d883242771940713fe00a0310a929cf0006b2c0b1e6a35f82dda9e86d7229df76870a3a0d37e436106788dc8490c9379a12fb67a6c1c8f44ed1e7c9401fc1c733414abf7efbe6c758f74c8b61d6ebd3ec1bb83b8a900515a454689913bdac84694b41097e4c4bca5df0a4369b0af213c4b96c80910419ef5b63eddce3c9dd66258f2b47b7a8f8009fe3f8769e7e0d410e3c5ad26076bc2dea5921f98cee8fa374f68c2a77f134b5d7ce2dd6036fb64c5ffa8ee155b6d581970da81181b8c4262aa7ce2ded9788cc42f2381bd4294cd09bc8973c876e34e629822b4091c9e6b103305a09d684d82711f1ab7657bc4c633c4e5ee6c31a2ecb26825eb6026edc57a4292f413abd0d23e8d7d523d3889f24aee0efdb01f13b6e1d6c57a124e6fe1cb66359325d48e00ebb7bfdf074ddad1bbb555568078826a32347ad3c21e68a1ff049f03c2e6dd2021991e80f6230abf05a72d6bc510e4d0e025427082ceab311dfb85a02482b443fdfee7a7f024e640224687f93c2e6033ad7add8fdee824739b1fc871f3eb219fdc5611c827678f5b9ed5a6d26b3050e7bb8ef5c7831a1a7c761483291010cef9984dba9e985cfb71f8b681c1814ed1a86b1f601c3921010fc6dc599d427634cdc6d3f640877954dd2fae627212bdc6f7701b1a024577b049ad2787a89a289f0da1c0946a3ed5ce0b18c3d18475c9a8de260069261cfb49c5b48b0fc86ada96a5fbaeb486e0932d7a574e0517c517b6460224fcc4ff240973199cb364e5e9c83f3a22d50521241bc43b8ccb330dbc613c4631af3b3b12f73c211c56fa7fda1ac67753919d09014692cedb8959e57f544963f6cb12e2f7a29f14fe299a1c7defe9e33b2cd2468a5a0054af16a4a908621492536290e40114e228ca81300772c7d92c765e810c673400d04a4a3c38624d3ab607af2a841fbbe68c57d9f52700a5d2dc1192399937b9e0fb6b7d38e67f58d76824d2f04053c24ad3b43591a6f4a3908681da1ae70f5241a3d1517d2f887929590d55fe961842b8d469e8014c520a5a1f96f0c3bf7767e24755ae13289b8718e6637d479d8f8b9a91ea09ad31b5a17b74e87f9af824178721eda028364f984aeea93919114c3a7ddef76ddf1ff21a25b470bbabfd0ac3a04c8c95f726d29cbb1d77d31552865b3fd54c7eeec6c3cc0cf7760151ec2e3dbdf415129324e9bc332b16d76172ccc00aa46941165ca611d94231",
"transcript_hash": "f703a2fbd7531a672cf6366c74f0b308f77c221f22b1b569e8acc7fe5e8e6003c3d56e45d9d40a0d820ea8b818a96873",
"shares": [
"00cf002100e6003a00a9002400500003006c003d005f00eb00f40050000900820099000b00f6006f000e002d00f2005c003b00c800ee000d00a900b100bd0057",
"0047000e005800fa001a006e00ca00d6009a0052008500bd00030076001300d200be006b00af00fe00cc00f600710008002700e00088007500ad0082008900ca",
"00e7001300a10055000400b40017006200d90022005500b2006800b7007000b3001a00a0004400060056005e005f006900dd005c004b0057005e00ab003f007f",
"00ad003000c0004d006700f6003900a9002800ae00d000ca00210012001f002500af00aa00b6008a00ae006700bc007e005b003d003700b400bd002b00e00077",
"009a006500b500e200420033002f00aa008900f500f50004002f008900210029007b00890003008800d300100087004700a30083004c008b00c90003006a00b2"
"000a007600b400e300ed000c00ef0037006a00a2002c002900f2008800e800b9007c001000600077004100ef00e500e8006900ad008e00d20041003b00ba0067",
"00cb00490028001d0008003e00a600e7001c003f00cd006800250018000600550076005c005500e20099001900d000fb001200e100a40095008900ae00130069",
"00b800b300d1009d00b8001d00ed00b1006300b9007a006500c2009a003600ec00420052008600e900dc008c004c00c400dd00130039003f003600fc00590063",
"00d200b300ad006100fb00aa00c30096003e000e0034002000c7000c0077007c00e100f300f3008c00090046005a004300c80045004e00d100490024008b0055",
"0018004900bd006a00d100e40028009600ae004000fc009a0034007000c900060051003d009b00cc0022004800fa007900d4007600e3004900c2002800a9003f"
]
},
{
"mode": "Pulsar-M-65",
"mode": "Pulsar-65",
"n": 7,
"t": 4,
"committee": [
@@ -50,16 +50,16 @@
"0600000000000000000000000000000000000000000000000000000000000000",
"0700000000000000000000000000000000000000000000000000000000000000"
],
"public_key": "93cb808332d041c11f29c830222a8e84712495ee9d83a513a089ae1c274c3021f2f774ccc165ef7876a6dbb13d5877b4304fbd96133520d3eaea1d18f8cf0724167f84045ff6c767d396b947db5d974006db4a34853ac3f19108dba9dd6ffd0fb4238e3631a4860af846956bd93cb4233ceb4394d23765640a39059460b1d7d42363cf3f2adc7f41b3da2504e43ae33095facf3af24b3d0f17de81ff2dd8514345f9af538467bb10e4bccc8d925556b588ca1d5412b66920e08b693b86a8910474c3a5abaed92431af944114d32d07b21106d2229e031553c83aa1916b26d38243526614e6bd17d3b5e078750b20a62cbed7f88abb3c0ddf30d9bb2653a42f389008bc2f07d5fe3f6b72e98fa74aa6a117a57d3e425d0cb1d51f8c852bd4fe871b74f63f2fd00e839ae004ea39068dadbf153b19fb0047944b0265c4f22ec299738cfc7d123d8155240c39f29108373274cb58109aacda1ba4972b6be3253e71171b1df536e62da1de4d55b359f2e9d788447bfdb3f4004cd68573e6bf63a9c54dd0c1295bcaddfc25917eeaa4b5305e35774ee72827c744520eb8a8cf9ac5e93fb1949586d477f04a9e508ed87e91c395f4180581af06048cde57cb76ae3479a400aeb0612943e39b619a70d47d70c9dfc33244845c8b68c6fe865718331c9d07046cb92f278acd314a764c28c6b083edd4931b35c1e189eee8045a840bc7f3f469fd81619be0c733d6dc9f5c2a8e6924db66a8bf6d28d30cf5feb92028d40e806aa26b306c8550bdbe0f5c35a18683c336c5a14dd2366d72b0c7527d21bbad2b3d7b77655cde6bede155efeb77f98f6cf465ac7f5bc09bbaa9bd7e847dcbddeb9945f02acc25dc3ab228a2a6fb737547c94febeb2889fba2e43bbef0b69a1185695c019ca7f7f18495cacde181aab9a3547faade8a08763312aec901eb90973d9e034e5bbcc954c8c8c88d23bfc2bb446bde2b38967defa839754eefdc2a9aa9a770e81a01db30522943700f463079b99b809ef9f4d7a0c141c099ddb5b203621a7e2f52431c70673833c7bf618ce0881a4b75133c0f6ca33e66e87a8911cb56fa08e9e570db29e41d66ac2be20fdfdf29b82eac2aeac6f4d81bae101bee2b759823ee5b24e7b2b34cf6d37563c31aed83ad5b9be3db6897ba8ca40df99b3e992694c3be4287f883d3a1155c9907f8e25728379c4d7cffd7a2920f2ea0547347e055a3cfa9152216721e355debcf918cec2403e7b2df6589fb3a17add579c54f5477d1a043a00b8f60d49ed760d5fd8a7148d3c49d3602272879be52458b90705b78ed274e7c06b732a8c04c40d53f6b6ac5d5ba3eb2b1851b7f0cae561c76ceaa9a4bad238875ed9cdc16049c7fdec4013bba6b189753aeb5e9ab1a518cac368746ba8896acfa1a22e4198164e8a9403d52a71cbefb3557303a247d20ea57513a1961209aaa67b78967396a76b187da3f2a64f185e2451a3ed880ddab78c84b23dfb6f7fb0d63a62237011f41525e1686a3c8a88db75de3b2f0849f28636e5b6695a61f15f4fd4b86275cb1f0a5a0bc92a231b5a08d2241336f0cdc16f2e85c17a852776bc63988ed86d5c4b19f3f6e519f877ac6d99939588626f13b8c2e510dec03048190485a7c31388d8d98f1df3c152166b101f9a2bbdb7a48bde8ebe993c4aca7bafc559f6485001caa29902dbfb1fd0f3ee66acdf9b2e0f7c4cd2e4c45e5a8d56288b9ab4ab0f3c3b9904f0b8f04c79d4617324459582c5932da9fad1322982248b28d1753532f42ca15a394b54d4da1d083c903babb8bcb389f59976a9a064facf5e2cf6097214651e31e28ed48ac10f955ef79a39359e82edfcaa7c2428a5a80ed970a6b2525724821a59dee68f63845dfc7377061b7f591f09fd6abb9f491ee24e2cf5be3d38e15e5eef12d17f175a06e0c71bc991b091b09dcc6ad099957582e09e441ca17473f9394200c0a8f6879c9637680ef7b4095d8f7a8edfd702bcbe1307437e0ee0280a662a42205d0750eb8e56bb395f92428ee257fdff1336d0b6d1f341cb69c36704fc8e8f520c73ce13425873195e39b5dfb62b5a96f43ade92e87e682ed45c20485a87d9453a56e1e1e6274164d1ce63e3e5159bcf69d76ffa4e4ea22d154ac9f64c9128f9c9e9032ae719ef7bcc97509ecec7830045aa27164510a742aa8293eb6ce34b0555d8f792df72ea5e1199bfbe883696696111e3e09723a3b7e2db8b4e23722671d935ff65857cbae0b8bf30e27864ac2fdb6ba6867b9ac57c87d27bf349edb87b615a0f2a19066536fde779c0f32f23e75f70fc6ce7d7f5358da2c9b3199ea634514ecd61554502d9c094e6dc762d9fa0896c06f79570657868a8252b587566c1bb75aa1b2625af1bd91f82315be29ad8d539f7d929f851e257cff94478b86569a8a4dcabb2b82065860b2578446ef12914e73a5ead2435ea471965f2eff6780b4ec394f57c2533318dee2225117150b0a5c7f1413c2768e9613e0880d8fcbe2e4662e1c9dea3fca12c94d1b5e1ca8fc655743dd9dc2df87aa2996751975fbc1da2966ad32265a6a73aeaa5b858fdef7fa11274f81f958991b888d14e630b76f2155e42de30843b41a6def2c1978d1c2083f385af6c1e6c69e705ed3296c75a78e437a7a07eb5ecbc8f1824287a6e075a750729f0275ee768da5167c9312372febe3f79520ac0669ae7b4942cb590ec4ab5d9897e3cc0f27697dc813683909f9b541d464b42452100bd3b2fad974",
"transcript_hash": "02563349dacb35616a76320d660ad9972200c45a82202171007a5fc334503436eaf9b3d980d3ea75d460d8e8dc63d93f",
"public_key": "42e29990bb3b554e0643411a6d114dd008e4a7f6722f914b99f3a8480602acf2e6775cbc3c58662d77f08cf41f4edc25147c09868f7c3c7060de803984f01a0c6ef5480921e83eaaca5d460310794fad76de857d45f3eb691691651345f0c95691b27faeb451cbb379e5718253bd4ff54213af54027bd4d336786802d2f1e98ea83fa1e722997dc5fbd6e2572a0cfd33e0357167f16181808740b030a41279a61efed5816e8b96f9b0719773dfd4f7420084450deb5cd9efdc9d550a61e45a9c287122083c1b9452f1f775b2efd00d972397c65e3f23a0d6a7b742d3422a64e883e6e3949b647048c2457a954bac2436d3e8858de5d891d016a1ad7d0fcc3930b56ae52d641b8f1ca6129aabbb65f463978cd371c9bada8508243b5966cc08ceaf543b8eb3645107c8a057d6427ac908e605b1c273b54352e47925c40583d2ac1abb0810ba8d93e403c9ff83647f90d20292786fce9828bd6713c9a603c846a0b2a5e7ab856072af588c1a8c7db1bed38ea9dd25590913304d815b1347631162ca5587a143f36c2d54e14de328013e458692d7fabcd882839d07857c904e041521cb52b7937c3fad4563649f8780de27b0200ec2189d89c60fa1a6b117343051dd421a2404fa330b29670bd2853e622f4ef4d01c1c11f2b2b7b0a4b76d83056fd63b3d6ce29a124e50258d80c147c21a82d868d016413d2289b4d2d7df20f486c6f46045710720f433c413f4fd692e517c206055bb0e576e57ace2038d333b2c3f1a1c886adad243a0c1118c353ef63d51118f9c9eed1f2bdfcc66de5055ab4e5f000909e9191a77e86cf89f023c447c84c504fd6b279600e4cf728085095d10acece6e7d1ee4dd2e1cf097073d3831db59ef5ad7040214ba9cfb8aabaf5203423138c54cb075008e65f8db068bd0f9d1e0079cf5edf39bb3037c72ed1b9ad484ab2f489e2472abd57e26a00527f62f623d4e5a29ebdabc3b1547d1176e894e710cae17a79b576cb4ecf82b9c78a1ec7cc026391b46a17faec31cbe38f5712930643e6116dd4ef7123cb8ba01ae2781af4c22cff23be912c1301ee066ba30e434b61036b3bee6617e4d2b873a812008cfed14cebfd249b5f57a28e7e59bd6558fa036d58dcfcb6f48ac64a772d4345d6244eedfbdeb33a233caf85ef37f75f028f4fd2bc7850003eea389076ac158f524cf6220ca4b07b13f690bc04da735ef4ffda0c5b49e1d22b34ad8bc7e0fa1bd76af95fc2ffe16539fdc7b2e4f418fe4be279b05c79151b385dd63b319991dc67ff4496063b35b4bf6130851fd9945512953ee999de503a57e3bfd41e949dc96efa6d2d825297e1590a52a5a46c58f9015c4f7ab43b0a5101754f3ee048402386eb9e29260c0ed0003928f4910dc7c81bac58e6f77e3701dc9b1b470e7c59a68b7c4ca3ecf6c23827c4a3cbf4289866ee5fbdccd2d660c1632c8d026425fe7d9b2c7d5299a8accd1b9dc74111ca5f392a4dd7a2db5a8a2b9f8bfb5f1f010f1e276d5a14ed30eea0d56c2fe2500f6112d16979666df5ca90d0ca1822896c97aa1ef769589e21841687d55a6ec482dd7e80446aff253cf476b0979e49715decbaa9cd0181ebda1240c4ca31b634f149d45118b0f8fb69194b3ff1c7028d7feb2cc45a48e72b760188def60ad5372953ac94829e5af6da9718fa2705cdf17427d34aebe42fa0b3e37a7e282c16daad2d330d8bc3150883548cbd78583e6496783a7ca9e91f0d9ad866309e17d7b0f9af989eba33922d456e5f0e0dd6dc9e06ae422e8ff0732c2a4f158a368ab7fa88357ef5876ca1c5746c1094a0af36fb11d16be3042350fc733f161f3770eca0084d7ba529f487418ffbeeee0a8820692b902637a23e83fa643cb0e6738a2013606fc64ae0b8816bb14f798e3bd270dd25b6adb7ecf6e90fc3b569326aa9ba7240002214e37735489231e46cbf26bac3f6e6648f13c8ca49f6e52f4b20ac9d4dd1daef6cba24301fe082f62131b2f1bafdd753fa537e884ce3fbf73bee6f1625ceea7e1f303bb46f6d1b8a70345b60b1d20430bdf64fdda61ec301c36d8be7482336b2f4a4ee28a73d11d9a76b7e891c4e4be983bab74f2719d2a68596097ebbb965dd770adca761ce99bcd285f66975a3c3e7b29f396df9116e9294571057407a12fed31854cdc3cdf159913e77e937190cd832e80859211d13235d756b7e65b719302bbc86605824ccd886dc3cf6a344b2eb456a3b38127dda6e99f55a1bcd073957f56b721fb4a0ff4424cd63d82a9431517b05a523d5f63e8e5a237f5c5da82397473b8deb34ea9c502e3332938d921cf0407a7f5825dd178081a57ad36062ff594fb6dc5012091676ef0d90f2d69c6799569483cedd4371bb71af89eb60e8f7b9d93a2d3c3e18eb9b66f93d7060d79a8dbdf254a4f0b8837e5c064c4b541838a0e8a4a03353523866a21d3ef4eaffa9e9a2ffdec52e42e62adbd1d8f78295d30f61b378bbed9ea760dcf2f053943f4538888a397d0aac222366ab4825e651bb9fd0bd611c687ff5977f58e85f35712b94d74197e223b5436d735c8f6261dbe1c15edbf750107e1667f7bd74d6c8e2689b7f8ccb5b0bde113ab10ccc5db3fdc0cdb0cc53cd5bd6def4896955a43e9685c615fe391a9b2170ecd54e7374be592442925ced27fa0bf980f5d5ce24af82b052831af1467c661d0e7149b6c85d8eacc4d217cd89b047b44d17e9d19cac72903b93139ef38ad340bd8744ebdbec64422f3f",
"transcript_hash": "ca29f49e0dff709871da74e052384466bce6c440ee04231bb5cdd852db9f76875209b18eeb530363230a663b661ac973",
"shares": [
"00da00a0000b00d700c600d60073001300b800490087000f00f60064006c004100560057009800180054001d008e006c00e2003e00ac0036003d00fe00dc0046",
"00c4004300500049004d00af004e007f00dc0037002700de00d700280010000a00aa0001004f0046006100fc005a005e0024008b00580024004000e00072000a",
"00e900100054002400d00047005300b200e700d90030000100f300fd001100d30046006200a000050100008f00e500b7007f008c00b2003000e200a000860077",
"00ed00b5008c006600cc00cc005b001700900047008000610068001f000800c100e900cf00eb00cf005f002a00bf00aa0078008c006400c00039001300d900b8",
"007400de006c000c00c00069003f001b008f009d00f500e3005600d0008f00fc004e009d0090001a00b00020007a006b009600d6001a0038005f000f002b00f9",
"0023003800690015002a004c00d90029009b00f4006c006c00dc004c003e00aa0034002200f10061002100c400a8002e005f00b400800100006b0069003f0065",
"009f007200f8007f008a00a2000000ad006b006500c500e4001700d400b000f3005800b5006d001b00e4006700da0027005a00710040007b007500f600d60029"
"010000ef00d40069001f00c000650008002500210089003e00a1006000250062007b005c00ad004800f50096004c00c800d9007c00a9003f00bb00fa00af00d9",
"009d010000b50019004b000c0032004900f200250043008b00d700e6003a0030004b00d2003800490091006300dd007100ba000900f100e0007200f000a200f6",
"002d000e0098007400b70005005000de0000005d0090006100e3000700c800d40100004b00f200e9008500be0033008d00a800e500f900b9007c0035003100a3",
"002c002000f3007600fe003c009d0089005200b4003d007d00e00011000300470079002f001600ca00620052003c00cf00b8005d002c00d4003700c000dc006a",
"0015003a003a001c00bb004200f7000e00e700140019009b00e9004f00230086009900e500e5009000ba00cd00e400ea00ff00c300f8003900020084001f00d5",
"0064006100e50064008a00a9003b003100be006a00f300770018000c005d008b004000d2009a00df001d00da001500910091006500c600f3003c0077007b006c",
"0094009a0067004a00060001004900b500d800a0009700ce008a009500e700510050005d00740059001e002500be007800840094000200080043008e006d00ba"
]
}
]
+9 -9
View File
File diff suppressed because one or more lines are too long
+27 -27
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+18 -18
View File
File diff suppressed because one or more lines are too long