区块链以太坊智能合约运⾏原理和开发实例
⼀、以太坊智能合约的运⾏原理
1. 智能合约
智能合约是⼀种特殊协议,旨在提供、验证及执⾏合约。
具体来说,智能合约是区块链被称之为“去中⼼化的”重要原因,它允许我们在不需要第三⽅的情况下,执⾏可追溯、不可逆转和安全的交易。
在以太坊,记录在区块链账本⾥的不仅仅是账户余额,还有函数调⽤后变量的新状态。
2. 开发步骤
step1: 启动以太坊节点
启动⼀个以太坊节点(如Geth)
step2:编写
使⽤智能合约编程语⾔(如Solidity)编写智能合约(后缀为.sol)。
可以将⼀个智能合约实例理解成⼀个对象,编写⼀个智能合约类似于编写⼀个类,其可以在这个类⾥定义各种变量以及函数。
这⾥给出⼀个简单的例⼦。下⾯这段代码就是⼀个智能。合约SimpleStorage,⾥⾯只有⼀个变量storedData,以及set和get⽅法。contract SimpleStorage {
string storedData;
function set(string s) {
storedData = s;
}
function get() constant returns (string) {
returnstoredData;
}
}
坊
step3: 编译
⽤solc编译器将.sol合约代码编译成EVM字节码。
step4:部署
通过以太坊客户端将编译好的合约代码上传部署到以太坊区块链需要消耗GAS,并且需要合约发起⽤户使⽤⾃⼰的外部所有账户对将要部署的合约进⾏签名,通过矿⼯确认后,将合约代码存于以太坊区块链上,即智能合约被发送到所有连接到⽹络的设备上。在这⼀步中,⽤户可获得合约的地址,以及调⽤合约所需的接⼝,以便之后使⽤。
图1-4展⽰了在以太坊⽹络中创建智能合约的过程。
当Bob将⼀个包含智能合约信息(如上例代码)的交易发送到以太坊⽹络中后,节点的EVM执⾏这个交易并⽣成对应的合约实例,图中
的“0x6f8ae93..”代表了这个合约的地址。节点间通过共识机制达成⼀致后,这个合约就正式⽣效了,之后⽤户就可以调⽤SimpleStorage合约了。
当⽤户将这个智能合约发布到以太坊⽹络中时,相当于给这个类⽣成⼀个对象,合约发布之后⽤户会得到⼀个合约地址,相当于合约对象的指针。
step5:调⽤
使⽤web3.js库所提供的JavaScript API接⼝来调⽤合约。这⼀步也会消耗以太币。
当⽹络中的⽤户调⽤这个智能合约时,可以直接给这个合约地址发送“交易”,并声明本次调⽤的函数名称和参数,使得智能合约执⾏对应的逻辑。
⽆论发布还是调⽤智能合约,智能合约的信息都被附在“交易”中,以交易的形式发布到⽹络中。
因此以太坊⽹络中的节点接收到这些交易后,其中的EVM会执⾏对应的合约代码,最后各个节点通过PoW或PoS等达成共识,合约的内容和状态也就实现了全⽹⼀致
图1-5展⽰了在以太坊上调⽤智能合约的过程。
Bob同样以交易的形式在“To”字段填上SimpleStorage合约的地址,在“Data”字段填上调⽤的⽅法(set)
和参数(“Hello”),就可以调⽤智能合约SimpleStorage,将其中的storedData设为“Hello”。节点收到这条交易后,通过EVM执⾏对应的操作,并通过共识机制实现以太坊⽹络上合约状态的改变。
之后,当Alice查看这个合约的变量时,就会发现这个合约中storedData变量的值变成了“Hello”。
由于查看的过程不涉及状态的修改,⽽且以太坊上数据是分布式的,⽹络中的每个节点都可以在本地保存⼀份完整的数据,因此Alice可以不通过交易的形式查看到这个变量的值。
--《以太坊技术详解与实战》
ps:
a、合约地址和合约接⼝()是到合约并调⽤合约的必要信息。
b、在以太坊上创建(部署)、调⽤⼀个合约是通过发送⼀个交易完成的。
3. 太坊虚拟机EVM
以太坊虚拟机(EVM)是以太坊上智能合约的运⾏环境。
每个以太坊节点都运⾏着EVM。
它实际上是完全隔离的,这意味着在EVM上运⾏的代码⽆法访问⽹络、⽂件系统和其他进程。
智能合约对其他的智能合约的访问权也有限,在区块链⽹络上单独运作。
4. 矿⼯的职责
以太坊中miner的职责有:
接收(receive)交易
验证(verify)交易
传播(propagate)交易
执⾏(execute)交易(ps:执⾏交易主要是调⽤合约交易)。
接收区块,
验证区块,
传播区块。
这些职责都是诚实矿⼯做的,理性矿⼯可能只是产⽣区块。
5. 智能合约的数据存在哪⾥的?
智能合约的数据(状态变量)存在区块链上。
6. 调⽤合约传进来的参数存在哪⾥?
参数不⼀定,参数如果⽤的是栈那就不存,默认的栈不是memory类型
数据位置,变量的存储位置属性。有三种类型
memory(内存)
storage(持久化到硬盘上)
calldata。
最后⼀种数据位置⽐较特殊,⼀般只有外部函数的参数(不包括返回参数)被强制指定为calldata(⼤多数表现和memory⼀样)。这种数据位置是只读的,不会持久化到区块链(即leveldb中)。
⼀般我们可以选择指定的是memory和storage。
memory存储位置同我们普通程序的内存类似。即分配,即使⽤,越过作⽤域即不可被访问,等待被回收。
⽽对于storage的变量,数据将永远存在于区块链上(持久化到硬盘上)。
memory就相当于栈的数据。可以把栈⾥的元素放到storage位置和memory位置。
⼀个合约⾥的局部(local)变量,状态(state)变量都存在链上,即持久化到leveldb中了。
7. 深⼊分析
storage 存储结构是在合约创建的时候就确定好了的,它取决于合约所声明状态变量。但是内容可以被(交易)调⽤改变(所有的节点修改⼀样)。
Solidity 称这个为状态改变,这也是合约级变量称为状态变量的原因。也可以更好的理解为什么状态变量都是storage存储。
memory 只能⽤于函数内部,memory 声明⽤来告知EVM在运⾏时创建⼀块(固定⼤⼩)内存区域给变量使⽤。
storage 在区块链中是⽤key/value的形式存储,⽽memory则表现为字节数组
8. 关于栈(stack)
EVM是⼀个基于栈的语⾔,栈实际是在内存(memory)的⼀个数据结构,每个栈元素占为256位,栈最⼤长度为1024。
值类型的局部变量是存储在栈上。
9. 不同存储的消耗(gas消耗)
storage 会永久保存合约状态变量,开销最⼤
memory 仅保存临时(temporary)变量,函数调⽤之后释放,开销很⼩
stack 保存很⼩的局部变量(small local variables),⼏乎免费使⽤,但有数量限制。
合约storage是以太坊帮我们实现好了。开发者只需要根据合约地址和ABI调⽤合约的函数就⾏。
以太坊⾥⾯的合约有点像服务端程序,业务调⽤合约的接⼝就是了。
交易数据存储在区块链上,账户的状态数据存储在本地;区块只保存该区块最终实现的账户状态的默克尔根。
部署交易的时候只需要携带合约的EVM字节码。当合约源程序⽐较⼤,相应的⼆进制码也会很⼤。
⽤户发送特定的交易(该交易被存储在某⼀区块⾥),部署合约到以太坊上,最后⽣成的合约地址(每⼀个合约地址对应⼀个合约账户,即内部账户)是所有的以太坊节点都有。
(合约账户只存合约的以太坊虚拟机字节码(⼀种以太坊专⽤的的⼆进制格式)。)
合约账户可以存储以太币;存储智能合约的可执⾏字节码;可响应别的⽤户或合约执⾏此智能合约的请求,并返回结果;可调⽤别的智能合约。
10. 为什么⽐特币这些项⽬喜欢⽤leveldb?是有哪些⼯程上的考量吗?
每个节点全量备份只能考虑嵌⼊式数据库。嵌⼊式数据库只有leveldb,rocksdb,sqlite。
在以太坊上部署和运⾏智能合约⼤致流程
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论