Solidity

函式輸入條件檢查

  • March 30, 2019

我有一個接受字元串參數作為輸入參數的函式。

這個字元串是一個 IPFS 雜湊,我想檢查輸入是否真的只是那個,而不是惡意連結等。

我如何使用 require check 來實現這一點?

例如,檢查輸入參數是否與諸如 mtYgPpHdWEz79ojWnPbdGgPpHdWEz7 之類的格式配對,而不是malware.com

您可以使用以下修飾符:

modifier onlyIPFSHash (string memory str) {
   bytes memory b = bytes (str);
   require (b.length > 6);
   for (uint i = 0; i < b.length; i++)
       require (0x7ffeffe07ff7dfe03fe000000000000 & (uint(1) << uint8 (b [i])) > 0);

   _;
}

像這樣:

function foo (string memory s) onlyIPFSHash (s) public {
   ...
}

說明: IPFS 雜湊是至少 5 個字節的 Base58 編碼,因此至少有 7 個字元。Base58 允許以下字元:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz. 幻數0x7ffeffe07ff7dfe03fe000000000000的二進製表示在對應於 Base58 中允許的字元程式碼的位置具有 1,在所有其他位置具有 0。

**關於幻數較長的解釋:**讓我們看看神奇數字的二進制表示(你可以使用這個線上工具來轉換十六進制表示成二進制):111111111111110111111111110000001111111111101111101111111100000001111111110000000000000000000000000000000000000000000000000

傳統上,數字中的位從零開始從右到左編號。此外,EVM 使用 256 位數字執行,但我們的數字只有 123 位,因此 EVM 將為其添加 133 個前導零。當然,在任何位置編碼中為數字表示添加前導零不會影響其值:

bit #255 --+    +-- bit #122                                                                                                     bit #0 --+
          |    |                                                                                                                         |
          V    V                                                                                                                         V
          0...0111111111111110111111111110000001111111111101111101111111100000001111111110000000000000000000000000000000000000000000000000
                             ^                               ^
                             |                               |
                  bit #108 --+                               +-- bit #76

正如我在 中所說Explanation,每一位對應一個字元程式碼。如果 Base85 中允許使用此程式碼的字元,則將其設置為 1,如果不允許使用該字元,則將其設置為零。例如,'l'Base58 中不允許使用字元(小拉丁文“El”)。該字元的程式碼為 108,因此位 #108 為零。允許使用字元'L'(大寫拉丁語“El”),其程式碼為 76,因此位 #76 為 1。您可以在此處找到字元程式碼。請注意,正好有 58 個。這是因為 Base58 中允許有 58 個字元,因此得名。

關於公式的更長解釋: uint(1)只是數字 1 表示為 256 位無符號整數,即二進制形式0..<253 zeros>..01b [i]是我們正在檢查的字元串的 UTF-8 編碼的第 i 個字節。 uint8 (b [i])是否將此字節轉換為 8 位無符號整數。對於 ASCII 字元,這將是字元程式碼,對於非 ASCII Unicode 字元,這將介於 128 和 255 之間。有關詳細資訊,請參閱UTF-8 描述uint(1) << uint8 (b [i])是 1 左移字元程式碼的二進製表示,即如果字元程式碼為 108,則二進製表示的結果將是0...010...0唯一的“一”在位置 108 處。 操作&就是所謂的按位“AND”。它輸出數字,其二進製表示僅在那些位置有一個,其中兩個參數的二進製表示都有一個。只要右參數在一個位置只有一個,如果左參數在這個位置有“一”,結果將與右參數相同,如果左參數在這個位置為零,結果將為零。左參數是幻數,僅在與有效 Base58 字元相對應的位置有一個,因此如果目前字元不允許,則返回值將為零,並且值將與右參數相同(始終大於零),如果允許使用字元。因此,我們將結果與零進行比較,以了解 Base46 中是否允許字元,並且我們要求此比較返回 true。

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