diff --git a/source/design_documents/smart_contract.rst b/source/design_documents/smart_contract.rst index 5a3d0ffb..5216f88b 100644 --- a/source/design_documents/smart_contract.rst +++ b/source/design_documents/smart_contract.rst @@ -3,9 +3,9 @@ ============= XuperChain 通过 XuperBridge 实现了合约与虚拟机的解耦,由 XuperBridge 统一进行合约上下文的管理,虚拟机只需要关注无状态的合约执行,从而实现一体化的智能合约引擎。 -当前在编程语言方面支持 C++, JAVA, Go, Solidity, 在运行时方面支持 Native 合约,WASM 合约和 EVM 合约。 +当前在编程语言方面支持 C++、JAVA、Go、Solidity。在运行时方面支持 Native 合约、WASM 合约和 EVM 合约。 -语言和运行时之间的关系如表所示 +语言和运行时之间的关系如下表所示。 .. list-table:: 语言虚拟机兼容矩阵 :widths: 25 25 25 25 @@ -35,7 +35,7 @@ XuperChain 通过 XuperBridge 实现了合约与虚拟机的解耦,由 XuperBr XuperBridge 桥接层 ------------------ -XuperBridge 桥接层实现合约和虚拟机的解耦,桥接层主要负责虚拟机的管理,合约上下文管理,合约执行沙盒,合约代码管理等。 +XuperBridge 桥接层实现合约和虚拟机的解耦,桥接层主要负责虚拟机的管理、合约上下文管理、合约执行沙盒和合约代码管理等。 智能合约虚拟机 >>>>>>>>>>>>>> @@ -50,8 +50,8 @@ XuperChain 对虚拟机的约束由于 InstaneCreator 接口表示 RemoveCache(name string) } InstanceCreator 主要有两个接口约束 - * CreateInstance: 创建一个虚拟机实例,用于执行一次合约调用 - * RemoveCache: 清除有关缓存,释放资源 + * CreateInstance:创建一个虚拟机实例,用于执行一次合约调用 + * RemoveCache:清除有关缓存,释放资源 每个 Instance 则负责一次具体的合约执行。Instance 的接口约束为 @@ -66,50 +66,50 @@ InstanceCreator 主要有两个接口约束 Instance 主要有两个资源消耗 - * Exec: 执行合约调用 - * ResourceUsed: 获取本次合约调用的资源消耗 - * Release: 合约执行完毕,释放有关资源 - * Abort: 合约执行异常,中止执行 + * Exec:执行合约调用 + * ResourceUsed:获取本次合约调用的资源消耗 + * Release:合约执行完毕,释放有关资源 + * Abort:合约执行异常,中止执行 当前 XuperChain 共提供四种类型的虚拟机实现 - * KernelInstance:用于 Kernel 合约的执行 + * KernelInstance:用于 Kernel 合约的执行 * EVMInstance: 用于 EVM 合约的执行 * XVMInstance: 用于 WASM 合约的执行 * NativeInstance: 用于Native 合约的执行 -XuperBridge 提供了虚拟机的注册机制,虚拟机实现只需要调用 如下代码即可完成虚拟机的注册 +XuperBridge 提供了虚拟机的注册机制,虚拟机实现只需要调用如下代码即可完成虚拟机的注册 .. code-block:: protobuf bridge.Register(contractType, Name, driver) -为同一种合约类型注册不同的虚拟机也是允许的 +为同一种合约类型注册不同的虚拟机也是允许的。 合约上下文管理 >>>>>>>>>>>>>> XuperBridge 负责管理合约上下文。 -每次合约运行都会有一个伴随合约执行的上下文(context)对象,context里面保存了合约的运行参数,执行沙盒,输出结果,事件,日志等。context用于隔离多个合约的执行,也便于合约的并发执行。所有合约执行的状态信息由 XuperBridge 管理,虚拟机只需要关注无状态的合约执行 +每次合约运行都会有一个伴随合约执行的上下文(context)对象,context里面保存了合约的运行参数,执行沙盒,输出结果,事件,日志等。context用于隔离多个合约的执行,也便于合约的并发执行。所有合约执行的状态信息由 XuperBridge 管理,虚拟机只需要关注无状态的合约执行。 -合约执行的所有状态信息由 XuperBridge 的上下文管理器(ContextManager) 统一管理。ContextManager 的主要功能包括 +合约执行的所有状态信息由 XuperBridge 的上下文管理器(ContextManager) 统一管理。ContextManager 的主要功能包括: * 维护全局递增的 ContextID * 按需要进行 Context 的创建和销毁 * 保存所有合约调用的状态 - * 根据 ContextID, 返回上下文有关信息 + * 根据 ContextID 返回上下文有关信息 1. Context 的创建和销毁 context在合约虚拟机每次执行合约的时候创建。每个context都有一个context id,这个id由 ContextManager 维护,在xchain启动的时候置0,每次创建一个context对象加1,ContextManager 保存了context id到context对象的映射。 - context id会传递给合约虚拟机,在之后的合约发起系统调用过程中需要带上这个context id来标识本次合约调用以找到对应的context对象。 + context id会传递给合约虚拟机,在之后的合约发起系统调用过程中需要带上这个context id来标识本次合约调用以找到对应的context对象。 - context的销毁时机比较重要,因为我们还需要从context对象里面获取合约执行过程中的Response以及读写集,因此有两种解决方案,一种是由调用合约的地方管理,这个是xuper3里面做的,一种是统一销毁,这个是目前的做法,在打包成块结束调用Finalize的时候统一销毁所有在这个块里面的合约context对象。 + context的销毁时机比较重要,因为我们还需要从context对象里面获取合约执行过程中的Response以及读写集,因此有两种解决方案,一种是由调用合约的地方管理,这个是xuper3里面做的。一种是统一销毁,这个是目前的做法,在打包成块结束调用Finalize的时候统一销毁所有在这个块里面的合约context对象。 2. 合约上下文的操作 - 合约上下文主要包括以下三个操作 + 合约上下文主要包括以下三个操作: * NewContext,创建一个context,需要合约的参数等信息。 * Invoke,运行一个context,这一步是执行合约的过程,合约执行的结果会存储在context里面。 @@ -117,30 +117,30 @@ XuperBridge 负责管理合约上下文。 4. 合约上下文信息的传递 - 合约虚拟机和 XuperBridge 通过系统调用进行通信获取合约状态的通信与传递,通过全局唯一的ContextID 标示需要获取的 Context对象,相关的系统调用具体包括 + 合约虚拟机和 XuperBridge 通过系统调用进行通信获取合约状态的通信与传递,通过全局唯一的ContextID 标示需要获取的 Context对象,相关的系统调用具体包括: - * GetCallArgs: 获取上下文参数 - * SetOutput:上下文执行结果 + * GetCallArgs:获取上下文参数 + * SetOutput:上下文执行结果 * PostLog: 输出上下文执行日志 - * EmitEvent: 输出上下文事件 + * EmitEvent:输出上下文事件 合约 SDK 对上下文管理的有关系统调用进行了封装,合约开发者在合约开发过程中只需要调用本地方法即可完成状态信息的获取和传递。 合约执行沙盒 >>>>>>>>>>>> -XuperBridge 采用两阶段提交技术,预执行阶段生成合约的读写集,提交阶段对带读写集的交易进行签名和提交,节点收到完整交易后进行交易验证,验证通过后将有关数据写入到状态数据库中。 +XuperBridge 采用两阶段提交技术,预执行阶段生成合约的读写集,提交阶段对带读写集的交易进行签名和提交。节点收到完整交易后进行交易验证,验证通过后将有关数据写入到状态数据库中。 -XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 +XuperBridge 通过合约执行沙盒(Sandbox)生成读写集,主要包括: - * XMState: 合约 KV 数据的读写集 + * XMState:合约 KV 数据的读写集 * UTXOState: 合约 UTXO 的读写集 - * CrossQuerryState: 跨链调用的读写集 + * CrossQuerryState:跨链调用的读写集 * ContractEventState:合约事件相关的读写集 1. KV 数据读写集 -合约 KV 数据的读写集需要实现事务隔离,具体包括 +合约 KV 数据的读写集需要实现事务隔离,具体包括: - 读请求不会读到最新的其他事务带来的变更 - 读请求会读到最新的自己的写请求(包括删除)的变更 @@ -148,12 +148,12 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 - 新写入的会被迭代器读到 - 为实现以上目标,每次在交易预执行阶段生成一个空白执行沙盒,交易执行过程中记录有关数据的读写情况,各个接口对读写集的影响如下 +为实现以上目标,每次在交易预执行阶段生成一个空白执行沙盒,交易执行过程中记录有关数据的读写情况,各个接口对读写集的影响如下: - - Get会生成一个读请求 - - Put会产生一个读加一个写 - - Delete会产生一个读加一个特殊的写(TODO) - - Iterator会对迭代的key产生读 + - Get会生成一个读请求 + - Put会产生一个读加一个写 + - Delete会产生一个读加一个特殊的写(TODO) + - Iterator会对迭代的key产生读 在 Get 请求中,如果访问的值已在读集中存在,则直接返回,如果不存在,则从账本中进行读取。 @@ -162,8 +162,8 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 系统调用设计 >>>>>>>>>>>> - XuperBridge为所有合约提供统一的合约接口,从抽象方式上类似于linux内核对应于应用程序,内核代码是一份,应用程序可以用各种语言实现,比如 go,c。 - 类比到合约上就是各种合约的功能,如KV访问,QueryBlock, QueryTx等,这些请求都会通过跟xchain通信的方式来执行,这样在其上实现的各种合约虚拟机只需要做纯粹的无状态合约代码执行。 + XuperBridge为所有合约提供统一的合约接口,从抽象方式上类似于linux内核对应于应用程序,内核代码是一份,应用程序可以用各种语言实现,比如 Go,C。 + 类比到合约上就是各种合约的功能,如KV访问,QueryBlock,QueryTx等,这些请求都会通过跟xchain通信的方式来执行,这样在其上实现的各种合约虚拟机只需要做纯粹的无状态合约代码执行。 .. figure:: /images/contract.png :alt: XuperBridge @@ -174,7 +174,7 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 1.合约与 xchain 的通信机制 - xchain进程需要调用合约虚拟机来执行具体的合约代码,合约虚拟机也需要跟xchain进程通信来进行具体的系统调用,这是一个双向通信的过程。这种双向通信在不同虚拟机里面有不同的实现, + xchain进程需要调用合约虚拟机来执行具体的合约代码,合约虚拟机也需要跟xchain进程通信来进行具体的系统调用,这是一个双向通信的过程。这种双向通信在不同虚拟机里面有不同的实现。 - 在native合约里面由于合约是跑在独立进程,采用跨进程通信的方式进行。这里选用了基于 TCP 作为跨进程通信的传输层,xchain 在启动合约进程的时候把 syscall 的地址以及合约进程的地址传递给合约进程。合约进程一方面监听在 socket 上等待xchain调用自己运行合约代码,另一方面通过 xchain 的 socket 创建一个指向xchain syscall服务的 grpc 客户端来进行系统调用。 @@ -185,10 +185,10 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 合约 socket - - 在WASM虚拟机里面情况有所不同,WASM 虚拟机是以 library 的方式链接到 xchain 二进制里面,所以虚拟机和xchain在一个进程空间,通信是在 xchain 和 WASM虚拟机之间进行的,这里牵扯到xchain的数据跟虚拟机里面数据的交换,在实现上是通过WASM自己的模块机制实现的,xchain实现了一个虚拟的WASM模块,合约代码执行到外部模块调用的时候就转到对应的xchain函数调用。:ref:`xvm_communitation` 对 WASM虚拟机与宿主的通信方式有更多的描述 + - 在WASM虚拟机里面情况有所不同,WASM 虚拟机是以 library 的方式链接到 xchain 二进制里面,所以虚拟机和xchain在一个进程空间,通信是在 xchain 和 WASM虚拟机之间进行的,这里牵扯到xchain的数据跟虚拟机里面数据的交换,在实现上是通过WASM自己的模块机制实现的,xchain实现了一个虚拟的WASM模块,合约代码执行到外部模块调用的时候就转到对应的xchain函数调用。:ref:`xvm_communitation` 对 WASM虚拟机与宿主的通信方式有更多的描述。 - - 在 EVM 合约中,合约解释器被嵌入到 xchain 二进制中, 有关调用通过本地函数调用的方式执行 - - 在 kernel 合约中,合约代码本身是 xchain 进程的一部分,有关系统调用通过本地函数调用的方式进行即可 + - 在 EVM 合约中,合约解释器被嵌入到 xchain 二进制中,有关调用通过本地函数调用的方式执行。 + - 在 kernel 合约中,合约代码本身是 xchain 进程的一部分,有关系统调用通过本地函数调用的方式进行即可。 2. 数据传输协议 无论是在 WASM 合约中还是在原生合约中,由于 xchain 和合约的地址空间不同,需要涉及到数据的序列化和反序列化。选择 ` protobuf `_ 作为数据的序列化和反序列化协议。 @@ -196,15 +196,16 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 3. 系统调用接口 - XuperChain 提供了通用的系统调用接口,所有服务由 SyscallService 提供,不同合约根据合约类型的不同采用grpc 活着 memrpc 的方式请求系统调用。 + XuperChain 提供了通用的系统调用接口,所有服务由 SyscallService 提供,不同合约根据合约类型的不同采用grpc 或者 memrpc 的方式请求系统调用。 - 按照系统调用的不同可以分为以下几类 - * 数据访问: 合约对状态数据的读写,主要包括 KV 访问和迭代器访问 - * 链上服务: 合约查询链上数据,主要包括查询区块,查询交易,合约调用,合约内转账,跨链查询 - * 状态管理: 和执行上下文交互,主要包括获取调用参数,调用日志,调用事件,返回调用结果 - * 其他: 心跳信息,主要用于 native 合约 + 按照系统调用的不同可以分为以下几类: + + * 数据访问:合约对状态数据的读写,主要包括 KV 访问和迭代器访问 + * 链上服务:合约查询链上数据,主要包括查询区块,查询交易,合约调用,合约内转账,跨链查询 + * 状态管理:和执行上下文交互,主要包括获取调用参数,调用日志,调用事件,返回调用结果 + * 其他:心跳信息,主要用于 native 合约 - 完整的 SyscallService pb 声明如下 + 完整的 SyscallService pb 声明如下。 .. code-block:: protobuf :linenos: @@ -239,11 +240,11 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 4. xchain 对合约的调用 - 在 XuperCahin 中, 除了合约会通过系统调用接口请求 xchain 提供的各种服务外, xchain 也需要请求执行合约代码。xchain 对合约的调用随合约类型的不同而不同。 + 在 XuperChain 中, 除了合约会通过系统调用接口请求 xchain 提供的各种服务外, xchain 也需要请求执行合约代码。xchain 对合约的调用随合约类型的不同而不同。 - 在原生合约中,每个合约是一个进程,合约进程和 xchain 拥有不同的地址空间,甚至可能处于不同的 `namespace `_, 合约进程在启动的时候会监听一个本地 TCP 端口,作为 grpc 服务端等待 xchain 进程发起的执行合约调用的请求。 + 在原生合约中,每个合约是一个进程,合约进程和 xchain 拥有不同的地址空间,甚至可能处于不同的 `namespace `_,合约进程在启动的时候会监听一个本地 TCP 端口,作为 grpc 服务端等待 xchain 进程发起的执行合约调用的请求。 - 原生合约提供的GRPC 服务如下所示 + 原生合约提供的GRPC 服务如下所示。 .. code-block:: protobuf @@ -256,7 +257,7 @@ XuperBridge 通过合约执行沙盒(Sandbox)技生成读写集,主要包括 在 EVM 合约中,合约采用解释执行的方式,合约虚拟机作为一个库,被嵌入到 xchain 二进制文件中,合约调用时只需要为解释器设置对应的参数,调用解释器编程库提供的方法即可。 - 在 Kernel 合约中,Kernel 合约和 xchain 在同一个二进制中, 共享同一个地址空间。XuperChain 通过 Register 机制实现 Kernel 合约的注册,执行时只需要使用 Register的getKernelMethod 方法,找到对应的合约代码的地址进行本地调用即可。 + 在 Kernel 合约中,Kernel 合约和 xchain 在同一个二进制中, 共享同一个地址空间。XuperChain 通过 Register 机制实现 Kernel 合约的注册,执行时只需要使用 Register的getKernelMethod 方法,找到对应的合约代码的地址进行本地调用即可。 WASM 合约支持 >>>>>>>>>>>>> @@ -264,11 +265,11 @@ WASM 合约支持 在 WASM 合约中,每个合约是一个被编译成一个 WASM 模块,xchain 为合约提供执行沙盒环境,不同合约之间互相隔离,合约访问的系统资源受到严格的控制。 - WASM 合约性能高,安全性好,支持 GAS 计费机制,适用于公链,也适用于联盟链等场景。 + WASM 合约性能高,安全性好,支持 GAS 计费机制,适用于公链,也适用于联盟链等场景。 原生合约支持 >>>>>>>>>>>>>> - XuperChain 也提供原生合约(也称 native 合约)支持,当前支持通过 GO/JAVA 来进行智能合约开发,也可以方便地拓展到其他语言。 + XuperChain 也提供原生合约(也称 native 合约)支持,当前支持通过 GO/JAVA 来进行智能合约开发,也可以方便地拓展到其他语言。 在原生合约中,每个合约是一个运行在本地或者容器中的进程,合约和 xchain 之间通过 GRPC 协议进行通讯。需要注意的是,原生合约不支持 GAS 机制,安全性略弱。可以使用容器技术对原生合约可以访问的资源做基本的限制。 @@ -278,13 +279,13 @@ EVM 合约支持 >>>>>>>>>>> XuperChain 提供了对 EVM 合约的支持,可以使用 solidity 语言进行智能合约开发,以太坊合约开发者可以方便的使用自己熟悉的语言。 - 在 EVM 合约中,合约以解释执行的方式执行,合约解释器被嵌入到 xchain 二进制中. + 在 EVM 合约中,合约以解释执行的方式执行,合约解释器被嵌入到 xchain 二进制中。 相比于 WASM 合约和 原生合约,以太坊合约在性能方面路弱,主要适用于已有业务迁移至xhcian 的场景。 合约代码管理 >>>>>>>>>>>> - XuperBridge 负责合约代码的管理,合约代码管理由 ContractCodeProvider 提供,主要接口约束为 + XuperBridge 负责合约代码的管理,合约代码管理由 ContractCodeProvider 提供,主要接口约束为: .. code-block:: go @@ -294,14 +295,14 @@ EVM 合约支持 GetContractAbi(name string) ([]byte, error) } - ContractCodeProvider 主要功能提供合约代码以及合约的ABI(针对 EVM 合约) - 合约部署时,合约代码从请求中获取代码,合约调用时从账本获取代码, ContractCodeProvider 还维护了合约代码的缓存,当存在内存活着磁盘的缓存时,ContractCodeProvider 直接返回对应的代码缓存。 + ContractCodeProvider 主要功能提供合约代码以及合约的ABI(针对 EVM 合约) + 合约部署时,合约代码从请求中获取代码,合约调用时从账本获取代码。 ContractCodeProvider 还维护了合约代码的缓存,当存在内存活着磁盘的缓存时,ContractCodeProvider 直接返回对应的代码缓存。 .. _xvm: XVM WASM 虚拟机 --------------- - XVM 是 XuperChain 自研的 WebAssembly(简称WASM) 虚拟机, 采用AOT(Ahead Of Time) 模式执行,用于支持 WASM 合约的执行。其基本思路是将每一个 WASM 模块编译成一个动态链接库,每一个 export 方法通过编译成动态链接库里的一个全局符号, xchain 通过 CGO 进行调用。 + XVM 是 XuperChain 自研的 WebAssembly(简称WASM) 虚拟机, 采用AOT(Ahead Of Time) 模式执行,用于支持 WASM 合约的执行。其基本思路是将每一个 WASM 模块编译成一个动态链接库,每一个 export 方法通过编译成动态链接库里的一个全局符号, xchain 通过 CGO 进行调用。 广义的 XVM 除了 XVM 运行时之外,还包括构建工具 XDEV,编译工具 EMCC,合约标准库 contract-sdk-cpp。 @@ -312,7 +313,7 @@ XVM WASM 虚拟机 `WebAssembly `_ 起源于高性能的 Web 执行技术,后续作为一种通用的编译 `目标代码 `_ 得到浏览器外的支持,作为通用的沙盒执行技术,广泛应用于物联网,边缘计算,区块链等领域。 - WebAssembly 执行模式主要包括 `解释执行 `_ , `即时编译 (Just In time, abbr JIT) `_ , 提前编译 Ahead Of Time(AOT) 三种执行模式。 + WebAssembly 执行模式主要包括 `解释执行 `_ , `即时编译 (Just In time, abbr JIT) `_ ,提前编译 Ahead Of Time(AOT) 三种执行模式。 * 动态链接 @@ -326,22 +327,22 @@ XVM WASM 虚拟机 * dlerror: 获取动态链接库中符号的地址 * MMAP - Linux 将进程地址空间进行了划分成文本段(Text), 已初始化的数据段(Data), 未初始化的数据(BSS),堆(Heap),内存映射(MMAP),栈(Stack) 等区域。通过 `MMAP `_ 匿名映射可以为进程分配大块的虚拟内存。与 `brk 系统调用 `_ 相比, MMAP 在处理大块内存时有更高的内存利用效率。 + Linux 将进程地址空间进行了划分成文本段(Text),已初始化的数据段(Data),未初始化的数据(BSS),堆(Heap),内存映射(MMAP),栈(Stack) 等区域。通过 `MMAP `_ 匿名映射可以为进程分配大块的虚拟内存。与 `brk 系统调用 `_ 相比, MMAP 在处理大块内存时有更高的内存利用效率。 XVM 编译流程 >>>>>>>> - WebAssembly 作为一种中间表示,本身无法在处理器上执行。为了能够执行WebAssembly,需要有另一个程序将 WebAssembly 转化为本地二进制码。通常有解释执行,JIT (预编译)执行和AOT(预编译)执行三种执行模式。 + WebAssembly 作为一种中间表示,本身无法在处理器上执行。为了能够执行WebAssembly,需要有另一个程序将 WebAssembly 转化为本地二进制码。通常有解释执行,JIT (即时编译)执行和AOT(预编译)执行三种执行模式。 解释执行模式是一边读取 WebAssembly 字节码,一边执行有关指令。通常,在解释执行模式下,解释器需要为不同的模块存储运行时数据等等。在解释执行模式下,解释器每次读取一条或多条 WASM 指令,并修改对应的运行时数据。 JIT(Just In Time)执行模式是针对解释执行模式的性能优化,将频繁执行的指令提前编译成本地机器码,首次执行时会比较慢,随着时间推移,热点代码被编译成本地机器码之后性能获得大幅提升。 - AOT(Ahead of Time) 执行模式则是提前讲所有WASM 字节码编译成本地指令,执行的时候没有编译过程,因此性能通常最高。AOT 模式启动时需要进行字节码编译,因此启动速度慢。此外,AOT 编译由于不能利用运行时信息,因此特殊条件性性能可能不如 JIT 模式。 + AOT(Ahead of Time) 执行模式则是提前将所有WASM 字节码编译成本地指令,执行的时候没有编译过程,因此性能通常最高。AOT 模式启动时需要进行字节码编译,因此启动速度慢。此外,AOT 编译由于不能利用运行时信息,因此特殊条件下性能可能不如 JIT 模式。 XuperChain 采用 AOT 模式,将每一个 WASM 模块编译成一个动态链接库供 XVM 调用。 - 完整编译加载流程如图所示 + 完整编译加载流程如图所示。 .. figure:: /images/xvm_compile.png :alt: XVM编译加载流程 @@ -350,9 +351,9 @@ XVM 编译流程 XVM编译加载流程 - 针对C++ 合约,完整的编译加载流程为: CPP -> WASM -> C -> 动态链接库 + 针对C++ 合约,完整的编译加载流程为: CPP -> WASM -> C -> 动态链接库。 - 针对GO 合约,完整的编译加载流程为: GO -> WASM-> C -> 动态链接库 + 针对GO 合约,完整的编译加载流程为: GO -> WASM-> C -> 动态链接库。 其中动态链接库的格式随 XVM 环境的不同而不同, 在Linux 上是 ELF 格式的可执行文件,在 Mac 上是一个 MAC-O 格式的可执行文件。 @@ -410,18 +411,18 @@ XVM 内存管理 XVM 计费和机制 >>>>>>>>>>>> - 和 wasmtime, wasmer 等通用 WebAssembly 运行时略有差异, XVM 主要用于智能合约的执行,需要满足可停止,可计费等特性。解释执行模式下,每一条指令的执行都可以被 WASM 运行时提前拦截,运行时只需要在每次执行指令前统计对应的指令的 GAS 消耗即可。为了在 AOT 模式下实现以可停止性和可计费等特性,XVM 采用代码注入的方式的方式实现资源与计费机制。 + 和 wasmtime, wasmer 等通用 WebAssembly 运行时略有差异,XVM 主要用于智能合约的执行,需要满足可停止,可计费等特性。解释执行模式下,每一条指令的执行都可以被 WASM 运行时提前拦截,运行时只需要在每次执行指令前统计对应的指令的 GAS 消耗即可。为了在 AOT 模式下实现以可停止性和可计费等特性,XVM 采用代码注入的方式的方式实现资源与计费机制。 - 在 XVM 编译加载的第二阶段(WASM -> C),XVM 采用 `WABT `_ 完成从 WASM 到 C 的转换。XVM 使用的 WABT 为定制版本,在完成基本的分析和转换之后,WABT 会在每个 `基本块 `_ 的第一条指令前插入一条 GAS 消耗检查的指令,判断当前基本块执行完成后是否会超出 GAS 限制,如果执行完成会超出限制,则跑抛出异常。异常会被 XVM 运行时捕获并返回给上层调用方,由调用方来决定GAS 超出限制后的处理方式。需要注意的是,XVM 的 GAS 消耗检查指令是在实际执行之前进行的,不需要进行后续指令的执行即可确认是否超出限制。 + 在 XVM 编译加载的第二阶段(WASM -> C),XVM 采用 `WABT `_ 完成从 WASM 到 C 的转换。XVM 使用的 WABT 为定制版本,在完成基本的分析和转换之后,WABT 会在每个 `基本块 `_ 的第一条指令前插入一条 GAS 消耗检查的指令,判断当前基本块执行完成后是否会超出 GAS 限制,如果执行完成会超出限制,则抛出异常。异常会被 XVM 运行时捕获并返回给上层调用方,由调用方来决定GAS 超出限制后的处理方式。需要注意的是,XVM 的 GAS 消耗检查指令是在实际执行之前进行的,不需要进行后续指令的执行即可确认是否超出限制。 - XVM 的 GAS 限制是调用粒度的,每次函数调用的时候会设置此次函数调用的最大 GAS 限制,此次调用失败只会影响到这次调用 + XVM 的 GAS 限制是调用粒度的,每次函数调用的时候会设置此次函数调用的最大 GAS 限制,此次调用失败只会影响到本次调用。 XVM 异常处理 >>>>>>>> - XVM 提供异常机制用于支持运行时错误。系统初始化时自动设置 wasm_rt_trap,其中 wasm_rt_trap 是一个 GO 的函数。该函数主要是功能是做一些数据格式与数据类型的转换,如果发生异常则直接 panic。 在每次进行 cgo 在每个进行 CGO 调用的时候通过延迟执行(defer) 注册一个错误处理函数,捕获有关异常, + XVM 提供异常机制用于支持运行时错误。系统初始化时自动设置 wasm_rt_trap,其中 wasm_rt_trap 是一个 GO 的函数。该函数主要是功能是做一些数据格式与数据类型的转换,如果发生异常则直接 panic。 在每次进行 CGO 调用的时候通过延迟执行(defer) 注册一个错误处理函数,捕获有关异常。 - XVM 异常主要分为两种类型,分别是 WASM 执行异常和外部函数异常,前者是 WASM 规范规定的的异常以及 GAS 异常,后者主要是执行一些外部函数过程中的异常。 + XVM 异常主要分为两种类型,分别是 WASM 执行异常和外部函数异常。前者是 WASM 规范规定的的异常以及 GAS 异常,后者主要是执行一些外部函数过程中的异常。 WASM 执行异常主要包括 * WASM_RT_TRAP_OOB, /** Out-of-bounds access in linear memory. */ @@ -434,13 +435,13 @@ XVM 异常处理 * WASM_RT_TRAP_GAS_EXHAUSTION, /** Gas exhaustion. */ * WASM_RT_TRAP_INVALID_ARGUMENT, /** Invalid argument. */ - 外部函数异常主要发生在 XVM 运行时执行外部函数时的异常,如 GO 的 runtime 初始化的时间的异常,WASM 的外部函数中使用某系未支持的功能等等。 + 外部函数异常主要发生在 XVM 运行时执行外部函数时的异常,如 GO 的 runtime 初始化的时间的异常,WASM 的外部函数中使用未支持的功能等等。 XVM 语言运行时 >>>>>>>>>>>>>> - 当前 XVM 对 GO 语言 和 C/C++ 语言提供了支持 + 当前 XVM 支持 GO 语言 和 C/C++ 语言。 1. C/C++ 语言 @@ -476,7 +477,7 @@ XVM 语言运行时 3. WASI 支持 - `WASI `_ 提供了一套引擎无关的非 Web 环境下的系统 API,给 WASM 引擎提供了通过系统引擎访问外部资源的能力。 + `WASI `_ 提供了一套与引擎无关的非 Web 环境下的系统 API,给 WASM 引擎提供了通过系统引擎访问外部资源的能力。 XVM 也提供了 WASI 的支持。 .. _xvm_communitation: @@ -485,8 +486,10 @@ XVM 和 WASM 模块的通信 >>>>>>>>>>>>>>>>> XVM 和 WASM 模块的交机制主要包括 XVM 向 WASM 模块传递数据以及 WASM 模块向 XVM 传递数据。 - 在 XVM 和到 WASM 模块的通信方面,主要依靠 xvm_call 函数完成,该函数接受 params, param_len 两个参数,XVM 在进行函数调用前设置者两个参数即可。 - 在 WASM 模块到XVM的通信方面,主要依靠外部函数完成。由于 WASM 的内存是 XVM 宿主进程的页映射,XVM 可以访问 WASM 模块的内存。在进行少量数据传输时,可以直接通过外部函数的参数进行传递,在需要进行大量内容传递时,需要调用方和被调用方约定参数的序列化方式(如PB),数据地址,数据的长度,并通过外部函数参数传递数据地址和数据长度即可。 + + 在 XVM 向 WASM 模块的通信方面,主要依靠 xvm_call 函数完成,该函数接收 params, param_len 两个参数,XVM 在进行函数调用前设置这两个参数即可。 + + 在 WASM 模块向XVM的通信方面,主要依靠外部函数完成。由于 WASM 的内存是 XVM 宿主进程的页映射,XVM 可以访问 WASM 模块的内存。在进行少量数据传输时,可以直接通过外部函数的参数进行传递,在需要进行大量内容传递时,需要调用方和被调用方约定参数的序列化方式(如PB),数据地址,数据的长度,并通过外部函数参数传递数据地址和数据长度即可。 以 C++ 合约的系统调用为例,其的函数签名为 @@ -503,8 +506,8 @@ XVM 和 WASM 模块的通信 各个参数含义如下 * methodAddr 和 methodLen 指定了需要调用的方法的地址和长度,method 为 ASCII 字符串 - * requestAddr 和 requestLen 指定了请求的地址和长度, Request 为 PB 序列化的的 Request - * responseAddr 和 responseLen 返回值的地址和长度, Response 为 PB 序列化的 Response + * requestAddr 和 requestLen 指定了请求的地址和长度,Request 为 PB 序列化的的 Request + * responseAddr 和 responseLen 返回值的地址和长度,Response 为 PB 序列化的 Response * successAddr 为标志,表示调用是否成功 当合约执行过程中需要进行系统调用时,首先分配返回值所需的内存空间,将请求序列化后放到指定的位置,然后发起系统调用(WASM 的外部函数调用)。 @@ -520,6 +523,6 @@ XVM 工具链 XVM 作为一个智能合约设计的虚拟机,广义的 XVM 除了 XVM 运行时之外,还包括构建工具 XDEV,编译工具 EMCC,合约标准库 contract-sdk-cpp/contract-sdk-go 中和 XVM 交互的部分。为了能够运行将 C 编译成动态链接库,还需要在宿主节点上提供本地的 C++ 开发工具链。 - 在本地 C/C++ 工具链的选择上,XVM 没有单独的编译工具链,而是直接采用宿主工具支持。选择宿主工具的优势在于可以移植性和扩展性。在使用 XVM 的过程中,选择和平台架构适配的工具即可完成编译成该平台的动态链接库,如果本地开发工具支持交叉编译,那么也支持编译到不同的目标后端;同时,也可以根据自己的需求选择使用 CLANG 或者使用 GCC 进行编译,充分发挥不同工具的优势。 + 在本地 C/C++ 工具链的选择上,XVM 没有单独的编译工具链,而是直接采用宿主工具支持。选择宿主工具的优势在于可移植性和扩展性。在使用 XVM 的过程中,选择和平台架构适配的工具即可完成编译成该平台的动态链接库,如果本地开发工具支持交叉编译,那么也支持编译到不同的目标后端;同时,也可以根据自己的需求选择使用 CLANG 或者使用 GCC 进行编译,充分发挥不同工具的优势。 - 在 wasm2c 的选择上,XVM 自带了一份经过定制的 wabt。可以使用 XVM 自带的 wasm 工具,针对智能合约场景优化,支持 GAS 机制,也可以使用用户自定义的 wasm2c 工具,不提供 GAS 支持,作为通用的 WebAssembly 运行时. + 在 wasm2c 的选择上,XVM 自带了一份经过定制的 wabt。可以使用 XVM 自带的 wasm 工具,针对智能合约场景优化,支持 GAS 机制,也可以使用用户自定义的 wasm2c 工具,不提供 GAS 支持,作为通用的 WebAssembly 运行时。