読者です 読者をやめる 読者になる 読者になる

Counterpartyd create_broadcastとcreate_bet APIを使って賭けをする

f:id:yzono:20141208212354j:plain

はじめに

今回はCounterpartyが提供するPeer to Peer のBetプラットフォームについて書きます。

この記事はCounterparty Bettingの利用方法の説明を目的にしています。利用は自己責任でお願いします。

目次

  • Counterparty P2P Betの概要
  • Counterpartyのプラットフォームを使っているブックメーカー
  • Bettingの仕組み
  • ブックメーカーのオッズ(倍率)の見方
  • 使用するアドレスと残高
  • create_broadcast実行(オペレーターが賭けの内容をブロードキャストする)
  • create_bet実行(プレイヤーXとプレイヤーYが賭けをする)
  • create_broadcast実行(オペレーターが賭けの結果をブロードキャストする)
  • 結果確認

Counterparty P2P Bettingの概要

CounterpartyはPtoPのBetプラットフォームを提供しています。自前でBettingサイトを構築するには大きなコストがかかりますが、Counterpartyを使うことで堅牢で透明性のあるシステムを低コストで構築することができます。

Bettingシステムを利用するユーザーにも恩恵があります。1つはシステム構築コストが安い分ユーザーへの還元が増えます。他のシステムに比べて収益性を高くできます。Bettingの透明性と個人情報の匿名性も優れています。透明性に関しては、取引内容はインターネットで公開され自由に閲覧できるため不正を防止できます。匿名性については、システム利用時に一切の個人情報を提供せずに利用できます。

もちろん欠点もあります。1つはBettingシステムで利用する通貨はXCPに限られます(※1)。現状XCPを入手できる人は限られます。(一般の人にとっては手間がかかるという意味です。)また法律の問題もあります。私は専門家ではありませんが、Bettingサービスを立ち上げること自体が違法な国もあると聞きます。

※1 XBTCも利用可能らしいですが未確認です。

Counterpartyのプラットフォームを使っているブックメーカー

BetXCP.comXbet.ioがCounterparty Bettingを採用しています。どちらもスポーツの勝敗、得点結果を賭けるサイトです。

Bitcoinプラットフォームを使っているため、XCPの送金完了(Confirmation)には時間がかかります。ただし、スポーツの勝敗であれば結果が出るまでに時間がかかるため理想的なユースケースと言えます。

ただ現状はどちらのサービスも活発に取引されていません。(またはこの時期はスポーツゲームが少ないからでしょうか..)

blockscanで、broadcast名"bet"で検索してください。両方のサービスがどのくらい利用されているか見れます。(こうやって取引内容を見れるのも、透明性のメリットですが..)

Bettingの仕組み

BetXCP.comのサイトにあるHow it worksが分かりやすいので、そのまま使わせてもらいます。

f:id:yzono:20141229173625j:plain

3人の登場人物がいます。ここでは、オペレーター、プレーヤーX、プレーヤーYと定義します。

  1. オペレーターが賭けの内容をBroadcastします。
  2. プレーヤーXがその賭けにBetします。
  3. プレーヤーXのBet内容に対するカウンターパーティがプレーヤーYです。プレーヤーYがBetします。
  4. オペレーターが賭けの結果をBroadcastします。
  5. 賭けの結果に合致したプレーヤーXまたはプレーヤーYのどちらかが報酬を受け取ります。

動画でも分かりやすく説明しています。これを見るとすごい簡単にBetできていることが分かります。

ブックメーカーのオッズ(倍率)の見方

オッズ(倍率)の見方に慣れない方は、ブックメーカーのオッズ(倍率)の見方を参照ください。Counterpartyでは、フラクショナル式(Fractional Odds)を採用しています。

使用するアドレスと残高

実際にAPIを実行していきます。その前に上記で説明した登場人物のアセット状況を整理します。

  • プレイヤーXのXCPの数量 = 5000001

  • プレイヤーYのXCPの数量 = 5000000

オペレーター

(ビットコインインスタンス)自分のサーバー

(ビットコインアドレス)1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy

(保有しているアセット)

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy"}}}'

{"result": [{"address": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "asset": "XCP", "quantity": 120819997}, {"address": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "asset": "XSTAR", "quantity": 70}, {"address": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "asset": "XZCOIN", "quantity": 99495}], "id": 0, "jsonrpc": "2.0"}

プレイヤーX

(ビットコインインスタンス)自分のサーバー

(ビットコインアドレス)1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ

(保有しているアセット)

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ"}}}'

{"result": [{"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XCP", "quantity": 5000001}, {"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XSTAR", "quantity": 10}, {"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XZCOIN", "quantity": 101}], "id": 0, "jsonrpc": "2.0"}

プレイヤーY

(ビットコインインスタンス)自分のサーバー

(ビットコインアドレス)143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y

(保有しているアセット)

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y"}}}'

{"result": [{"address": "143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y", "asset": "XCP", "quantity": 5000000}], "id": 0, "jsonrpc": "2.0"}

create_broadcast実行(オペレーターが賭けの内容をブロードキャストする)

賭けの内容は"A vs. B"です。プレイヤーは"A"が勝つと思うなら1、"B"が勝つと思うなら2に対してBetします。

$  curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"create_broadcast", "params":{"source":"1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "fee_fraction":0.05, "text":"A vs. B - A=1, B=2", "timestamp":1419836433, "value":-1}}'

トランザクションブロードキャスト後のtx_hashは..

{"jsonrpc": "2.0", "result": "f2a822fa470a0798b331072fa95c1a0d753563fce873decd3cfec47305112e8f", "id": 0}

Blockscanを見るとBroadcastの登録状況を確認できます。

create_bet実行(プレイヤーXとプレイヤーYが賭けをする)

プレイヤーXが"B"に3:1でBetする。

curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"create_bet", "params":{"source":"1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "feed_address":"1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "bet_type":2, "deadline":1419937909, "wager_quantity":1, "counterwager_quantity":3, "target_value":2, "expiration":120}}'

トランザクションブロードキャスト後のtx_hashは..

{"jsonrpc": "2.0", "result": "00602c62059c2af5549646d6f1b0d8de1795fbcfa68892bdfcb5c70280f70a06", "id": 0}

Blockscanでトランザクションを確認

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ"}}}'

{"jsonrpc": "2.0", "result": [{"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XCP", "quantity": 5000000}, {"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XSTAR", "quantity": 10}, {"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XZCOIN", "quantity": 101}], "id": 0}

5000001 -> 5000000に減っています。0.0000001XCPがescrowされているということでしょうか。(*2)

プレイヤーYが"A"に1:3でBetする。

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"create_bet", "params":{"source":"143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y", "feed_address":"1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "bet_type":2, "deadline":1419937909, "wager_quantity":3, "counterwager_quantity":1, "target_value":1, "expiration":120}}'

トランザクションブロードキャスト後のtx_hashは..

{"jsonrpc": "2.0", "result": "1b23d932cfb73a12dc0be593b95164c00524864ee21580c6bf799fd78ed9e045", "id": 0}

Blockscanでトランザクションを確認

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y"}}}'

{"jsonrpc": "2.0", "result": [{"address": "143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y", "asset": "XCP", "quantity": 4999997}], "id": 0}

5000001 -> 5000000に減っています。0.0000001XCPがescrowされているということでしょうか。(*2)

create_broadcast実行(オペレーターが賭けの結果をブロードキャストする)

今回は"B"が勝ったとします。つまりプレイヤーXが賭けに勝ったということです。

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"create_broadcast", "params":{"source":"1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "fee_fraction":0.05, "text":"A vs. B - A=1, B=2", "timestamp":1419842706, "value":2}}'

トランザクションブロードキャスト後のtx_hashは..

{"jsonrpc": "2.0", "result": "a784ce9290153ea296e859385163690976955c1d333c82981c98e3162bc515d9", "id": 0}

Blockscanでトランザクションを確認

結果確認

Betting完了後のアセット数量を確認します。

オペレーター

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy"}}}'

{"jsonrpc": "2.0", "result": [{"address": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "asset": "XCP", "quantity": 120819997}, {"address": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "asset": "XSTAR", "quantity": 70}, {"address": "1A31xhRp9FyQZXG57hXczaVLkH5Dm3m9jy", "asset": "XZCOIN", "quantity": 99495}], "id": 0}

プレイヤーX

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ"}}}'

{"jsonrpc": "2.0", "result": [{"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XCP", "quantity": 5000000}, {"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XSTAR", "quantity": 10}, {"address": "1KMdf7VWLEBdCo9iwmtpW7kJaSzSAUz2zJ", "asset": "XZCOIN", "quantity": 101}], "id": 0}

プレイヤーY

$ curl http://127.0.0.1:4000/api/ --user rpc:xcppw1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc":"2.0", "id":0, "method":"get_balances", "params":{"filters": {"field": "address", "op": "==", "value": "143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y"}}}'

{"jsonrpc": "2.0", "result": [{"address": "143q1MJUTRgsaXEcU86f8mMx6UThZFfW1Y", "asset": "XCP", "quantity": 4999997}], "id": 0}

まとめ

オペレーターとプレイヤーXは数量が増える想定でしたが、想定と異なる結果になっています。 整理してアップデートします。

参考

Issuance of an asset: What is callable parameter?

Bet: Bet is finished but the winner cannot get XCP.