宇宙链 宇宙链
Ctrl+D收藏宇宙链
首页 > FIL币 > 正文

技术入门 | Solidity编程语言 : 基本编译原理介绍与添加新指令

作者:

时间: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//用于出错回滚

ICON计划在1月激活ICON 2.2升级,并改进BTP技术:1月3日消息, ICON区块链更新开发路线图,今年1月的核心重点将是激活ICON 2.2,此次升级将是完成从ICON 1.0到ICON 2.0过渡的最后一步。作为此次升级的一部分, ICON将寻求将主要P-Rep的人数从22人增加到25人。ICON 2.2还将包括一个用Java编写的新Governance SCORE,合约所有者将变更为Governance SCORE。

在互操作性解决方案区块链传输协议(BTP)方面,目标是在1月份完成以下项目:

-在无需信任的桥模型下开始研究减少Gas消耗。

-将代币迁移合约部署到MoonRiver测试网和ICON的Berlin测试网进行测试。

-如果成功解决Gas消耗问题,将合约部署到MoonRiver和ICON主网。

-完成NEAR与Nexus门户的集成。

-更多合作伙伴集成(待定)。

-开始DApp到DApp的集成,展示跨链传输的真实用例。[2022/1/3 8:20:45]

部署代码指令:PUSH10xC2DUP1PUSH20x23PUSH10x0CODECOPYPUSH10x0RETURNINVALID//部署合约的核心指令

固定指令:PUSH10x80PUSH10x40MSTORE

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

加载合约代码:PUSH10x43JUMPIPUSH10x0CALLDATALOADPUSH290x100000000000000000000000000000000000000000000000000000000SWAP1DIVDUP1PUSH40x6D4CE63CEQPUSH10x48JUMPIDUP1PUSH40xB8E010DEEQPUSH10x70JUMPIJUMPDESTPUSH10x0DUP1REVERTJUMPDEST

内联函数:CALLVALUEDUP1ISZEROPUSH10x53JUMPIPUSH10x0DUP1REVERTJUMPDESTPOP

get函数:PUSH10x5APUSH10x84JUMPJUMPDESTPUSH10x40MLOADDUP1DUP3DUP2MSTOREPUSH10x20ADDSWAP2POPPOPPUSH10x40MLOADDUP1SWAP2SUBSWAP1RETURNJUMPDEST

内联函数:CALLVALUEDUP1ISZEROPUSH10x7BJUMPIPUSH10x0DUP1REVERTJUMPDESTPOP

set函数:PUSH10x82PUSH10x8DJUMPJUMPDESTSTOPJUMPDESTPUSH10x0DUP1SLOADSWAP1POPSWAP1JUMPJUMPDESTNUMBERPUSH10x0DUP2SWAP1SSTOREPOPJUMPINVALID

其他指令:LOG1PUSH60x627A7A723058KECCAK256DUP30x5cMSTORE80x4eSWAP50xb4DUP8COINBASE0xeLTSTATICCALLSIGNEXTEND0xa50xdaGTPC0x4cSIGNEXTENDEXP0xd20xbdSWAP15JUMPCODECOPYPUSH270x3DFA89E504EE1F0029000000000000000000000000000000000000"//

上述abi,data是在部署合约和执行合约需要的数据。其中abi包含了合约中用到的函数名,函数的输入输出,与函数的属性。opcodes是虚拟机要执行的具体代码指令,data是opcodes的16进制,二者之间可以互相转化。下面介绍下如何生成abi与opcodes。

工信部信发司司长:加快推动区块链技术和产业创新发展:工业和信息化部信息技术发展司司长谢少锋近日在2021国际工业区块链大会线上会议中表示,当前,新一轮科技革命和产业变革蓬勃兴起,以区块链为代表的新一代信息技术迅猛发展,在支撑数字经济、赋能实体经济、提升治理能力等方面呈现出巨大价值和广阔前景。下一步,工业和信息化部将加大工作力度营造良好政策环境,从产品、企业、标准、人才、生态等多方面加强统筹形成合力,深化技术应用、提升创新能力、完善产业生态。同时,加大对地方支持力度,加快推动区块链技术和产业创新发展。(上海证券报)[2021/11/30 12:39:46]

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步

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步;

人社部启动全国新职业技术技能大赛:区块链应用操作员入选赛项:8月17日消息,人力资源和社会保障部将于2021年11—12月在浙江省杭州市举办全国新职业技术技能大赛,本次赛项总计20个,其中包括区块链应用操作员。获得各比赛项目前5名(双人赛项前3名)的选手,经人力资源社会保障部核准后,授予“全国技术能手”称号,颁发奖章、奖牌和证书。(北京日报)[2021/8/17 22:19:21]

14、先根据所有的函数名生成对应的函数地址,如例子中的0x6D4CE63C,0xB8E010DE,实际调用函数的时候在查看交易的input中,就有这个值,转15步;

15、编译函数,生成各个函数的指令,可参照前文示例。转16步;

16、最后编译missingFunctions。转17步;

17、打印结果,编译结束。

上述解析的流程只是介绍了基本的思路,实际的处理过程要复杂的多,因为合约中可以有类,继承,多态,接口,库等形式的存在,需要进行一些额外的处理。

生成abi:

abi的内容是合约内函数的相关信息,包括函数的constant,name,inputs,outputs,payable,stateMutability,type,从上述第2至8步的解析即可获取到上述信息,然后封装成json返回给前端即可。

生成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)

动态 | 陕西农业农村厅:把区块链等技术与农业农村相融合:据三秦都市报4月11日报道,昨日陕西省农业农村厅称,陕西省农业农村信息化工作将以网络强国、数字陕西战略为引领,聚焦实施乡村振兴战略、产业脱贫、“3+X”工程和农村人居环境等重点工作,把人工智能技术、5G技术、区块链技术、空间遥感等先进信息化技术与农业农村相融合,全面提升信息化服务农村经济和乡村振兴的水平。[2019/4/11]

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指令冲突。

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的级别,根据需要填写即可。

云南省旅游商品协会会长:区块链等技术助力“新零售”:近日,2018首届亚太国际旅游新零售高峰论坛在昆举行,云南省旅游商品协会会长蔡超表示,“新零售”与传统实体零售、传统电商零售的区别在于通过互联网、大数据、区块链解决经营过程的透明化、合理化、精准化、去中心化、规模化问题。[2018/4/18]

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添加即可。

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“蓝莲花”知名。

标签:IONNSTUSHPUSHBitnationPolkaMonsterROUSH币PUSH币最新价格

FIL币热门资讯
蚂蚁区块链云栖大会:2020年用区块链服务1亿中国人

“我预测,到明年这个时候,区块链在中国能够服务的人群会超过一个亿”,蚂蚁金服资深总监李杰力说。这一幕发生在9月26日的云栖大会·蚂蚁区块链生态峰会上,在这场峰会的圆桌论坛环节,李杰力与金融机构的代表们进行了深度对话,探讨了各行业的核心.

1900/1/1 0:00:00
数据显示:矿工致使BTC价格产生波动,2018年曾导致BTC价格下跌

新数据显示,比特币矿工导致了价格的波动,2018年比特币一度触及3100美元。 24小时BTC全网合约成交数据显示:多方占优:据合约帝数据显示,最近24小时BTC全网合约成交量中开多比例为52.53%,开空比例为47.47%.

1900/1/1 0:00:00
全球经济衰退,区块链抵押贷款可以做什么?

导语:?区块链技术和智能合约将节约巨大的运营成本,打开新的未开发市场。近期有很多关于经济衰退的讨论,所有的迹象都已渐渐浮现:证券市场摇摇欲坠、美国经济疲软、欧洲银行正在下行趋势中、中美贸易摩擦持续进行、美联储自上次金融危机以来首次降息.

1900/1/1 0:00:00
以太坊2.0将加速落地,简化分片方案新鲜出炉

昨天在日本大阪举办的Devcon5大会上,ConsenSys创始人透露称以太坊2.0的phase1-2阶段将大大提前,可能在2020年底就可以推出,而这比原计划要提前近两年的时间.

1900/1/1 0:00:00
观点:比特币不是更好的Paypal,它是更好的美元

前言:本文适合初学者阅读。作者认为,当前主流人群对比特币存在很多误解,包括比特币的主要用例,其他加密货币比比特币更适合做交换媒介和账户单位等。而作者认为,比特币是目前设计最好的货币形式,首先它足够稀缺,有固定的上限.

1900/1/1 0:00:00
DeFi 成了以太坊的护城河,其它公链还有竞争空间吗?

以太坊上的DeFi不可复制,但不等于以太坊DeFi的成功不可复制。上海区块链周已经结束一周有余,我的重感冒算是恢复了70%,说起来,这场感冒也是区块链周的副产品,在上海区块链举办的7天时间内,体力和脑力有点透支,后面竟然还自不量力的和.

1900/1/1 0:00:00