leomedina (OP) |
Welcome to bustabit's third provably fair seeding event. Our provably fair system, based on the first seeding event, is evolving into an advanced multi-party provably fair scheme. We have integrated ActuallyFair.com's Vx, a third-party service contributing to the algorithm that converts game hashes to game results. This not only helps us have a more secure system, but also preserves all provably fair guarantees while allowing Actually Fair to verify all games on behalf of our players. 1. Starting with a secret, we have generated a chain of 100,000,000 sha256 hashes by recursively hashing the binary value of the previous hash. Every hash in the chain will be used to generate a game result. The first element in the chain is the hash of game #100,000,000 and the last one is the hash of game #1, aka our terminating hash, which is: 567a98370fb7545137ddb53687723cf0b8a1f5e93b1f76f4a1da29416930fa59. You can verify if a hash is part of the chain with a function like this: Code: import { sha256 } from "@noble/hashes/sha256"; const TERMINATING_HASH = "567a98370fb7545137ddb53687723cf0b8a1f5e93b1f76f4a1da29416930fa59"; function verifyInChain(hash: Uint8Array) { Which could be used like: Code: verifyInChain( 2. Vx will use its BLS public key: b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1 749a1d5aab00020e4. 3. We will play through that chain of hashes, in reverse order, and use the hashes to determine the crash point in a provably fair manner. 4. To prove that Actually Fair and bustabit have picked a fair hash chain (and public key) we will also mix in the lowercase, hexadecimal representation of the hash of a Bitcoin block that has not been mined yet: Bitcoin block 831500. This will be known as our game salt. 5. Vx gives us a signature (vxSignature) by signing the concatenation of the previous game hash along with the game salt. Vx uses BLS signatures so that it is not possible to generate multiple valid signatures for a particular message. We can validate the signature with something like: Code: import { bls12_381 as bls } from "@noble/curves/bls12-381"; const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; function validateSignature( 5. Once we have a valid vxSignature, we take the next unused hash from the chain and use it to determine game results: Code: import { hmac } from "@noble/hashes/hmac"; export function gameResult(vxSignature: Uint8Array, gameHash: Uint8Array) { // 1. HMAC_SHA256(key=signature, message=hash) // 2. r = 52 most significant bits // 3. X = r / 2^52 // 4. X = 99 / (1 - X) // 5. return max(trunc(X), 100) For more reference code, take a look at our open-source verifier and at this illustrative demo. | |||
|
devans Sr. Member Activity: 528 |
Quoting to prevent editing of the OP: Quote from: leomedina on February 19, 2024, 03:22:42 PM Welcome to bustabit's third provably fair seeding event. Our provably fair system, based on the first seeding event, is evolving into an advanced multi-party provably fair scheme. We have integrated ActuallyFair.com's Vx, a third-party service contributing to the algorithm that converts game hashes to game results. This not only helps us have a more secure system, but also preserves all provably fair guarantees while allowing Actually Fair to verify all games on behalf of our players. 1. Starting with a secret, we have generated a chain of 100,000,000 sha256 hashes by recursively hashing the binary value of the previous hash. Every hash in the chain will be used to generate a game result. The first element in the chain is the hash of game #100,000,000 and the last one is the hash of game #1, aka our terminating hash, which is: 567a98370fb7545137ddb53687723cf0b8a1f5e93b1f76f4a1da29416930fa59. You can verify if a hash is part of the chain with a function like this: Code: import { sha256 } from "@noble/hashes/sha256"; const TERMINATING_HASH = "567a98370fb7545137ddb53687723cf0b8a1f5e93b1f76f4a1da29416930fa59"; function verifyInChain(hash: Uint8Array) { Which could be used like: Code: verifyInChain( 2. Vx will use its BLS public key: b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1 749a1d5aab00020e4. 3. We will play through that chain of hashes, in reverse order, and use the hashes to determine the crash point in a provably fair manner. 4. To prove that Actually Fair and bustabit have picked a fair hash chain (and public key) we will also mix in the lowercase, hexadecimal representation of the hash of a Bitcoin block that has not been mined yet: Bitcoin block 831500. This will be known as our game salt. 5. Vx gives us a signature (vxSignature) by signing the concatenation of the previous game hash along with the game salt. Vx uses BLS signatures so that it is not possible to generate multiple valid signatures for a particular message. We can validate the signature with something like: Code: import { bls12_381 as bls } from "@noble/curves/bls12-381"; const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; function validateSignature( 5. Once we have a valid vxSignature, we take the next unused hash from the chain and use it to determine game results: Code: import { hmac } from "@noble/hashes/hmac"; export function gameResult(vxSignature: Uint8Array, gameHash: Uint8Array) { // 1. HMAC_SHA256(key=signature, message=hash) // 2. r = 52 most significant bits // 3. X = r / 2^52 // 4. X = 99 / (1 - X) // 5. return max(trunc(X), 100) For more reference code, take a look at our open-source verifier and at this illustrative demo. | |||
|
leomedina (OP) |
I have also taken a snapshot here: https://web.archive.org/web/20240219162743/https://gist.github.com/leomedi/f1704f3ad74fbd11ec2f02e86d2f9d66. | |||
|
husseinhere Newbie Activity: 18 |
Also quoting to show the post hasn't been edited, and confirming bitcoin block 831500 has not yet been mined. Quote from: leomedina on February 19, 2024, 03:22:42 PM Welcome to bustabit's third provably fair seeding event. Our provably fair system, based on the first seeding event, is evolving into an advanced multi-party provably fair scheme. We have integrated ActuallyFair.com's Vx, a third-party service contributing to the algorithm that converts game hashes to game results. This not only helps us have a more secure system, but also preserves all provably fair guarantees while allowing Actually Fair to verify all games on behalf of our players. 1. Starting with a secret, we have generated a chain of 100,000,000 sha256 hashes by recursively hashing the binary value of the previous hash. Every hash in the chain will be used to generate a game result. The first element in the chain is the hash of game #100,000,000 and the last one is the hash of game #1, aka our terminating hash, which is: 567a98370fb7545137ddb53687723cf0b8a1f5e93b1f76f4a1da29416930fa59. You can verify if a hash is part of the chain with a function like this: Code: import { sha256 } from "@noble/hashes/sha256"; const TERMINATING_HASH = "567a98370fb7545137ddb53687723cf0b8a1f5e93b1f76f4a1da29416930fa59"; function verifyInChain(hash: Uint8Array) { Which could be used like: Code: verifyInChain( 2. Vx will use its BLS public key: b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1 749a1d5aab00020e4. 3. We will play through that chain of hashes, in reverse order, and use the hashes to determine the crash point in a provably fair manner. 4. To prove that Actually Fair and bustabit have picked a fair hash chain (and public key) we will also mix in the lowercase, hexadecimal representation of the hash of a Bitcoin block that has not been mined yet: Bitcoin block 831500. This will be known as our game salt. 5. Vx gives us a signature (vxSignature) by signing the concatenation of the previous game hash along with the game salt. Vx uses BLS signatures so that it is not possible to generate multiple valid signatures for a particular message. We can validate the signature with something like: Code: import { bls12_381 as bls } from "@noble/curves/bls12-381"; const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; function validateSignature( 5. Once we have a valid vxSignature, we take the next unused hash from the chain and use it to determine game results: Code: import { hmac } from "@noble/hashes/hmac"; export function gameResult(vxSignature: Uint8Array, gameHash: Uint8Array) { // 1. HMAC_SHA256(key=signature, message=hash) // 2. r = 52 most significant bits // 3. X = r / 2^52 // 4. X = 99 / (1 - X) // 5. return max(trunc(X), 100) For more reference code, take a look at our open-source verifier and at this illustrative demo. | |||
|
dannnyboy Newbie Activity: 15 |
so the house edge is still 1%? | |||
|
husseinhere Newbie Activity: 18 |
Quote from: dannnyboy on February 19, 2024, 04:49:45 PM so the house edge is still 1%? Yeah, you are able to verify this by analyzing the by the "gameResult" function | |||
|
John_Cryptobeard Newbie Activity: 2 |
What about bustadice's new seeding event? Can you send me a link to the forum talking about that or can you post all of the particulars as you did here for Bustabit.com about Bustadice.com please? Thank you! | |||
|
leomedina (OP) |
Quote from: John_Cryptobeard on February 21, 2024, 12:45:14 AM What about bustadice's new seeding event? Can you send me a link to the forum talking about that or can you post all of the particulars as you did here for Bustabit.com about Bustadice.com please? Thank you! bustadice doesn't require one. While on bustabit, game results come from a hash-chain, bustadice calculates them with input from the player, the game server, and the auditor. The only change is that ActuallyFair.com will be the new auditor; however, aside from that, the game will remain largely the same. You can find more information here. The Bitcoin block 831500 has been mined! Our game salt is: 000000000000000000011f6e135efe67d7463dfe7bb955663ef88b1243b2deea. | |||
|
Babquestion Newbie Activity: 4 |
Quote from: leomedina on February 22, 2024, 12:29:15 AM Quote from: John_Cryptobeard on February 21, 2024, 12:45:14 AM What about bustadice's new seeding event? Can you send me a link to the forum talking about that or can you post all of the particulars as you did here for Bustabit.com about Bustadice.com please? Thank you! bustadice doesn't require one. While on bustabit, game results come from a hash-chain, bustadice calculates them with input from the player, the game server, and the auditor. The only change is that ActuallyFair.com will be the new auditor; however, aside from that, the game will remain largely the same. You can find more information here. The Bitcoin block 831500 has been mined! Our game salt is: 000000000000000000011f6e135efe67d7463dfe7bb955663ef88b1243b2deea. So, basically everything will remain identical except for a new hash chain? Any plans to change any game limits or betting functionality? | |||
|
KloNEM Member Activity: 182 |
In the "previous bustabit", I used this part of code for calculating hash and game result : Code: var CryptoJS = require('./node_modules/crypto-js/crypto-js.js'); var hash_input = process.argv[2]; let prevHash = null; prevHash = hash; function gameResult(seed, salt) { // 1. HMAC_SHA256(message=seed, key=salt) // 2. r = 52 most significant bits // 3. X = r / 2^52 // 4. X = 99 / (1-X) // 5. return max(trunc(X), 100) E.g. this is "prevHash" for game #7600000 (so I'm able to count all the games from #7600000 till hash of the game as a parameter of this script). So I supposed, when I replace this prevHash with (e.g.) hash of game #10000001, and change salt ("let bust = gameResult" row) to the new one ( 000000000000000000011f6e135efe67d7463dfe7bb955663ef88b1243b2deea), everything will work again. But it is not | |||
|
KloNEM Member Activity: 182 |
Quote from: KloNEM on February 27, 2024, 08:39:26 AM E.g. this is "prevHash" for game #7600000 (so I'm able to count all the games from #7600000 till hash of the game as a parameter of this script). So I supposed, when I replace this prevHash with (e.g.) hash of game #10000001, and change salt ("let bust = gameResult" row) to the new one ( 000000000000000000011f6e135efe67d7463dfe7bb955663ef88b1243b2deea), everything will work again. But it is not PS: The script that I mentioned above I successfully ran as "node script.js" from linux command line. Now I'm trying to process your code in the same manner (or like /usr/bin/node script.mhs), but it has probably troubles with the type definition in the function (e.g. hash: Uint8Array, gameSalt: string, etc.), it gives me SyntaxError: Unexpected token ':' error. So, if you'd place example here, how to run this JS script (ideally from the cmd line as well), it'll be really useful. | |||
|
leomedina (OP) |
Quote from: KloNEM on February 27, 2024, 05:24:58 PM Quote from: KloNEM on February 27, 2024, 08:39:26 AM E.g. this is "prevHash" for game #7600000 (so I'm able to count all the games from #7600000 till hash of the game as a parameter of this script). So I supposed, when I replace this prevHash with (e.g.) hash of game #10000001, and change salt ("let bust = gameResult" row) to the new one ( 000000000000000000011f6e135efe67d7463dfe7bb955663ef88b1243b2deea), everything will work again. But it is not PS: The script that I mentioned above I successfully ran as "node script.js" from linux command line. Now I'm trying to process your code in the same manner (or like /usr/bin/node script.mhs), but it has probably troubles with the type definition in the function (e.g. hash: Uint8Array, gameSalt: string, etc.), it gives me SyntaxError: Unexpected token ':' error. So, if you'd place example here, how to run this JS script (ideally from the cmd line as well), it'll be really useful. Have you seen the new verifier I wrote? It runs in the browser and already does what you're asking for (uses a vxSignature to calculate game results). Take a look at this file to see how you could do it. | |||
|
KloNEM Member Activity: 182 |
Quote from: leomedina on February 28, 2024, 02:05:30 AM Have you seen the new verifier I wrote? It runs in the browser and already does what you're asking for (uses a vxSignature to calculate game results). Take a look at this file to see how you could do it. Thanks, that TypeScript looks great! Just tell me, please, (from) where should I import ./constants, ./utils/math and ./utils/vx ? Thanks! | |||
|
leomedina (OP) |
Quote from: KloNEM on February 28, 2024, 08:02:29 AM Quote from: leomedina on February 28, 2024, 02:05:30 AM Have you seen the new verifier I wrote? It runs in the browser and already does what you're asking for (uses a vxSignature to calculate game results). Take a look at this file to see how you could do it. Thanks, that TypeScript looks great! Just tell me, please, (from) where should I import ./constants, ./utils/math and ./utils/vx ? Thanks! You could just copy those from the verifier, they are all there. Just make sure you import the right dependencies and it should work. | |||
|
KloNEM Member Activity: 182 |
Quote from: leomedina on February 28, 2024, 11:49:58 PM Quote from: KloNEM on February 28, 2024, 08:02:29 AM Quote from: leomedina on February 28, 2024, 02:05:30 AM Have you seen the new verifier I wrote? It runs in the browser and already does what you're asking for (uses a vxSignature to calculate game results). Take a look at this file to see how you could do it. Thanks, that TypeScript looks great! Just tell me, please, (from) where should I import ./constants, ./utils/math and ./utils/vx ? Thanks! You could just copy those from the verifier, they are all there. Just make sure you import the right dependencies and it should work. Yeah, thanks, I probably missed it. It just looks like it needs lot of modules/dependencies for a "webrunning", which I don't need, so I'm transferring the code to the Node.JS format (I hope I'm close now, otherwise I'll think about re-writing the code into Python, someday Just a question to a second part of code (generating vxSignature) : Code: import { bls12_381 as bls } from "@noble/curves/bls12-381"; const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; function validateSignature( What is input for the validateSignature function, are they the results from the previous hash ? So, if I'm finding e.g. vxSignature for game #10002813, do I have to find and input here prevGameHash of game #10002812, and the vxSignature of this game as well? | |||
|
leomedina (OP) |
Quote from: KloNEM on February 29, 2024, 02:32:35 AM Yeah, thanks, I probably missed it. It just looks like it needs lot of modules/dependencies for a "webrunning", which I don't need, so I'm transferring the code to the Node.JS format (I hope I'm close now, otherwise I'll think about re-writing the code into Python, someday Just a question to a second part of code (generating vxSignature) : Code: import { bls12_381 as bls } from "@noble/curves/bls12-381"; const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; function validateSignature( What is input for the validateSignature function, are they the results from the previous hash ? So, if I'm finding e.g. vxSignature for game #10002813, do I have to find and input here prevGameHash of game #10002812, and the vxSignature of this game as well? Yeah, that's correct. We concatenate the previous game hash with our game salt, and ask Vx to sign the message. Vx gives us as a signature (which reveals the previous game to Vx) and then what that function does is to verify that the signature is authentic. By the way, there is also a crash demo here, in case you haven't seen it. | |||
|
KloNEM Member Activity: 182 |
Quote from: leomedina on February 29, 2024, 05:16:24 AM Quote from: KloNEM on February 29, 2024, 02:32:35 AM Yeah, thanks, I probably missed it. It just looks like it needs lot of modules/dependencies for a "webrunning", which I don't need, so I'm transferring the code to the Node.JS format (I hope I'm close now, otherwise I'll think about re-writing the code into Python, someday Just a question to a second part of code (generating vxSignature) : Code: import { bls12_381 as bls } from "@noble/curves/bls12-381"; const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; function validateSignature( What is input for the validateSignature function, are they the results from the previous hash ? So, if I'm finding e.g. vxSignature for game #10002813, do I have to find and input here prevGameHash of game #10002812, and the vxSignature of this game as well? Yeah, that's correct. We concatenate the previous game hash with our game salt, and ask Vx to sign the message. Vx gives us as a signature (which reveals the previous game to Vx) and then what that function does is to verify that the signature is authentic. By the way, there is also a crash demo here, in case you haven't seen it. Interesting. I tried to "re-make" second part of code for Node.js and game #10002812, in that way : Code: const BLS = require('./node_modules/@noble/curves/bls12-381.js'); const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; // this is prevGameHash for the game #10002812 When I use vxSignature for the game #10002812, it gives me node_modules/@noble/curves/bls12-381.js:144 throw new Error('No root'); . When I change vxSignature for the game #10002813, it gives me node_modules/@noble/curves/abstract/weierstrass.js:258 throw new Error('bad point: not in prime-order subgroup');. Just for sure - the length of the prevGameHash is 64 bytes, length of the vxSignature 192 bytes and lenght of the message 128 bytes, correct ? Maybe there will be some issue with the re-code of string to Uint8Array in Node.js ... | |||
|
leomedina (OP) |
Quote from: KloNEM on February 29, 2024, 11:42:03 AM Interesting. I tried to "re-make" second part of code for Node.js and game #10002812, in that way : Code: const BLS = require('./node_modules/@noble/curves/bls12-381.js'); const VX_PUBKEY = "b40c94495f6e6e73619aeb54ec2fc84c5333f7a88ace82923946fc5b6c8635b08f9130888dd96e1749a1d5aab00020e4"; // this is prevGameHash for the game #10002812 When I use vxSignature for the game #10002812, it gives me node_modules/@noble/curves/bls12-381.js:144 throw new Error('No root'); . When I change vxSignature for the game #10002813, it gives me node_modules/@noble/curves/abstract/weierstrass.js:258 throw new Error('bad point: not in prime-order subgroup');. Just for sure - the length of the prevGameHash is 64 bytes, length of the vxSignature 192 bytes and lenght of the message 128 bytes, correct ? Maybe there will be some issue with the re-code of string to Uint8Array in Node.js ... You need to use the previous hash. So, if prevGameHash is the hash of game #10002812, you have to validate the signature of game #10002813, and so on. I didn't try to run your code, but you probably want to use hexToBytes instead of Uint8Array(Buffer.from(foo)) where you declare prevGameHash and vxSignature. | |||
|
KloNEM Member Activity: 182 |
Quote from: leomedina on March 01, 2024, 01:22:40 AM You need to use the previous hash. So, if prevGameHash is the hash of game #10002812, you have to validate the signature of game #10002813, and so on. I didn't try to run your code, but you probably want to use hexToBytes instead of Uint8Array(Buffer.from(foo)) where you declare prevGameHash and vxSignature. Yep, you're right, hexToBytes did the trick, thanks a lot! And a last question (I promise it'll be really last one :-) ) : How could I deduct vxSignature for the next (in the reverse manner) hash/game ? return bls.verify(vxSignature, message, VX_PUBKEY); just gives me back true/false like a validation, whether the current signature is correct (or not). In any case many thanks again, Leo, for your co-operation, I really appreciate it! | |||
|
leomedina (OP) |
Quote from: KloNEM on March 01, 2024, 04:22:03 PM Quote from: leomedina on March 01, 2024, 01:22:40 AM You need to use the previous hash. So, if prevGameHash is the hash of game #10002812, you have to validate the signature of game #10002813, and so on. I didn't try to run your code, but you probably want to use hexToBytes instead of Uint8Array(Buffer.from(foo)) where you declare prevGameHash and vxSignature. Yep, you're right, hexToBytes did the trick, thanks a lot! And a last question (I promise it'll be really last one :-) ) : How could I deduct vxSignature for the next (in the reverse manner) hash/game ? return bls.verify(vxSignature, message, VX_PUBKEY); just gives me back true/false like a validation, whether the current signature is correct (or not). In any case many thanks again, Leo, for your co-operation, I really appreciate it! No problem at all! Happy to help. Well, it's Vx that gives us that signature, so you need to communicate with its API. For example, in the same verifier, we call getVxSignature (line 12 in https://stackblitz.com/edit/bustabit-verifier?file=src%2Futils%2Fvx.ts), validate it, and then finally use it to generate the game's result. | |||
|