-
Notifications
You must be signed in to change notification settings - Fork 147
feat(prover-ray): shared randomness public input #3766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0641653
aaa41ab
3c1d83a
487a4df
b1a2190
fc86cf1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,24 @@ | ||
| // Package preflight implements the pre-phase that establishes a shared | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this package is never used
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but it will eventually be used once we wire it with the arithmetization to concretely compute the shared randomness. |
||
| // Fiat-Shamir seed across shards without a coordinator. | ||
| // Package preflight implements the pre-phase that establishes γ, the shared | ||
| // Fiat-Shamir seed the message bus binds every shard against. | ||
| // | ||
| // Each shard receives the full collection of cross-shard column sets S_1 … | ||
| // S_n. It commits to each set with FRI (obtaining Merkle roots R_1 … R_n), | ||
| // maps each root through an [AdditiveHasher] (landing in a commutative group), | ||
| // accumulates the sum A = Σ AdditiveHash(R_i), and converts A to a | ||
| // [field.Octuplet] via [AdditiveHasher.ToSeed]. Every shard that holds the | ||
| // same S_i data produces the same octuplet regardless of processing order, | ||
| // because the group operation is commutative. | ||
| // [Run] takes the full collection of bus input sets S_1 … S_n — one per shard — | ||
| // commits to each with FRI (obtaining Merkle roots R_1 … R_n), maps each root | ||
| // into the multiset-hash group, sums them, and compresses the sum to a | ||
| // [field.Octuplet]. Because the group operation is commutative, the result does | ||
| // not depend on the order the sets are processed in, so no coordinator has to | ||
| // impose one. | ||
| // | ||
| // The octuplet is used as the Fiat-Shamir seed: each shard's prover and | ||
| // verifier call [wiop.Runtime.SetFSState] with it inside a | ||
| // [wiop.Round.RegisterPreSamplingHook] so the shared challenges α and β are | ||
| // derived from an identical state on every participating shard. | ||
| // This runs in the orchestrator, once, before any shard proof is produced — not | ||
| // inside a proof. It cannot run inside one: it consumes every shard's data, | ||
| // while a shard's prover holds only its own, and a verifier holds none at all. | ||
| // The resulting γ is handed to each shard as a public input; see | ||
| // [github.com/LFDT-Lineth/lineth-monorepo/prover-ray/zkcdriver/risc5.RegisterSharedRandomness] | ||
| // for how it enters a shard proof, and why a shard leaves it unconstrained. | ||
| package preflight | ||
|
|
||
| import ( | ||
| "github.com/LFDT-Lineth/lineth-monorepo/prover-ray/crypto/koalabear/fri" | ||
| multisethashing "github.com/LFDT-Lineth/lineth-monorepo/prover-ray/crypto/koalabear/multiset_hashing" | ||
| "github.com/LFDT-Lineth/lineth-monorepo/prover-ray/maths/koalabear/field" | ||
| ) | ||
|
|
||
|
|
@@ -32,23 +34,21 @@ type BusInputSet struct { | |
| Encoders []*fri.RSEncoder | ||
| } | ||
|
|
||
| // Run computes the shared Fiat-Shamir seed from a collection of cross-shard | ||
| // column sets. | ||
| // Run computes γ, the shared Fiat-Shamir seed, from the bus input sets of every | ||
| // participating shard. | ||
| // | ||
| // For each set s it commits to s.Table using s.Encoders (obtaining a Merkle | ||
| // root), maps the root through hasher.Hash, and accumulates the results with | ||
| // hasher.Combine. The final accumulated value is converted to a [field.Octuplet] | ||
| // via hasher.ToSeed. | ||
| // root) and accumulates the root; the final accumulated value is compressed | ||
| // into the returned octuplet. | ||
| // | ||
| // The result is deterministic and order-independent as long as hasher.Combine | ||
| // is commutative and associative, ensuring every shard computes the same seed. | ||
| func Run[P any](sets []BusInputSet, hasher AdditiveHasher[P]) field.Octuplet { | ||
| acc := hasher.Identity() | ||
| // The result is deterministic and order-independent. Callers must pass the sets | ||
| // of *all* shards: a γ computed from a subset binds only that subset, and the | ||
| // shards left out would be proving against a seed unrelated to their own data. | ||
| func Run(sets []BusInputSet) field.Octuplet { | ||
| acc := multisethashing.Identity() | ||
| for _, s := range sets { | ||
| cs := fri.Commit(s.Encoders, s.Table) | ||
| root := cs.Tree.Nodes[0] | ||
| a := hasher.Hash(root) | ||
| acc = hasher.Combine(acc, a) | ||
| acc = multisethashing.Combine(acc, multisethashing.Hash(cs.Tree.Root())) | ||
| } | ||
| return hasher.ToSeed(acc) | ||
| return multisethashing.ToSeed(acc) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package messagebus | ||
|
|
||
| import "github.com/LFDT-Lineth/lineth-monorepo/prover-ray/wiop" | ||
|
|
||
| // ensureCoinRound returns the round on which [Compile] declares the shared α | ||
| // and β coins, allocating it if it does not exist yet. | ||
| // | ||
| // A sharded protocol needs this round *before* [Compile] runs, so it can | ||
| // register a [wiop.Round.RegisterPreSamplingHook] that seeds the Fiat-Shamir | ||
| // state with the shared randomness every shard agrees on. [Compile] calls this | ||
| // same function rather than repeating the lookup, so the round a caller | ||
| // pre-allocated and the round α and β land on are the same by construction. | ||
| // | ||
| // The result is one past the last bus-impacting round. In the sharded RISC-V | ||
| // layout that means: round 0 commits the program verification data, round 1 | ||
| // commits the columns the message bus reads, and the coins therefore land on | ||
| // round 2 — after everything the bus binds, and before the shard-specific data | ||
| // that must not influence the shared challenges. | ||
| // | ||
| // Call it after every [wiop.MessageBus] entry has been declared and before | ||
| // [Compile]. The round is derived from the participant columns, so an entry | ||
| // declared afterwards can move Compile's choice and leave the hook stranded on | ||
| // a round that no longer carries the coins — a divergence that produces | ||
| // mismatched challenges across shards rather than an error. | ||
| func ensureCoinRound(sys *wiop.System) *wiop.Round { | ||
| return ensureRoundAfter(sys, latestUnreducedParticipantRound(sys)) | ||
| } | ||
|
|
||
| // latestUnreducedParticipantRound returns the highest-ID round touched by any | ||
| // unreduced [wiop.MessageBus] entry in sys, or nil if no such entry exists. | ||
| // It mirrors the logic of [latestParticipantRound] but operates directly on | ||
| // sys.MessageBuses rather than on a pre-built by-handle map, so it can be | ||
| // called before [Compile] has grouped entries. | ||
| func latestUnreducedParticipantRound(sys *wiop.System) *wiop.Round { | ||
| var best *wiop.Round | ||
| for _, mb := range sys.MessageBuses { | ||
| if mb.IsReduced() { | ||
| continue | ||
| } | ||
| if r := mb.Round(); r != nil && (best == nil || r.ID > best.ID) { | ||
| best = r | ||
| } | ||
| } | ||
| return best | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Combine is never used, yet it is this feature that guarantees that the randomness is the same between the shards; what are the shared randomness tests actually testing ?