Author

Topic: Rocketpot Seed Event (Read 293 times)

legendary
Activity: 2604
Merit: 2353
May 29, 2020, 01:33:49 PM
#13
Thank you very much for these very precise and clear clarifications RHavar.  Smiley

But now, I don't understand why you're dividing "97" by this number :
crash = Math.floor(97 / crash);

I'm sorry for these questions but I'm trying to understand how that works.
TYVM RHavar

So the first thing to note is that a final outcome of 123 means a multiplier of 1.23x. So `123 / crash` is easier to reason about if you think of it more like `1.23/crash` in maths terms. And as we already discussed, `crash` is evenly distributed between 0 and 1. So if you wanted to simply turn it into a multiplier you'd do:   `100 / crash`  ... but no casino is going to do that, as they need a house edge for themselves. I know bustabit effectively uses `99 / crash` to make a house edge of 1%, but rocketpot is using `97 / crash` which is going to result in a significantly higher edge (of which some will be used to fund the bonuses/jackpots/other benefit thats bustabit might not have).
hehehe TYVM for those very useful explanations  Smiley
You should have added the part on the house edge in the comments of your code IMHO, in order to allow people to easily compare the house edge between the different crash games "clones"   Wink
legendary
Activity: 2557
Merit: 1886
May 29, 2020, 01:08:52 PM
#12
Thank you very much for these very precise and clear clarifications RHavar.  Smiley

But now, I don't understand why you're dividing "97" by this number :
crash = Math.floor(97 / crash);

I'm sorry for these questions but I'm trying to understand how that works.
TYVM RHavar

So the first thing to note is that a final outcome of 123 means a multiplier of 1.23x. So `123 / crash` is easier to reason about if you think of it more like `1.23/crash` in maths terms. And as we already discussed, `crash` is evenly distributed between 0 and 1. So if you wanted to simply turn it into a multiplier you'd do:   `100 / crash`  ... but no casino is going to do that, as they need a house edge for themselves. I know bustabit effectively uses `99 / crash` to make a house edge of 1%, but rocketpot is using `97 / crash` which is going to result in a significantly higher edge (of which some will be used to fund the bonuses/jackpots/other benefit thats bustabit might not have).
legendary
Activity: 2604
Merit: 2353
May 29, 2020, 12:31:15 PM
#11
Hello
I'm sorry but I don't understand that part

       // Step 3. Calculate crash = r / 2^52, uniformly distributed in [0; 1)
      const twoPower52 = Math.pow(2, nBitsToUse);
      let crash = r / twoPower52;


I don't understand why we need to divide this number by 2^52?
The result will always be <=1, no?


I think I'm the original author of this, as it appears to be copied from bustabit. I was just trying to convert a sha256 hash into a number between 0 and 1 (and then turn that into a multiplier). The most obvious and correct way to do this would be simply get the hash (as a number) and then divide by 2^256. But as the original bustabit was written in javascript (both the server and client), I wanted to approximate that in a simple way. Javascript's only number type was a 64 bit floating point, which means it can only represent integers accurately up to 2^53 - 1. So the cleanest number less than that is 2^52, which is the max number if you read the 13 hex characters of a hash.

So basically the logic is "read the first 13 hex characters from a hash, parse as a number, divide by 2^52" and now you have a number scaled between 0 and 1.

But it's really just an artifacts of the limitations I was working with at the time (e.g. python if i was working in python, I would've just done divided the whole thing. Or if i was working with a language with proper 64 bit numbers, would've done that, etc. )
Thank you very much for these very precise and clear clarifications RHavar.  Smiley

But now, I don't understand why you're dividing "97" by this number :
crash = Math.floor(97 / crash);

I'm sorry for these questions but I'm trying to understand how that works.
TYVM RHavar
  

legendary
Activity: 2557
Merit: 1886
May 22, 2020, 08:25:24 PM
#10
Hello
I'm sorry but I don't understand that part

       // Step 3. Calculate crash = r / 2^52, uniformly distributed in [0; 1)
      const twoPower52 = Math.pow(2, nBitsToUse);
      let crash = r / twoPower52;


I don't understand why we need to divide this number by 2^52?
The result will always be <=1, no?


I think I'm the original author of this, as it appears to be copied from bustabit. I was just trying to convert a sha256 hash into a number between 0 and 1 (and then turn that into a multiplier). The most obvious and correct way to do this would be simply get the hash (as a number) and then divide by 2^256. But as the original bustabit was written in javascript (both the server and client), I wanted to approximate that in a simple way. Javascript's only number type was a 64 bit floating point, which means it can only represent integers accurately up to 2^53 - 1. So the cleanest number less than that is 2^52, which is the max number if you read the 13 hex characters of a hash.

So basically the logic is "read the first 13 hex characters from a hash, parse as a number, divide by 2^52" and now you have a number scaled between 0 and 1.

But it's really just an artifacts of the limitations I was working with at the time (e.g. python if i was working in python, I would've just done divided the whole thing. Or if i was working with a language with proper 64 bit numbers, would've done that, etc. )
legendary
Activity: 2604
Merit: 2353
May 22, 2020, 05:08:40 PM
#9
The seed event has been designed to reflect launches of similar games on this forum.

To make it provably fair we have generated a chain of 8,000,000 SHA256 hashes where each hash is the hash of the hexadecimal representation of the previous hash. The last hash in the chain is 5de24be2ba88f21070aca0b909a23ba8977a60e047e750dc6bd637aa3b4defc8.

The formula for generating the game result:

Code:
const CryptoJS = require("crypto-js");

    function generateGameResultFromSeed(roundSeed, salt) {

      // Number of most significant bits to use
      const nBitsToUse = 52;

      // Step 1. HMAC_SHA256(message=seed, key=salt)
      const hmac = CryptoJS.HmacSHA256(roundSeed, salt);
      const roundHash = hmac.toString(CryptoJS.enc.Hex);

      // Step 2. r = 52 most significant bits
      const roundRandSource = roundHash.slice(0, nBitsToUse / 4);
      const r = parseInt(roundRandSource, 16);

      // Step 3. Calculate crash = r / 2^52, uniformly distributed in [0; 1)
      const twoPower52 = Math.pow(2, nBitsToUse);
      let crash = r / twoPower52;

      // Step 4. Calculate crash normalized in 100 - 100B range
      crash = Math.floor(97 / crash);
      crash = Math.min(crash, 100000000000);
      crash = Math.max(crash, 100);

      // Step 5. Take next 52 bits as seed for player selection in Jackpot round
      const jpPlayerRandSource = roundHash.slice(nBitsToUse / 4, 2 * nBitsToUse / 4);
      const jpPlayerRandom = parseInt(jpPlayerRandSource, 16);

      // Step 6. Take next 52 bits as seed for picking Jackpot value on the wheel
      const jpValueRandSource = roundHash.slice(2 * nBitsToUse / 4, 3 * nBitsToUse / 4);
      const jpValueRandom = parseInt(jpValueRandSource, 16);

      return {roundHash, jpPlayerRandom, jpValueRandom, crash, roundSeed};
    }

The client seed is the hash of a future bitcoin block that has not been mined at the time of this post. The block we will use is 591433. This way players can be certain that we did not deliberately pick a client seed which advantages the house.
Hello
I'm sorry but I don't understand that part

       // Step 3. Calculate crash = r / 2^52, uniformly distributed in [0; 1)
      const twoPower52 = Math.pow(2, nBitsToUse);
      let crash = r / twoPower52;


I don't understand why we need to divide this number by 2^52?
The result will always be <=1, no?
copper member
Activity: 83
Merit: 5
September 10, 2019, 11:26:52 AM
#8
This is post #7.

I confirm the topic doesn't show any deleted posts yet (except maybe by moderators). If you move (bottom-left) the thread to a board that doesn't allow self-moderation (Archival for instance) and move it back to Gambling right after that, it will no longer be self-moderated.

Here's OP's unedited post scraped 7 seconds after posting: http://loyce.club/archive/posts/5224/52246534.html (archived).

Thanks a lot LoyceV for the archiving. We followed your suggestion of moving the thread to Archival and then back to Gambling in order to remove the self moderation and the self moderation is now removed!
legendary
Activity: 3290
Merit: 16489
Thick-Skinned Gang Leader and Golden Feather 2021
September 02, 2019, 03:05:44 PM
#7
This is post #7.

I confirm the topic doesn't show any deleted posts yet (except maybe by moderators). If you move (bottom-left) the thread to a board that doesn't allow self-moderation (Archival for instance) and move it back to Gambling right after that, it will no longer be self-moderated.

Here's OP's unedited post scraped 7 seconds after posting: http://loyce.club/archive/posts/5224/52246534.html (archived).
copper member
Activity: 83
Merit: 5
August 23, 2019, 06:42:21 PM
#6
I'd recommend recreating this thread not as a self-moderated thread. The whole point of doing the seed event on bitcointalk is that it's a neutral 3rd party place to host it. If it's a self-moderated thread, it kinda detracts from that a lot.

We intended to use the archived snapshot of the page: https://archive.is/Mwq4s as the third party place to host it.
legendary
Activity: 2557
Merit: 1886
August 23, 2019, 06:23:49 PM
#5
I'd recommend recreating this thread not as a self-moderated thread. The whole point of doing the seed event on bitcointalk is that it's a neutral 3rd party place to host it. If it's a self-moderated thread, it kinda detracts from that a lot.


Edit: Nevermind, realized the block is already mined  Embarrassed
legendary
Activity: 2758
Merit: 3282
August 23, 2019, 06:18:45 PM
#4
Archived on archive.org for you. Not a lot of point in getting people to quote the thread though since you can delete any post at your pleasure, but might as well quote it too:

The seed event has been designed to reflect launches of similar games on this forum.

To make it provably fair we have generated a chain of 8,000,000 SHA256 hashes where each hash is the hash of the hexadecimal representation of the previous hash. The last hash in the chain is5de24be2ba88f21070aca0b909a23ba8977a60e047e750dc6bd637aa3b4defc8.

The formula for generating the game result:

Code:
const CryptoJS = require("crypto-js");

    function generateGameResultFromSeed(roundSeed, salt) {

      // Number of most significant bits to use
      const nBitsToUse = 52;

      // Step 1. HMAC_SHA256(message=seed, key=salt)
      const hmac = CryptoJS.HmacSHA256(roundSeed, salt);
      const roundHash = hmac.toString(CryptoJS.enc.Hex);

      // Step 2. r = 52 most significant bits
      const roundRandSource = roundHash.slice(0, nBitsToUse / 4);
      const r = parseInt(roundRandSource, 16);

      // Step 3. Calculate crash = r / 2^52, uniformly distributed in [0; 1)
      const twoPower52 = Math.pow(2, nBitsToUse);
      let crash = r / twoPower52;

      // Step 4. Calculate crash normalized in 100 - 100B range
      crash = Math.floor(97 / crash);
      crash = Math.min(crash, 100000000000);
      crash = Math.max(crash, 100);

      // Step 5. Take next 52 bits as seed for player selection in Jackpot round
      const jpPlayerRandSource = roundHash.slice(nBitsToUse / 4, 2 * nBitsToUse / 4);
      const jpPlayerRandom = parseInt(jpPlayerRandSource, 16);

      // Step 6. Take next 52 bits as seed for picking Jackpot value on the wheel
      const jpValueRandSource = roundHash.slice(2 * nBitsToUse / 4, 3 * nBitsToUse / 4);
      const jpValueRandom = parseInt(jpValueRandSource, 16);

      return {roundHash, jpPlayerRandom, jpValueRandom, crash, roundSeed};
    }

The client seed is the hash of a future bitcoin block that has not been mined at the time of this post. The block we will use is 591433. This way players can be certain that we did not deliberately pick a client seed which advantages the house.


The hash of 591433 is 00000000000000000014ccc7303b1be1fd8c6b2cb5e961d57fbdc57f661db418
newbie
Activity: 3
Merit: 1
August 23, 2019, 04:09:10 PM
#3
Reserved.
copper member
Activity: 83
Merit: 5
August 23, 2019, 03:56:36 PM
#2
Here’s an archived snapshot of the page: https://archive.is/Mwq4s
Feel free to quote this post and save the original post (and confirm that block 591433 is still not mined).
copper member
Activity: 83
Merit: 5
August 23, 2019, 03:53:42 PM
#1
The seed event has been designed to reflect launches of similar games on this forum.

To make it provably fair we have generated a chain of 8,000,000 SHA256 hashes where each hash is the hash of the hexadecimal representation of the previous hash. The last hash in the chain is 5de24be2ba88f21070aca0b909a23ba8977a60e047e750dc6bd637aa3b4defc8.

The formula for generating the game result:

Code:
const CryptoJS = require("crypto-js");

    function generateGameResultFromSeed(roundSeed, salt) {

      // Number of most significant bits to use
      const nBitsToUse = 52;

      // Step 1. HMAC_SHA256(message=seed, key=salt)
      const hmac = CryptoJS.HmacSHA256(roundSeed, salt);
      const roundHash = hmac.toString(CryptoJS.enc.Hex);

      // Step 2. r = 52 most significant bits
      const roundRandSource = roundHash.slice(0, nBitsToUse / 4);
      const r = parseInt(roundRandSource, 16);

      // Step 3. Calculate crash = r / 2^52, uniformly distributed in [0; 1)
      const twoPower52 = Math.pow(2, nBitsToUse);
      let crash = r / twoPower52;

      // Step 4. Calculate crash normalized in 100 - 100B range
      crash = Math.floor(97 / crash);
      crash = Math.min(crash, 100000000000);
      crash = Math.max(crash, 100);

      // Step 5. Take next 52 bits as seed for player selection in Jackpot round
      const jpPlayerRandSource = roundHash.slice(nBitsToUse / 4, 2 * nBitsToUse / 4);
      const jpPlayerRandom = parseInt(jpPlayerRandSource, 16);

      // Step 6. Take next 52 bits as seed for picking Jackpot value on the wheel
      const jpValueRandSource = roundHash.slice(2 * nBitsToUse / 4, 3 * nBitsToUse / 4);
      const jpValueRandom = parseInt(jpValueRandSource, 16);

      return {roundHash, jpPlayerRandom, jpValueRandom, crash, roundSeed};
    }

The client seed is the hash of a future bitcoin block that has not been mined at the time of this post. The block we will use is 591433. This way players can be certain that we did not deliberately pick a client seed which advantages the house.
Jump to: