Skip to content

Instantly share code, notes, and snippets.

@NostrCasino
Last active March 7, 2023 04:55
Show Gist options
  • Save NostrCasino/9eda61f2244d2bf0327379d8d92cd24e to your computer and use it in GitHub Desktop.
Save NostrCasino/9eda61f2244d2bf0327379d8d92cd24e to your computer and use it in GitHub Desktop.
verifiable_coinflip.py
"""
coinflip@nostrcasino.com, the quickest way to to double your sats on Nostr!
npub: npub179afcatzjjex3zm3ya04xzg55cqzeklakw0atcstwlygujh88scsuyvgjy
You can verify the fairness and result of the coinflip from this python
script.
In order to ensure it's a fair flip, we follow the following protocol:
1. You start a game by posting `@coinflip num_sats`
2. We generate a seed, and share the hash of the seed (`seed_hash`) with you (along with a lightning invoice for num_sats)
3. You pay the invoice, then respond with 'heads' or 'tails'
4. We use the signature from your response (that we couldn't know ahead of time)
in the code below.
5. We share the seed with you (and your signature for convenience)
"""
import hashlib
import hmac
# fill in the following variables from your game
seed_hash = ... # shared in step 2
seed = ... # shared in step 5
signature = ... # shared in step 5
player_guess = ... # either "heads" or "tails", provided by you in step 3
# first, verify that the seed_hash really comes from the seed
def verify_seed_hash(seed, seed_hash):
computed_seed_hash = hashlib.sha256(seed).hexdigest()
if seed_hash == computed_seed_hash:
print("We verified that the seed_hash comes from the seed!")
else:
print("The seed_hash does not come from the seed, something is wrong!")
# next, verify the result of the coinflip
def heads_or_tails(seed, signature, player_guess):
precision = 12
house_edge = 0.0099 # 0.99% house edge
signature_bytes = bytes.fromhex(signature)
computed_hmac = hmac.new(signature_bytes, msg=seed , digestmod=hashlib.sha512).hexdigest()
hmac_substring = computed_hmac[precision - 1::-1] # take a subset of the computed hmac
assert len(hmac_substring) == precision
int_result = int.from_bytes(bytes.fromhex(hmac_substring), byteorder="big", signed=True) + 0.5
normalized_result = int_result / 16 ** precision # normalize result between (-0.5, 0.5)
if player_guess == "heads":
normalized_result -= house_edge
else:
normalized_result += house_edge
if normalized_result > 0:
final_result = "heads"
else:
final_result = "tails"
print(f"the result of the coinflip is {final_result}!")
# The following 2 steps verify that it was a fair coin flip!
verify_seed_hash(seed, seed_hash)
heads_or_tails(seed, signature, player_guess)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment