以太坊交易所 以太坊交易所
Ctrl+D 以太坊交易所
ads
首頁 > BNB價格 > Info

技術入門 | Solidity編程語言 : 基本編譯原理介紹與添加新指令

Author:

Time:1900/1/1 0:00:00

本文目標

本文的主要目的:1、了解solidity的基本編譯原理2、通過示例的方式了解如何添加新的指令,不會涉及到solidity語言的語法講解。

solidity簡介

solidity是智能合約的開發語言,是一種語法類似于javascript的高級語言。合約源碼經過編譯生成虛擬機代碼運行在虛擬機中。

開發文檔:https://solidity

functionget()publicviewreturns(uint){returnstoredData;}}

abi,data,opcodes

以上代碼在remix:

http://remix.ethereum.org/中使用0.5.1commit版本編譯生成

abi=,"name":"get","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"set","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"}]

data="0x60806040526000805534801561001457600080fd5b5060c2806100236000396000f3fe6080604052600436106043576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c146048578063b8e010de146070575b600080fd5b348015605357600080fd5b50605a6084565b6040518082815260200191505060405180910390f35b348015607b57600080fd5b506082608d565b005b60008054905090565b4360008190555056fea165627a7a72305820825c534e94b487410e10fa0ba5da11584c0b0ad2bd9e56397a3dfa89e504ee1f0029"

opcodes="

固定指令:PUSH10x80PUSH10x40MSTORE

變量:PUSH10x0DUP1SSTORE//對應的storedData=0

內聯函數:CALLVALUEDUP1ISZEROPUSH20x14JUMPIPUSH10x0DUP1REVERTJUMPDESTPOP//用于出錯回滾

部署代碼指令:PUSH10xC2DUP1PUSH20x23PUSH10x0CODECOPYPUSH10x0RETURNINVALID//部署合約的核心指令

固定指令:PUSH10x80PUSH10x40MSTORE

固定指令:PUSH10x4CALLDATASIZELT//用于校驗input大小。

加載合約代碼:PUSH10x43JUMPIPUSH10x0CALLDATALOADPUSH290x100000000000000000000000000000000000000000000000000000000SWAP1DIVDUP1PUSH40x6D4CE63CEQPUSH10x48JUMPIDUP1PUSH40xB8E010DEEQPUSH10x70JUMPIJUMPDESTPUSH10x0DUP1REVERTJUMPDEST

經濟日報:積極探索區塊鏈等在工業互聯網中的技術融合和豐富應用:5月8日,經濟日報刊文“新型基建助力數字經濟高質量發展”。文章表示,通過完善數字基礎設施建設,加快發展數字經濟,可以釋放大規模“數字紅利”,為我國謀取未來國際競爭優勢。發展壯大數字經濟,推動產業數字化轉型和智能化升級,有利于促進新舊動能轉換,打造高質量發展的新引擎。數字基建是技術創新的新載體,有助于5G、人工智能、大數據、物聯網、云計算和區塊鏈等技術的融合創新和場景化應用,為數字經濟發展厚植“數字土壤”。積極探索5G、人工智能、大數據、物聯網、云計算、區塊鏈等新技術在工業互聯網中的技術融合和豐富應用,為各垂直行業和領域賦能賦智,促進產業集群數字化發展。[2020/5/8]

內聯函數:CALLVALUEDUP1ISZEROPUSH10x53JUMPIPUSH10x0DUP1REVERTJUMPDESTPOP

get函數:PUSH10x5APUSH10x84JUMPJUMPDESTPUSH10x40MLOADDUP1DUP3DUP2MSTOREPUSH10x20ADDSWAP2POPPOPPUSH10x40MLOADDUP1SWAP2SUBSWAP1RETURNJUMPDEST

內聯函數:CALLVALUEDUP1ISZEROPUSH10x7BJUMPIPUSH10x0DUP1REVERTJUMPDESTPOP

set函數:PUSH10x82PUSH10x8DJUMPJUMPDESTSTOPJUMPDESTPUSH10x0DUP1SLOADSWAP1POPSWAP1JUMPJUMPDESTNUMBERPUSH10x0DUP2SWAP1SSTOREPOPJUMPINVALID

其他指令:LOG1PUSH60x627A7A723058KECCAK256DUP30x5cMSTORE80x4eSWAP50xb4DUP8COINBASE0xeLTSTATICCALLSIGNEXTEND0xa50xdaGTPC0x4cSIGNEXTENDEXP0xd20xbdSWAP15JUMPCODECOPYPUSH270x3DFA89E504EE1F0029000000000000000000000000000000000000"//

上述abi,data是在部署合約和執行合約需要的數據。其中abi包含了合約中用到的函數名,函數的輸入輸出,與函數的屬性。opcodes是虛擬機要執行的具體代碼指令,data是opcodes的16進制,二者之間可以互相轉化。下面介紹下如何生成abi與opcodes。

solidity編譯原理簡述

這里以上述合約代碼為例,簡單介紹下解析流程

1、以字符串的形式讀入完整合約代碼,轉第2步;

2、去除字符串前的空格,然后遍歷字符串,并以空格,‘{’,'}',';','(',')'等為分隔符將字符串進行分割,然后與TOKEN_LIST中定義的TOKEN進行對比,并替換為應的TOKEN,轉第3步。

3、第一個TOKEN是pragma,然后以pragma為開始,直到';'結束,確定語言為solidity,版本號大于等于0.5.0,并比較當前編譯器版本是否匹配,轉第4步。

4、繼續遍歷,TOKEN為contract,,然后從contract開始,確定下一個字符串storenumber為contractname,繼續遍歷,從‘{’開始,,到配對的‘}’結束,此時確定了合約名為storenumber的合約內容,轉第9步。

5、繼續遍歷,TOKEN為uint,判斷為數據類型,以‘;’為結尾,確定數據類型為uint,類型名為storedData,轉第6步

聲音 | 周強:加快推進區塊鏈技術攻關和應用場景落地,形成統一的人民法院區塊鏈應用體系:據新京報報道,1月18日,記者從全國高級法院院長會議上獲悉,今年最高人民法院將落實法律適用分歧解決機制實施辦法,從制度和機制層面推動解決裁判尺度問題。在智慧法院建設方面,最高人民法院院長周強提出,要以電子卷宗深度應用為抓手,全面推廣庭審語音識別、文書智能糾錯、類案強制檢索等應用,努力攻克以人工智能為核心的一批關鍵技術,持續深化智慧審判建設。要以建設人民法院區塊鏈統一平臺為重點,加快推進區塊鏈技術攻關和應用場景落地,形成全國統一的人民法院區塊鏈應用體系。[2020/1/18]

6、繼續遍歷,TOKEN為function,后續字符串set為函數名,以‘(’,開始,以‘)’為終確定input為空,繼續遍歷TOKEN為public,確定函數屬性,繼續遍歷TOKEN為‘{’,以配對的‘}’為結束,確定函數體,轉第7步。

7、繼續遍歷,TOKEN為function,處理邏輯與第6步相同,但是增加了view屬性與returns,returns的解析結果對應了abi中的outputs,轉第8步。

8、繼續遍歷遇到與合約初始‘{’配對的‘}’,轉第4步繼續處理。

9、遍歷結束,進行合法性檢查(語法檢查,命名規則檢查,指令檢查等),轉第10步。

10、開始編譯合約,即opcodes的生成過程。編譯過程可分成三個過程,轉第11步。

11、編譯初始化。初始化指令是固定的:PUSH10x80PUSH10x40MSTORE。然后取出所有的狀態變量,這里的狀態變量會被編譯為:PUSH10x0DUP1SSTORE,轉到第12步。

備注:1、這里的指令并不是一開始就是這樣,而是后期經過翻譯過的,比如PUSH10x80在這里的正確表示方式是AssembllyItem(type:pushdata,data:0x80),之后經過token,instruction的對應轉化為指令2、狀態變量指令PUSH10x0DUP1SSTORE表示初始化變量為值為零,變量位置偏移為0。如果代碼中初始化為1,這里的指令會編譯成PUSH10x1PUSH10x0SSTORE。如果增加一個變量初始化為3,則會被編譯為PUSH10x1PUSH10x0SSTOREPUSH10x3PUSH10x1SSTORE

12、繼續編譯,主要是完成對函數的編譯,添加一個用于檢查并回滾的內聯函數。對應的指令:CALLVALUEDUP1ISZEROPUSH20x14JUMPIPUSH10x0DUP1REVERTJUMPDESTPOP,轉13步;

13、添加合約初始化:PUSH10xC2DUP1PUSH20x23PUSH10x0CODECOPYPUSH10x0RETURN。至此,部署合約的主要opcodes生成完畢。下面開始編譯函數,轉14步;

14、先根據所有的函數名生成對應的函數地址,如例子中的0x6D4CE63C,0xB8E010DE,實際調用函數的時候在查看交易的input中,就有這個值,轉15步;

15、編譯函數,生成各個函數的指令,可參照前文示例。轉16步;

16、最后編譯missingFunctions。轉17步;

17、打印結果,編譯結束。

上述解析的流程只是介紹了基本的思路,實際的處理過程要復雜的多,因為合約中可以有類,繼承,多態,接口,庫等形式的存在,需要進行一些額外的處理。

生成abi:

abi的內容是合約內函數的相關信息,包括函數的constant,name,inputs,outputs,payable,stateMutability,type,從上述第2至8步的解析即可獲取到上述信息,然后封裝成json返回給前端即可。

動態 | 天音控股:研究區塊鏈技術在彩票行業應用不存在政策與法律風險:天音控股(000829)12月30日晚間回復深交所關注函稱,公司與火幣中國進行合作,合作內容是在彩票行業進行區塊鏈技術應用的探索和研究,是嚴格遵守國家和有關部門制定的法律法規的。公司在主營業務范圍內進行區塊鏈技術的研究和應用亦是遵循國家發展戰略和彩票行業發展趨勢,因此不存在政策與法律的相關風險。(證券時報e公司)[2019/12/30]

生成opcodes:

上述第10到16步內流程即是生成cpcodes的過程,在實際使用中,用的opcodes的16進制。

添加新指令

影響范圍

根據上述編譯流程的解析,要添加新的指令,需要考慮以下4點

1、token的定義:語法定義,比如token{Add,+},將+與Add對應起來,解析的時候將代碼中的+替換為Add

2、instruction的定義:提供給虛擬機執行的指令,需要在編譯器和虛擬機中添加相同的定義

3、casetoken的處理:將token與instruction對應起來,編譯的過程中將token::Add替換為instruction::ADD指令,供虛擬機識別。

4、新指令對編譯的影響:比如對函數的影響,對存儲的影響等,這個修改可以參考其他的同類型指令,比如添加的是運算符就參考加減乘除指令,添加的是塊屬性就參考已有的number,gaslimit指令。

5、虛擬機中對新加指令的定義與處理

示例:以添加RANDOM指令(獲取塊中的隨機數屬性,可參考number屬性,合約中以block.number,block.random的方式進行使用)為例,說明在代碼中添加的位置。

修改編譯器代碼

1、查看token定義,代碼位置:liblangutil/Token.h。在TOKEN_LIST已定義了2中類型的token,一種是關鍵字token,一種是非關鍵字token,如括號,運算符,數據類型。要添加的random不是以上類型,不需要進行token定義。

#token定義示例,格式為M(name,string,precedence),M可以是T或者K,T表示非關鍵字token,K表示關鍵字token。name表示token名稱,string為token的原生字符串,precedence表示優先級。

#defineTOKEN_LIST(T,K)

......

T(LParen,"(",0)

T(RParen,")",0)

T(LBrack,"[",0)

T(RBrack,"]",0)

T(AssignShr,">>>=",2)

T(AssignAdd,"+=",2)

T(AssignSub,"-=",2)

......

K(Continue,"continue",0)

K(Contract,"contract",0)

K(Do,"do",0)

K(Else,"else",0)

......

2、指令定義,代碼位置:libevmasm/Instruction.h。在enumcalssInstruction中找到block的相關屬性,并在其后追加RANDOM指令。如下所示,RANDOM=0x46。注意添加的指令號不能與其他的沖突,比如不能再添加一個0x40的指令,會與現有的BLOCKHASH指令沖突。

聲音 | 普華永道王斌:未來普華永道會更多參與智慧城市區塊鏈技術應用等方面的服務領域:金色財經報道,10日,普華永道粵港澳大灣區西岸服務基地在珠海正式成立,當天,普華永道分別與珠海市商務局、珠海華發集團有限公司、橫琴發展有限責任公司簽署了戰略合作框架協議。普華永道中國廣東市場主管合伙人王斌表示,在珠海成立的粵港澳大灣區西岸服務基地是普華永道嶄新面貌的展示窗口,未來普華永道會更多參與數字化轉型,智慧城市區塊鏈技術應用等方面的服務領域。[2019/12/11]

enumclassInstruction:uint8_t{......BLOCKHASH=0x40,///<gethashofmostrecentcompleteblockCOINBASE,///<gettheblock'scoinbaseaddressTIMESTAMP,///<gettheblock'stimestampNUMBER,///<gettheblock'snumberDIFFICULTY,///<gettheblock'sdifficultyGASLIMIT,///<gettheblock'sgaslimitRANDOM,......

}

上述定義為16進制,需要有一個字符串的"RANDOM"與指令對應,代碼位置libevmasm/Instruction.cpp中。

std::map<std::string,Instruction>constdev::solidity::c_instructions={......{"NUMBER",Instruction::NUMBER},{"DIFFICULTY",Instruction::DIFFICULTY},{"GASLIMIT",Instruction::GASLIMIT},{"RANDOM",Instruction::RANDOM},......}staticstd::map<Instruction,InstructionInfo>constc_instructionInfo={......{Instruction::ADD,{"ADD",0,2,1,false,Tier::VeryLow}},{Instruction::NUMBER,{"NUMBER",0,0,1,false,Tier::Base}},{Instruction::DIFFICULTY,{"DIFFICULTY",0,0,1,false,Tier::Base}},{Instruction::GASLIMIT,{"GASLIMIT",0,0,1,false,Tier::Base}},{Instruction::RANDOM,{"RANDOM",0,0,1,false,Tier::Base}},......}//后面的0,0,1,false,Tier::Base是可變的,根據指令的需要。第一個默認為0即可,第二個0表示參數個數,1表示需要1個返回值。false可理解為只在虛擬機內部使用,如果涉及到數據庫的讀寫,這里要填成true。最后的Tier::Base是gasprice的級別,根據需要填寫即可。

3、指令的處理:代碼位置libsolidity/codegen/ExpressionCompiler.cpp

boolExpressionCompiler::visit(MemberAccessconst&_memberAccess){......caseType::Category::Magic:if(member=="coinbase")m_context<<Instruction::COINBASE;elseif(member=="timestamp")m_context<<Instruction::TIMESTAMP;elseif(member=="difficulty")m_context<<Instruction::DIFFICULTY;elseif(member=="number")m_context<<Instruction::NUMBER;elseif(member=="gaslimit")m_context<<Instruction::GASLIMIT;elseif(member=="random")m_context<<Instruction::RANDOM;......}//不同的指令有不同的case進行處理,比如token:Add的處理如下:voidExpressionCompiler::appendArithmeticOperatorCode(Token_operator,Typeconst&_type){......switch(_operator){caseToken::Add:m_context<<Instruction::ADD;break;caseToken::Sub:m_context<<Instruction::SUB;break;caseToken::Mul:m_context<<Instruction::MUL;break;......}//如果添加的是其他類型的指令,就找到對應的case添加即可。

金色獨家 UMINING技術負責人:比特幣是無法取代的:金色財經獨家專訪,UMINING技術負責人Terry在接受金色財經獨家專訪時表示:“比特幣是無法取代的,是整個數字貨幣行業的代表。“就算有更加實用、高效的數字貨幣出現,比特幣依然會在那里。”[2018/6/14]

4、對函數,存儲的影響:

確定數據類型,代碼位置libsolidity/ast/Types.cpp

MemberList::MemberMapMagicType::nativeMembers(ContractDefinitionconst*)const{//指定存儲的數據類型......caseKind::Block:returnMemberList::MemberMap({{"coinbase",make_shared<AddressType>(StateMutability::Payable。,{"timestamp",make_shared<IntegerType>(256。,{"blockhash",make_shared<FunctionType>(strings{"uint"},strings{"bytes32"},FunctionType::Kind::BlockHash,false,StateMutability::View。,{"difficulty",make_shared<IntegerType>(256。,{"number",make_shared<IntegerType>(256。,{"gaslimit",make_shared<IntegerType>(256。,{"random",make_shared<IntegerType>(256。//注意這里,設置數據類型為uint256,如果需要其他數據類型,參考libsolidity/ast/Types.h中的類型定義});......

對函數的影響:代碼位置libevmasm/Semanticlnformation.cpp

boolSemanticInformation::invalidInPureFunctions(Instruction_instruction)

{

switch(_instruction)

{

......

caseInstruction::TIMESTAMP:

caseInstruction::NUMBER:

caseInstruction::DIFFICULTY:

caseInstruction::GASLIMIT:

caseInstruction::RANDOM://增加的random指令影響函數的Pure屬性。returntrue表示該函數不能使用pure關鍵字。

caseInstruction::STATICCALL:

caseInstruction::SLOAD:

returntrue;

default:

break;

}

returninvalidInViewFunctions(_instruction);

}

修改虛擬機代碼

random指令的定義,代碼位置:hvm/evm/opcodes.go

const(

//0x40range-blockoperations

BLOCKHASHOpCode=0x40+iota

COINBASE

TIMESTAMP

NUMBER

DIFFICULTY

GASLIMIT

RANDOM//新增

)

varopCodeToString=mapstring{

......

NUMBER:"NUMBER",

DIFFICULTY:"DIFFICULTY",

GASLIMIT:"GASLIMIT",

RANDOM:"RANDOM",//新增

......

}

varstringToOp=mapOpCode{

......

"NUMBER":NUMBER,

"DIFFICULTY":DIFFICULTY,

"GASLIMIT":GASLIMIT,

"RANDOM":RANDOM,//新增

......

}

指令操作的定義:代碼位置:hvm/evm/jump_table.go,添加指令的操作屬性

instructionSet=operation{

execute:opRandom,

gasCost:constGasFunc(GasQuickStep),

validateStack:makeStackFunc(0,1),

valid:true,

}

上述操作碼對應函數opRandom的定義:代碼位置hvm/evm/instrucitons.go,可參考number函數的定義

funcopNumber(pc*uint64,evm*EVM,contract*Contract,memory*Memory,stack*Stack)(byte,error){

stack.push(math.U256(new(big.Int).Set(evm.BlockNumber)))

returnnil,nil

}

funcopRandom(pc*uint64,evm*EVM,contract*Contract,memory*Memory,stack*Stack)(byte,error){

stack.push(math.U256(new(big.Int).Set(evm.Random)))

returnnil,nil

}

上述opRandom中使用了evm.Random,因此需要在evm結構體增加Random的屬性。代碼位置hvm/evm/evm.go

typeContextstruct{

......

Coinbasecommon.Address//ProvidesinformationforCOINBASE

GasLimit*big.Int//ProvidesinformationforGASLIMIT

BlockNumber*big.Int//ProvidesinformationforNUMBER

Time*big.Int//ProvidesinformationforTIME

Difficulty*big.Int//ProvidesinformationforDIFFICULTY

Random*big.Int//新增

}

上述增加了Random屬性,需要對其進行初始化,代碼位置為:hvm/hvm.go

funcNewEVMContext(msgMessage,header*types.Header,chainChainContext,author*common.Address)evm.Context{

......

returnevm.Context{

CanTransfer:CanTransfer,

Transfer:Transfer,

GetHash:GetHashFn(header,chain),

Origin:msg.From(),

Coinbase:beneficiary,

BlockNumber:new(big.Int).Set(header.Number),

Time:new(big.Int).Set(header.Time),

Difficulty:new(big.Int).Set(header.Difficulty),

GasLimit:new(big.Int).Set(header.GasLimit),

Random:new(big.Int).Set(header.Random),//新增

GasPrice:new(big.Int).Set(msg.GasPrice()),

}

}

上述獲取的header為當前校驗的塊的header。header.Random的增加與生成此處不介紹了。

至此,編譯源碼與虛擬機源碼添加Random指令修改完成。

生成編譯器

1、下載源碼:gitclone

https://github.com/ethereum/solidity

2、cdsolidity&&gitcheckoutv0.5.7#本文例子以v0.5.7版本為基礎版本進行修改

3、按照前文介紹修改相關代碼

4、編譯源碼生成編譯器

二進制編譯器:mkdirbuild&&cdbuild&&cmake..&&make#執行完成后生成二進制文件:solc

js編譯器:執行./scripts/build_emscripten.sh#執行完成后生成js文件:soljson.js

5、使用編譯器編譯合約代碼

使用二進制編譯器:solc--abitest.sol#生成abi

solc--bintest.sol#生成data

solc--opcodestest.sol#查看opcodes

使用js編譯器:可以將soljson.js替換到remix中進行測試。需要搭建remix環境并修改soljson.js的加載路徑或者自行編寫js腳本進行測試。

6、按照前文介紹修改虛擬機代碼并部署到測試鏈,使用上述生成的abi,data進行鏈上測試,合約部署和調用過程不在贅述。

注:如有問題請在下方留言聯系我們技術社群。

汪曉明博客:http://wangxiaoming.com/

汪曉明:HPB芯鏈創始人,巴比特專欄作家。十余年金融大數據、區塊鏈技術開發經驗,曾參與創建銀聯大數據。主創區塊鏈教學視頻節目《明說》30多期,編寫了《以太坊官網文檔中文版》,并作為主要作者編寫了《區塊鏈開發指南》,在中國區塊鏈社區以ID“藍蓮花”知名。

Tags:IONNSTUSHPUSHCrypto Legions V3MONSTA價格TARUSHPUSH幣最新價格

BNB價格
繼Telegram后,我們認為SEC會對這兩個項目下手_LEG:GRAM

那位曾經被自己國家政府封殺但依舊無所謂的黑客,這次似乎要對美國SEC妥協了。10月15日,CNBC加密貨幣評論員RanNeuNer發推特稱,加密聊天工具Telegram團隊開發的Telegram.

1900/1/1 0:00:00
Facebook發幣施壓,各國央行都要發行數字貨幣了_FACE:Daiquilibrium

據德國媒體《Wirtschaftswoche》報道,德國財政部長兼副總理OlafScholz贊成使用國家數字貨幣,表示將引入歐元支持的央行數字貨幣“e-euro”.

1900/1/1 0:00:00
什么是多抵押 Dai 存款利率 — DSR_DAI:Maker

Dai存款利率是多抵押Dai最令人期待的功能之一。 存款利率將讓Dai進一步脫穎于其他穩定幣。除了繼續提供去中心化的穩定幣,多抵押Dai支持任何持有人將Dai鎖定在Dai存款利率(DSR)智能合.

1900/1/1 0:00:00
Devcon大會首日精編:狀態租金、Uniswap和Plasma的第二層DEX_EVE:devt幣有希望嗎

對于以太坊社區來說,今年最值得關注的無疑是正在日本大阪舉行的Devcon開發者大會,由于大部分去中心化金融應用程序都建立在以太坊區塊鏈上.

1900/1/1 0:00:00
8問 | 別開場面:大咖齊聚DVP,大話白帽與黑客_區塊鏈:DVP

9月,北京秋高氣爽,藍天白云。受去中心化漏洞平臺DVP邀約,《8問》欄目組在工體北路的科技寺做了一期別開場面的訪談.

1900/1/1 0:00:00
巴西擬放棄現有支付系統 并推出基于區塊鏈技術的即時支付系統_OIN:florincoin

29日,有媒體報道稱,由于效率低下,成本高昂,巴西中央銀行已經決定放棄現有的支付系統,并將于2020年11月啟動新的支付系統,而新的支付系統為一個基于區塊鏈技術研發的即時支付系統.

1900/1/1 0:00:00
ads