區塊鏈-NFT 的實現原理

指尖下的幽靈發表於2021-08-20

作者:林冠巨集 / 指尖下的幽靈。轉載者,請: 務必標明出處。

部落格:http://www.cnblogs.com/linguanh/

掘金:https://juejin.im/user/1785262612681997

GitHub : https://github.com/af913337456/

出版的書籍:


NFT (Non-Fungible Token),這2年又火了起來,早在18年已經火過一波。

本文只從寫程式碼實現NFT的技術方案層面去介紹 NFT,不從其金融意義、案例,等層面去談,因為這類內容可以隨便在瀏覽器搜尋到,而我接下來要談的內容,淺層搜尋下,數量不多。

第一步: 製作id

製作id,這是把物質製作成 NFT 的第一步。物質有哪些?一段文字、一張圖片,一件衣服等,誇張的說,現實世界的物質,無論是虛擬的(遊戲裝備)或實質物質,都可以被通證化。

如何操作?

通過第三方技術手段獲取物質的唯一標誌性中間產物。

因此製作 NFT 第一步,廣義於下面等式:

  • id = F(I)
    1. I = 輸入的物質
    2. F = 處理函式,代表一種方法
    3. id 唯一標誌性的中間產物

最簡單的例子就是雜湊函式,不考慮雜湊碰撞,它就可以根據不同的內容輸出不同的雜湊值。思維在這裡不要侷限於雜湊函式。

獲取圖片的唯一id

這裡用圖片代表一系列的檔案類資料。

  1. 我們可以將圖片轉換成 []byte 位元組陣列,然後計算其雜湊值。這種操作雖然比較簡單,但是圖片別人卻不能訪問,看不到;
  2. 如果我們想向外部任何人提供圖片的讀許可權,在計算完 id 後,有兩種做法:
    1. 上傳圖片到檔案伺服器,任何人可以通過 url 連結訪問。這裡的伺服器是中心化的;
    2. 增加區塊鏈屬性。上傳檔案到 IPFS (ipfs是什麼,自行搜尋),如此一來,檔案別人能訪問,同時還具備了區塊鏈的去中心化等屬性。其中 IPFS 會在上傳完檔案後,會使用它的演算法,幫你計算好雜湊值返回,可以直接用它的作為id。

獲取衣服的唯一id

這裡用衣服來代表一系列的實際物質。如果獲取它們的唯一id呢?做法可以放飛思維去思考,比如可以:

  • 衣服的出廠資訊、掃描內容、照片,等系列關於它的資訊,資料化,然後用這些資料製作成檔案,最後參考圖片的做法。

第二步:通證化

第一步中獲取了物質的id,現在要把它們通證化。切記一點:目前公認的 NFT 都是基於區塊鏈公鏈的,那麼以後是不是會一直這樣呢?不一定,說不準出來了新的共識。

基於不同公鏈的流程

通證化的流程如下:

  1. 選擇一條區塊鏈公鏈。這裡的選擇會決定後面智慧合約等系統元件的技術棧,這一點很核心;
  2. 在所選的公鏈上開發智慧合約;
  3. 所開發的智慧合約需要遵循一些基礎約定,比如至少能保證物質的id能達到驗證去重,什麼意思呢?意思是,如果 A 在今天上傳了 id=1 到鏈上,明天 B 也上傳同個 id=1 到鏈上,合約要能告訴 B,你不能上傳了,id 已經存在;
  4. 部署智慧合約到鏈上,此時它變成 DApp;
  5. 通過發交易的方式,呼叫該智慧合約的方法,將id等相關資料儲存到鏈上。

NFT 的智慧合約

NFT 智慧合約可以基於不同的公鏈開發,它不侷限於任何一條公鏈。不同公鏈的智慧合約方案實現也不同,下面以 以太坊 公鏈舉例說明。

在以太坊上面,開發 NFT 智慧合約,已經有很多標準,比如 ERC-721 \1155 \998,各有各的特點,但它們的特點是在基礎屬性上擴充而來的。(各標準文件: https://eips.ethereum.org/EIPS/eip-721)

如果選擇 ERC-721 標準開發 NFT 智慧合約,在後設資料儲存部分,就有 tokenUrl 這項,它相當於物質的唯一id,像下面的樣子, _tokenURIs 儲存的就是通證當前計數id與其對應的 tokenUrl,這裡的tokenUrl 是字串格式,一般是檔案url,儲存在 IPFS 或其他服務上面的檔案的連結,但不侷限於連結,也可以是其它的內容。

// 虛擬碼
contract MyERC721 is IERC721Metadata, ... {
    ...
    mapping(uint256 => address) private _tokenOwner;
    mapping(uint256 => string) private _tokenURIs;
    
    uint256 public tokenCounter; // 計數,當前總的 NFT 的數量,累增
    
    constructor () public ERC721 ("name", "symbol"){
        tokenCounter = 0;
    }
    // 外部呼叫方,呼叫這個函式,傳引數:tokenURI 即物質的id,tokenURI 唯一
    function createNFT(string memory tokenURI) public returns (uint256) {
        uint256 tokenId = tokenCounter;
        _mint(msg.sender, tokenId); // 將交易傳送者和當前的 tokenId 繫結
        _setTokenURI(tokenId, tokenURI); // tokenId 對映到 tokenUrl
        tokenCounter = tokenCounter + 1; // 累加
        return tokenId;
    }
    // _exists 函式判斷 tokenId 是否存在,_tokenOwner[tokenId]
    // 根據 id 讀取對應的 url
    function tokenURI(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId));
        return _tokenURIs[tokenId];
    }
    // 根據 tokenId 和 url 建立 map 資料關係
    function _setTokenURI(uint256 tokenId, string memory uri) internal {
        require(_exists(tokenId)); // _exists
        _tokenURIs[tokenId] = uri;
    }
    ... // 省略系列介面,包含讀介面
}

上面的 tokenUrl 是標準要求的儲存資料項。整個合約具備下面約束功能:

  1. NFT 持有者,即 msg.sender(owner) 和 tokenId 一對多關係,代表一個人可以擁有多個 NFT;
  2. tokenId 和 tokenUrl 一對一關係,代表每份資料一個鏈上的唯一id,同時 tokenUrl 沒要求是唯一,但在呼叫方,一般會把 tokenUrl 設定唯一,即使不唯一也沒關係,衝突的時候,tokenId 越小的,其當初被設定的時間就越早;
  3. NFT 持有者在將資料寫入鏈上後,能夠獲取 NFT 的鏈上唯一 id,後續可以根據 id 進行系列的讀寫操作。

一般來說,我們常規的 NFT 有一個和資料建立關係的項就足夠了,但並不侷限於此,合約在實現了標準要求的介面後,完全可以自己新增自定義資料項及其讀寫函式。

第三步:展示與修改

展示 NFT 內容

所謂展示,就是對 NFT 的資料進行讀取再展示。一般的流程如下:

  1. 根據當初設定 NFT 資料到鏈上時獲得的 id 去智慧合約讀取資訊;
  2. 將獲得的資訊通過某介質應用還原出原始的 NFT 資料。

比如將圖片 NFT 展示出。(藉助上面的 721 合約標準和 IPFS 結合為例)

  1. 假設呼叫合約儲存資料時候得到的 tokenId 是 3,那麼使用這個 tokenId 去呼叫合約的讀資料方法;
  2. 執行完 1 步驟,可以得到 tokenUrl,即檔案儲存在 IPFS 中所得到的連結;
  3. 直接將 tokenUrl 連結在瀏覽器開啟,看到圖片。

修改 NFT 內容

修改是一項 NFT 智慧合約的擴充功能,可有可無,具體是怎樣的方式,完全看需求的實現。比如:

  1. 允許重置 tokenId 所對應的內容;
  2. 在 NFT 原資料中增加其他欄位內容,再允許修改這些欄位;
  3. 轉讓 NFT,可以把某 tokenId 對應的 NFT 資訊轉讓給其他 owner,達到轉讓目的;
  4. 出售 NFT拍賣 NFT 等操作....

所有權共識

目前 NFT,非同質化通證。本質是想借助區塊鏈的屬性來標示一種資產的所有權證明。

比如曾拍賣出6000多萬美金的數字作品(圖片)《Everydays: The First 5000 Days》,中標者能獲得原圖 和 該圖的 NFT。這兩樣東西,一樣是實質的作品,一樣是它的所有權者的證明。

我們假設下,如果持有某作品的人,是一位匿名者A,過了多年後,該作品本身不小心被盜並被找回。那麼如何證明 A 是真正的擁有者,此時 A 只需要展示他對該作品的 NFT 擁有權,就可以證明。

那麼 NFT 是不是類似於我們現實中的證照?不全是,分兩點:

  1. NFT 和證照都能證明某資產的所有權;
  2. 對比的儲存介質 與 永恆時效:
    1. 證照可能要找個保險櫃保養放著,但它終究佔據一方土地,僅受一方土地容納的保險櫃保證安全,在時過境遷的影響下,持續性儲存下去的時間會較短;
    2. NFT 儲存在區塊鏈上,受整個網際網路的鏈節點所保護。它能夠存活到整個鏈網路垮掉那天,對於節點數量眾多的公鏈來說,這個概率幾乎等同於網際網路終結那天。

第三方平臺

現在已經有很多的第三方的 NFT 製作與釋出平臺。比如 opensea、rarible 等,這些平臺自己實現了 NFT 的智慧合約 和 NFT 展示應用(介質應用---網站),方便大眾 0 程式碼基礎體會 NFT。但也有一些門檻,需要具備錢包和發交易的油費。

相關文章