Solidity

如何使用 bytes32 儲存 IPFS 雜湊?

  • August 5, 2020

以下問答(我應該為 IPFS 地址散列使用什麼數據類型?)建議我們使用bytes來儲存 IPFS 散列。

我正在使用以下範例(https://github.com/AdrianClv/ethereum-ipfs/blob/master/NotSoSimpleStorage.sol),它用於string儲存 IPFS 雜湊,成本約為 110,000 天然氣價格,這似乎相當昂貴。

**$$ Q $$**使用bytes而不是string為了儲存 IPFS 雜湊成本是否更便宜?我觀察到儲存bytes而不是string成本非常接近string(110,000 gas)。由於這兩種數據類型的儲存似乎都很昂貴,我應該使用事件來儲存它們嗎?

是否有任何與使用儲存 IPFS 雜湊相關的範例/教程bytes

這會起作用嗎:

myContract.insertHash("QmWmyoMoctfbAaiEs2G46gpeUmhqFRDW6KWo64y5r581Vz");

contract Example_bytes {
   bytes[] list;
   function insertHash(bytes ipfsHash) {
      list.push(ipfsHash); //costs around 110,000 gas. 
   }
}

contract Example_string {
   struct hashes{
        string hash;
   }

   hashes[] list;
   function insertHash(string ipfsHash) {
      list.push(hashes{hash: ipfsHash); //costs around 110,000 gas. 
   }
}

Qm...您的範例顯示使用它的字母數字編碼 ( )儲存 IPFS 身份,這與比特幣使用的Base58編碼相同。然而,它的核心是一個數字(雜湊)。以 Base58 格式儲存標識符需要是一個字元串,因為它包含字母(實際上保存的是標識符中每個字母數字字元的 ASCII 碼)。這意味著您需要QmWmyoMoctfbAaiEs2G46gpeUmhqFRDW6KWo64y5r581Vz從範例中儲存 46 個字節。

但是,該標識符也可以用十六進製表示為12207D5A99F603F231D53A4F39D1521F98D2E8BB279CF29BEBFD0687DC98458E7F89,它只有 34 個字節長(以十六進制寫出需要 68 個字元,因為十六進制中的每兩個字元是一個數據字節)。

但是,這兩個都大於 32 字節,這是最大固定大小的字節數組,所以他們需要使用動態大小的字節數組來儲存 (bytesstring,這兩者都很昂貴,正如你所指出的)。

但是,IPFS 雜湊實際上是兩個連接的部分。它是一個多雜湊標識符,所以前兩個字節表示正在使用的雜湊函式和大小。0x12是 sha2,0x20長度為 256 位。目前,這是 IPFS 使用的唯一格式,所以你可以只剪掉前兩個字節,這會留下一個 32 字節的值,它足夠小以適合bytes32固定大小的字節數組,並且你可以節省一些空間(並且在檢索時,您的契約可以重新附加0x1220到它的前面,或者您的客戶需要足夠聰明才能在檢索到值後執行此操作)。

但是,如果您想確保您的程式碼是面向未來的,您可能希望保存該雜湊函式程式碼和大小,您可以將其與雜湊結合為一個結構:

struct Multihash {
 bytes32 hash
 uint8 hash_function
 uint8 size
}

這適用於任何多雜湊格式,只要size小於或等於 32(任何更大且實際有效負載不適合該hash屬性)。這個結構需要兩個儲存槽(兩個 32 字節的塊)來儲存,因為這兩個uint8塊可以放在一個槽中。您還可以向該結構添加最多 30 字節的附加數據,而無需增加儲存成本。

引用自:https://ethereum.stackexchange.com/questions/17094