Plutus Pioneer Program - Week 2 筆記
Plutus Pioneer Program – Lecture #2
區塊鏈上的智能合約
智能合約分為兩部分:
- 區塊鏈上讓節點對合約做驗證,並且操作被記錄在區塊鏈上的帳目
- 區塊鏈外建立並上傳合約,在使用者的錢包中可以核對是否能夠成功與合約互動
接下來(兩周)會先介紹在區塊鏈上建立智能合約的基礎步驟。
在這個教學的初期,我們先以最粗略的資料型態 Data
來作為基礎。可以看到以下是 Data
的建構子:
-- Haskell
module PlutusTx.Data
-- able to represent arbitrary custom data
data Data =
Constr Integer [Data]
| Map [(Data, Data)]
| List [Data]
| I Integer
| B BS.ByteString
在 Nix 底下可以進入 GHCI 來得到所有結構的詳細資訊:
$ cd plutux/
$ nix-shell
$ cd plutus-poineer-program/code/week02
$ cabal repl # opens GHCI
################# GHCI ##################
# Show construction information for Data
Prelude > :i Data
在 Plutus 上的智能合約叫做 Validator Script,是讓使用者往區塊鏈上執行寫入的控制腳本。一個控制腳本會含有三個部分:
- 資料元(Datum):附屬於該合約的資料,會被寫到記錄到區塊鏈上
- 參與者(Redeemer):參與合約的資料,由合約參與者提供
- 合約內容(Validation context):合約本身所夾帶的基本內容,例如簽名者、合約有效時間區間、手續費
基本練習
Gift.hs
第一個例子 Gift.hs 中展示了合約中的基本架構
- 區塊鏈上:
mkValidator
函數來取得智能合約的三個部分
mkValidator :: Data -> Data -> Data -> () mkValidator _ _ _ = ()
- 區塊鏈下:
- 產生合約地址(script address)
validator :: Validator validator = mkValidatorScript $$(PlutusTx.compile [|| mkValidator ||]) valHash :: Ledger.ValidatorHash valHash = Scripts.validatorHash validator scrAddress :: Ledger.Address scrAddress = ScriptAddress valHash
例子中有兩個動作:
type GiftSchema =
BlockchainActions
.\\/ Endpoint "give" Integer
.\\/ Endpoint "grab" ()
- 動作 Give 上傳合約
give :: (HasBlockchainActions s, AsContractError e) => Integer -> Contract w s e ()
give amount = do
let tx = mustPayToOtherScript valHash (Datum $ Constr 0 []) $ Ada.lovelaceValueOf amount
ledgerTx <- submitTx tx
void $ awaitTxConfirmed $ txId ledgerTx
logInfo @String $ printf "made a gift of %d lovelace" amount
- 動作 Grab 用
utxoAt
取得合約並作為 validator 來執行合約
grab :: forall w s e. (HasBlockchainActions s, AsContractError e) => Contract w s e ()
grab = do
utxos <- utxoAt scrAddress
let orefs = fst <$> Map.toList utxos
lookups = Constraints.unspentOutputs utxos <>
Constraints.otherScript validator
tx :: TxConstraints Void Void
tx = mconcat [mustSpendScriptOutput oref $ Redeemer $ I 17 | oref <- orefs]
ledgerTx <- submitTxConstraintsWith @Void lookups tx
void $ awaitTxConfirmed $ txId ledgerTx
logInfo @String $ "collected gifts"
Burn.hs
將 mkValidator
函數轉為 error,這樣 give 動作執行並被貨幣鎖到智能合約上後,任何人都無法成功執行合約來把他取下來。等於是把貨幣燒掉的意思。
FortyTwo.hs
原本 mkValidator
並沒有實際讀入資料,這個例子調整 redeemer(可以想成是合約參與者輸入密碼的概念)來參與合約的執行。
mkValidator :: Data -> Data -> Data -> ()
mkValidator _ r _
| r == I 42 = ()
| otherwise = traceError "wrong redeemer"
在動作 grab 的地方也要修改讓它能讀入數字。
grab :: forall w s e. (HasBlockchainActions s, AsContractError e) => Integer -> Contract w s e ()
Typed.hs, isData.hs
上一個例子中用粗略的資料型態 Data
來作為 mkValidator
函數的參數型態。但是實際上我們會想要自己構造資料結構來儲存自己的智能合約資料還有邏輯。
這裡將剛剛數字的輸入型態從 Data
改為 Integer
,這樣輸入字串時就無法成功寫出合約。
mkValidator :: () -> Integer -> ValidatorCtx -> Bool
mkValidator () r _
| r == 42 = True
| otherwise = False
而自定義的合約也需要宣告參與合約的資料型別為哪些。(這就像在其他物件導向語言一樣要宣告自己的 structure)
data MyTypedScript
instance Scripts.ScriptType MyTypedScript where
type instance DatumType MyTypedScript = ()
type instance RedeemerType MyTypedScript = Integer
再來有了 structure,就可以宣告自己的 script instance。(可以想像成是宣告變數)
inst :: Scripts.ScriptInstance MyTypedScript
inst = Scripts.validator @MyTypedScript
$$(PlutusTx.compile [|| mkValidator ||])
$$(PlutusTx.compile [|| wrap ||])
where
wrap = Scripts.wrapValidator @() @Integer
validator :: Validator
validator = Scripts.validatorScript inst
在現實世界中的 validation 不可能是根據 raw data type Data
來執行,這樣會非常不安全,而且也需要更複雜的結構來儲存邏輯。在 Plutus 中,有 IsData
, FromData
還有 ToData
的函數介面,只要你的 custom data type 有建構對這兩個函數構造建構子,就可以把客製化的結構放進 validator script 之中。
而 Plutus 提供了 template 來讓使用者可以生成這些建構子介面。利用 PlutusTx.unstableMakeIsData
可以生成建構子。
newtype MySillyRedeemer = MySillyRedeemer Integer
deriving Show
PlutusTx.unstableMakeIsData ''MySillyRedeemer
接下來就可以使用 PlutusTx.toData
來將資料結構傳入智能合約中。
tx = mconcat [mustSpendScriptOutput oref $ Redeemer $ PlutusTx.toData $ MySillyRedeemer r | oref <- orefs]
Homework 1
照著語法,把 raw boolean tuple 傳入並且跟 tutorial 影片中一樣,構造 Typed 的 script 後再創造 script instance。基本上就是把 Typed.hs
自己親手操作一遍。
Homework 2
跟上一個 homework 一樣,只是換成現在是 custom structure。基本上就是把 isData.hs
自己親手操作一遍。
(文章歡迎轉載,請註明出處為 eopxd.com)
Original link: eopXD
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!
- 来自作者
- 相关推荐