以太坊公链上的智能合约有哪些
是一种旨在以信息化方式传播、验证或执行合同的计算机协议。
网络中的每个节点(电脑)都用来运行以太坊虚拟机(EthereumVirtualMachine,EVM)。可以把EVM想象成是一个操作系统,它能够理解并且执行用以太坊上特定的编程语言编写的软件。由EVM所执行的软件或者应用就叫作“智能合约”。
智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。这是因为一个合约写好以后,就无法再被编辑或者修改。因此,你可以保证无论合约的内容是什么,它都会无条件执行。智能合约提供的是一种优于传统合同方法的安全,并减少与合同相关的其他交易成本。要在以太坊系统上运行智能合约,你需要付费。但是,并不是使用美元、英镑等常规货币进行支付。而是使用以太坊燃料—gas。
以太坊的智能合约
智能合约是运行在计算机里面的,用于保证让参与方执行承诺的代码,般情况下,普通合约上记录了甲方与乙方各方面的关系条款,并通常是通过法律强制执行或保护的,而“智能合约”则是用密码或密钥来执行关系。以更加直接的角度来理解的话,即“智能合约”的程序内容将同-开始大家一起设定好的那样百分百执行,并且零差错。
举个例子,以太坊用户可以使用智能合约在特定日期向朋友发送10个以太币。在这种情况下,用户可以操作创建一个合约,然后将程序推人该合约中进行特殊计算,以便它能够执行所需的命令。而以太坊就是专门把精力集中在这件事上的这么一个平台。
比特币是第一个支持“智能契约”的资源币种,因为网络的价值在于把价值或数据从一个点或人转移到另一个点或人身上。节点网络只在满足某些条件时才会进行验证,但是,比特币仅限于货币用例。相反,以大坊取代了比特币那种带有不小限制性的编程语言,取而代之的是一种允许开发人员编写自己程序的语言。以太坊允许开发人员编写他们自己的“智能契约”,即“自主代理”或“自治代理”,正如ETH白皮书所称的那样。该编程语言是“图灵完备”语言,这意味着它支持一组更广泛的计算指令。智能合约能做些什么呢?
1.“多签名”账户功能,只有在一定比例的人同意时才能使用资金。这个功能经常用在与众筹或募捐类似的活动中。
2.管理用户之间所签订的协议。例如,一方从另一方购买保险服务3.为其他合同提供实用程序。
4.存储有关应用程序的信息,如“域注册信息”或“会员信息记录”。概念有时候比较晦涩,我们举一个募捐的智能合约的例子来帮助理解:假设我们想向全网用户发起募捐,那就可以先定义一个智能账户,它有三个状态:当前募捐总量,捐款目标和被捐赠人的地址,然后给它定义两个函数:接收募捐函数和捐款函数。
接收募捐函数每次收到发过来的转账请求,先核对下发送者是否有足够多的钱(EVM会提供发送请求者的地址,程序可以通过地址获取到该人当前的区块链财务状况),然后每次募捐丽数调用时,都会比较下当前募捐总量跟捐款目标的比较,如果超过目标,就把当前收到的捐款全部发送到指定的被捐款人地址,否则的话,就只更新当前募捐总量状态值。
捐款函数将所有捐款发送到保存的被捐赠人地址,并且将当前捐款总量清零。每一个想要募捐的人,用自己的ETH地址向该智能账户发起一笔转账,并且指明了要调用接受其募捐函数。于是我们就有一个募捐智能合约了,人们可以往里面捐款,达到限额后钱会自动发送到指定账户,全世界的矿工都在为这个合约进行计算和担保,不再需要人去盯着看有没有被挪用,这就是智能合约的魅力所在。
以太坊源码分析--p2p节点发现
节点发现功能主要涉及 Server Table udp 这几个数据结构,它们有独自的事件响应循环,节点发现功能便是它们互相协作完成的。其中,每个以太坊客户端启动后都会在本地运行一个 Server ,并将网络拓扑中相邻的节点视为 Node ,而 Table 是 Node 的容器, udp 则是负责维持底层的连接。下面重点描述它们中重要的字段和事件循环处理的关键部分。
PrivateKey - 本节点的私钥,用于与其他节点建立时的握手协商
Protocols - 支持的所有上层协议
StaticNodes - 预设的静态 Peer ,节点启动时会首先去向它们发起连接,建立邻居关系
newTransport - 下层传输层实现,定义握手过程中的数据加密解密方式,默认的传输层实现是用 newRLPX() 创建的 rlpx ,这不是本文的重点
ntab - 典型实现是 Table ,所有 peer 以 Node 的形式存放在 Table
ourHandshake - 与其他节点建立连接时的握手信息,包含本地节点的版本号以及支持的上层协议
addpeer - 连接握手完成后,连接过程通过这个通道通知 Server
Server 的监听循环,启动底层监听socket,当收到连接请求时,Accept后调用 setupConn() 开始连接建立过程
Server的主要事件处理和功能实现循环
Node 唯一表示网络上的一个节点
IP - IP地址
UDP/TCP - 连接使用的UDP/TCP端口号
ID - 以太坊网络中唯一标识一个节点,本质上是一个椭圆曲线公钥(PublicKey),与 Server 的 PrivateKey 对应。一个节点的IP地址不一定是固定的,但ID是唯一的。
sha - 用于节点间的距离计算
Table 主要用来管理与本节点与其他节点的连接的建立更新删除
bucket - 所有 peer 按与本节点的距离远近放在不同的桶(bucket)中,详见之后的 节点维护
refreshReq - 更新 Table 请求通道
Table 的主要事件循环,主要负责控制 refresh 和 revalidate 过程。
refresh.C - 定时(30s)启动Peer刷新过程的定时器
refreshReq - 接收其他线程投递到 Table 的 刷新Peer连接 的通知,当收到该通知时启动更新,详见之后的 更新邻居关系
revalidate.C - 定时重新检查以连接节点的有效性的定时器,详见之后的 探活检测
udp 负责节点间通信的底层消息控制,是 Table 运行的 Kademlia 协议的底层组件
conn - 底层监听端口的连接
addpending - udp 用来接收 pending 的channel。使用场景为:当我们向其他节点发送数据包后(packet)后可能会期待收到它的回复,pending用来记录一次这种还没有到来的回复。举个例子,当我们发送ping包时,总是期待对方回复pong包。这时就可以将构造一个pending结构,其中包含期待接收的pong包的信息以及对应的callback函数,将这个pengding投递到udp的这个channel。 udp 在收到匹配的pong后,执行预设的callback。
gotreply - udp 用来接收其他节点回复的通道,配合上面的addpending,收到回复后,遍历已有的pending链表,看是否有匹配的pending。
Table - 和 Server 中的ntab是同一个 Table
udp 的处理循环,负责控制消息的向上递交和收发控制
udp 的底层接受数据包循环,负责接收其他节点的 packet
以太坊使用 Kademlia 分布式路由存储协议来进行网络拓扑维护,了解该协议建议先阅读 易懂分布式 。更权威的资料可以查看 wiki 。总的来说该协议:
源码中由 Table 结构保存所有 bucket , bucket 结构如下
节点可以在 entries 和 replacements 互相转化,一个 entries 节点如果 Validate 失败,那么它会被原本将一个原本在 replacements 数组的节点替换。
有效性检测就是利用 ping 消息进行探活操作。 Table.loop() 启动了一个定时器(0~10s),定期随机选择一个bucket,向其 entries 中末尾的节点发送 ping 消息,如果对方回应了 pong ,则探活成功。
Table.loop() 会定期(定时器超时)或不定期(收到refreshReq)地进行更新邻居关系(发现新邻居),两者都调用 doRefresh() 方法,该方法对在网络上查找离自身和三个随机节点最近的若干个节点。
Table 的 lookup() 方法用来实现节点查找目标节点,它的实现就是 Kademlia 协议,通过节点间的接力,一步一步接近目标。
当一个节点启动后,它会首先向配置的静态节点发起连接,发起连接的过程称为 Dial ,源码中通过创建 dialTask 跟踪这个过程
dialTask表示一次向其他节点主动发起连接的任务
在 Server 启动时,会调用 newDialState() 根据预配置的 StaticNodes 初始化一批 dialTask , 并在 Server.run() 方法中,启动这些这些任务。
Dial 过程需要知道目标节点( dest )的IP地址,如果不知道的话,就要先使用 recolve() 解析出目标的IP地址,怎么解析?就是先要用借助 Kademlia 协议在网络中查找目标节点。
当得到目标节点的IP后,下一步便是建立连接,这是通过 dialTask.dial() 建立连接
连接建立的握手过程分为两个阶段,在在 SetupConn() 中实现
第一阶段为 ECDH密钥建立 :
第二阶段为协议握手,互相交换支持的上层协议
如果两次握手都通过,dialTask将向 Server 的 addpeer 通道发送 peer 的信息
以太坊解读——Recursive Length Prefix协议图解(上)
在以太坊中,采用了一种名为Recursive Length Prefix(RLP)的方法对交易、账号、合约等基础的数据结构进行序列化处理,从而实现对链上数据的网络传输和持久化存储。RLP作为最为底层的编码方法,其重要性是不言而喻。因此,网上介绍RLP的文章也不少,但是由于RLP是二进制编码,又涉及到嵌套结构,造成编码过程的可读性较差,在学习中过程中,也一直没有找到完整的、易于理解的说明,总是绕在各种规则之中,且不能"自拔",着实有点无奈。所以,在本文中,采用图形化的解释和举例的方法,帮助大家理解RLP嵌套等特点、编解码过程等。
和其他的序列化协议不同,RLP只支持两种数据类型:
1)byte数组,可以是二进制数组,当然也可以是字符串;
2)byte数组的数组,也就是列表。并支持列表内的嵌套。
对于其他的数据类型,RLP都不支持,需要用户自己先转化为数组和列表的类型。
从RLP的命名中就可以看出两个关键字:一个是递归Recursive和前缀Prefix。首先,关于递归,也就是嵌套结构,结构上非常接近“树”,在Ethereum WiKi中,更是直接地采用树的items来进行命名,叶子节点(leaf tress)来存储“byte数组”,嵌套的节点就是一个树的分叉(branching trees)。
比如,需要是对如下对象进行RLP的编码,该对象中包含一个字符数组的列表、一个单个字符的字符数组、一个空字符数组。
, [0xbf], [] >
将该对象展开为树的结构,就如下图。其中[0xbf]和[]属于字符数组。属于列表,可以嵌套展开,再根据各个节点,进行编码。然后,对于不同长度的数组和列表,编码的方法略有不同,这个也就是Length Prefix相关的内容,和“编码过程”相关的内容,在第二节进行详细地说明。
关于为什么以太坊需要单独设计一种序列化协议,目前还没有找到官方的描述。但与其他序列化方法相比,RLP协议具有一些直接的优点,比如:
1)在以太坊中,最小货币单位为1 Wei,并且1 ETH = 10^18 Wei,所以在编码中,需要考虑对很大的整数类型的序列化,在RLP中采用去除前导零(leading zero)的大端big-endian方式,可以有效处理大整数;
2)使用了灵活的长度前缀来表示数据的实际长度,并且使用递归的方式能编码相当大的数据;
3)为了实现在链上节点的“共识Consensus”,防止出现数据的不一致,以太坊中并不支持浮点数类型,所以一般的序列化协议也不适用。
编码的过程就是将嵌套结构(nested sequence)的树形结构,添加长度前缀(Length Prefix)后,转化为顺序结构(flat sequence)的过程。添加长度前缀的目的,就是在反序列化时,可以根据长度前缀(Length Prefix),将(flat sequence)重构出树的结构(nested sequence)。
关于前缀的生成规则,《Ethereum Yellow Paper》[2]给出了非常形式化的数学符号描述,漂亮是非常漂亮,可惜不是人类的语言,非常难于理解和表达。网上大部分文章的写法也是引用了Yellow Paper中的5个文字形式上的描述,把原文和翻译一并给出如下:
将上面这个“长度”Length Prefix的编码规则,通过“决策树”可以图形化的表达如下图。
首先,根据编码的类型,进行分类,分为“字节数组”和“列表”两类;第二,根据不同的长度,编码的长度前缀不同。若待编码对象的长度小于56,就是把长度和“前缀字符”进行求和,占用一个字节。反之,待编码对象的长度大于56,其前缀需要多个字节,第一个字节,求出“长度”所占的字节数,再加上“前缀字符”,比如:长度为56,占用1字节。然后对“长度”进行编码,其实也是一个嵌套的过程。
还是以上文中的例子,该编码对象,已经完成了“树的构建”,然后根据“长度前缀”的原则,对树的各个项目进行长度前缀的计算。
, [0xbf], [] >
-对于属于嵌套数组,需要对内部各项非常进行长度编码的计算
? `对于[cat],属于字符数组,且长度为3,其对应的长度为0x80+3 = 0x83
? `对于[dog],属于字符数组,且长度为3,其对应的长度为0x80+3 = 0x83
? `整体上,其长度前缀为0xc0 + 2(新增的两个子项的长度所占用的字节)+6(待编码字符的长度)=0xC8
- 对于[0xbf], 属于字符数组,且长度为1,其对应的长度为0x80+1 = 0x81
- 对于[dog],属于字符数组,且长度为3,其对应的长度为0x80+3 = 0x83
- 对于[],属于字符数组,且长度为0,其对应的长度为0x80+0=0x80
总体上,增加的“长度编码”的字节数为6,加上原来的长度为10,所以整个对象的长度前缀为0xC0+16d=0xD0。所以最后的编码结果为:
D0 C8 83636174 83646F67 81B7 83646F67 80
解码过程将在 《以太坊解读——Recursive Length Prefix协议图解(下)》 一文中,给出图形化的解读说明。
一文读懂以太坊—ETH2.0,是否值得长期持有?
ETH 2.0 的影响:以太坊网络用户会很高兴,因为 ETH 将改变其费用结构,用户将为交易支付更少的费用。这意味着当前的矿工将减少每笔交易的新包含费用,而不是以太坊的拍卖式费用市场,但预计由于 PoS 的能源效率提高和数量的增加,他们的每笔交易成本将下降。由于成本较低,用户和验证者都受益,因此交易量会更高。
ETH 2.0 降低的成本和更高的速度将使更多类型的 Defi 交易成为可能,并为新的和不同类型的安全令牌、NFT 和其他分布式金融应用程序提供机会,这些应用程序在 ETH 1.0 中没有经济意义。
ETH 2.0 还将允许使用零知识汇总和乐观汇总的更复杂和更便宜的智能合约。通过汇总,所有交易数据都以比使用常规基于区块链的交易更便宜的方式捆绑并在以太坊上可用。汇总所需的计算负载是在链下完成的,进一步提高了吞吐量和交易成本效率。
分片将使网络民主化,最终使普通用户能够在个人设备上操作以太坊。越来越多的网络参与者将进一步分散区块链。ETH 的发行量也会减少;ETH 联合创始人 Vitalik Buterin 曾表示,在 ETH 2.0 下,新代币的发行量应在每年 10 万至 200 万之间,低于目前的每年 470 万,这可能会增加硬币需求。
总结:
ETH 2.0 升级将使这个有益的全球去中心化智能合约系统能够以其速度、安全性和可靠性的愿景向前发展,减少其碳足迹,并为投资者提供公平的竞争环境,通过赌注他们对 ETH 的未来拥有民主发言权以太坊。以太坊 2.0 是对已经最广泛用于智能合约的区块链网络的必要升级。随着加密货币、智能合约 Dapp 和 NFT 的接受度不断增长,以太坊 2.0 网络的可扩展性无疑将吸引更多用户,使其成为首选服务。