FairRandom

class FairRandom(seam: Seam, peers: Set<PeerId>, tamperedReveal: Boolean = false, fixedSecret: ByteArray? = null, fixedNonce: ByteArray? = null)

Two-phase commit-reveal protocol for deriving a shared random Long seed.

All peers (including the local peer identified by seam's Seam.selfId) participate. Once every peer has committed and then revealed, every participant derives the same seed:

seed = first 8 bytes of SHA-256(H(id₁ ‖ secret₁) ‖ … ‖ H(idₙ ‖ secretₙ))

Per-contributor inputs are hashed as SHA-256(peerId.encodeToByteArray() ‖ secret) before combination, making the seed framing self-describing: the 32-byte hash domain-separates each contributor by identity, preventing length-extension and ambiguous-split attacks. Contributors are sorted by PeerId value (lexicographic) before concatenation so the result is deterministic regardless of reveal-arrival order.

Abort resistance

A last-mover peer can observe all other peers' reveals before deciding whether to reveal, allowing it to abort when the outcome is unfavourable. This is a known limitation of the basic commit-reveal protocol. Applications enforce forfeit semantics for abort at the game layer. Full abort-resistance requires threshold signatures or a VRF — out of scope here.

A peer that never sends a reveal (or never sends a commit) will cause roll to stall until the coroutine is cancelled. Applications should apply an outer timeout. Similarly, a seam that becomes us.tractat.kuilt.core.FabricState.Torn during either phase will never deliver the missing message; callers should observe seam state and cancel accordingly.

Usage

val fairRandom = FairRandom(seam, setOf(aliceId, bobId))
val seed: Long = fairRandom.roll() // suspends through both phases

FairRandom is single-use: each roll is a fresh protocol run. Create a new instance for each roll if repeated rounds are needed.

Parameters

seam

the woven seam shared with all peers.

peers

all participant PeerIds, including seam's own Seam.selfId.

Constructors

Link copied to clipboard
constructor(seam: Seam, peers: Set<PeerId>, tamperedReveal: Boolean = false, fixedSecret: ByteArray? = null, fixedNonce: ByteArray? = null)

Functions

Link copied to clipboard
suspend fun roll(): Long

Run one full commit-reveal round and return the agreed seed.