terms
• server seed: 64-character hex string generated using crypto.randomBytes(32) and hashed with SHA-256
• drand seed: essentially your client seed from other modes, ours is from https://www.drand.love/ - it's public, unpredictable and verifiably random information
• nonce: always a 0, but means the round number in other modes
• drand round ID: points to a future randomness value on the drand's public timeline
• HMAC: cryptographic function that mixes unhashed server seed, drand seed and nonce to produce a result
here's a 3rd party HMAC tool to verify each step for yourself: https://cryptii.com/pipes/hmac - (or any other one you prefer)
how HMAC is used to get the crash point, example round to demonstrate
server seed: 72ebf12bfaf8d996438fcf8a4a88c01dbb022c05f4ac831b392d196a67ff9261
drand:
95812946c71502a50b85c0b6c8ad0bb821de4d5a2c011717ba0a668843295bfecd85aee347544c89cf809bad32a9d3fc
first, the drand randomness is converted into bytes and decoded to UTF-8
invalid sequences are replaced by unicode character " " (U+FFFD)
some byte sequences can't exist in UTF-8, this is standard for text decoder and doesn't affect fairness
use this command in browser console to easily decode the Drand
use this command in browser console to easily decode the Drand
const d='REPLACEWITHDRAND';console.log(Array.from(new TextEncoder().encode(new TextDecoder().decode(Uint8Array.from(d.match(/.{2}/g).map(x=>parseInt(x,16)))))).map(b=>b.toString(16).padStart(2,'0')).join('')+'3a30');
(the 3a30 added to the end is due to the nonce value, this is 0 for every round which means it doesn't change)
here's what the provided Drand Randomness looks like as hexadecimal bytes: efbfbdefbfbd2946efbfbd1502efbfbd0befbfbdefbfbdefbfbdc8ad0befbfbd21efbfbd4d5a2c011717efbfbd0a66efbfbd43295befbfbdcd85efbfbdefbfbd47544cefbfbdcf80efbfbdefbfbd32efbfbdefbfbdefbfbd3a30
that with the HMAC key (unhashed server seed) gives the following hexadecimal value: 663e918e0174be61054c5a4eaec63328f5fc1d626f5be4a00801271fa8acc04d
how does that equate to a crash number
the first 8 hex characters are used from the final string, in this case "663e918e" then converted from hexadecimal -> decimal (663e918e -> 1715376526)
here's the formula to calculate crash point using the decimal value: (2^32 / (1715376526 + 1)) * (1 - 0.001) = 2.50130059562
the final crash point was at 2.50x as can be verified using the fairness/verify page
but your minions are doing tricks in the backend to make it crash
Drand randomness is public and verifiable, Duel doesn't have control over it. the hashed server seed and drand round ID's are visible before the round starts, this locks in the result - proving it can't be altered or manipulated by anyone
Drand round ID and the corresponding Drand Randomness string can be found here: api.drand.sh/v2/beacons/quicknet/rounds/22842664 with 22842664 being the round above
due to the drand value being public and random, committing to a certain drand round ID and server seed before the drand itself is published means not even god himself could rig the game
TL;DR
• drand acts as the client seed from other modes
• duel's server seed signs it
• combination of drand and server seed decide the multiplier
• everyone can verify every last bit for themselves
if a drand round is committed to & the hashed server seed is shown before the round starts, it's provably fair.