其他
硬核干货!智能合约编写之Solidity运行原理,内核原理理解+实战解析看到过瘾!
以下文章来源于FISCO BCOS开源社区 ,作者储雨知
来源 | FISCO BCOS开源社区
pragma solidity ^0.4.25;
contract Demo{
uint private _state;
constructor(uint state){
_state = state;
}
function set(uint state) public {
_state = state;
}
}
608060405234801561001057600080fd5b506040516020806100ed83398101806040528101908080519060200190929190505050806000819055505060a4806100496000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b1146044575b600080fd5b348015604f57600080fd5b50606c60048036038101908080359060200190929190505050606e565b005b80600081905550505600a165627a7a723058204ed906444cc4c9aabd183c52b2d486dfc5dea9801260c337185dad20e11f811b0029
PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP1 PUSH2 0xED DUP4 CODECOPY DUP2 ADD DUP1 PUSH1 0x40 MSTORE DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP PUSH1 0xA4 DUP1 PUSH2 0x49 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3F JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x60FE47B1 EQ PUSH1 0x44 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x4F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x6C PUSH1 0x4 DUP1 CALLDATASIZE SUB DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x6E JUMP JUMPDEST STOP JUMPDEST DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x4e 0xd9 MOD DIFFICULTY 0x4c 0xc4 0xc9 0xaa 0xbd XOR EXTCODECOPY MSTORE 0xb2 0xd4 DUP7 0xdf 0xc5 0xde 0xa9 DUP1 SLT PUSH1 0xC3 CALLDATACOPY XOR 0x5d 0xad KECCAK256 0xe1 0x1f DUP2 SHL STOP 0x29
JUMPDEST DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP JUMP STOP
客户端将部署请求(合约二进制,构造参数)作为交易的输入数据,以此构造出一笔交易 交易经过rlp编码,然后由发送者进行私钥签名 已签名的交易被推送到区块链上的节点 区块链节点验证交易后,存入交易池 轮到该节点出块时,打包交易构建区块,广播给其他节点 其他节点验证区块并取得共识。不同区块链可能采用不同共识算法,FISCO BCOS中采用PBFT取得共识,这要求经历三阶段提交(pre-prepare,prepare, commit) 节点执行交易,结果就是智能合约Demo被创建,状态字段_state的存储空间被分配,并被初始化为0x123
EVM是栈式虚拟机,其核心特征就是所有操作数都会被存储在栈上。下面我们将通过一段简单的Solidity语句代码看看其运行原理:
uint a = 1;uint b = 2;uint c = a + b;
这段代码经过编译后,得到的字节码如下:
PUSH1 0x1PUSH1 0x2ADD
为了读者更好了解其概念,这里精简为上述3条语句,但实际的字节码可能更复杂,且会掺杂SWAP和DUP之类的语句。
PUSH1:将数据压入栈顶。 ADD:POP两个栈顶元素,将它们相加,并压回栈顶。
contract Demo{
//状态存储
uint private _state;
function set(uint state) public {
//栈存储
uint i = 0;
//内存存储
string memory str = "aaa";
}
}
uint i = 1;
string memory str = "aaa";
bytes32 data;
assembly{
data := mload(str)
}
function strStorage() public view returns(bytes32, bytes32){
string memory str = "你好";
bytes32 data;
bytes32 data2;
assembly{
data := mload(str)
data2 := mload(add(str, 0x20))
}
return (data, data2);
}
0: bytes32: 0x0000000000000000000000000000000000000000000000000000000000000006
1: bytes32: 0xe4bda0e5a5bd0000000000000000000000000000000000000000000000000000
function memAlloc() public view returns(bytes32, bytes32){
string memory str = "aaa";
string memory str2 = "bbb";
bytes32 p1;
bytes32 p2;
assembly{
p1 := str
p2 := str2
}
return (p1, p2);
}
0: bytes32: 0x0000000000000000000000000000000000000000000000000000000000000080
1: bytes32: 0x00000000000000000000000000000000000000000000000000000000000000c0
0x40~0x60:空闲指针,保存可用地址,本例中是0x100,说明新的对象将从0x100处分配。可以用mload(0x40)获取到新对象的分配地址。 0x80~0xc0:对象分配的起始地址。这里分配了字符串aaa 0xc0~0x100:分配了字符串bbb 0x100~...:因为是顺序分配,新的对象将会分配到这里。
同时,欢迎所有开发者扫描下方二维码填写《开发者与AI大调研》,只需2分钟,便可收获价值299元的「AI开发者万人大会」在线直播门票!
2020年,这20个大家都认识的加密交易所过得怎么样? 在Kubernetes上部署一个简单的、类PaaS的平台,原来这么容易! 全球呼吸机告急!医疗科技巨头美敦力“开源”设计图和源代码 互联网之父确诊新冠,一代传奇:任谷歌副总裁、NASA 访问科学家 微软为一人收购一公司?破解索尼程序、写黑客小说,看他彪悍的程序人生!