ZooBC ウィキ
アプリと ZooBC での開発

1 枚の HTML ページでアプリを作る

ZooBC のアプリケーションは、背後にサーバーを持たない 1 つの HTML ファイルにすることができます。ページはノードの HTTP API からチェーンを読み、ユーザーの鍵でブラウザの中でトランザクションを構築・署名し、署名済みのバイト列を送信します。ユーザーはノードを動かす必要がなく、申請すべき API キーもありません。公式ウォレットがその証拠です。それ自体が 1 つの HTML ファイルで、すべてのノードが / と /wallet で提供しています(ウェブウォレット)。

1 つの HTML ファイルが GET で読み、ブラウザで署名し、署名済みのバイト列をノードまたはゲートウェイに POST します。
1 つの HTML ファイルが GET で読み、ブラウザで署名し、署名済みのバイト列をノードまたはゲートウェイに POST します。

ノード API

すべてのノードは、既定ではポート 8080 で平文の HTTP/1.1 API を提供しており、/api/v1/ の下に、ブロック、アカウント、トークン、アプリ、取引所など 100 を超えるルートがあります(ノード API)。すべての応答にはこれらのヘッダーが付き、OPTIONS リクエストには直ちに 200 で答えるため、どこでホストされたページからでもどのノードでも呼び出せます。

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-Node-Public-Key, X-Timestamp, X-Signature

ノード自体は TLS を持ちません。公開ドメインでは ゲートウェイで TLS が終端され、ゲートウェイは独自の CORS ヘッダーを加えます。ブラウザは HTTPS で読み込まれたページからの平文 HTTP の呼び出しをブロックするため、公開のページはゲートウェイと通信します。

8 つを除くすべてのルートは認証のない読み取りで、トランザクションの送信にはどんな種類の鍵も要りません。トランザクションが自分の署名を運んでいるからです。制限はクライアントのアドレスごとに適用されます。書き込みのリクエストは 1 分あたり 300 回で、それを超えると Retry-After ヘッダー付きの 429 になります。読み取りは運用者が制限を設定しない限り無制限です。そして 5 分以内に署名付きの認証に 20 回失敗すると、クライアントは 300 秒間締め出されます。

ブラウザでの署名

ページは、トランザクションを 1 つのチェーンに結び付けるダイジェストに署名します。

digest = SHA3-256("ZBC-TX" ‖ genesis hash ‖ unsigned transaction bytes)

ネイティブのアカウントは Ed25519 でそれに署名します。ページは GET /api/v1/node/info から genesis_hash と signing_version(2)を読み取ります。ジェネシスハッシュがダイジェストの中にあるため、あるチェーン用に作られた署名は別のチェーンでは無価値です(チェーン束縛署名)。SDK は必要ありません。Ed25519、SHA3-256、そしてジェネシスハッシュで十分で、バイトの構成は トランザクションのエンベロープ に記載されています。公開のツールには、script タグで読み込める依存関係のない JavaScript ファイルを含め、すぐに使えるライブラリもあります(コマンドラインツール)。鍵がページから出ることはありません。

送信と追跡

POST /api/v1/transactions               → 202, with "transaction_hash"
GET  /api/v1/transactions/<hash>/status → staging, mempool, confirmed (with block_height),
                                          rejected (with the reason and stage), or 404 not_found

202 は「受理した」という意味であって、「完了した」ではありません。ノードはトランザクションを解析し、最初の確認を行い、ステージングに取り込みましたが、ブロックの生成者がまだそれを取り込む必要があります。ステータスが confirmed になるまで、残高は何も変わっていません。15 秒に 1 ブロックなので、数秒ごとのポーリングで十分です。

応答が失われた場合は、まったく同じ署名済みのバイト列を再送してください。トランザクションのハッシュは未署名のバイト列と署名の SHA3-256 なので、すでにそのトランザクションを持っているノードは "duplicate": true 付きの 202 で答え、ブロックに入っていれば "state": "confirmed" を加えます。トランザクションは一度しか実行されません。新しいタイムスタンプで署名し直すと別のトランザクションになり、二重払いはそうして起こります。

既定では、ブロックはトランザクションのタイムスタンプから 3,600 秒後までそれを取り込めます。バージョン 3 のトランザクションは最大 86,400 秒まで自身の時間枠を示し、3,600 秒より先の未来のタイムスタンプは拒否されます(有効期限とタイムスタンプ)。支払いと引き換えに商品を引き渡す前には、確認済みになるのを待ち、さらに finalized フラグを待ってください。トランザクションは、共同署名されたスパインブロックがそのブロックを対象にした時点でこのフラグを得ます(ファイナリティとロールバック)。API は finalized_height、各ブロックの block_seed_proof、トランザクションの expiry、そして /spine/blocks/:height でスパインブロックも報告します。

202 の後:staging、mempool、confirmed、finalized。失われた応答には同じバイト列を再送します。
202 の後:staging、mempool、confirmed、finalized。失われた応答には同じバイト列を再送します。

アプリのためのルート

アプリのルートを提供するのは、アーカイブのサービスではなくノード自体です。/apps(フィルター status、limit、そして solo、pvp、party のいずれかである category)、/apps/open、/apps/pool、/apps/stats、/apps/:id(決済があればそれも)、/accounts/:a/apps です。

チェックリスト

  • 読み取りは HTTPS でゲートウェイを通じて行い、書き込みは鍵をページの中に置いたまま署名済みのバイト列を送信して行います。
  • ハッシュで追跡し、再試行は署名し直すのではなく、同じバイト列を再送して行います。
  • 429 と Retry-After を守ります。
  • チェーン上のテキストは textContent で表示します(チェーンデータは信頼できない入力)。
  • 「confirmed」は受領、「finalized」は決済完了として扱います。

関連項目