摘要:上一篇我們講了中的參數(shù)含義以太坊介紹一,但是只有函數(shù)定義也是不行的,我們還需要調(diào)用,當(dāng)調(diào)用一個函數(shù)時也需要對該函數(shù)進(jìn)行編碼,這樣才能執(zhí)行,那么以太坊是如何生成可供調(diào)用的字節(jié)碼的。
上一篇我們講了ABI中的參數(shù)含義 以太坊ABI介紹(一),但是只有函數(shù)定義也是不行的,我們還需要調(diào)用,當(dāng)調(diào)用一個函數(shù)時也需要對該函數(shù)進(jìn)行編碼,這樣EVM才能執(zhí)行,那么以太坊是如何生成可供EVM調(diào)用的字節(jié)碼的。
生成的字節(jié)碼主要分兩部分:函數(shù)選擇器和參數(shù)編碼
函數(shù)選擇器即函數(shù)編碼,對函數(shù)名稱+參數(shù)類型進(jìn)行sha3(keccak256)哈希運(yùn)算之后,取前4個字節(jié)
1、方法一:
安裝pyethereum [https://github.com/ethereum/p...]
> from ethereum.utils import sha3 > sha3("set(uint256").hex() "0x60fe47b16ed402aae66ca03d2bfc51478ee897c26a1158669c7058d5f24898f4" > sha3("setA(uint256)")[0:4].hex() "60fe47b1"
2、方法二:
打開Ganache,默認(rèn)端口7545,然后再命令行執(zhí)行以下命令
curl -X POST -i http://localhost:7545 --data "{ "jsonrpc":"2.0", "method":"web3_sha3", "params":["set(uint256)"] }" 返回結(jié)果: { "jsonrpc": "2.0", "result": "0x60fe47b16ed402aae66ca03d2bfc51478ee897c26a1158669c7058d5f24898f4" }
3、方法三:
const Web3 = require("web3") const web3 = new Web3() console.log(web3.sha3("set(uint256)")) # 0x60fe47b16ed402aae66ca03d2bfc51478ee897c26a1158669c7058d5f24898f4
取前四個字節(jié)(一個字節(jié)=2個16進(jìn)制字符)即:0x60fe47b1
參數(shù)編碼由于函數(shù)編碼占用了4個字節(jié),所以參數(shù)編碼從第五位開始
參數(shù)的編碼根據(jù)類型的不同,編碼方式也有所區(qū)別。主要分為固定類型和動態(tài)類型
1、固定類型
uint
int
uint和int:整型,分別是uint256和int256的別名。注意: 函數(shù)參數(shù)類型是uint,轉(zhuǎn)sha3碼時要變成uint256。
address:地址,20個字節(jié),160bits。
bool:布爾類型,1個字節(jié),true:1,false:0。高位補(bǔ)0
bytes 2、動態(tài)類型 bytes:動態(tài)分配大小字節(jié)數(shù)組。不是一個值類型! string:動態(tài)大小UTF8編碼的字符串,不是一個值類型! T[] 某個類型的不定長數(shù)組 T[k] 某個類型的定長數(shù)組 固定類型的編碼就很簡單,直接將參數(shù)值轉(zhuǎn)成32字節(jié)長度的16進(jìn)制即可。但是有區(qū)別的是:不足32bytes時,數(shù)字類型,如果是正數(shù)高位補(bǔ)0,如果是負(fù)數(shù)高位補(bǔ)1,布爾類型高位補(bǔ)0,字節(jié)類型、字符串類型在低位補(bǔ)全 介紹的例子和官方文檔一樣,如果理解有偏差可以查看源文檔 案例一:
0xcdcd77c0,在node中使用new Web3().sha3("baz(uint32,bool)")生成
0x0000000000000000000000000000000000000000000000000000000000000045,十進(jìn)制69,轉(zhuǎn)成16進(jìn)制為45,因為是正數(shù),高位補(bǔ)0至32bytes
0x0000000000000000000000000000000000000000000000000000000000000001,bool類型,true=1,false=0,高位補(bǔ)0 所以最終字符串為:(換行顯示是為了方便查看,實際是沒有換行) 返回:該函數(shù)返回的是true,output將會是 案例二:
0xfce353f6,在node中使用new Web3().sha3("bar(bytes3[2])")生成 固定長度不需要計算偏移量
0x6162630000000000000000000000000000000000000000000000000000000000,字符串abc轉(zhuǎn)成16進(jìn)制后為616263,低位補(bǔ)0,字符串轉(zhuǎn)16進(jìn)制可以使用這個工具
0x6465660000000000000000000000000000000000000000000000000000000000,同上 所以最終字符串為:(換行顯示是為了方便查看,實際是沒有換行) 案例三:
0x8be65246,在node中使用f(uint256,uint32[],bytes10,bytes)生成
0x0000000000000000000000000000000000000000000000000000000000000123,0x123對應(yīng)的16進(jìn)制,正數(shù)補(bǔ)全
0x0000000000000000000000000000000000000000000000000000000000000080,動態(tài)類型,計算偏移量。這個的偏移量是指實際存儲值的位置,由于這個函數(shù)有4個變量,那么實際存儲值的位置就是第五個32bytes位置,也就是說偏移量等于4*32bytes=128,轉(zhuǎn)成16進(jìn)制后就是對應(yīng)的值
0x3132333435363738393000000000000000000000000000000000000000000000,字符串1234567890轉(zhuǎn)成16進(jìn)制后為31323334353637383930,bytes類型,低位補(bǔ)全
0x00000000000000000000000000000000000000000000000000000000000000e0,動態(tài)類型,計算偏移量,這個偏移量就等于參數(shù)長度4*32bytes+前面的動態(tài)參數(shù)參數(shù)占有的長度(因為前面只有一個動態(tài)參數(shù),所以這個長度就是1*32bytes+2*32bytes,1*32bytes是第一個動態(tài)參數(shù)長度所占的bytes數(shù),2*32bytes是因為該函數(shù)中的第一個動態(tài)參數(shù)有2個值),那么具體的值就是 4*32bytes+(1*32bytes+2*32bytes)=7*32bytes=224,轉(zhuǎn)成16進(jìn)制就是e0,高位補(bǔ)全就是對應(yīng)的值
0x0000000000000000000000000000000000000000000000000000000000000002,第一個動態(tài)參數(shù)的長度,長度為2
0x0000000000000000000000000000000000000000000000000000000000000456,第一個動態(tài)參數(shù)中的第一個元素
0x0000000000000000000000000000000000000000000000000000000000000789,第一個動態(tài)參數(shù)中的第二個元素
0x000000000000000000000000000000000000000000000000000000000000000d,第二個動態(tài)參數(shù)的長度,長度為13
0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000,第二個動態(tài)參數(shù)的值編碼 所以最終字符串為:(換行顯示是為了方便查看,實際是沒有換行) 以上就是以太坊調(diào)用函數(shù)時生成字節(jié)碼的完整過程了!編碼規(guī)則
動態(tài)類型的編碼稍微復(fù)雜點,如果是固定長度就不需要計算偏移量,如果是不定長度就需要先計算偏移量,并在最后加上長度和具體值的編碼,詳細(xì)步驟下面會介紹具體編碼過程
pragma solidity ^0.4.16;
contract Foo {
function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
function bar(bytes3[2] memory) public pure {}
function f(uint, uint32[], bytes10, bytes) public pure {}
}
案例
函數(shù):baz(bytes3[2] memory)
調(diào)用:baz(69, true)const Web3 = require("web3")
const web3 = new Web3()
console.log(web3.sha3("f(uint256,uint32[],bytes10,bytes)"))
0xcdcd77c0
0x0000000000000000000000000000000000000000000000000000000000000045
0x0000000000000000000000000000000000000000000000000000000000000001
0x0000000000000000000000000000000000000000000000000000000000000000
函數(shù):bar(bytes3[2] memory)
調(diào)用:bar(["abc", "def"])0xfce353f6
0x6162630000000000000000000000000000000000000000000000000000000000
0x6465660000000000000000000000000000000000000000000000000000000000
函數(shù):f(uint,uint32[],bytes10,bytes)
調(diào)用:f(0x123, [0x456, 0x789], "1234567890", "Hello, world!")0x8be65246
0000000000000000000000000000000000000000000000000000000000000123
0000000000000000000000000000000000000000000000000000000000000080
3132333435363738393000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000e0
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000456
0000000000000000000000000000000000000000000000000000000000000789
000000000000000000000000000000000000000000000000000000000000000d
48656c6c6f2c20776f726c642100000000000000000000000000000000000000
歡迎訂閱「K叔區(qū)塊鏈」 - 專注于區(qū)塊鏈技術(shù)學(xué)習(xí)
博客地址:http://www.jouypub.com
簡書主頁:https://www.jianshu.com/u/756c9c8ae984
segmentfault主頁:https://segmentfault.com/blog/jouypub
騰訊云主頁:https://cloud.tencent.com/developer/column/72548
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/24343.html
摘要:但是對于調(diào)用者來說,就需要知道合約有哪些方法,方法的參數(shù)是什么,返回值是什么,而這些信息就記錄在智能合約的中。 ABI是什么 ABI全稱 Application Binary Interface,字面意思是應(yīng)用程序二進(jìn)制接口,可以通俗的理解為合約的接口說明,當(dāng)合約被編譯后,它對應(yīng)的abi也就確定了。abi有點類似于程序中的接口文檔,描述了字段名稱、字段類型、方法名稱、參數(shù)名稱、參數(shù)類型...
摘要:合約規(guī)定了公共職能部門,以創(chuàng)造新的投資和撤資,這將成為對沖基金的主要職能。對沖基金的用戶通過其以太坊地址來識別,該地址相當(dāng)于公鑰。我發(fā)現(xiàn)與其他程序如程序的以太坊智能合約進(jìn)行交互的最簡單方法是使用他們的。 在以太坊和其他區(qū)塊鏈中,仍有很多被證明的概念正在實施,開發(fā)人員在嘗試如何應(yīng)對這些新概念。作為dInvest 系列文章一部分,我也在研究以太坊并嘗試在區(qū)塊鏈中實施對沖基金。在上一篇文章中...
摘要:一系列的類似的對象,如果無返回值時,可以省略。表示函數(shù)聲明自己不會改變狀態(tài)變量的值。表示函數(shù)可以接收,否則表示不能。哈哈,恭喜大家,到這里這里就完整的實現(xiàn)了一個基于以太坊去中心化網(wǎng)頁錢包。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:[使用 ethers.js 開發(fā)以太坊Web錢包4 - 發(fā)送Token (代幣)](https://learnblockchain.cn/20...,請讀者前往...
摘要:一系列的類似的對象,如果無返回值時,可以省略。表示函數(shù)聲明自己不會改變狀態(tài)變量的值。表示函數(shù)可以接收,否則表示不能。哈哈,恭喜大家,到這里這里就完整的實現(xiàn)了一個基于以太坊去中心化網(wǎng)頁錢包。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:[使用 ethers.js 開發(fā)以太坊Web錢包4 - 發(fā)送Token (代幣)](https://learnblockchain.cn/20...,請讀者前往...
摘要:是以太坊開發(fā)的個人區(qū)塊鏈,可用于部署合約,開發(fā)應(yīng)用程序和運(yùn)行測試。安裝是一個用于與以太坊交互的庫。啟動以太坊測試區(qū)塊鏈服務(wù)器要部署智能合約,我們應(yīng)該啟動測試以太坊服務(wù)器。最后,你將在以太坊合約中設(shè)置調(diào)用用戶對象時獲得的值。 將數(shù)據(jù)存儲在數(shù)據(jù)庫中是任何軟件應(yīng)用程序不可或缺的一部分。無論如何控制該數(shù)據(jù)庫都有一個該數(shù)據(jù)的主控。區(qū)塊鏈技術(shù)將數(shù)據(jù)存儲到區(qū)塊鏈網(wǎng)絡(luò)內(nèi)的區(qū)塊中。因此,只要某個節(jié)點與網(wǎng)...
閱讀 3228·2021-11-08 13:21
閱讀 1209·2021-08-12 13:28
閱讀 1419·2019-08-30 14:23
閱讀 1938·2019-08-30 11:09
閱讀 852·2019-08-29 13:22
閱讀 2699·2019-08-29 13:12
閱讀 2560·2019-08-26 17:04
閱讀 2270·2019-08-26 13:22