LiquidおよびElementsベースの他の環境向けに、新しい0-confインフラを公開しました。
Blockstreamが運用するこのサービスは、Liquidトランザクションに関するmempoolの可視性を集約します。ネットワーク上のnodeがトランザクションを確認した時点で報告し、サービスがそのデータを公開します。連携事業者は、特にswapや低遅延決済flowで、未承認支払いを受け入れるか判断する際の情報のひとつとして利用できます。
0-confサービスは、このsignalを標準化された照会可能な形式で提供します。独自のfederation監視を構築せず、設定済みのnetwork tier全体でトランザクションがどの程度広く観測されたかを、ひとつのサービスへ問い合わせられます。
ベータ期間中に協力してくださったLiquid Federationメンバーに、特に感謝します。swap workload、運用面のfeedback、テストを通じてAPI設計を検証できました。
0-confが必要な理由
現在、Liquidトランザクションは、格納されたブロックの上にもう1ブロックが追加されるとfinalとみなされます。実際には、Liquid Networkで決済済みとして扱うまで2承認、すなわち2分待つことになります。
Liquid決済を受け付けるswapサービス、取引所、その他のアプリケーションでは、より速い決済が必要になることがあります。0承認で受け入れると待ち時間を短縮できますが、二重支払いのriskが生じます。
新しい0-confインフラは、そのrisk評価を支援します。指定されたLiquidトランザクションが、設定済みのnetwork observation tierにどの程度伝播したかを報告するhosted APIです。Non-Replace-By-Fee(non-RBF)トランザクションでは広い可視性が有用なsignalとなりますが、riskを完全に排除するものではありません。
たとえばElementsでは、RBFが有効でない場合、nodeは同じinputを使用する競合トランザクションのうち最初に受け入れたものを保持します。その後に同じinputを再利用するトランザクションが届いても、手数料が高くても無視されます。Federationメンバーが誠実に行動するという前提では、non-RBFトランザクションがmempoolで広く確認されていれば、承認前の二重支払いの可能性が非常に低いことを示します。
Liquidの信頼モデルを理解する
Federated sidechainであるLiquidでは、functionary operatorと呼ばれる一部のメンバーがブロックを生成します。RBFを選択していない支払いについて、多数の観測nodeで確認されることは、Federationメンバーが誠実に行動しmempoolが正常なら、ネットワークがひとつの支払いversionに収束したことを示す強いsignalです。
0-confは、確認されたトランザクションが必ず承認されることを保証しません。指定されたトランザクションをmempoolで確認したと、どの観測nodeが報告したかを示すだけです。
したがって0-confは、network mempoolの可視性を正確かつリアルタイムに示します。受入判断の信頼できる根拠にはなりますが、可視性はあくまで指標であり、決済完了の証明ではありません。
実際のobservations
各API responseにはobservations objectが含まれ、observation tierごとに、設定されたnodeのうち何台がトランザクションを確認したかを示します。
seen:そのtierでトランザクションを報告したnode数total:そのtierに設定されているnode総数
{
"txid": "<txid>",
"observations": {
"bridge": { "seen": 1, "total": 2 },
"public": { "seen": 0, "total": 8 },
"functionary": { "seen": 12, "total": 15 }
}
}このAPIには、未承認トランザクションを安全に受け入れられると判断するfieldはありません。受入policyはアプリケーション側で定義します。
RESTとWebSocketの選択
どちらも同じobservation dataを返します。違いは更新の受け取り方です。
REST
txidを指定して現在の観測数をすぐに知りたい、単純でstatelessな確認に適しています。
- 任意のHTTP client、cron job、backend serviceから容易に統合できます。
- 接続維持が不要で、各requestは独立しています。
- 失敗時にretryしやすい方式です。
一方、観測数は時間とともに増えるため、RESTが返すのはrequest時点のsnapshotだけです。可視範囲の拡大を待つ場合はpollingが必要です。「受入前に1回確認する」用途や低頻度の状態照会に向き、リアルタイムの伝播監視には適していません。
WebSocket
観測数が基準値へ達するのを待ち、到達後すぐに処理したい低遅延flowに適しています。
- txidをsubscribeすると即座にsnapshotを受け取り、観測状況の変化ごとに追加snapshotが届きます。
- ひとつの接続で複数txidをsubscribeできます。
- pollingより遅延が小さく、待機中の反復HTTP requestも不要です。
一方、常時接続を維持し、切断、再接続、再subscribeを処理する必要があります。単一REST callよりclient logicが増えます。
REST interface
GET /api/v1/zeroconf/:txidトランザクションIDと現在のobservationsを含むJSON responseを返します。
{
"txid": "<txid>",
"observations": {
"bridge": { "seen": 1, "total": 2 },
"public": { "seen": 0, "total": 8 },
"functionary": { "seen": 12, "total": 15 }
}
}WebSocket interface
WS /ws/v1/zeroconfWebSocket接続後、txidの監視開始・停止をJSON messageで管理します。
Subscribe:
{ "action": "subscribe", "txid": "<txid>" }Unsubscribe:
{ "action": "unsubscribe", "txid": "<txid>" }同じ接続で複数のsubscriptionを同時に維持できます。
Subscribe成功時:
{ "action": "subscribed", "txid": "<txid>", "message": "subscription created" }Snapshotまたは更新時:
{
"action": "snapshot",
"txid": "<txid>",
"observations": {
"bridge": { "seen": 1, "total": 2 },
"public": { "seen": 0, "total": 8 },
"functionary": { "seen": 12, "total": 15 }
}
}期限切れ時:
{ "action": "expired", "txid": "<txid>", "message": "subscription expired" }エラー時:
{ "action": "error", "reason": "bad_txid", "message": "TXID must be 64 hex characters" }Subscriptionはserver設定のtimeout後に自動で期限切れとなります。更新が必要なら再度subscribeできます。
データ保持
Serverは定期的にトランザクションをmemoryから削除します。このサービスは最近のmempool可視性を確認するもので、長期的なトランザクションindexではありません。すでに承認された、または長期間mempoolにあるトランザクションは、結果が不完全または存在しない場合があります。
フィードバックとバグ報告
問題やAPI・ドキュメントの改善提案がある場合は、Liquid Developer Telegram channelの@liquid_develまでご連絡ください。
デバッグに役立てるため、報告時には次の情報を含めてください。
- 照会したtxid(該当する場合)
- RESTまたはWebSocketのどちらを使用したか
- 送信requestと受信response(error messageを含む)
- timezoneを含むおおよその時刻
- 連携context(swap flow、加盟店checkoutなど)