Solidity語言學習筆記————44、合約的後設資料

FLy_鵬程萬里發表於2018-07-11

合約的後設資料

Solidity編譯器自動生成JSON檔案,即合約的後設資料,其中包含了當前合約的相關資訊。 它可以用於查詢編譯器版本,所使用的原始碼,應用二進位制介面Application Binary Interface(ABI) 和 以太坊標準說明格式Ethereum Nature Specification Format(natspec) 文件,以便更安全地與合約進行互動並驗證其原始碼。

編譯器會將後設資料檔案的 Swarm 雜湊值附加到每個合約的位元組碼末尾(詳情請參閱下文), 以便你可以以認證的方式獲取該檔案,而不必求助於中心化的資料提供者。

當然,你必須將後設資料檔案釋出到 Swarm (或其他服務),以便其他人可以訪問它。 該檔案可以通過使用 solc --metadata 來生成,並被命名為 ContractName_meta.json 。 它將包含原始碼的在 Swarm 上的引用,因此你必須上傳所有原始檔和後設資料檔案。

後設資料檔案具有以下格式。 下面的例子將以人類可讀的方式呈現。 正確格式化的後設資料應正確使用引號,將空白減少到最小,並對所有物件的鍵值進行排序以得到唯一的格式。 程式碼註釋當然也是不允許的,這裡僅用於解釋目的。

{
  // 必選:後設資料格式的版本
  version: "1",
  // 必選:原始碼的程式語言,一般會選擇規範的“子版本”
  language: "Solidity",
  // 必選:編譯器的細節,內容視語言而定。
  compiler: {
    // 對 Solidity 來說是必須的:編譯器的版本
    version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
    // 可選: 生成此輸出的編譯器二進位制檔案的雜湊值
    keccak256: "0x123..."
  },
  // 必選:編譯的原始檔/源單位,鍵值為檔名
  sources:
  {
    "myFile.sol": {
      // 必選:原始檔的 keccak256 雜湊值
      "keccak256": "0x123...",
      // 必選(除非定義了“content”,詳見下文):
      // 已排序的原始檔的URL,URL的協議可以是任意的,但建議使用 Swarm 的URL
      "urls": [ "bzzr://56ab..." ]
    },
    "mortal": {
      // 必選:原始檔的 keccak256 雜湊值
      "keccak256": "0x234...",
      // 必選(除非定義了“urls”): 原始檔的字面內容
      "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
    }
  },
  // 必選:編譯器的設定
  settings:
  {
    // 對 Solidity 來說是必須的: 已排序的重定向列表
    remappings: [ ":g/dir" ],
    // 可選: 優化器的設定( enabled 預設設為 false )
    optimizer: {
      enabled: true,
      runs: 500
    },
    // 對 Solidity 來說是必須的:用以生成該後設資料的檔名和合約名或庫名
    compilationTarget: {
      "myFile.sol": "MyContract"
    },
    // 對 Solidity 來說是必須的:所使用的庫的地址
    libraries: {
      "MyLib": "0x123123..."
    }
  },
  // 必選:合約的生成資訊
  output:
  {
    // 必選:合約的 ABI 定義
    abi: [ ... ],
    // 必選:合約的 NatSpec 使用者文件
    userdoc: [ ... ],
    // 必選:合約的 NatSpec 開發者文件
    devdoc: [ ... ],
  }
}

註解
需注意,上面的 ABI 沒有固定的順序,隨編譯器的版本而不同。
註解
由於生成的合約的位元組碼包含後設資料的雜湊值,因此對後設資料的任何更改都會導致位元組碼的更改。 此外,由於後設資料包含所有使用的原始碼的雜湊值,所以任何原始碼中的, 哪怕是一個空格的變化都將導致不同的後設資料,並隨後產生不同的位元組程式碼。

後設資料雜湊位元組碼的編碼

由於在將來我們可能會支援其他方式來獲取後設資料檔案, 類似 {"bzzr0":<Swarm hash>} 的鍵值對,將會以CBOR 編碼來儲存。 由於這種編碼的起始位不容易找到,因此新增兩個位元組來表述其長度,以大端方式編碼。 所以,當前版本的Solidity編譯器,將以下內容新增到部署的位元組碼的末尾:

0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29

因此,為了獲取資料,可以檢查部署的位元組碼的末尾以匹配該模式,並使用 Swarm 雜湊來獲取後設資料檔案。

自動化介面生成和以太坊標準說明格式(natspec) 的使用方法

後設資料以下列方式被使用:想要與合約互動的元件(例如,Mist)讀取合約的位元組碼, 從中獲取後設資料檔案的 Swarm 雜湊,然後從 Swarm 獲取該檔案。該檔案被解碼為上面的 JSON 結構。

然後該元件可以使用ABI自動生成合約的基本使用者介面。

此外,Mist可以使用 userdoc 在使用者與合約進行互動時向使用者顯示確認訊息。

有關以太坊標準說明格式Ethereum Nature Specification Format(natspec) 的其他資訊可以在這裡找到。

原始碼驗證的使用方法

為了驗證編譯,可以通過後設資料檔案中的連結從 Swarm 中獲取原始碼。 獲取到的原始碼,會根據後設資料中指定的設定,被正確版本的編譯器(應該為“官方”編譯器之一)所處理。 處理得到的位元組碼會與建立交易的資料或者 CREATE 操作碼使用的資料進行比較。 這會自動驗證後設資料,因為它的雜湊值是位元組碼的一部分。 而額外的資料,則是與基於介面進行編碼並展示給使用者的構造輸入資料相符的。


相關文章