Cardanoのパフォーマンスと台帳最適化のロードマップに関する最近のブログ記事に続き、今回はEUTXO台帳のアーキテクチャーを掘り下げたテクニカルダイブ記事を用意しました。
ここでは、アーキテクチャーの例を提示するとともに、トランザクションスループットを拡大し、トランザクション処理の待ち時間を最小化するような改良の可能性について論じたいと思います。
CardanoのEUTXOモデルは分散型金融(DeFi)と分散型アプリケーション(DApp)開発のための堅固な基盤であり、トランザクションの並列処理を可能にすることにより、アカウントベースモデルよりも優れたスケーラビリティと、強化された安全設定を提供します。
しかし、EUTXOモデルよりもアカウントベースのシステムに適用可能な設計やメカニズムを使用すると(特に分散型取引所の構築時)、競合の問題を引き起こす恐れが生じます。この結果、新しいトランザクションは前回のトランザクションのアウトプットに依存することとなり、そのため特にトランザクションの数が多いときには遅延が発生することになります。この問題を排除するために、開発者はシングルスレッドのステートマシンスタイルを使用することを避け、特にEUTXOプロパティを考慮したアプリケーションを設計する必要があります。
適切なアーキテクチャー例
オーダーブックパターンは、スマートコントラクトロジック対応であれば、DEX開発に適用できるアプローチの1つです。また、SundaeSwapのブログ記事で紹介、評価されているほとんどのプロトコルアーキテクチャーは、以下の一般的なアプローチに依存しています。
- ユーザーは、送信したオーダーの説明(トークンやデータムなど)と一緒に、中間スクリプト(リクエストスクリプト)に資金をロックする
第三者(バッチャー)がリクエストスクリプトにあるオーダーを、以下のような単一のトランザクションに集約
- ロックされたオーダーは、更新されるべきメインスクリプト(流動性プールなど)のグローバルステータスを保持しているUTXOと一緒に使用される
- オーダーを実行した結果は元のユーザーに返される
- 更新されたグローバルステータスを保持する新しいUTXOは、メインスクリプトアドレスに入る
このようなバッチパターンを採用するときは、リクエストスクリプトにあるNオーダーが単一のトランザクションにいつ使用されても、トランザクション送信でリクエストスクリプトがN回実行されることを念頭においてください。さらに、メモリー制限チェック(トランザクションが送信されたときにトリガーされる)は、各リクエストスクリプトの実行、メインスクリプトの実行、また、併せて実行されることもあるMintingPolicyスクリプト(プロトコル設計次第)ごとのメモリー消費を集計することによって実現されます。さらに、使用されたオーダー数に比例する同じトランザクションコンテキストが、各スクリプト実行の引数として渡されます。
これは良いアプローチですが、改良の余地はあります。
リクエストスクリプトの実行をN回(集約されたトランザクション内で)トリガーしないようにするための解決策の1つの可能性は、ユーザーが代わりに自分の公開鍵アドレスに直接オーダーを送信することです。リクエストスクリプトは、保留中のオーダーの存在を通知し、オーダーが処理された後にバッチャーが請求できるトランザクション手数料をロックするためにのみ使用されます。このソリューションを使うと、ユーザーは集約されたトランザクションに署名して、オーダーの使用を許可する必要もあります。このようなケースでは、バッチのすべてのユーザーがオンラインで参加する必要があるという点も重要です。このようなソリューションの単純化したアーキテクチャーは以下のようにまとめられます。
オーダーの送信:
- ユーザーの公開鍵アドレスに送信する「オーダー」トークンを発行するために、特定のMintingPolicyが使用可能
- ユーザーの公開鍵アドレスのハッシュは、オーダーの説明および必要なトランザクション手数料とともに、オーダーの通知のためにリクエストスクリプトに送信可能
オーダーの処理:
- バッチャーは、リクエストスクリプトアドレスにあるUTXOを調査して「オーダー」トークンを収集し、集約トランザクションを構築する。この際、「オーダー」トークンは集約トランザクションを検証するためにメインスクリプトで使用される。「オーダー」トークンが対応する公開鍵アドレスに存在しなかった場合、オーダーは無効とみなされる
- リクエストスクリプトにあるUTXOは、集約トランザクションでは使用されず、「オーダー」トークンを保持しているUTXOを収集するためにのみ使用される
- バッチャーは関係するユーザーに集約トランザクションを送信するために署名するよう通知
- メインスクリプトにバインドされたMintingPolicyは、処理済みのオーダー用の「レシート」トークンをミントするために使用される。この「レシート」トークンはバッチャーがリクエストスクリプトにロックされたトランザクション手数料を請求するために使用
トランザクション手数料の回収:
- バッチャーは、対応する「レシート」トークンを提供することによって、リクエストスクリプトにあるUTXOを使用することができる
パブリックテストネットで実行されたベンチマークは、この単純なアーキテクチャーで、およそ25から30のオーダーが1つのトランザクション内で1000万ユニットというメモリー制限を超えることなく容易に処理できることを示しています。またこの数値を増やすために、追加的な最適化を実行することができると確信しています。
開発者はまた、このアーキテクチャーを拡張して、決定性のあるオーダリング、設定時間内のユーザーによるオーダーキャンセル、悪質なバッチャーに対する追加的保護を保証する、より洗練されたメカニズムを検討することができます。
これは単に、DApp設計に使用できるEUTXO特有のアプローチの1例にすぎません。現在ドキュメントの拡張に取り組んでおり、今後他の例も紹介していく予定です。現時点では、ここでマルチシグを使用した並行を回避するサンプルコードが見つかります。
また、開発者コミュニティがさらに多くのモデルを特定することが想定されます。今後数か月、Plutus開発コミュニティのリソースを構築するために、そうした発見をリポジトリに加えていきたいと考えています。
本稿の執筆に協力いただいたJohn Woodsとチームに感謝します。
最新の記事
Hydra Doom Tournament 筆者: Fernando Sanchez
22 November 2024
Quality Engineering at IO: bridging research and reality in software development 筆者: Ivan Irakoze
20 November 2024
ブラックホーク空へ:ハリケーン「へリーン」を受けて英雄達を輸送 筆者: Fernando Sanchez
29 October 2024