重慶分公司,新征程啟航
為企業提供網站建設、域名注冊、服務器等服務
為企業提供網站建設、域名注冊、服務器等服務
這篇文章主要講解了“怎么使用以太坊的預編譯合約”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么使用以太坊的預編譯合約”吧!
創新互聯專業為企業提供霍林郭勒網站建設、霍林郭勒做網站、霍林郭勒網站設計、霍林郭勒網站制作等企業網站建設、網頁設計與制作、霍林郭勒企業網站模板建站服務,10年霍林郭勒做網站經驗,不只是建網站,更提供有價值的思路和整體網絡服務。
以太坊包含了一些用于密碼學計算的預編譯合約,可以用來實現高級隱私保護功能。在這個教程中我們將了解以太坊提供的預編譯合約清單,并通過bn256ScalarMul
和bigModExp
這兩個實例學習以太坊預編譯合約的使用方法。
在繼續下面的教程之前,我們需要對以太坊和Solidity有一些基本的了解。我們關心的重點在于,以太坊有一個分布式的虛擬機即EVM,EVM提供了一組指令可以用于在區塊鏈上執行交易并更新狀態。關于EVM的一些基本概念如下:
storage:可以永久在鏈上存儲信息
memory:EVM虛擬機的工作內存,用于保存計算過程中的變量內容
uint:uint256類型的別名,可保存256位,完美匹配橢圓曲線坐標的要求
public:用來聲明函數位公開可調用
view:用來告訴編譯器,所裝飾的函數不會修改合約狀態
pure:表示所裝飾的函數不涉及合約狀態的讀寫
以太坊Geth客戶端的預編譯合約清單看起來像這樣:
var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{5}): &bigModExp{}, common.BytesToAddress([]byte{6}): &bn256Add{}, common.BytesToAddress([]byte{7}): &bn256ScalarMul{}, common.BytesToAddress([]byte{8}): &bn256Pairing{}, }
上述代碼中的映射結構記錄了預編譯合約的地址,是最后4個是新增的預編譯 合約:
bigModExp:地址0x05,執行操作:b^e mod m。bigModExp預編譯合約的輸入為: 底數長度、指數長度、模長度、底數即b的值、指數即e的值、模即m的值
bn256Add:地址0x06,執行操作:(x1, y1) + (x2, y2),其中x1, y1, x2, y2 都是256位的域成員,因此 (x1, y1)和 (x2, y2)都是bn256曲線上的有效點,滿足公式y^2 = x^3 + 3 mod fieldOrder
。 bn256預編譯合約的輸入就是x1, y1, x2, y2。
bn256ScalarMul:地址0x07,執行操作:k * (x, y),其中k屬于群,(x,y)是曲線上的有效點。 bn256scalarMul的輸入是x, y, k。
bn256Pairing:地址0x08,執行操作:配對檢查e(g1, g2) = e(-h2, h3
,其中g1和h2屬于群G1, g2和h3屬于群G2。bn256Pairing可以接收任意多對橢圓曲線上的點。群G1上的點形式為(x,y),群 G2上的點形式為(ai + b, ci + d),其中a, b, c, d (依次為虛部、實部、虛部、實部) 需要在預編譯 調用時傳入。bn256Pairing代碼首先檢查已經送出6的倍數個成員,然后執行配對檢查。
x, y, a, b, c, d的值都是域成員,因此都會按域大小取模。在bn256ScalarMul中使用的k的值,則是按橢圓曲線群的階取模。
下面我們將要學習兩個主要的示例:bn256ScalarMul和bigModExp。bn256ScalarMul操作和bn256Add非常類似,而bn256Pairing操作則更像bigModExp,因為這兩者都接受可變長度的輸入,因此調用時需要指定輸入大小。下面是調用bn256ScalarMul的代碼:
function ecmul(uint ax, uint ay, uint k) public view returns(uint[2] memory p) { uint[3] memory input; input[0] = ax; input[1] = ay; input[2] = k; assembly { if iszero(staticcall(gas, 0x07, input, 0x60, p, 0x40)) { revert(0,0) } } return p; }
目前內聯匯編已經支持if語句,調用時設置gas數量也比以前簡單 —— 在調用時使用gas,就表示利用所有可用gas,這避免了我們自己猜測需要的gas數量。
revert操作碼將回滾所有的狀態變化,起作用是在gas不足時或對預編譯合約的調用發生故障后,可以回滾部分完成的狀態更新。
每個地址關聯的持久化內存被稱為存儲(Storage),這時一個key-value庫,實現從256位到256位數據的映射。在合約內這個鍵值庫沒有辦法枚舉,合約也不能訪問其他地址關聯的存儲。
如果采用如下形式初始化變量:uint256 blah
,那么就會將變量blah保存到持久化存儲。uint是uint256的別名,如果需要更細粒度的管理,可以使用uint8,uint16等等。
EVM有一個虛擬棧可以保存256位的值。選擇256位的目的是與密碼學操作保持兼容。所有的EVM操作都是利用這個虛擬棧完成的,它最多可以容納1024個成員。你可以拷貝棧頂16個成員之一,或者兩兩交換。所有其他的操作碼都利用棧頂特定位置的成員作為輸入并將結果壓入棧。
對于每一個消息調用,易失內存都被復位,內存以32字節為單位分配,使用gas支付內存利用的成本。我們需要調用預編譯合約的值保持在這個內存的頂部。
我們可以將之前保存在持久化存儲中的變量賦值給內存,方式如下:
uint256[2] memory inputToPrecompile; input[0] = somePreviouslyStoredValue; input[1] = someOtherPreviouslyStoredValue;
這實際上就是我們在ecmul中的開始4行的操作。我們將值ax,ay,k壓入虛擬棧的頂部。然后通過調用bn256ScalarMul預編譯合約的地址就完成調用了。看下一部分的代碼:
assembly { if iszero(staticcall(gas, 0x07, input, 0x60, p, 0x40)) { revert(0,0) } }
staticcall操作碼的調用形式如下:
staticcall(gasLimit, to, inputOffset, inputSize, outputOffset, outputSize)
可以看到在上面的調用bn256ScalarMul的代碼中,我們:
在扣除2000后,發送當前可用的gas
調用地址0x07的預編譯合約,這對應bn256ScalarMul
使用內存變量input作為輸入偏移參數
將輸入大小聲明為0x60,這對應3個256位數值,表示一個橢圓曲線點和一個256位標量
將輸出保存在p中
輸出大小為0x40,對應要返回的橢圓曲線點
這樣就完成了對以太坊預編譯合約bn256ScalarMul的調用,ecmul函數的返回值現在就是bn256ScalarMul預編譯合約的返回值!
下面的代碼調用bigModExp預編譯合約:
function expmod(uint base, uint e, uint m) public view returns (uint o) { assembly { // define pointer let p := mload(0x40) // store data assembly-favouring ways mstore(p, 0x20) // Length of Base mstore(add(p, 0x20), 0x20) // Length of Exponent mstore(add(p, 0x40), 0x20) // Length of Modulus mstore(add(p, 0x60), base) // Base mstore(add(p, 0x80), e) // Exponent mstore(add(p, 0xa0), m) // Modulus if iszero(staticcall(sub(gas, 2000), 0x05, p, 0xc0, p, 0x20)) { revert(0, 0) } // data o := mload(p) }}
需要注意的是,0x40始終是空閑內存,因此可以使用p:=mload(0x40)
來初始化內存指針。
感謝各位的閱讀,以上就是“怎么使用以太坊的預編譯合約”的內容了,經過本文的學習后,相信大家對怎么使用以太坊的預編譯合約這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創新互聯,小編將為大家推送更多相關知識點的文章,歡迎關注!