Fig 1. Gimbalabs Plutus PBL - Japanese version
この包括的な3部作シリーズの最終部では、ブロックチェーンとスマートコントラクトの重要な概念である「時間」の理解により、旅の終わりに到達します。
Plutusにおける時間の動作、POSIXTime
およびLedger Slot Numbers
という重要な概念を含む理解を得るでしょう。
時間は、ブロックチェーンやスマートコントラクト開発の世界で重要な役割を果たします。
それは、さまざまな操作の実行、契約の検証、および分散型アプリケーション(DApps)のオーケストレーションに影響を与えます。
このレッスンでは、時間に敏感なスマートコントラクトやアプリケーションを作成するためにPOSIXTimeを使用する方法、およびこれらのslot numbersが時間間隔を測定し、契約の実行をスケジュールし、ブロックチェーンイベントを管理する方法について学びます。
Student Learning Targets (SLT)
- 私は自分自身のPlutus契約を計画し、実装することができます。
- 私はPlutusプロジェクトを作成し、更新し、メンテナンスすることができます。
- 以下のシナリオで時間がどのように機能するかを理解しています:Plutus(‘POSIXTime’)、‘Ledger’(‘Slot Number’)。
シリーズの最初の部分では、最初のSLTをカバーしました:私は自分自身のPlutus契約を計画し、実装することができます。第2部では、第2のSLTをカバーしました:私はPlutusプロジェクトを作成し、更新し、メンテナンスすることができます。本日、このシリーズの第3部である最終部では、次のSLTに焦点を当てます:
以下のシナリオで時間がどのように機能するかを理解しています:Plutus(‘POSIXTime’)、‘Ledger’(‘Slot Number’)。
Fig 2. このドキュメントとビデオレッスンのレッスンをGimbalabs Plutus PBL - SLT 302.3で見つけてください。
それでは、「理解しました」という成果を得ましょう。
Lockbox契約の仕組み
このスマートコントラクトでは、PlutusおよびCardano Ledgerで時間がどのように機能するかを理解するのに役立つ実験を作成しました。これを、3つの段階を含むロックボックスと考えてください。各段階には一定のADAやトークンが含まれています。これらの各段階には、内部の資金を請求するための締め切りがあります。
さて、ロジックを段階的に解説しましょう。まず、3つのUTxOsをこのロックボックス契約に送信します。各UTxOには一定量のADAまたはトークンが含まれており、それぞれに固有の番号を添付します。その番号がそれらのUTxOsの「datum」となります。この番号は重要です。なぜなら、これによって契約がこれらのUTxOsを区別できるからです。
コンパイル段階で、POSIXTime
という概念を使用して、3つの期限を指定します。これらの期限は、ロックボックスの各段階が期限切れになるタイムスタンプです。各段階にタイマーを設定するのと同じです。
興味深いことがここから始まります。各UTxOを、それぞれの期限前にロック解除、または「支出」したい場合、トランザクションを構築する際に Slot numbers
の概念を使用します。Slot numbers は、カレンダーのスロットのようなもので、Cardanoブロックチェーン上の特定の時間を表します。
さて、2つの重要なコンポーネントについて話しましょう:Redeemer
と Datum
です。どちらもパラメータを持ち、これらのパラメータは、コンパイル段階で期限と一緒に割り当てた固有の番号です。
なぜこれを行うのか?それはただ楽しいだけではありません。パラメータ化されたデータの力を実践で示すためです。これらの数字を Redeemer
と Datum
に添付することで、契約が異なる UTxOs を認識し区別する方法を示しています。それぞれが固有の番号と期限を持っています。
要するに、このスマートコントラクトは、PlutusとCardanoで時間、データ、およびロジックの相互作用を探索するための遊び場です。タイムスタンプ、スロット番号、およびパラメータ化されたデータを使用して、この契約を実現するための実践的な経験を積むことができます。さあ、一緒に時間とスマートコントラクトの謎を解き明かしましょう!
準備
ステップ1: リポジトリをクローンまたは更新します。
- もしあなたがppbl-2023-plutus-templateを持っていない場合、それをクローンしてください。
- すでに持っている場合は、
git pull
を行って最新の状態にしてください。
ステップ2: 開発環境を準備します。
cabal update
を実行して、Cabal Package managerを更新してください。cabal repl
を実行して、インタラクティブな開発のためのREPL(Read-Eval-Print Loop)を開いてください
ステップ3: Compilerモジュールをロードします。
- REPL内で、次のコマンドを入力して
Lockbox.Compiler
モジュールをロードしてください。
AlwaysSucceeds.Compiler> :l Lockbox.Compiler
ステップ4: Outputフォルダを作成します。
createOutputFolder
関数を呼び出して、すべての契約ファイル、datums、および redeemers が保存される output フォルダを作成してください。
Lockbox.Compiler> createOutputFolder
ステップ5: DeadlinesとNumbersを設定します。
./src/Lockbox/Compiler
にあるCompiler.hs
ファイルに移動してください。lockboxParams
セクションを探し、firstDeadline
、secondDeadline
、thirdDeadline
、num1
、num2
、およびnum3
の値を、要件に応じて変更してください。- deadlinesをPOSIXTimeミリ秒で指定してください。
num1 :: Integer
num1 = 1
num2 :: Integer
num2 = 2
num3 :: Integer
num3 = 3
lockboxParams :: LockboxParams
lockboxParams = LockboxParams
{ firstDeadline = 999999999
, secondDeadline = 999999999
, thirdDeadline = 999999999
, number1 = num1
, number2 = num2
, number3 = num3
}
ステップ6: 契約をコンパイルし、DatumsとRedeemersを生成します。
- 契約をコンパイルし、次のコマンドを1つずつ使用してdatumsとredeemersを生成してください。
Lockbox.Compiler> writeLockboxScript
Lockbox.Compiler> writeDatum1
Lockbox.Compiler> writeDatum2
Lockbox.Compiler> writeDatum3
Lockbox.Compiler> writeFirstClaimRedeemer
Lockbox.Compiler> writeSecondClaimRedeemer
Lockbox.Compiler> writeThirdClaimRedeemer
資金のロック
資金を契約にロックするには、次の手順に従ってください。手順を進める前に、すべての必要な要件を満たしていることを確認してください。
ステップ1: 契約アドレスを生成します。
UTxOsを契約に作成して送信する前に、契約ファイルから契約アドレスを生成する必要があります。ターミナルを開き、「output」ディレクトリに移動してください。
$ cd output
次に、以下のコマンドを実行して契約アドレスを構築します。契約ファイル lockbox.plutus
の正しいパスを指定することを確認してください。
$ cardano-cli address build --payment-script-file ./lockbox.plutus --testnet-magic 1 > lockbox.addr
ステップ2:トークンをロックします
今、コントラクトアドレスを取得したら、lockboxコントラクトに3つのUTxOsを作成して送信する時です。 cardano-node
とcardano-cli
のバージョン8.1.2以上がインストールされていることを確認してください。
各UTxOについて、適切なdatumファイルでこれらの手順を繰り返します。
UTxO 1:
cardano-cli transaction build \
--testnet-magic 1 \
--tx-in "INPUT_UTxO_TxID_FROM_YOUR_WALLET" \
--tx-in-collateral "COLLATERAL_UTxO_TxID_FROM_YOUR_WALLET_IN_CASE_TX_FAIL" \
--tx-out "$(cat lockbox.addr)+2000000" \
--tx-out-inline-datum-file lockboxDatum1.json \
--change-address "YOUR_WALLET_ADDRESS" \
--out-file tx.body
cardano-cli transaction sign \
--testnet-magic 1 \
--out-file tx.signed \
--tx-body-file tx.body \
--signing-key-file "YOUR_WALLET_SINGING_KEY"
cardano-cli transaction submit \
--testnet-magic 1 \
--tx-file tx.signed
UTxO 2:
- 前述の手順を繰り返しますが、datumファイルの名前を
lockboxDatum2.json
に変更します。--tx-out-inline-datum-file
フラグを適切に調整してください。
UTxO 3:
- 前述の手順を繰り返しますが、datumファイルの名前を
lockboxDatum3.json
に変更します。--tx-out-inline-datum-file
フラグを適切に調整してください。
資金の解除
現在、契約内に安全にロックされた資金を解除する、という面白いプロセスを探索していきましょう。lockbox コントラクトの first claim 条件を調査しましょう。
(FirstClaim redeemerNumber, LockboxDatum datumNumber) ->
traceIfFalse "First Deadline Has NOT Been Reached"
(from firstDeadline `contains` txInfoValidRange info )
&& traceIfFalse "Numbers Mismatched"
( number1 == redeemerNumber
&& number1 == datumNumber
)
このセクションでは、redeemer が FirstClaim
に設定され、datum が LockboxDatum
に設定されている場合のシナリオに対処しています。この条件下では、契約は次の基準に基づいてトランザクションを検証する必要があります:
ステップ1:
First Deadline Check: トランザクションの時刻は firstDeadline
よりも「後」でなければなりません。これにより、指定された締め切り時刻が過ぎた後にのみトランザクションが試行されることを保証します。
ステップ2:
Number Matching: 我々は、contract parameter である number1
の値を、redeemer parameter (redeemerNumber
) と datum parameter (datumNumber
) の両方と比較します。このチェックにより、数字が正しく整合していることを保証し、契約に追加のセキュリティレイヤーを提供します。
最初の締め切りが達成され、条件が満たされたことを確認したので、UTxO 1 をアンロックすることができます。これを行うには、現在の slot number を知る必要があります。そして、トランザクションを構築する必要があります。
node をクエリして現在の slot number を取得できます:
$ cardano-cli query tip --testnet-magic 1
{
"block": 1390609,
"epoch": 94,
"era": "Babbage",
"hash": "844cb91b7a8c9f26ada3db6249d094cfff91f4c2343d9eafd7bd3852cee6bf00",
"slot": 39309638,
"slotInEpoch": 343238,
"slotsToEpochEnd": 88762,
"syncProgress": "100.00"
}
この例では、現在のslot numberは 「slot」: 39309638
です。この情報を元に、「UTxO 1」 をアンロックするために必要なトランザクションを構築することができます。
cardano-cli transaction build \
--testnet-magic 1 \
--tx-in "INPUT_UTxO_TxID_FROM_YOUR_WALLET_TO_PAY_THE_TX_FEE" \
--tx-in-collateral "COLLATERAL_UTxO_TxID_FROM_YOUR_WALLET_IN_CASE_TX_FAIL" \
--tx-in "INPUT_UTxO_TxID_FROM_LOCKBOX_CONTRACT" \
--tx-in-inline-datum-present \
--tx-in-script-file ./output/lockbox.plutus \
--tx-in-redeemer-file ./output/firstClaimRedeemer.json \
--tx-out "YOUR_WALLET_ADDRESS+2000000" \
--invalid-before "NOW_SLOT_NUMBER" \
--change-address "YOUR_WALLET_ADDRESS" \
--out-file tx.body
cardano-cli transaction sign \
--testnet-magic 1 \
--out-file tx.signed \
--tx-body-file tx.body \
--signing-key-file "YOUR_WALLET_SINGING_KEY"
cardano-cli transaction submit \
--testnet-magic 1 \
--tx-file tx.signed
前のコマンドのシーケンスは、所望の資金をアンロックするトランザクションを構築し、署名して送信します。プレースホルダーを実際のトランザクションの詳細で置き換えてください。YOUR_WALLET_ADDRESS
と NOW_SLOT_NUMBER
は、以前に取得した “あなたの” ウォレットアドレスと現在のslot numberで置き換える必要があります。
さて、lockbox コントラクト内の second claim 条件の詳細について掘り下げましょう。
(SecondClaim redeemerNumber, LockboxDatum datumNumber) ->
traceIfFalse "Second Deadline Has NOT Been Reached"
(from secondDeadline `contains` txInfoValidRange info)
&& traceIfFalse "Third Deadline Has Been Reached"
(to thirdDeadline `contains` txInfoValidRange info)
&& traceIfFalse "Numbers Mismatched"
( number2 == redeemerNumber
&& number2 == datumNumber
)
このセクションでは、redeemer が SecondClaim
に設定され、datum が LockboxDatum
に設定されている場合のシナリオに対処しています。この条件下では、契約は次の基準に基づいてトランザクションを検証する必要があります:
ステップ3:
Second Deadline Check: トランザクションの時刻は secondDeadline
よりも「後」でなければなりません。これにより、指定された締め切り時刻が過ぎた後にのみトランザクションが試行されることを保証します。
ステップ4:
Third Deadline Check: 逆に、トランザクションの時刻は thirdDeadline
よりも「前」でなければなりません。この条件により、トランザクションが指定された締め切り前のみに試行されることが保証されます。
ステップ5:
Number Matching: first claim と同様に、number2
の値(contract parameter)を redeemer parameter (redeemerNumber
) および datum parameter (datumNumber
) と比較します。このチェックにより、数字が正しく整合していることが確認され、契約に追加のセキュリティレイヤーが追加されます。
第二の締め切りが到達したことを確認しましたが、まだ第三の締め切り前にあるため、「UTxO 2」 をアンロックする準備ができました。前回と同様に、トランザクションを構築するには現在の slot number を知る必要があります。これに関する情報は、UTxO 1の場合と同様に、node をクエリすることで取得できます。
cardano-cli transaction build \
--testnet-magic 1 \
--tx-in "INPUT_UTxO_TxID_FROM_YOUR_WALLET_TO_PAY_THE_TX_FEE" \
--tx-in-collateral "COLLATERAL_UTxO_TxID_FROM_YOUR_WALLET_IN_CASE_TX_FAIL" \
--tx-in "INPUT_UTxO_TxID_FROM_LOCKBOX_CONTRACT" \
--tx-in-inline-datum-present \
--tx-in-script-file ./output/lockbox.plutus \
--tx-in-redeemer-file ./output/secondClaimRedeemer.json \
--tx-out "YOUR_WALLET_ADDRESS+2000000" \
--invalid-before "NOW_SLOT_NUMBER" \
--invalid-hereafter "$((NOW_SLOT_NUMBER + 60))" \
--change-address "YOUR_WALLET_ADDRESS" \
--out-file tx.body
これらのコマンドを正常に実行すると、UTxO 2 内の資金がアンロックされます。素晴らしいですね!しかし、何が起こったのか、--invalid-before
とは何で、なぜ今 --invalid-hereafter
も必要になったのでしょうか?
「Invalid Before」か「Invalid Here After」、それが問題だ。
--invalid-before
および --invalid-hereafter
パラメータは、Cardanoトランザクション内で時間制約を指定するために使用されます。lockboxスマートコントラクトでは、時間に敏感な条件を扱っています。契約内での資金の請求には異なる段階や締め切りがあります。これらの締め切りを強制するために、Cardanoブロックチェーン上の時間を測定するために slot numbers を使用します。これらの意味と、lockbox スマートコントラクトのコンテキストで両方が必要な理由を探ってみましょう:
--invalid-before
: このパラメータは、「最も早い」有効な slot number を設定するために使用されます。lockbox コントラクトの文脈では、ここで指定された値以上のslot numberを持つブロックにトランザクションが含まれる場合にのみ、トランザクションが有効であることを保証します。これは重要です。なぜなら、特定の slot(締め切り)が達成された後にのみトランザクションが発生する条件を強制するからです。たとえば、契約の第2フェーズで資金を請求する場合、第2の締め切り前に行われないようにしたいと思います。- –invalid-hereafter: このパラメータは、「最新の」有効なスロット番号を設定するために使用されます。指定された値よりも小さいslot numberを持つブロックにトランザクションが含まれる場合にのみ、トランザクションが有効であることを保証します。lockbox契約では、この条件を強制するために不可欠です。つまり、トランザクションが特定の slot(締め切り)に達する前に発生する必要があります。たとえば、第2段階で資金を請求する場合、トランザクションが第3の締め切り前に送信されることを確認したいと思うでしょう。
–invalid-before と –invalid-hereafter の両方を使用することで、トランザクションが有効な時間ウィンドウが作成されます。この時間ウィンドウは、契約内で対象としている特定のフェーズや締め切りに合わせています。これにより、トランザクションが発生できるタイミングを正確に制御し、契約の時間ルールに準拠することが保証されます。
オリジナルのレッスン(ビデオレッスンを含む)はこちらからご覧いただけます。
今後のお知らせについては、Gimbalabsをフォローしてください。
GimbalabsのDiscordに参加して、Gimbalabsコミュニティとのやり取りを始めましょう。
もう一つだけ :
カルダノブロックチェーンを活用した開発の奥深くに携わりたい方、そしてその技術を使って重大な問題解決に取り組んでいる方々と共に歩みたい方を対象に、Andamio platformでは、どなたでも参加可能な「ライブコーディング」セッションを開催しています。Live Coding は、ブロックチェーンプロジェクトを公開で、生放送で、秘密や保留なしに構築することを指します。そして、何でも質問する権利があります。Andamio’s calendarには、以下のセッションがあります:
Cardano Go Live Coding:Goプログラミング言語を使用した構築。毎週月曜日、13:00 UTC。
Mesh Live Coding:Cardanoのよく知られたMeshライブラリを使用した構築。毎週月曜日、13:00 UTC
よろしくお願いします、
Sebastian Pabon
Gimbalabs チーム