智能合约

Vite 是一个通用的去中心化应用平台,Vite 支持用户部署自己的智能合约。Vite 采用了消息驱动的架构,智能合约之间不共享任何状态,可以通过消息传递的方式进行通信。Vite 使用一种扩展自 Solidity 的语言 Solidity++ 开发智能合约,Solidity++ 兼容大部分 Solidity 语法,并支持异步语义。

什么是异步智能合约

以太坊里的合约间调用是通过消息调用,或者叫内部交易的方式来完成的,这组调用要么同时完成,要么全部失败,这是一个原子性的 ACID 语义,会成为性能瓶颈。Vite 借鉴了一些中心化互联网技术中比较成熟的方案,采用了消息驱动的架构,合约之间不共享任何状态,只通过彼此发送消息来进行通信。

和普通转账交易类似,Vite 中一个合约调用交易被拆成了一个合约请求交易和一个合约响应交易,分别被插入到合约调用的请求方和响应方的账户链上。

合约交易被写入账本和确认也是异步的。当一个请求交易被快照链快照,则代表该交易被成功发起。当一个响应交易被快照链快照时,表示这笔交易确认完成了。

在异步合约中,合约调用是没有返回值的,如果一个合约调用需要将执行结果返回给调用方,应该通过在合约执行过程最后发起一笔新交易的方式来实现回调。

智能合约由谁来执行

用户创建智能合约时,需要指定一个所属的委托共识组,委托共识组中有一组指定的代理节点,通过 DPoS 算法进行共识,代替合约账户打包账户链上的交易。

一个合约只能指定一个委托共识组,并且一旦指定就不能修改所属的委托共识组。一个委托共识组可以包含多个不同的合约。

Vite 提供了一个默认的委托共识组,来帮助所有未单独建立委托共识组的账户打包交易,也称为公共共识组。公共共识组每一轮的出块节点和快照共识组相同,但出块顺序不同。

合约响应交易的优先级

委托共识组在打包合约的响应交易时,会按合约当前的配额对注册到这个委托共识组的合约账户进行排序,优先打包配额高的合约的响应交易。但是合约响应交易的优先级不属于协议的一部分,委托共识组可以自定义合约响应交易的优先级。

同一个账户发往某个合约的多个消息,需要保证 FIFO,即高度低的请求交易先被合约响应。不同账户向同一个合约发送的消息并不保证 FIFO。

如果有多个账户同时给一个合约发消息,委托共识组节点会随机地响应来自这些账户的请求交易。这里多个账户之间的接收顺序也不属于协议的一部分,委托共识组可以自定义优先级算法。

合约的成本

创建合约的费用

创建合约需要消耗 vite。在预主网中,创建一个合约需要消耗 10 vite,这部分 vite 会销毁。

合约的配额

创建合约的请求交易消耗的配额由合约创建者提供,创建合约的响应交易配额由创建合约时销毁的 vite 提供,在预主网中,创建合约的响应交易最高可以使用 47.62 UTPS 的配额。

合约执行需要消耗配额。合约请求交易和合约响应交易分别消耗交易发起者和合约账户的配额。

预主网中,合约账户只能通过抵押 Vite 的方式来获取配额。如果合约账户没有足够的配额,则合约所属委托共识组不会打包这个合约的任何交易,因此合约提供者应该及时为合约抵押 vite

如果合约账户已经抵押了 vite,但由于合约账户代码过于复杂,抵押的 vite 不足以提供一次接响应交易消耗的配额,那么这笔交易会在消耗完合约当前持有的所有配额后,在合约账户链上生成一个响应失败的块。如果请求交易转账金额大于 0,那么响应失败后会将转账金额退还给请求账户。如果合约链上有一个由于配额不足执行失败的响应块,那么这个合约账户会被锁定 75 个快照块(大约 75s),即这笔响应交易之后的 75 个快照块内,委托共识组节点不再打包这个合约的响应交易。

智能合约语言

以太坊提供了一种图灵完备的编程语言 Solidity,用于开发智能合约。为了支持异步语义,Vite 对 Solidity 进行了扩展,定义了一组用于消息通信的语法。扩展之后的 Solidity 称为 Solidity++。

Solidity++ 将支持 Solidity 的大部分语法,但不再支持合约外的函数调用。开发者可以通过 message 关键字来定义消息,并通过 onMessage 关键字定义消息处理器,从而实现跨合约通信功能。Solidity++ 中的消息会被编译成 CALL 指令,并生成一个请求交易加入账本。在 Vite 中账本充当了合约之间异步通信的消息中间件,可以确保消息可靠存储并防止重复。

参见 Solidity++ 语法说明

虚拟机

当前以太坊已经拥有大量开发者,也有不少基于 Solidity 和 EVM 开发的智能合约投入应用。因此,Vite 虚拟机部分兼容 EVM,大部分 EVM 指令可以在 Vite 中保持原有语义。但由于 Vite 的账本结构及交易定义与以太坊不同,一些 EVM 指令的语义需要重新定义。

指令集

参见 Vite 指令集

合约调试

参见 调试智能合约