您的位置: 首頁(yè) >科技 >

BIGBEECOIN-發(fā)明與運(yùn)轉(zhuǎn)時(shí)刻代碼解析

2022-07-03 12:09:50 編輯:蔡驊素 來源:
導(dǎo)讀 BIGBEECOIN-發(fā)明與運(yùn)轉(zhuǎn)時(shí)刻代碼解析正在解構(gòu)一個(gè)簡(jiǎn)略的solidity智能合約的EVM字節(jié)碼。今日,讓BIGBEECOIN開端用分而治之的戰(zhàn)略來拆解智能

BIGBEECOIN-發(fā)明與運(yùn)轉(zhuǎn)時(shí)刻代碼解析

正在解構(gòu)一個(gè)簡(jiǎn)略的solidity智能合約的EVM字節(jié)碼。

今日,讓BIGBEECOIN開端用“分而治之”的戰(zhàn)略來拆解智能合約的雜亂代碼吧。BIGBEECOIN在介紹性的前言中說過,這個(gè)反匯編的代碼其實(shí)十分初級(jí),但與原始字節(jié)碼比較會(huì)比較易讀。

請(qǐng)確保已在遵從了我在前言中介紹的操作,把BasicToken的代碼在remix編譯器中進(jìn)行了布置。

免責(zé)聲明:本文中供給的一切闡明均受我自己對(duì)transaction運(yùn)作辦法的解說,不代表以太坊官方定見。

現(xiàn)在,讓咱們聚集在JUMP、JUMPI、JUMPDES、RETURN和STOP操作嗎,并疏忽一切其他的操作。每逢咱們發(fā)現(xiàn)不是其間之一的操作碼時(shí),咱們就疏忽它,并跳到下一條指令,不要被他們干涉。

當(dāng)EVM履行代碼時(shí),是自上而下的次序,代碼中沒有其他進(jìn)口點(diǎn),一向從頂部開端履行。JUMP和JUMPI能夠讓代碼跳轉(zhuǎn)。JUMP獲取倉(cāng)庫(kù)中的最上面的值,并將履行移動(dòng)到該方位的指令??墒?,方針方位有必要包括JUMPDEST操作碼,不然履即將失利。這樣做的僅有意圖是:JUMPDEST將方位標(biāo)記為有用的跳轉(zhuǎn)方針。JUMPI也徹底相同,但倉(cāng)庫(kù)的第二個(gè)方位必定不能有“0”,不然就沒有跳轉(zhuǎn)。所以這是一個(gè)有條件的跳轉(zhuǎn),STOP是讓智能合約徹底中止的指令,RETURN則是暫停智能合約的履行,但回來EVM內(nèi)存的一部分?jǐn)?shù)據(jù),這很便利。

所以,讓咱們開端解說代碼時(shí)考慮到一切這些。在Remix的調(diào)試器中,將“ transaction”的滑塊滑到最左面。你能夠運(yùn)用Step Into按鈕(看起來像一個(gè)向下的小箭頭)并按照闡明進(jìn)行操作。

前面的指令能夠疏忽,直接到第11條指令,咱們找到了第一條JUMPI。假如它沒有跳轉(zhuǎn),它將持續(xù)經(jīng)過指令12到15并終究進(jìn)入REVERT,接著將中止履行。但假如跳轉(zhuǎn),它將越過這些指令到方位16(十六進(jìn)制0x0010,它在指令8被壓入倉(cāng)庫(kù))。指令16是一個(gè)JUMPDEST。

持續(xù)單步履行操作碼,直到“ transaction”滑塊一向向右。剛剛發(fā)作了許多等等,但只要在68的方位才干找到RETURN操作碼(以及STOP指令69中的操作碼,以防萬一)。這很古怪。假如您考慮一下,本智能合約的操控流程將一向在指令15或68完畢。咱們剛剛完結(jié)它并確認(rèn)沒有其他或許的流程,那么剩余的指令是什么?(假如您滑動(dòng)“ 指令”面板,您將看到代碼在方位566處完畢)。

咱們剛剛遍歷的指令集(0到69)便是所謂的合約的“創(chuàng)立代碼”。它永久不會(huì)成為智能合約代碼自身的一部分,但僅在創(chuàng)立智能合約的買賣期間由EVM履行一次。咱們很快就會(huì)發(fā)現(xiàn),這段代碼擔(dān)任設(shè)置創(chuàng)立的合約的初始狀況,以及回來其運(yùn)轉(zhuǎn)時(shí)代碼的副本。剩余的497條指令(70到566),正如咱們所見,履行流程永久不會(huì)到達(dá)的,正是這些代碼將成為已布置智能合約的一部分。

接下來,咱們對(duì)代碼進(jìn)行第一次拆分:把創(chuàng)立時(shí)的代碼與運(yùn)轉(zhuǎn)時(shí)的代碼區(qū)分隔。

創(chuàng)立部分

現(xiàn)在,咱們將深入研究代碼的創(chuàng)立部分。

圖1.解構(gòu)BasicToken.sol的創(chuàng)立時(shí)EVM字節(jié)碼

這是本文中要了解的最重要的概念。創(chuàng)立代碼在業(yè)務(wù)中履行,該業(yè)務(wù)回來運(yùn)轉(zhuǎn)時(shí)代碼的副本,該副本是智能合約的實(shí)踐代碼。正如咱們將看到的,結(jié)構(gòu)函數(shù)是創(chuàng)立代碼的一部分,而不是運(yùn)轉(zhuǎn)時(shí)代碼的一部分。智能合約的結(jié)構(gòu)函數(shù)是創(chuàng)立代碼的一部分; 一旦布置,它將不會(huì)呈現(xiàn)在智能合約的代碼中。

這種法力是怎么發(fā)作的?這便是咱們現(xiàn)在要逐漸剖析的內(nèi)容。

好的。所以現(xiàn)在咱們的問題被簡(jiǎn)化為了解這些與創(chuàng)立時(shí)代碼相對(duì)應(yīng)的70條指令。

讓咱們從頭選用自上而下的辦法,這次了解一切指令,而不是越過任何指令。首要,讓咱們重視運(yùn)用PUSH1和MSTORE操作碼的指令0到2 。

圖2.閑暇內(nèi)存指針EVM字節(jié)碼結(jié)構(gòu)

PUSH1只需將一個(gè)字節(jié)壓入倉(cāng)庫(kù)頂部,而MSTORE從倉(cāng)庫(kù)中抓取終究?jī)蓚€(gè)項(xiàng)并將其間一個(gè)存儲(chǔ)在內(nèi)存中:

mstore(0x40, 0x80)

| |

| What to store.

Where to store.

(in memory)

留意:上面的代碼片段是Yul-ish代碼。留意它是怎么從左到右耗費(fèi)倉(cāng)庫(kù)中的元素,總是首要耗費(fèi)倉(cāng)庫(kù)頂部的元素。

這是將數(shù)字0x80(十進(jìn)制128)存儲(chǔ)在方位0x40(十進(jìn)制64)的方位。

在咱們現(xiàn)在評(píng)論的問題中,不必去管它,假如有必要有一個(gè)原因,我后面會(huì)解說。

現(xiàn)在,在Remix的Debugger選項(xiàng)卡中翻開Stack 以及Memory的面板,以便在逐漸檢查這些指令時(shí)能夠可視化。

你或許想知道:指令1和3發(fā)作了什么?PUSH是僅有由兩個(gè)或多個(gè)字節(jié)組成的EVM指令。所以,PUSH 80是兩條指令。所以咱們揭開了謎底:指令1是0x80,而指令3的 0x40。

接下來我會(huì)闡明從5到15的指令。

圖3.non-payable檢查EVM字節(jié)碼結(jié)構(gòu)。

在這兒,又有一大堆的新的操作碼:CALLVALUE,DUP1,ISZERO,PUSH2,和REVERT。CALLVALUE推送創(chuàng)立業(yè)務(wù)中觸及的wei的數(shù)量,DUP1仿制倉(cāng)庫(kù)中的第一個(gè)元素,假如倉(cāng)庫(kù)的最高值為零,ISZERO則將1推送到倉(cāng)庫(kù),PUSH2就像PUSH1,但它將兩個(gè)字節(jié)推送到倉(cāng)庫(kù),而REVERT則是中止履行。

那么這兒發(fā)作了什么?在Solidity中,咱們能夠像這樣編寫這個(gè)匯編:

if(msg.value!= 0)revert();

這段代碼實(shí)踐上不是咱們?cè)糞olidity源的一部分,而是由編譯器注入的,因?yàn)樵蹅儧]有將結(jié)構(gòu)函數(shù)聲明為payable。在Solidity的最新版別中,未清晰聲明為payable的函數(shù)不能接納以太?;貋淼絽R編代碼,在指令11的JUMPI將越過指令12到15,假如沒有相關(guān)的以太幣,則跳轉(zhuǎn)到16。不然,REVERT將以兩個(gè)參數(shù)履行為0(意味著不會(huì)回來有用的數(shù)據(jù))。

好的!讓咱們中場(chǎng)歇息一下,來杯咖啡。

(下一部分會(huì)有點(diǎn)扎手,所以最好歇息幾分鐘。在你再次會(huì)集專心力之前,為自己預(yù)備一杯好咖啡。確保你了解咱們到目前為止看到的內(nèi)容,因?yàn)橄乱徊糠钟悬c(diǎn)雜亂。)

假如您想要另一種辦法來可視化咱們剛剛完結(jié)的作業(yè),請(qǐng)測(cè)驗(yàn)運(yùn)用我構(gòu)建的這個(gè)簡(jiǎn)略東西:solmap。它答應(yīng)您實(shí)時(shí)編譯Solidity代碼,然后單擊EVM操作碼以杰出顯現(xiàn)相關(guān)的Solidity代碼。反匯編與Remix有點(diǎn)不同,但你應(yīng)該能夠經(jīng)過比較來了解它。

預(yù)備持續(xù)前進(jìn)了嗎?接下來是指令16到37。請(qǐng)持續(xù)運(yùn)用Remix的調(diào)試器。(記住,remix是你的好朋友^ ^)。

圖4. EVM字節(jié)碼結(jié)構(gòu),用于從智能合約字節(jié)碼結(jié)尾附加的代碼中檢索結(jié)構(gòu)函數(shù)參數(shù)

前四個(gè)指令(17到20)讀取方位在存儲(chǔ)器中的任何內(nèi)容0x40,并將其推送到倉(cāng)庫(kù)。假如你能回想起來,那應(yīng)該是數(shù)字0x80。下面是推0x20(十進(jìn)制32)到倉(cāng)庫(kù)(指令21),并仿制該值(指令23),壓棧0x0217(十進(jìn)制535)(指令24),終究仿制第四個(gè)值(指令27),這應(yīng)該是0x80。

在檢查這樣的EVM指令時(shí),能夠暫時(shí)不了解發(fā)作了什么。別憂慮,它會(huì)時(shí)不時(shí)呈現(xiàn)在你的腦際。

在指令28,履行了 CODECOPY,它承受三個(gè)參數(shù):方針內(nèi)存方位,用來存儲(chǔ)仿制代碼,從中仿制的指令編號(hào),以及要仿制的代碼的字節(jié)數(shù)。因而,在這種情況下,0x80從坐落代碼中的字節(jié)方位(535,32字節(jié)代碼長(zhǎng)度的方針方位)開端。

假如檢查整個(gè)反匯編代碼,有566條指令。為什么這段代碼企圖仿制終究32個(gè)字節(jié)的代碼呢?實(shí)踐上,在布置包括參數(shù)的結(jié)構(gòu)函數(shù)的合約時(shí),參數(shù)作為原始十六進(jìn)制數(shù)據(jù)附加到代碼的結(jié)尾(向下翻滾“闡明”面板能夠檢查此內(nèi)容)。在這種情況下,結(jié)構(gòu)函數(shù)承受一個(gè)uint256參數(shù),因而一切這些代碼所做的便是將參數(shù)從附加在代碼結(jié)尾的值仿制到內(nèi)存中。

這些32條指令作為反匯編代碼沒有意義,可是它們用原始的十六進(jìn)制表明:0x0000000000000000000000000...0000000000000000000002710。當(dāng)然,這是咱們?cè)诓贾弥悄芎霞s時(shí)傳遞給結(jié)構(gòu)函數(shù)的十進(jìn)制值10000!

你能夠一步一步地在Remix中重復(fù)這一部分,確保您了解剛剛發(fā)作的工作。終究成果應(yīng)該是0x00..002710的方位,看到在內(nèi)存中的數(shù)字0x80。

好,開端下一部分之前,我主張來一杯威士忌歇息一下。

威士忌韶光!

為什么主張你來一杯威士忌,因?yàn)閺倪@兒開端,都是下坡路了。

下一組指令是29到35,更新內(nèi)存地址0x40的值0x80到值0xa0,能夠看到,它們將值偏移了0x20(32)字節(jié)。

現(xiàn)在咱們能夠開端了解指令0到2了。Solidity追尋稱為“空內(nèi)存指針”的東西:即內(nèi)存中咱們能夠用來存儲(chǔ)東西的當(dāng)?shù)?,確保沒有人會(huì)掩蓋它(除非咱們犯了過錯(cuò))。因而,因?yàn)樵蹅儗?shù)字10000存儲(chǔ)在舊的閑暇內(nèi)存方位,咱們經(jīng)過向前移動(dòng)32個(gè)字節(jié)來更新閑暇存儲(chǔ)器指針。

即使是經(jīng)驗(yàn)豐富的Solidity開發(fā)人員在看到“閑暇內(nèi)存指針”或代碼時(shí)也會(huì)感到困惑,mload(0x40, 0x80),這些僅僅說,“每逢咱們寫一個(gè)新條目時(shí),咱們將從這一點(diǎn)開端寫入內(nèi)存并保存偏移記載”。

Solidity中的每個(gè)函數(shù),當(dāng)編譯為EVM字節(jié)碼時(shí),將初始化此指針。

在0x00到0x40之間的內(nèi)存有什么,你或許不知道。沒有。Solidity保存的一段內(nèi)存,核算哈希值,咱們很快就會(huì)看到,這關(guān)于映射和其他類型的動(dòng)態(tài)數(shù)據(jù)是必需的。

現(xiàn)在,在指令37中,MLOAD從存儲(chǔ)器讀取方位0x40并根本大將咱們10000的值從內(nèi)存下載到倉(cāng)庫(kù)中,在那里它將是新的,而且能夠鄙人一組指令中運(yùn)用的。


免責(zé)聲明:本文由用戶上傳,如有侵權(quán)請(qǐng)聯(lián)系刪除!

最新文章

精彩推薦

圖文推薦

點(diǎn)擊排行

2016-2022 All Rights Reserved.平安財(cái)經(jīng)網(wǎng).復(fù)制必究 聯(lián)系QQ280 715 8082   備案號(hào):閩ICP備19027007號(hào)-6

本站除標(biāo)明“本站原創(chuàng)”外所有信息均轉(zhuǎn)載自互聯(lián)網(wǎng) 版權(quán)歸原作者所有。