11

Everyone knows what SatoshiDice is. Their core mechanic is gambling through the use of Bitcoin transactions with the payout being directly linked to the transaction that fuelled the bed to avoid double-spend attacks. My question is, how to implement such a mechanism? Can it be done in the Standard Client, or does it need some extra software to pick the exact inputs of a transaction?

3 Answers 3

8

Creating a SatoshiDice-like game is rather easy. Below are the high level steps involved in making such a game.

For each incoming transaction...

Get the customer amount and payment address

  1. Call bitcoind getrawtransaction [The incoming transaction ID] 1. The 1 at the end will return the data in "verbose mode", which essentially the raw data in JSON format.

  2. From the raw transaction details, take the txid and vout from the vin object. With this transaction, again call bitcoind getrawtransaction on the txid.

  3. From these raw transaction details find the vout object, referenced by the vout index from step #2. Within this vout object, there should be a list of payment recipient addresses. Take and store the first address.

Determine the Win/Loss state of the round and return the results

  1. Hash the txid+vout index of the transaction. Seed your hash function with a secret key. As an aside note, you will need to provide your secret key on a periodic basis. Without updating and providing your secret keys, there is no way for your players to verify your fairness.

  2. Compare the last four bytes of your hash to determine the win/loss condition.

In case of a loss...

  1. Call bitcoind createrawtransaction. You must pass in the originating txid and vout of your customers payment. With the customers address, include a small, fractional value to send back to the customer. This informs them that they've lost the round. Also, include a second payment address that will receive the remaining portion of bitcoins from the customers originating payment. This should be an address within your wallet.

  2. Call bitcoind signrawtransaction to sign the transaction. If it returns a value of complete=true, your transaction is valid.

  3. Call bitcoind sendrawtransaction and include the above constructed raw transaction.

In case of a win

  1. Calculate the customers winning amount.

  2. Call bitcoind listunspent. This will return a list of inputted transactions that have not been spent by your wallet.

  3. Create a list of transactions to process as payments. First, include the customer's originating txid and vout index of their payment. Next, append to the list any number of unspent transactions (from step #1) that are necessary to pay your customer their winnings.

    Remember to include an additional payment address that will receive the remaining portion of bitcoins from the final unspent transaction that may contain overages above the player's winnings.

  4. Call bitcoind createrawtransaction, passing in all of the transactions accumulated in step #3.

  5. Call bitcoind signrawtransaction to sign the transaction.

  6. Call bitcoind sendrawtransaction and include the above constructed raw transaction.


That's it! That's a very simplistic, SatoshiDice processor. You may want to add more validation, cache your transactions, monitor orphaned blocks and just integrate some other administrative routines.

It is worth mentioning that you always include a portion of the customers original payment with all of your return transactions. This is because if their payment is orphaned, or is marked as invalid, you want to be sure that your transaction is also removed from the block-chain.

Using this method you can actually respond near-instantaneously and there is no need for confirmations. If their transaction is malformed and rejected by the network, your transaction will also be thrown out by the network since it is a child of their original transaction.

2
  • I guess to get "For each incoming transaction...", you would just call listtransactions?
    – kristianp
    Dec 1, 2013 at 3:09
  • Yes, or listsinceblock.
    – RLH
    Dec 4, 2013 at 14:30
3

Real Satoshi dice uses the bitcoinj library.

0

You could easily write a piece of software that runs on the same machine as a bitcoin daemon and let it use the JSON-RPC API from the local bitcoin daemon.

There are JSON-RPC implementation examples for all popular programming languages like Python and Java.

This piece of software will poll for new transactions, validate them and applying your game rules, and again making new transactions. Note that a server with such a piece of software needs only to have it's bitcoin port open to the internet, while the RPC port can be limited to local connections for safety.

4
  • Well, after attempting to implement it through Bitcoin API, I ran into the problem that since 0.8 and the new database system, bitcoind does not have all information on old transactions, so finding out the sender of a given transaction can be problematic.
    – ThePiachu
    Apr 9, 2013 at 5:54
  • How is an "old" transaction defined? SatoshiDice acts fast, right? I guess transaction details should be kept several blocks at least, no? Apr 11, 2013 at 20:24
  • Well, in order to determine the issuing address using the API, you need to look to a transaction previous to the one gambling, which can be arbitrarily old.
    – ThePiachu
    Apr 11, 2013 at 22:08
  • You could keep track of previous transactions in a database, and then query that if it's older in the blockchain. Jun 8, 2013 at 19:07

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