-1

I'm working on a "provably fair" site where let's say X participants enter into a drawing and we need to pick first 1 overall winner, but then ideally we also want to pick N sub-winners out of the X total.

(for the curious, the SHA-256 Hash will be the merkle tree root of a Bitcoin block at a pre-specified time)

So, given a SHA-256 hash, how do we generate N random numbers?

I think I know how to generate 1 random number (within ruby's Fixnum range). According to this article: http://patshaughnessy.net/2014/1/9/how-big-is-a-bignum

The maximum Fixnum integer is: 4611686018427387903

Let's pluck the first Y characters of the SHA-256 hash. We can generate one instead of relying on a Bitcoin merkle root with:

d = Digest::SHA256.hexdigest('hello')
> "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

Let's take the first 6 characters, or: 2cf24d

Convert this to base 10:

'2cf24d'.to_i(16)
> 2945613

We now have a unique Fixnum based on our merkle root.

With X participants, let's say 17, we decide the winner with:

2945613 % 17
> 6

So assuming all entries know their order of entry, the sixth entrant can prove that they should be the winner.

Now -- what would be the best way to similarly pick N sub-winners? Let's say each of these entrants should get a smaller but still somewhat valuable prize.

p4x
  • 1
  • 1
  • This sounds like a dusty illegal gambling operation. The chain certainly has enough of those. – Jeremy Mar 01 '16 at 03:29
  • Crypto.SE: [Getting an integer from bytes](http://crypto.stackexchange.com/questions/8826/map-bytes-to-number), [Using a hash as PRNG](http://crypto.stackexchange.com/questions/9076/using-a-hash-as-a-secure-prng). Those are the pieces, now go have fun breaking the law. Try not to get hacked before you get arrested. – Jeremy Mar 01 '16 at 03:51

1 Answers1

0

Why not just use the hash for the seed?

[*1..17].shuffle(random: Random.new(0x2cf24d))
# => [15, 5, 9, 7, 14, 3, 16, 12, 2, 1, 17, 4, 6, 13, 11, 10, 8]
[*1..17].shuffle(random: Random.new(0x2cf24d))
# => [15, 5, 9, 7, 14, 3, 16, 12, 2, 1, 17, 4, 6, 13, 11, 10, 8]

EDIT: This is dependent on Ruby version though - I believe shuffle is different between JRuby and MRI, even though Random produces the same sequence. You could circumvent this by implementing shuffle yourself. See this question for more details. This workaround works consistently for me in both JRuby and MRI:

r = Random.new(0x2cf24d)
[*1..17].sort_by { r.rand }
# => [14, 11, 4, 10, 1, 3, 9, 13, 16, 17, 12, 5, 8, 2, 6, 7, 15] 
r = Random.new(0x2cf24d)
[*1..17].sort_by { r.rand }
# => [14, 11, 4, 10, 1, 3, 9, 13, 16, 17, 12, 5, 8, 2, 6, 7, 15]
Community
  • 1
  • 1
Amadan
  • 191,408
  • 23
  • 240
  • 301