I am trying to make a smart contract that acts similar to a lottery or gambling game. Here is an example:

Alice and Bob send funds to a P2SH address. Bob is the lottery. The funds needs to be locked for some time (until the draw for example, like 5 days). For this we can use OP_CHECKLOCKTIMEVERIFY. After the nLockTime expires, if Alice guessed 3 numbers, she will get 50% of her deposit back. If she guesses 6 numbers, she will get 200% of her deposit back.

How can Bob (the lottery) commit to some numbers that Alice needs to guess before Alice funds the deposit address? Bob needs to be able to prove that the numbers were chosen before she funded the deposit address, and cannot simply deny any numbers Alice would guess.

On the other side, how can we enforce the funds go back to Alice if she guesses the numbers that were previously committed to by Bob in case Bob disappears before the draw (nLickTime expiration) time comes?

The simplest thing I can think of is Bob puts a hash of the numbers he committed to in OP_RETURN in the transaction funding the deposit address, but this is kind of a PITA and annoying and it does not offer a guarantee for Alice that she will take her money if she guesses the numbers Bob committed to even if he disappears until the draw (nLockTime expire) time comes.

Thank you.

  • If the numbers were quite small, in most cases I can think of there would be nothing stopping Alice attempting multiple guesses until she unlocks the script (bruteforce) which isn't in the spirit of the game you've described. Commented Jul 9, 2017 at 1:33

1 Answer 1


You might be able to combine a hash lock with a conditional payout.

Here's a somewhat simplified example that shows how to make a payout depend on knowledge of a secret. Bob makes a bet with Alice that she can't guess Bob's secret before a deadline. Alice proves she knows the secret by publishing the preimage to its hash value, which Bob publishes. Alice and Bob each contribute one bitcoin. The winner receives two bitcoin. If Bob doesn't reveal the secret after the deadline, Alice takes all the money.

There are two one-bitcoin inputs, signed respectively by Alice and Bob.

There is one two-bitcoin output. It is protected by a nested conditional challenge script that looks something like this:

  // Alice spends with secret before deadline
  OP_HASH256 <hash> OP_EQUALVERIFY <Alice pubkey> OP_CHECKSIG
  // deadline has expired

    // Bob spends by revealing the secret
    OP_HASH256 <hash> OP_EQUALVERIFY <Bob pubkey> OP_CHECKSIG
    // Alice spends if Bob refuses to publish the secret
    <Alice pubkey> OP_CHECKSIG

To spend the output before the deadline, Alice uses this response script:

<Alice signature> <secret> <1>

After the deadline, Bob uses this response script:

<0> <Bob signature> <secret> <1> <0>

If Bob fails to spend the output after the deadline (revealing the secret), Alice takes all the money with this response script:

<0> <Alice signature> <0> <0>

There's a problem with this approach, though. If Alice doesn't guess the secret and Bob publishes it, Alice can use the secret to make her own transaction claiming the output. This sets up a race condition in which Alice and Bob each have pending transactions trying to spend the output.

One way to fix this problem would be to give Bob a grace period immediately after the deadline (say, one day). During the grace period, Alice would be unable to spend, but Bob could.

  • 1
    Thank you very much! Nice thinking. However, it partially fixes my problem. If Bob disappears before the checklocktimeverify expires, and no results are published (no secret published) alice should be able to get only her bet back, e.g. 50% of the funds available in the p2sh address. How can this be achieved? Also, is there a limit of how many bits can the secret have? I would like to add like to add some random data to make brute force unworkable. Last but not least, is there some magic that Bob can do so the secret is published at some time regardless if he disappears?
    – skydanc3r
    Commented Jul 9, 2017 at 8:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.