ブログ > 2025 > February > Plutus TxがPlinthに衣替え

Plutus TxがPlinthに衣替え

Plutus Txが新機能を備えてPlinthに。名称変更により、高度なスマートコントラクト開発とCardanoのPlutus Core実行レイヤーの区別が明確化

2025年 2月 20日 Ziyang Liu 11 分で読めます

Plutus TxがPlinthに衣替え

進化を続けるCardanoのスマートコントラクト機能においては、明確さと精度が鍵となる。最近のPlutus TxのPlinthへのリブランディングは、この方向への一歩を表している。先日のPlutusワーキンググループ会議で承認されたこの変更は、Plutus TxとPlutus Coreの区別を明確にし、エコシステムにおける混乱の原因に対処することを目的としている。

Plinthとは

Plinth(プリンス、旧称Plutus Tx)は、Cardanoでスマートコントラクトを記述するための高レベル言語である。開発者はHaskellのサブセットでコントラクトを書くことができ、そのコントラクトはUntyped Plutus Core(UPLC)にコンパイルされる。UPLCはCardanoノードがスクリプトを実行するために使用する言語である。このため、CardanoはHaskellに精通した開発者やそれを学びたい人にとって親しみやすいものになっている。

Plutus TxをPlinthに改称した理由

「Plutus」という用語は「Plutus Tx」と「Plutus Core」の両方を指す用語として曖昧に使われてきた。今回の名称変更は、この曖昧さにまつわる混乱を解消することを目的としている。この混乱はしばしば誤解を招き、特にCardanoのオンチェーン実行言語がHaskellベースであるという誤った仮定が生じた。

実際には、Cardanoはラムダ計算に基づく低レベル言語であるUPLCを使用してスマートコントラクトを実行している。PlinthはAiken、Opshin、plu-ts、Plutarch、Scalusと並んでUPLCにコンパイルされる高レベル言語の1つである。詳細については、Plinthユーザーガイドの「Overview of Languages Compiling to UPLC(UPLCにコンパイルされる言語の概要)」を参照のこと。

曖昧さを避けるために、「Plutus」の名称は単独での使用を避けるか、Untyped Plutus Coreを参照するためにのみ使用されるべきであろう。

名称変更以外のPlinthの新機能

Plinthの元々の魅力は、スタンドアロン言語や埋め込みドメイン固有言語(DSL)ではなく、Haskellのサブセットであるというシンプルさにある。これにより、Haskellの経験がない人でも、特に単純なHaskellコードを効率的に生成し説明することができる現代のAIツールを使ってアクセスできるようになる。加えてPlinthは、Haskellの既存ツールやフレームワーク(Cabal、GHCi、言語サーバー、メタプログラミング用のTemplate Haskellなど)に完全に対応している。

しかし、効率性が重要な課題となってきた。トランザクション手数料はスクリプトの実行コストとサイズに依存し、Cardanoは両方に厳格な制限を課しているため、最適化は不可欠である。この問題に対処するため、Plinthは最近、スクリプトの効率を向上させるための複数の機能強化を行った。以下は簡単な概要である。

DataエンコードされたScriptContext

以前、PlinthはScottエンコーディング、SOP(sums-of-products)と並んでデータ型をエンコードする3番目の方法を導入した。これが、Plutus Coreの組み込み型「Data」を使用したデータ型のエンコーディングである。Plinthに代わる選択肢のほとんどがScottおよびSOPエンコーディングをサポートしていないため、これが唯一の利用可能なエンコーディング手法となる。最近では、Dataエンコーディングベースの新しいPlutus台帳 APIが導入された。このAPIはScriptContext、MAP、Listなど、さまざまな型にサポートを拡張している。

Dataエンコーディングにはトレードオフがある。一般的に処理に時間がかかり(equalsDataプリミティブの恩恵を受けた等価性チェックを除く)、Dataオブジェクトには関数を含めることができないため表現力が劣る。しかし、主な強みはスクリプト実行における効率の良さである。スクリプトは引数(特にScriptContext)をDataとして受け取り、アウトプットデータもDataオブジェクトであるため、Dataを直接使用することでDataとScottもしくはSOPエンコーディング間の変換が不要になる。

Plinthの従来のアプローチは、unsafeFromBuiltinDataを使って全てのスクリプト引数をScottmもしくはSOPエンコーディングに変換するというものであった。これは、「常に成功する」平凡なPlinthスクリプトでさえ、他の選択肢に比べてかなり高額になるという懸念を生じさせてきた。Dataを直接操作することでこのオーバーヘッドを回避することは常に可能であったが、そのためには低レベルの型安全でないコードを必要とした。

Plinthでは、開発者はスクリプト内の各データ型に対して最も効率的なエンコーディング方式を選択できる。

  • DataエンコードされたScriptContextを使用するには、PlutusLedgerApi.V3(またはV1/V2)の代わりにPlutusLedgerApi.Data.V3(またはV1/V2)からインポートする
  • Dataエンコーディングをカスタム型に適用するには、asDataで定義をラップする

これらのデータ型を構築して検査するプロセスは、ほとんど変わらない。詳細はPlinthユーザガイドのOptimizing Scripts with asData(asData`によるスクリプトの最適化)を参照のこと。

その他のインラインコントロール

インライン化には、スクリプトのコストとサイズのトレードオフが絡んでくる。インライン化を増やすとスクリプトの実行コストは削減されるが、スクリプトのサイズは増加する可能性がある。ただし、インライン化を行うことでさらなる最適化が可能になり、サイズの増加を抑えることも可能になる。従来、Plinthコンパイラーはスクリプトサイズの制約に優先順位を付けて保守的なアプローチをとってきた。しかし、ユーザーには実行速度が速いほうが好まれる。これはスクリプトのコストを下げることでトランザクション手数料を削減できるためである。このことは、特に参照スクリプトにあてはまる。

インライン化をより細かくコントロールできるように、Plinthには以下の機能が含まれる。

  • inline-fixコンパイラーフラグ:再帰的束縛をコンパイルするときに自動的に挿入されるすべての不動点コンビネーターをインライン化するようコンパイラーに指示する。ベンチマークは、このフラグを有効にするとスクリプトコストが削減されることを示しており、スクリプトのサイズ増加はあってもわずかである。このため、inline-fixはデフォルトで有効になっている。
  • PlutusTx.Optimize.Inline.inline関数:束縛が再帰的でない限り、サイズに関係なく、特定の呼び出し元で束縛をインライン化するようPlinthコンパイラーに指示する。この関数はPlinthにおけるGHC.Magic.inlineとして機能する。すべての呼び出し元で束縛をインライン化するには、代わりにINLINEプラグマを使う。

スクリプトコストに影響する他のコンパイラーフラグには、inline-constantsとpreserve-loggingがある。完全なフラグリストは、ユーザーガイドのPlinth Compiler Options(Plinthコンパイラーオプション)を参照のこと。

再帰展開

スクリプトのコストとサイズのバランスを取るためのアプローチとしては、インライン化以外にも、命令型言語のループ展開に似た再帰展開がある。この最適化は将来コンパイラーで処理できるようになるかもしれないが、Plinthは現在Template Haskellを使って言語レベルでの再帰展開のためのユーティリティを提供している。

具体的には、PlutusTx.Optimize.spacetimeモジュールに2つの関数を導入している。

  • peel:指定した数の再帰層を削除する
  • unroll:再帰が完全に展開されるまで、従来のループ展開を模して、設定された数の層を繰り返しpeelする

例として、peelを使用してlength関数の3つの層を削除することができる。

lengthPeeled :: [Integer] -> Integer
lengthPeeled =
  $$( peel 3 $ \self ->
        [||
        \case
          [] -> 0
          _ : xs -> 1 + $$self xs
        ||]
    )

このアプローチにはTemplate Haskellが必要であるが、Haskellでは難しい概念とも言える。しかし、ここでの用法は比較的単純である。

再帰展開をコンパイラーに直接導入する計画があるが、そうすれば開発者はlengthのような標準的な再帰関数を追加の変換なしで作成することができる。

つまり、この技術を理解することには価値がある。同様の最適化が必要な場合、開発者はコンパイラーのサポートを待つのではなく、peelやunrollを使って自分でそれを実装することができる。

Plinthの次のステップとは

High Assurance:スマートコントラクト自動検証

Plutusチームは、Cardanoスマートコントラクト用の自動形式検証ツールを開発中である。このツールは、SMT解法とリーン定理証明機を利用することにより、正確性と安全性を保証する。そして、開発者が、Plinthを含む表面言語でコントラクトプロパティを形式的に仕様記述できるようなアノテーション言語を導入する。

アノテーション言語の表現力は、ブロックチェーンのステータスに関連するグローバルプロパティと、トランザクション関連のプロパティまたは一時的なプロパティの両方を記述することを可能にする。この機能により、個々のスマートコントラクトやDAppプロトコル全体の形式的検証が可能になる。

証明付きコンパイル

チームは、AGDAで形式化した変換認証フレームワークを使ったPlinthコンパイラーの強化に取り組んでいる。Plinthプログラムをコンパイルするとき、コンパイラーはコードに適用される変換に対応する変換証明書(AGDA証明オブジェクト)を生成する。これにより、コンパイラーがPlinthのソースコードをUPLCに正確に変換したことを保証することができる。

終わりに

Plutus TxからPlinthへのリブランディングは、単なる名称変更に留まらない。これは、Cardanoエコシステム全体で開発者が利用できる言語をより明確にするための動きである。Cardanoが成長するにつれて、Plinthのようなツールは、開発者がブロックチェーンで洗練された高保証アプリケーションを構築できるようにする上で重要な役割を果たすだろう。

本ブログ記事はLars BrünjesとOlga Hryniukの共同執筆による。また、Philip DiSarroの貴重な情報提供にも感謝する。