如何在以太坊上存一張圖片
學習以太坊有一段時間了,今天突然在想能不能在鏈上存一張圖片?真正檔案上鍊肯定不能直接存,這裡主要還是為了學習智慧合約的操作。
首先看看官方api
以太坊並不提供操縱檔案的方法,不過我們可以把檔案轉化成base64字串再存在鏈上。
首先寫好合約
pragma solidity ^0.4.11; contract Mrc{ mapping (uint => string) pic; uint x=0; address owner; function Mrc(){ owner = msg.sender; } function save(string s) public{ require(msg.sender == owner); pic[x]=s; x++; } function getpic(uint i) constant public returns (string){ require(msg.sender == owner); return pic[i]; } }
這個合約十分簡單,意思是隻有合約建立者可以存取內容,你可以使用remix建立合約,也可以用infura建立合約(參考我的另外一篇文章)。
remix裡點選deploy部署合約(要下好metamask錢包,並且選擇inject web3)
然後選擇一張要存的圖片
隨便選了張圖片,這張圖片的大小是46KB
要注意的是如果我們要把這樣一個檔案存在鏈上,呼叫一次合約存下整個圖片是不行的,因為每一個塊有gas限制,也就是gaslimit,當前的gaslimit可以通過ethstats檢視,寫這篇文章的時候gaslimit大約是8000000。
我把這張圖片轉化成base64字串,然後分割成每個5KB的字串片段,逐個呼叫合約儲存
nodejs呼叫合約
可以使用infura傳送交易,使用sendSignedTransaction簽名傳送
交易引數可以使用encodeFunctionCall序列化成交易data,私鑰簽名之後直接傳送,不懂的可以參考web3js官方api裡的例項,因為我已經發送完了交易,這裡就不在重新演示。
傳送完成後可以在區塊鏈瀏覽器檢視
可以看到,儲存5KB的字串要花費大約0.0036的eth,費用不小,不過這是在測試網路所以隨便弄沒關係
最終我們就把這張圖片以base64的方式存在了鏈上,很顯然,想要獲得這張圖片只需要call合約的getpic就可以了,不過call得到的也是base64片段,需要再拼在一起去得到完整的圖片。
我們可以寫一個靜態html用js得到這張圖片(使用infura)
這裡為了保證傳過來的片段是順序的,使用遞迴
最後效果
成功的存了一張圖片在鏈上,如果你有興趣的話還可以存別的檔案,不過要注意gas消耗。