Epoch#233 | Marloweチュートリアル7章
こんにちは。カルダノのステークプールオペレータのSUGARです。Marloweのチュートリアルを少しずつ読んでみています。今回はデータ型に関してですが、プログラムが「文章の様に読める」とはいえ固有の表現などもありますし、分野的に馴染みがあまりないため勉強していきたいです。理解が深まってより分かりやすい文章がかけるようになっていけるといいなと思います。
そもそも「Marloweとは?」など、過去の記事をブログまとめページにまとめていますので、こちらもよろしくお願いします。
7. Marloweのデータ型
このチュートリアルでは、Haskellデータ型としてのMarloweを正式に紹介し、モデルで使用されるさまざまな型を紹介し、コントラクトが実行されるインフラストラクチャに関するいくつかの仮定について議論します。ここで説明するコードは、HaskellモジュールのSemantics.hsとUtil.hsから来ています。
7.1. Marlowe
Marloweドメイン固有言語(DSL)は、Haskellの代数型のコレクションとしてモデル化されており、契約はContract型で与えられます。
data Contract = Close
| Pay Party Payee Token Value Contract
| If Observation Contract Contract
| When [Case] Timeout Contract
| Let ValueId Value Contract
| Assert Observation Contract
前回のチュートリアルでは、これらのコントラクトが何をするのかを見ました。このチュートリアルの残りの部分では、アカウント、値、オブザベーション、アクションなど、コントラクトの様々なコンポーネントを表現するために使用されるHaskellの型をもう少し深く掘り下げていきます。また、入力、状態、環境を含むコントラクトの実行に関連する型についても見ていきます。
7.2. 基本のコンポーネント
Marloweの基本的な部分をモデリングする際には、新しい型を定義するHaskellデータ型と、既存の型に新しい名前を与える型同義語を組み合わせて使用します。
Marlowe アカウントは、複数の通貨の金額、および/または互換性のあるトークンと非互換性のあるトークンを保持します。具体的な金額は、CurrencySymbol と TokenName のペアである Token によってインデックス化されます。下記において、アカウントはトークンと整数値のマッピングと考えることができます。
data Token = Token CurrencySymbol TokenName
カルダノのAdaトークンはToken adaSymbol adaTokenです。しかし、独自の通貨やトークンを作るのは自由です。
通貨のトークンは、「買い手」と「売り手」のように、契約の中での役割を表すことができます。「これ以降パフォーマー/ベンダー/アーティスト/コンサルタントとして参照される」という意味での法的契約を考えてみてください。このようにして、契約上の役割の所有権という概念を切り離し、取引可能な状態にすることができます。つまり、ローンを売ってもいいし、何かの契約で役割の持ち分を買ってもいいわけです。
tradeRoles = CurrencySymbol "TradeRoles"
buyer = TokenName "buyer"
seller = TokenName "seller"
account = fromList[(Token tradeRoles buyer, 1), (ada 1000)]
ここでアカウントは、通貨 "TradeRoles"の1 buyerトークン、および1000 lovelaceを保持しています。
Partyは、公開鍵ハッシュまたは役割名のいずれかとして表されます。
data Party = PK PubKeyHash | Role TokenName
Marloweコントラクトを進めるためには、Partyは証拠を提供しなければなりません。PK Partyは、ビットコインのPay to Public Key Hashメカニズムと同様に、PartyのPubKeyHashをハッシュする公開鍵の秘密鍵で署名されたトランザクションの有効な署名となります。役割 Partyの証拠は、通常同じ所有者に対して同じトランザクション内で役割トークンを使用していることです。
そのため、役割としてのPartyは(Role "alice")や(Role "bob")などのようになります。しかし、Haskellでは、これらの値をより簡潔に(Showのカスタムインスタンスを宣言し、オーバーロードされた文字列を使用することで)提示して読み込むことができるので、これらの値を "alice", "bob "などのように入力して読み込むことができます。
スロット番号や金額も同様の方法で扱われます。同じshow/overloadのアプローチで、数字としてコントラクト上表示されます。
data Slot = Slot Integer
type Timeout = Slot
ここでは、コントラクトが終了したときに口座のお金が返金されるという意味で、"alice"が所有者であることに注意してください。
オーバーロードされた文字列を使って、このアカウントを所有者の名前で省略できるようにすることができます。この場合は "alice "です。
支払いは、コントラクトの当事者のいずれか、またはアカウントのいずれかに行われることができ、これは定義に反映されています。
data Payee = Account Party
| Party Party
整数である選択肢は、選択肢の名前とその選択肢をとったPartyを組み合わせたChoiceIdによって識別されます。
type ChoiceName = Text
data ChoiceId = ChoiceId ChoiceName Party
type ChosenNum = Integer
Letを使って定義された値も整数として識別されます。
data ValueId = ValueId Integer
7.3. 値、オブザベーション、アクション
基本的な型に基づいて、3つの上位レベルのコントラクトコンポーネントを記述することができます:値の型、オブザベーションの型、そして特定のケースをトリガーするアクションの型です。最初に、値を見てみると、次のようになります。
data Value = AvailableMoney Party Token
| Constant Integer
| NegValue Value
| AddValue Value Value
| SubValue Value Value
| MulValue Value Value
| Scale Rational Value
| ChoiceValue ChoiceId
| SlotIntervalStart
| SlotIntervalEnd
| UseValue ValueId
| Cond Observation Value Value
さまざまな種類の値(すべて整数)はほとんど自己説明的なものですが、完全性のために補足します。
・選択肢ChoiceValueとUseValueをすでに定義している識別子により作成されたアカウントAvailableMoneyの値を検索します。
・算術定数と演算子
・Scaleは、値に有理定数、例えば2/3を掛け、結果を「HALF EVEN」、別名「銀行」の丸めを使用して丸めます。つまり、14/10は1に、15/10と25/10は2に丸めます。
・現在のスロットインターバルの開始と終了を表します。これに関しては引き続き記載するディスカッションを参照ください。
・Condの最初の引数はチェックする条件(オブザベーション)で、2番目の引数は条件が満たされたときに取る値であり、最後の引数は条件が満たされていないときの値です。例: (Cond FalseObs (Constant 1) (Constant 2))は(Constant 2)と等価です。
・Assertはコントラクトの状態には何の影響も与えませんが、Observationが偽の場合は警告を発します。これは、実行結果Assertが偽となると、静的解析が失敗するため、コントラクトの任意のポイントでプロパティが保持されていることを確認するために使用することができます。
次はオブザベーションを見ます。
data Observation = AndObs Observation Observation
| OrObs Observation Observation
| NotObs Observation
| ChoseSomething ChoiceId
| ValueGE Value Value
| ValueGT Value Value
| ValueLT Value Value
| ValueLE Value Value
| ValueEQ Value Value
| TrueObs
| FalseObs
これらは本当に自己説明的です。 値に対し(不)等価や大小を比較し、ブール接続詞を使ってオブザベーションと組み合わせることができます。他の唯一の構成要素であるChoseSomethingは、与えられたChoiceIdに対して何か選択がなされたかどうかを示します。
Caseとアクションは、こちらの型によって与えられます。
data Case = Case Action Contract
data Action = Deposit Party Party Token Value
| Choice ChoiceId [Bound]
| Notify Observation
data Bound = Bound Integer Integer
3種類の動作が可能です。
・Deposit n p t v は、値 v のトークン t をパーティ p からアカウント n に預けます。
・特定のidに対して、許容される値の境界のリストを用いて選択が行われます。例えば、[Bound 0 0, Bound 3 5]は、0, 3, 4, 5のいずれかの選択肢を提供します。
・コントラクトは、特定のオブザベーションが行われることを通知します。通常、これはパーティのいずれか、またはウォレットのいずれかが自動的に実行することで行われます。
これで、Marloweコントラクトを構成する型の議論は終了です。
7.4. トランザクション
先に述べたように、Marloweのセマンティクス(プログラムが持つ意味)は、下記のようにトランザクションを構築することで成り立っています。
トランザクションの構築
トランザクションは、一連のステップから構築され、そのうちのいくつかは入力値を消費し、他のいくつかは効果、すなわち支払いを生み出します。これを説明する際に、トランザクションが(その継続へ向かう)コントラクトと状態を変更することを説明しましたが、より正確にはこちらの関数があります。
omputeTransaction :: TransactionInput -> State -> Contract -> TransactionOutput
ここで、型はこのように定義されています。
data TransactionInput = TransactionInput
{ txInterval :: SlotInterval
, txInputs :: [Input] }
data TransactionOutput =
TransactionOutput
{ txOutWarnings :: [ReduceWarning]
, txOutPayments :: [Payment]
, txOutState :: State
, txOutContract :: Contract }
| Error TransactionError
ここで使用される表記法は、コンストラクタの引数にフィールド名を追加し、データのセレクタを与え、各フィールドの目的をより明確にします。
TransactionInput型には2つの要素があります:ブロックチェーンに有効に追加できる期間SlotIntervalと、そのトランザクションで処理されるInput値の順序付けされたシーケンスです。
TransactionOutput値は4つのコンポーネントを持ちます。二番目(txOutPayments)はトランザクションによって生成された順序付けられた支払いのシーケンスを示すのに対して、最後の2つは更新されたStateとContractです。最初のコンポーネントは、トランザクションの処理によって生成された警告のリストを含みます。
7.5. スロットの範囲
これはCardano/Plutusのアーキテクチャの一部であり、特定のトランザクションがどのスロットで処理されるかを正確に予測することは不可能であることを認識しています。したがって、トランザクションには処理されると予想されるスロット・インターバルが与えられ、これはMarloweにも引き継がれます。Marloweコントラクトの各ステップは、スロットの範囲のコンテキストで処理されます。
data Slot = Slot Integer
data SlotInterval = SlotInterval Slot Slot
ivFrom, ivTo :: SlotInterval -> Slot
ivFrom (SlotInterval from _) = from
ivTo (SlotInterval _ to) = to
これはMarloweコントラクトの処理にどのように影響するのでしょうか?各ステップはスロット・インターバルに関連して処理され、現在のスロット値はその間隔内にある必要があります。
インターバルのエンドポイントはSlotIntervalStartとSlotIntervalEndの値としてアクセス可能で、オブザベーションで使用することができます。タイムアウトは明確に処理されなければならないので、スロット・インターバル内の全ての値は、それが有効になるためにタイムアウトを超えているか、通常の実行が有効になるためにタイムアウトより前に設定されていなければなりません。言い換えれば、タイムアウトの値は、(タイムアウトが有効になるために)SlotIntervalStart以下か、(通常の実行が行われるために)SlotIntervalEndよりも厳密に大きいかのいずれかでなければなりません。
注意事項
このモデルは、実行されるブロックチェーン・インフラストラクチャについて多くの仮定をしています。
・暗号化機能と操作はMarloweの外部レイヤーによって提供され、明示的にモデル化する必要はないと仮定しています。
・時間は「粗い粒度」であり、ブロックやスロット番号で測定されると仮定し、特にタイムアウトはブロックやスロット番号で区切られます。
・預金を行うことはコントラクトが実行できることではなく、預金を要求することができますが、外部的に確立されなければなりません。したがって、各トランザクションごとに(複数の)預金の入力をします。
・モデルは、コントラクトがCloseのポイントに達すると、特定のアカウントの所有者へ対する資金の払い戻しを管理します。
7章は以上です。
-----
Marlowe: Marlowe
Contract(契約書):コントラクト
Contract(契約):契約
Omniscient:全知全能
Fungible: 同等のタイプや価値のものと交換しやすいもの。等価交換可能
Account: アカウント
Value: 値
Observation: オブザベーション
Action: アクション
Role: 役割
Party: 当事者となる集団、パーティ
セマンティクス: プログラムが持つ意味
Rewards
Epoch#233になりました!ということで今回(Epoch#231分)の報酬結果です。
ステーク量、アドレスが増えているのと、プールの数が落ち着いてきたように見えます。
自分の委任量の場合、シミュレータによると年間2,056.081174 ADA、ROS: 5.1402%になりますので、よいパフォーマンスと思っています。
現在は12/6に飽和するであろうプールへ委任を移動して、飽和状態だとどれくらいの感覚で報酬が減るものなのか確認してみようと思っています。
ADA/USD
今回は週足でみてみました。先週の週足キャンドルは、遡ると2020年7月にタッチして跳ね返された0.17ドル付近を越えて、実体部分も含め今年の最高値を付けました。その前にこの価格帯に来たのは2018年7月になるため、強力なサポートレジスタンスになります。ボリュームもあるようにみえるので今後楽しみです。
※ 日足チャートで長期目線で考えています。あくまで一つの見方なのでトレードは自己責任でお願いします。
-----
最後まで読んでいただき、本当にありがとうございます。
役に立ったと思っていただけたら、スキや、Twitterのフォローをしていただけると幸いです。
過去のブログのまとめページもよろしくお願いします。(ステークプールの宣伝を含みます)
この記事が気に入ったらサポートをしてみませんか?