The only way to get a trust-less random value is to have it distributed and time-locked three ways, player, server and a future-entropy.
In the demo above, the moment you commit (Roll-Dice) a commit with the hash of a player secret is sent to the server and the server accepts that and sends back the hash of its secret back and the "future" drand round number at which the randomness will resolve. The future used in the demo is 10 secs
When the reveal happens (after drand's particular round) all the secrets are revealed and the random number is generated using "player-seed:server-seed:drand-signature".
All the verification is in Math, so truly trust-less, so:
1. Player-Seed should matches the player-hash committed
2. Server-Seed should matches the server-hash committed
3. Drand-Signature can is publicly not available at the time of commit and is available at the time of reveal. (Time-Locked)
4. Random number generated is deterministic after the event and unknown and unpredictably before the event.
5. No party can influence the final outcome, specially no "last-look" advantange for anyone.
I think this should be used in all games, online lottery/gambling and other systems which want to be fair by design not by trust.
hackingonempty3 days ago
> The only way to get a trust-less random value is to have it distributed and time-locked three ways, player, server and a future-entropy.
Are you sure? The protocol described in Chuck Norris book Applied Cryptography seems to work fine without a randomness beacon. Once you get the commitments from all parties they reveal the nonces and everyone verifies they match the commitments and extracts the same random bits.
rishi_blockrandop3 days ago
Great point—Schneier’s two-party protocol is the foundation... However, it suffers from the 'Last-Actor/Last-Look' problem in a client-server environment.
In a standard 2-party commit-reveal, one party always learns the result first. (Mostly servers in current setups).
By adding a Randomness Beacon (Drand) as a third entropy source, we solve two things: No Last-Look: Neither the player nor the server knows the outcome until a specific future timestamp (the Drand round). Forced Resolution: Since the Drand signature is public, once that round passes, the result is 'locked' by math. The server can't hold the result hostage because anyone can pull the Drand signature and verify the result themselves.
CGMthrowaway3 days ago
Right. In a strict two‑party client‑server provably fair system without economic penalties or extra trust assumptions, eliminating last‑actor bias requires external future entropy (or an equivalent third uncontrollable source)
rishi_blockrandop3 days ago
Exactly. For a web app where you can't easily "slash" a server for disappearing, you need that "uncontrollable third source" to force the game to finish.
I looked at VDFs and custom MPCs, but they felt like overkill for a dice roll. Drand is basically a "pre-computed" MPC that anyone can verify with a simple curl. It hits that pragmatic sweet spot for a trustless audit without the "math homework" for the user...
hackingonempty2 days ago
For others learning about this, the attack this project addresses is someone (maybe the web server) waits until everyone else reveals their committed bits then they alone know the outcome and if it is unfavorable they don't reveal and possibly repeat the game until they get the result they want.
rishi_blockrandop2 days ago
Spot on. By using Drand, we move from Optional Reveal to Deterministic Resolution — the result exists publicly the moment the round closes.
It turns the server from a "Judge" into a "Timestamped Vault" that can't hold the outcome hostage if it's unfavourable, giving the player a winning ticket they can verify independently.
rishi_blockrandop2 days ago
Thanks to everyone who poked at the site yesterday! It provided a great stress test for the architecture (Go + Firestore + Cloud Tasks).
For those interested in how a "Time-Lock" UX performs with a technical audience, here are the final numbers:
Total Reach: 370 hit the commit endpoint (Dice Roll).
The 10s Retention: Despite the mandatory 10-second wait for Drand entropy, we saw a 90% completion rate (333 revealed vs 37 abandoned). This suggests that for verifiable randomness, users are remarkably willing to trade instant gratification for proof. The abandoned commits are in read-to-reveal state in our database, can be revealed anytime.
Fairness Audit: A frequency test on the last character of the hex-randomness across all 333 rolls showed a healthy distribution (range of 13–29 hits per char), confirming no architectural bias during the surge.
If you’re interested in implementing trustless randomness for your own project—whether it’s for NFT minting, on-chain gaming, online casino, giveaway selection, or cryptographic auditing, you can reach me at [email protected] or dive directly via the [https://github.com/blockrand-api/blockrand-js].
I’ll be hanging around the thread for a bit longer if anyone has more questions about the Drand integration!
WatchDog3 days ago
Clicking the button sometimes displays an error:
Error: JSON.parse: unexpected character at line 1 column 1 of the JSON data
Looking at the network tab, the POST request to the commit API returns a 409 error with the message: Commitment already pending for Round 26020619. Please wait for settlement before starting a new round.rishi_blockrandop3 days ago
Oh yes, its only one commitment per call... this is a UI handling issue, will resolve it... the backend by design only takes one commitment per player, till it is resolved/revealed... Thanks
WatchDog3 days ago
This happened on the first click opening the page, no other commit request in progress from myself, although maybe it's conflicting with other users.
rishi_blockrandop3 days ago
Oh ok... so then thats definitely a bug then... actually drand issues randomness every 3 seconds... so may be multiple on the same drand round has a bug... will correct that... Thanks
rishi_blockrandop2 days ago
I just checked the code and it was a small demo/front-end issue of assigning the player_id (in javascript)... have corrected it now : )
The logic of back end api (written in go, commitment stored in firestore), is intact, the 409 will come only if the same user tries to commit again before the reveal, this is by design.
rishi_blockrandop2 days ago
The reason for having a deliberate delay (10 sec here in the demo) is that I think 'the next round' (of drand for example) is a security anti-pattern.
If a server sees the Drand beacon just a few milliseconds before the user's commit is finalized, they can 'veto' a winning roll by dropping the packet.
Is 10s of UX friction a fair price for a Time-Lock that ensures the result literally doesn't exist anywhere in the world at the moment of commitment?
rishi_blockrandop3 days ago
The current time (in the demo) is fixed around 10 secs, but it can be anything, minimum being 6 secs (as the fastest) Drand pulse is 3 second, and some latency buffer...
charv3 days ago
Cool stuff! I seem to have found a bug — often when I roll, I get this error and no roll happens:
Error: The string did not match the expected pattern.rishi_blockrandop3 days ago
Hmm... I have not been able to replicate that... Can u screenshot it ? Thanks for trying it out : )