瞭解 Tezos 的腳本語言 Michelson 是如何工作的,並學會編寫一些簡單的智能合約。

原文標題:《手把手教你使用 Michelson 編寫智能合約》
撰文:Claude Barde
翻譯:天道酬勤

Michelson 入門:Tezos 的腳本語言

Michelson 肯定是目前智能合約中最令人興奮的編程語言之一。它是一種基於堆棧的嚴格類型化語言,編寫智能合約可以確保 Tezos 區塊鏈的安全。Michelson 可以和以太坊智能合約的字節碼相媲美,但它更具可讀性,更安全,更強大。用來爲 Tezos 編寫智能合約的所有高級語言——比如 SmartPy、Ligo 或 Lorentz——最終都可以編譯成 Michelson。

在這第一篇文章中,我們將嘗試使用 Michelson 語言,理解「基於堆棧」的含義,並編寫一些非常簡單的智能合約。本文主要是爲編程或者 Tezos 開發的初學者編寫的,但是想要更多地瞭解 Michelson 的中級程序員也可以在這裏找到有用的信息。我們將使用 Baking Bad 開發的 Jupyter 內核,在 Jupyter 筆記本中編寫 Michelson 代碼。如果你想了解代碼的工作原理,可以在每個部分中找到一個鏈接。

讓我們寫一些代碼。

堆棧

要理解 Michelson 是如何工作的,堆棧是需要正確理解的主要概念之一。每一份 Michelson 合約都是相互遵循的指令清單。這些指令以準確的順序排列,並按照寫入的順序執行。

每條指令都會以某種方式操縱堆棧。把它想象成一堆數據。你編寫的指令將對堆中的數據產生影響。例如,你可以將堆上兩段數據相加,刪除頂部的數據,將另一段數據放在頂部,傳輸一些令牌,等等。該堆棧以後進先出的方式工作 :如果要訪問不在堆棧頂部的數據,必須先處理它上面的數據。

使用 Michelson 進行編碼時,你必須記住的三個主要概念:

  • 新數據放在堆棧的頂部。
  • 只有當堆棧中的數據位於堆棧頂部(或某些操作中位於第二個位置,如下所述)時,纔可以訪問堆棧中的數據。
  • 數據處理的順序是從堆棧的頂部到底部。

讓我們看一個例子。

PUSH 操作

如果你要在堆棧頂部添加一條數據,你將調用 PUSH 操作。它是這樣工作的:

此時需要注意的是,堆棧中可能已經有數據,在這種情況下,新值會放在它們之上。這是你在 Michelson 中推送新數據的方式:

    PUSH value-type value

例如,如果要推送一個整數,你會寫 PUSH int 2,對於一個字符串,你會寫 PUSH string 「 Tezos」。

Michelson 智能合約結構

Michelson 中的智能合約展現了一個由三部分組成的簡單結構:

  • 預期參數的類型。
  • 存儲的類型。
  • Michelson 代碼。

轉換成代碼表示如下:

    parameter parameter-type ;  
    storage storage-type ;  
    code {  
      ...  
    }

除此結構外,在 Michelson 中編寫智能合約時,你還必須牢記兩條規則:

1、在執行代碼時,自動將包含參數和存儲器的對推入堆棧中。需要記住的是——如果沒有參數,就用單位代替。

2、代碼必須始終返回一對,它包含操作列表和(更新的)存儲(對列表(操作)存儲)。當堆棧中只剩下此類對時,執行就會停止。

一個簡單的 Michelso 智能合約

現在我們已經瞭解了 PUSH 以及 Michelson 中智能合約的結構,讓我們來寫一個。

對於這個合約,我們將寫一個「 Hello world」合約,並將一個字符串保存到存儲中:

執行這段代碼後,會發生以下情況:

1、參數 unit 表示所傳遞的參數爲 unit 類型(基本上是無參數)。

2、storage string 表示合同的存儲類型爲 string。

3、DROP 是一種操作代碼,用於刪除堆棧頂部的任何內容。我們之前說過,一個帶有參數和存儲空間的對在開始時會自動包含在棧頂,我們不打算使用它,可以將其刪除。

4、PUSH 將一個值放到棧頂,這裏是字符串「 Hello world」。

5、NIL 是一種操作碼,它將指定類型的空列表 (此處操作) 添加到堆棧的頂部。

6、PAIR 將兩個元素放在堆棧頂部,創建一個包含這兩個元素的新對,然後將其推回堆棧中。

注意:每條指令都以分號結尾(最後一條指令是可選的)。

添加整數並保存結果

讓我們介紹一個新操作:ADD。你可能已經猜到了它的作用——將兩個數值相加。

這有一個簡單的合約,演示了它是如何工作的:

讓我們看一下每個操作,瞭解堆棧內部發生了什麼:

參數 unit:同樣,我們沒有使用任何參數,因此我們傳遞一個單位。

storage int:這一次,我們將整數類型的值保存到存儲器中。

DROP:我們不需要初始對,所以我們可以刪除它,爲我們實際需要的值騰出空間。

PUSH int 2; PUSH int 3;:這裏需要注意一下這個順序,它非常重要。推入 int 3 後,int 2 就會位於堆棧的底部。在加法的情況下,順序並不太重要,但如果你要做減法,必須將它們按正確的順序推入。

ADD 和 PAIR 的原理是一樣的。你取堆棧頂部的前兩個元素,並從中獲得一個值,然後將其推回堆棧。ADD 將兩個數字相加。需要注意的是,這些數字必須都是相同的數字類型(例如,你不能將 integer 和 nat 加在一起)。

NIL:和以前的合同一樣,我們將空的操作列表推入。

PAIR:創建一個對,包含操作列表和我們需要停止執行合同的新存儲。

結論

Michelson 語言的複雜性往往被高估了。這可能是由於目前沒有適合初學者的教程,並且在線提供的文檔技術性很強,對於新手來說也很難閱讀。這就是爲什麼我決定親自經歷學習 Michelson 的過程,使用困難的文檔來創建一系列教程,我希望這些教程更容易理解使用。

理解和欣賞 Tezos 區塊鏈的獨特性,以及使其變得更加安全和有用,關鍵是要理解 Michelson。

在下一部分中,我們將繼續深入研究 Michelson。我們將編寫一些簡單的智能合約,探索由 Baking Bad 團隊創建的令人驚歎的 Jupyter 筆記本,它使我們能夠編寫 Michelson 代碼,並準確瞭解正在發生了什麼。