ThunderDice is only available on the BTC TestNet. Follow us on Twitter for updates and crypto babblings.

Provably Fair 🎲 Rolls

A roll with ThunderDice consists of two Lightning Network payment invoices.

An invoice you pay, in order to send us your bet (known as the bet invoice), and an invoice you provide, which ThunderDice will pay in the event your roll is a winning roll (known as the payout invoice). These two invoices contain all the information to verify your roll value!

We'll show you how, but first some background info...

Lightning Network Payment Invoices

Each payment invoice on the Lightning Network contains, among other things, a secret payment preimage value and it's sha256 hash. The payment hash is encoded in payment invoice strings and QR codes you copy or scan to send payment:

$ lncli decodepayreq lnsb2m1pdxjs6hpp5jy6jnagc75l7ma8fdrnm6ded28r4xymfxrm7zgpe4ty9wsgvjm3qdqqcqzysxqzjcuzpp5r3dp4jzc4fxf34r3n0f7uvv8vmzjeqvhg5pd6pe8phhur9quegpx6h67mglwfl0keq4w92adh84xpfvgeu3dqlxn3fklnkrwhspamlkxn
{
    "destination": "0287467ff0f10d1bb35fb411e65ade66425cd34ccb283373befbcd85df20ea0d36",
    "payment_hash": "913529f518f53fedf4e968e7bd372d51c753136930f7e12039aac857410c96e2",
    "num_satoshis": "200000",
    "timestamp": "1516847959",
    "expiry": "600",
    "description": "",
    "description_hash": "",
    "fallback_addr": "",
    "cltv_expiry": "144"
}

The payment preimage value is kept secret by the person or node which generated the invoice, until it's given out in exchange for the invoice being paid.

For this reason, being able to produce the secret preimage value which generated the payment hash operates as sort of a "receipt" that you've paid an invoice, as it's impossible with today's technology to discover the preimage value with just the hash value.

Betting on ThunderDice

Once you choose how much you'd like to bet and the specific odds you want, we prompt you for a payout invoice for the amount that you'll receive in the event you win. You generate this on your side using a Lightning Network enabled wallet of choice.

Before prompting you for your payout invoice, we've already generated the secret payment preimage and payment hash for your bet invoice, and present you with the payment hash. You'll see a section like this below the form to paste in your payout invoice:

Fair Roll Verification

The payout invoice you paste above will be used to generate your roll value. It will be combined with the secret preimage value represented by the sha256 hash:

327889f8751ced9380c324691a40e2cfb29e90a39edbfca4495d7c5f5bd44f1a

(Learn more about our provably fair 🎲 rolls)

After pasting in your payout invoice, you'll be prompted to pay the bet invoice which contains the payment hash listed. Once you send payment, you'll receive the secret preimage value as your "receipt".

Verify Your Roll Value

Once you've paid the bet invoice and received the payment preimage value, you can generate your roll value completely on your own! Keep us honest. 😁

The following golang code generates a roll value from 0 to 65535 based on the payout invoice you provide for your potential winnings, and the secret preimage value from the bet invoice you paid:

package main

import (
	"fmt"
	"log"
	"bytes"
	"crypto/sha256"
	"crypto/hmac"
	"encoding/hex"
	"encoding/binary"
)

var payoutInvoice = "your payout invoice"
var betPaymentHash = "hex value of bet invoice preimage hash"
var betPaymentPreimage = "hex value of bet invoice preimage"

func main() {
	preimageHash, err := hex.DecodeString(betPaymentHash)
	if err != nil {
		log.Fatal(fmt.Errorf("betPaymentHash isn't a valid hex string. %v", err))
	}
	
	preimage, err := hex.DecodeString(betPaymentPreimage)
	if err != nil {
		log.Fatal(fmt.Errorf("betPaymentPreimage isn't a valid hex string. %v", err))
	}
	
	hash := sha256.Sum256(preimage)
	
	if !bytes.Equal(preimageHash, hash[:]) {
		log.Fatal("betPaymentPreimage isn't the preimage of betPaymentHash")
	}
	
	roller := hmac.New(sha256.New, preimage)
	roller.Write([]byte(payoutInvoice))
	val := roller.Sum(nil)[:4]
	
	roll := int(binary.BigEndian.Uint16(val))

	fmt.Printf("You rolled %d/65536", roll)
}

You can plug in information from each of your payment invoices and run the above code to verify your roll: https://play.golang.org/p/DoRBwCbK05j

⚡️🎲 thunderdice © 2017