首页 > 世链号 > 【瑞币交易所官网】x86 SimpleABI 协议与 abigen 工具
链圈茶室  

【瑞币交易所官网】x86 SimpleABI 协议与 abigen 工具

摘要:这是 Qtum x86 合约的一个轻量级的 ABI。这个 ABI 规范称为 Simple ABI。SimpleABI 只编码字段值(flat values)和简单数组(simple arrays)。它不是智能合约 ABI 的终极状态,只是实现起来非常简单,最重要的是使用起来非常顺手。
Qtum abigen
 
这是 Qtum x86 合约的一个轻量级的 ABI。这个 ABI 规范称为 Simple ABI。
 
SimpleABI 只编码字段值(flat values)和简单数组(simple arrays)。它不是智能合约 ABI 的终极状态,只是实现起来非常简单,最重要的是使用起来非常顺手。
 
abigen 可以以下 3 种方式运行:
 
1、Dispatcher -- 生成代码,用于解码 SCCS 上的 ABI 数据并调用适当的函数
 
2、Caller -- 为指定的合约生成代码,可使用 SimpleABI 轻松调用外部合约
 
3、Encoder -- 用一系列参数生成合约调用的数据。人们可以简单地用 sendtocontract 等即可调用 SimpleABI 合约
 
 
与 Solidity 的区别是什么?
 
Solidity 调用外部合约的 ABI 直接内建在语言中。Solidity 专门用于构建智能合约,因此这么设计是有一定道理的。
 
但是,x86 VM 支持多种不同的语言,这些语言不是专门为智能合约而设计的。这意味着我们必须在这些现有语言之上构建 ABI。使用复杂的语言分析库等或许可以自动构建适当的 ABI,但很难用,限制大,且不能在语言之间移植。
 
我们正在设计的这个新VM,应该是可以从你的 C 语言合约调用另一个 C 语言合约,也可以从你的 C++ 合约调用一个 Rust 合约等等。
 
这个 ABI 比 Solidity 的 ABI 简单得多,但与 Solidity 不同,它是显式调用的,即它只能调用在 ABI 文件中直接指定的函数。因此,这个 ABI 往往需要更多的模板代码来处理简单的事情,比如调用函数,甚至只是解码发送的 ABI 数据......所以,一个理想的工具是代码生成。我们可以使用模板代码来生成函数,这样开发人员实际中使用函数只要几行代码。
 
与 EVM 暴露“调用数据”的方式不一样的是,x86 VM具有“智能合约通信堆栈”(SCCS,smart contract communication stack)。我们只需要一个在合约之间传递和返回数据的栈,没必要解析一个大的扁平字节数组。
 
这大大简化了智能合约的实现,这个 ABI 就是为了利用这一点而设计的。SCCS 可以将每个参数视为栈上的一个子项,而不需要解码一大块数据。这也使得调用合约变得更容易,因为不再需要构造一大块数据。大块数据往往需要分配足够内存,将所有元素放入一个连续的内存区域;而 SCCS 可以使用许多较小的内存实现。
 
 
ABI 规范
 
ABI 规范很简单,每个函数 1 行。它还充当合约函数前后堆栈的表。即使不使用abigen,这也是一种有用的规范,可以手动实现对合约数据的编码解码的堆栈操作。
 
类似 ERC20 的接口示例:
 
ERC20Interface
# The first non-comment line is the name of the interface and used for all codegen prefixes
# this is a comment
selfBalance -> balance:uint64
address:UniversalAddress balance:fn -> balance:uint64
addressTo:UniversalAddress value:uint64 send:fn -> newFromBalance:uint64 newToBalance:uint64
address:UniversalAddress buyTokens:fn -> newBalance:uint64 -- payable
 
 
也可以使用数组:
 
ArrayExample
#declares someFunction takes an array of 20 bytes exactly
someData:uint8[20]:fixed someFunction:fn -> void
#declares someFunctionDynamic that takes an array of no more than 20 bytes
someData:uint8[20]:max someFunctionDynamic:fn -> void
 
支持的基本类型:
 
  • uint8
  • uint16
  • uint32
  • uint64
  • int8
  • int16
  • int32
  • int64
  • char
  • void -- 仅对返回数据有效。对应无返回数据
  • fn -- 特殊
 
更高级的类型:
 
  • UniversalAddress
 
基本类型尽可能传值使用。高级类型传引用。数组传引用,并指向值,值包括高级类型。
 
数组类型:
 
  • fixed(默认) - 数据必须是指定的确切大小
  • max(指定最大) -数据不能大于指定的大小。如果它较大,则会触发错误
  • dynamic(动态) - 任何长度都有效(使用前 uint8[])有效
  • clip(截断) - 如果数据大于指定的大小,那么它会被截断,不会触发任何错误
 
 
函数编号
 
函数编号的构造方式与 Solidity 类似。 sha256 哈希由函数行和接口名称组成,哈希值截断到后面 4 个字节作为函数号。
 
内存分配
 
大于 256 字节的数组都使用堆分配而不是栈。
 
接口
 
一个合约可以实现多个接口。每个接口使用该接口名称前缀来生成代码。对于具有相同名称的多个函数,只要它们由不同名称的接口定义,就可以同时存在于一个合约内。
 
包括其他接口:
 
MyContract
:interfaces ERC20, ERC721, MyParentContract
 
abigen 自动查找当前目录中的 ABI 文件名,并实现指定全局接口目录的方法。
 
 
语言
 
现在只支持 C. 之后会支持 Rust。
 
示例(手动生成) C代码:
 
struct simpletoken_Send_Params{
   UniversalAddressABI* address;
   uint64_t value;
};
 
struct simpletoken_Send_Returns{
   uint64_t recvvalue;
   uint64_t sendervalue;
};
 
void decodeABI(){
   //format: address:address value:uint64 SEND -> sendervalue:uint64 recvvalue:uint64
   //format: address:address BALANCE -> balance:uint6
   //format: SELFBALANCE -> balance:uint64
   uint32_t function = 0;
   if(qtumStackItemCount() == 0){
       //fallback function... 
   }
   QTUM_POP_VAL(function);
   switch(function){
       case CONTRACT_SELFBALANCE:
       {
           uint64_t resBalance;
           selfBalance(&resBalance);
           QTUM_PUSH_VAL(resBalance);
           return;
       }
       case CONTRACT_BALANCE:
       {
           UniversalAddressABI address;
           QTUM_POP_VAL(address);
 
           uint64_t resBalance;
           balance(&address, &resBalance);
           QTUM_PUSH_VAL(resBalance);
           return;
       }
       case CONTRACT_SEND:
       {
           struct simpletoken_Send_Params params;
           UniversalAddressABI __tmp1;
           params.address = &__tmp1;
 
 
           QTUM_POP_VAL(params.value);
           QTUM_POP_VAL(__tmp1);
           struct simpletoken_Send_Returns returns;
 
           send(&params, &returns);
           QTUM_PUSH_VAL(returns.sendervalue);
           QTUM_PUSH_VAL(returns.recvvalue);
           return;
       }
       default:
           qtumError("Invalid function");
           return;
   }
}
 
//format for this:
//address:address value:uint64 SEND -> sendervalue:uint64 recvvalue:uint64
struct QtumCallResultABI simpletoken_Send(const UniversalAddressABI* __contract, uint64_t __gasLimit,
   const struct simpletoken_Send_Params* params,
   struct simpletoken_Send_Returns* returns
   )
{
   if(__gasLimit == 0){
       __gasLimit = QTUM_CALL_GASLIMIT;
   }
   qtumStackClear();
   QTUM_PUSH_VAL(*params->address);
   QTUM_PUSH_VAL(params->value);
   uint32_t f = CONTRACT_SEND;
   QTUM_PUSH_VAL(f);
   struct QtumCallResultABI result;
   qtumCallContract(__contract, __gasLimit, 0, &result);
   if(result.errorCode != 0){
       return result;
   }
   QTUM_POP_VAL(returns->recvvalue);
   QTUM_POP_VAL(returns->sendervalue);
   return result;
}
 
 
其他
 
对于不支持内置数组大小的语言,不定长数组数组也会有个 "length" 参数暴露给 Caller 和 Dispatcher。

来源 量子链平台Qtum
免责声明
世链财经作为开放的信息发布平台,所有资讯仅代表作者个人观点,与世链财经无关。如文章、图片、音频或视频出现侵权、违规及其他不当言论,请提供相关材料,发送到:2785592653@qq.com。
风险提示:本站所提供的资讯不代表任何投资暗示。投资有风险,入市须谨慎。
世链粉丝群:提供最新热点新闻,空投糖果、红包等福利,微信:juu3644。