Skip to content

Instantly share code, notes, and snippets.

@NostrCasino
Created April 5, 2023 01:05
Show Gist options
  • Save NostrCasino/a9d6c31510f00c32deff8214261e7bd9 to your computer and use it in GitHub Desktop.
Save NostrCasino/a9d6c31510f00c32deff8214261e7bd9 to your computer and use it in GitHub Desktop.
Verifiable protocol for 3 card poker
"""
3_card_poker@nostrcasino.com, poker on Nostr!
npub: npub1hsl3xg22txclek63k6arwzjkydymzmea0y3fnxcffv7rylrysavq249hap
You can verify the fairness and result of the game from this python
script.
In order to ensure it's a fair game, we follow the following protocol:
1. You start a game by posting `@3_card_poker pair_plus_wager_amount ante_wager_amount`
2. We generate a seed, and share the hash of the seed (`seed_hash`) with you (along with a lightning invoice for pair_plus_wager_amount + ante_wager_amount)
3. You pay the invoice, then respond with 'deal'
4. We use the signature from your response (that we couldn't know ahead of time)
as a random input to deal the cards in the code below.
5. We deal your cards face up, and you're able to decide if you want to 'play' or 'fold'.
If you fold, the game is over and we share the seed (and your original comment signature for convenience)
so that you can verify the fairness of the game
If you choose 'play', you have to match the ante wager, so another invoice will be provided.
6. If you choose 'play' in step 5, after you pay the invoice, you can comment 'paid',
and the dealers cards will be turned face up. Winnings will be paid out if applicable.
And Finally, the seed (and your original comment signature for convenience)
so that you can verify the fairness of the game
"""
import hashlib
import hmac
# fill in the following variables from your game
seed_hash = ... # shared in step 2
seed = ... # shared in step 5 or 6
signature = ... # shared in step 5 or 6
# 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!")
def hmac_substring_to_card(hmac_substring, precision, deck):
int_max = 16 ** precision - 1
int_result = int.from_bytes(bytes.fromhex(
hmac_substring), byteorder="big", signed=False)
num_cards = len(deck)
card_index = int(num_cards * int_result / int_max)
dealt_card = deck[card_index]
new_deck = [x for x in deck if x != dealt_card]
return dealt_card, new_deck
def deal_cards(seed, signature):
precision = 14
deck = ['2s', '2h', '2c', '2d',
'3s', '3h', '3c', '3d',
'4s', '4h', '4c', '4d',
'5s', '5h', '5c', '5d',
'6s', '6h', '6c', '6d',
'7s', '7h', '7c', '7d',
'8s', '8h', '8c', '8d',
'9s', '9h', '9c', '9d',
'10s', '10h', '10c', '10d',
'Js', 'Jh', 'Jc', 'Jd',
'Qs', 'Qh', 'Qc', 'Qd',
'Ks', 'Kh', 'Kc', 'Kd',
'As', 'Ah', 'Ac', 'Ad']
signature_bytes = bytes.fromhex(signature)
computed_hmac = hmac.new(signature_bytes, msg=seed,
digestmod=hashlib.sha512).hexdigest()
# take a subset of the computed hmac
hmac_substring = computed_hmac[precision - 1::-1]
cards_dealt = []
for _ in range(6):
dealt_card, deck = hmac_substring_to_card(
hmac_substring, precision, deck)
cards_dealt.append(dealt_card)
signature_bytes = hashlib.sha256(signature_bytes).digest()
seed = hashlib.sha256(seed).digest()
computed_hmac = hmac.new(
signature_bytes, msg=seed, digestmod=hashlib.sha512).hexdigest()
# take a subset of the computed hmac
hmac_substring = computed_hmac[precision - 1::-1]
player_cards = cards_dealt[::2]
dealer_cards = cards_dealt[1::2]
return player_cards, dealer_cards
# The following steps verify that it was a fair game!
verify_seed_hash(seed, seed_hash)
player_cards, dealer_cards = deal_cards(seed, signature)
print(f"The player was dealt {player_cards}")
print(f"The dealer was dealt {dealer_cards}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment