Solidity

通過範例文件將簽名功能拆分為solidity

  • September 14, 2022

大家好,我正在研究簽名驗證過程。我在這里通過範例文件閱讀了solidity ,我發現了這段程式碼:

/// signature methods.
   function splitSignature(bytes memory sig)
       internal
       pure
       returns (uint8 v, bytes32 r, bytes32 s)
   {
       require(sig.length == 65);

       assembly {
           // first 32 bytes, after the length prefix.
           r := mload(add(sig, 32))
           // second 32 bytes.
           s := mload(add(sig, 64))
           // final byte (first byte of the next 32 bytes).
           v := byte(0, mload(add(sig, 96)))
       }

       return (v, r, s);
   }

為什麼它有效?有人可以解釋裝配部分嗎?非常感謝。謝謝。

我複制了 Solidity 中的邏輯,以便您在比較時更好地理解它。

看一下函式splitSignatureWithSlicing,它和函式做的事情splitSignature一樣,但沒有彙編。更容易理解它。

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

contract Contract {

   function splitSignature(bytes memory sig)
       public
       pure
       returns (uint8 v, bytes32 r, bytes32 s)
   {
       require(sig.length == 65);

       assembly {
           // first 32 bytes, after the length prefix.
           r := mload(add(sig, 32))
           // second 32 bytes.
           s := mload(add(sig, 64))
           // final byte (first byte of the next 32 bytes).
           v := byte(0, mload(add(sig, 96)))
       }

       return (v, r, s);
   }

   function splitSignatureWithSlicing(bytes calldata sig) public pure returns (uint8 v, bytes32 r, bytes32 s){

       r = bytes32(sig[0:32]); // Copy first 32 bytes

       s = bytes32(sig[32:64]); // Copy 32 more bytes

       v = uint8(bytes1(sig[64:65])); // Copy last byte

   }
   
}

嘗試使用以下字節:0x997997d543f68c7b77e62a13efc6e546bd2a81c2aa8769c3354422ebbbb4fba4001c4a94f7f79e3a29652092d905b5ce47e84d6c0dd13d0ef0dd063abc149dffa7,

他們都返回相同的:

在此處輸入圖像描述

請記住,我們只能對數組使用數組切片calldata,而不是使用memoryorstorage數組。這就是我宣布sigas的原因bytes calldata sig

它所做的是複制前 32 個字節,然後在前 32 個字節之後再复制 32 個字節,然後再复制最後一個字節。

組裝部分只是意味著將r := mload(add(sig, 32))32 添加到記憶體中sig字節的起始位置,然後mload將從該點讀取 32 個字節。

mload一次讀取 32 個字節。

然後,s := mload(add(sig, 64))從上一步中的剩餘字節中再讀取 32 個字節。

然後再v := byte(0, mload(add(sig, 96)))讀取 32 個字節,但我們知道現在這 32 個字節中只有一個字節有值。所以我們只需要一個字節,這就是為什麼將它轉換為一個字節,相當於uint8.

在Remix中自己嘗試一下。

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