写点什么

eosio.system 智能合约介绍(四)合约部署介绍

作者:BSN研习社
  • 2023-09-14
    北京
  • 本文字数:4083 字

    阅读完需:约 13 分钟

eosio.system智能合约介绍(四)合约部署介绍

01

目的

本文档结合系统合约,介绍了合约部署的核心概念和步骤,包括合约部署过程以及 setcode 和 setabi 方法,帮助初学者和开发者快速了解和掌握 EOS 系统合约部署的相关知识。


02

概述

“eosio.system”智能合约是 eos 的系统命令合约。这个合约几乎实现了 eos 全部的系统命令,包括创建账户、资源质押、超级节点投票、域名竞拍等功能,它定义了区块链核心功能所需的结构和操作。

下文将介绍合约部署的相关知识。


03

环境准备

(一)一条正在运行且可访问的区块链

中移链(基于EOS)测试环境搭建

(二)确保本地钱包已打开并解锁

如何创建钱包:

https://developers.eos.io/manuals/eos/latest/cleos/how-to-guides/how-to-create-a-wallet


04

合约部署介绍

(一)合约部署过程

假设您要将合约部署到的帐户名称是 addressbook,请执行以下命令:

cleos set contract addressbook you_local_path_to/addressbook/ -p addressbook@active
复制代码

命令详解:

set contract:cleos 工具的子命令,用于部署合约
addressbook:要部署合约的账户名称,即目标账户。请将 addressbook 替换为您自己的账户名称
you_local_path_to/addressbook/:合约的本地路径,指定了合约的位置。请将 /your_local_path_to/替换为您本地的实际路径,最好是绝对路径
-p addressbook@active:指定操作的权限。在这种情况下,-p参数后面的addressbook表示使用 addressbook 账户的active权限进行操作。请确保addressbook账户具有足够的权限来部署合约
复制代码

通过运行这个命令,合约将被部署到 addressbook 账户。

得到如下结果:

Reading WASM from /home/xxx/biosboot/genesis/test/addressbook/addressbook.wasm...Publishing contract...executed transaction: ea09081dc5e42bd1f2b5abe619a7388e1e52ec16a91adb221f3ecb11fa566dde  17840 bytes  16689 us#         eosio <= eosio::setcode               {"account":"addressbook","vmtype":0,"vmversion":0,"code":"0061736d01000000019a022a60000060037f7f7f01...#         eosio <= eosio::setabi                {"account":"addressbook","abi":"0e656f73696f3a3a6162692f312e32000305657261736500010475736572046e616d...
复制代码

部署 EOSIO 合约时,需经历以下步骤:

  • 读取 WAST/WASM 文件:读取存放在 build 目录下的 WAST/WASM 文件,这些文件是要部署的合约的编译结果;

  • 装配 WASM:对于读取的 WAST/WASM 文件,进行装配,将合约的二进制代码准备好供后续操作使用。

  • 将合约发布到区块链上

  • 执行交易(合约也是一个交易),需要执行两个关键动作:

  • setcode:该动作用于在区块链上部署或更新账户的合约代码。

  • setabi:该动作用于为通过 account 名称标识的合约设置 ABI(ApplicationBinaryInterface)。尽管在技术上 ABI 是可选的,但所有 EOSIO 工具都依赖于它以提供更便捷的合约交互体验。

执行完以上操作后,合约已成功部署到 EOS 区块链中的 addressbook 账户上。

从结果可以看出,调用

cleossetcontractaddressbookyou_local_path_to/addressbook/-paddressbook

等价于调用:

cleos push action addressbook setcode '[addressbook.wasm]' -p addressbookcleos push action addressbook setabi '[addressbook.abi]' -p addressbook
复制代码

(二)setcode 方法介绍

setcode 操作是 EOSIO 中的一种操作,用于在区块链上部署或更新账户的合约代码。它用于部署或更新与账户关联的智能合约。在使用 setcode 操作部署或更新合约时,会检查合约是否已经在运行代码。

具体而言,当执行 setcode 操作时,EOSIO 会获取合约的 wasm 文件,并对其进行处理。在处理过程中,会计算 wasm 文件的哈希值,以表示该合约的唯一标识。这个哈希值可以用于比对合约的版本和完整性,以确保在部署或更新合约时没有出现错误或篡改。

1、setcode 源码介绍

/*** Set code action sets the contract code for an account.** @param account - the account for which to set the contract code.* @param vmtype - reserved, set it to zero.* @param vmversion - reserved, set it to zero.* @param code - the code content to be set, in the form of a blob binary..*/[[eosio::action]]void setcode( name account, uint8_t vmtype, uint8_t vmversion, const std::vector<char>& code ) {}
复制代码

参数详解:

account:要部署或更新代码的账户名称

vmtype:此参数保留,应设置为零

vmversion:此参数保留,应设置为零

code:合约代码的二进制表示

2、setcode 操作的实现

读取合约的 WAST 或 WASM 文件:

合约的开发人员提供合约代码的文件,这可以是 WAST(WebAssemblyText)或 WASM(WebAssemblyBinary)格式。

装配合约代码:

读取的合约文件需要进行装配,即将其转换为内部可执行的格式,以便区块链节点能够理解和执行。

存储合约代码:

装配后的合约代码将被存储在区块链上,并与指定的账号关联起来。这样,当其他用户或合约需要调用该合约时,可以通过发送交易指向该账号,并执行相应的合约操作。

通过 setcode 操作,合约的代码被安全地存储在区块链上,并与账号关联。这样,所有参与者都可以通过调用合约的操作来执行合约的功能,而节点可以验证合约的代码哈希值,确保合约的代码没有被篡改,从而保障合约在执行过程中的安全性和可靠性。

(三)setabi 方法介绍

setabi 操作用于为通过 account 名称标识的合约设置 ABI(ApplicationBinaryInterface)。它在 abi_hash_table 索引中创建一个条目,使用 account 名称作为键,如果尚不存在,并将其值设置为 ABI 的哈希值。如果已存在,则更新现有 account 键的当前 ABI 哈希值。

1、setabi 源码介绍

源码:

  /**          * Set abi action sets the abi for contract identified by `account` name. Creates an entry in the abi_hash_table          * index, with `account` name as key, if it is not already present and sets its value with the abi hash.          * Otherwise it is updating the current abi hash value for the existing `account` key.          *          * @param account - the name of the account to set the abi for          * @param abi     - the abi hash represented as a vector of characters          */         [[eosio::action]]         void setabi( name account, const std::vector<char>& abi ){           abi_hash_table table(get_self(), get_self().value);           auto itr = table.find( account.value );           if( itr == table.end() ) {              table.emplace( account, [&]( auto& row ) {                 row.owner = account;                 row.hash  = eosio::sha256(const_cast<char*>(abi.data()), abi.size());              });           } else {              table.modify( itr, eosio::same_payer, [&]( auto& row ) {                 row.hash = eosio::sha256(const_cast<char*>(abi.data()), abi.size());              });           }        }
复制代码

参数详解:

account:要部署 ABI 的目标账户的名称。它是一个 name 类型的参数,表示 EOSIO 中的账户名

abi:要设置的合约的 ABI 数据,以 std::vector<char>类型的参数传入

源码详解:

  • 通过 abi_hash_table 类创建一个名为 table 的表对象。该表用于存储账户的 abi 哈希值。

  • 使用 table.find()函数查找表中是否已经存在与目标账户相关的记录。

  • 如果在表中没有找到与目标账户相关的记录(即 itr==table.end()),则执行 table.emplace()操作。

  • 在 table.emplace()中,通过 lambda 表达式将新的记录插入到表中。lambda 表达式接收一个 row 参数,用于访问新插入的记录。在 lambda 表达式中,将 row.owner 设置为目标账户的名称,将 row.hash 设置为传入的 ABI 数据的 SHA256 哈希值。

  • 如果在表中找到了与目标账户相关的记录(即 itr!=table.end()),则执行 table.modify()操作。

  • 在 table.modify()中,通过 lambda 表达式修改找到的记录。这里使用 eosio::same_payer 权限,确保修改操作的付款账户与原始记录的付款账户相同。在 lambda 表达式中,将 row.hash 更新为传入的 ABI 数据的 SHA256 哈希值。

ABI 的实际存储方式在 EOSIO 中与常见的 JSON 文件存储方式存在较大的差异。相反,ABI 被以一种被称为"原始 ABI"的打包方式进行存储。

传统的开发环境中通常将 ABI 表示为 JSON 格式的文件,其中包含了合约的接口和数据结构定义。然而,在 EOSIO 中为了减少存储空间和提高效率,ABI 被以一种更紧凑的格式进行存储。

“原始 ABI”是指将 ABI 数据按照一定的规则进行打包和编码,以减少其存储空间。这种打包方式不同于常见的 JSON 文件格式,它更加紧凑,节省了存储空间,并提高了读取和解析的效率。原始 ABI 存储方式在 EOSIO 中被使用,以满足区块链中存储资源的限制和性能需求。

每个 ABI 都需要包含一组特定的字段,这些字段用于描述合约的不同方面,如版本信息、类型定义、结构定义、操作定义、表格定义等。这些字段的内容将被序列化为一种更节省空间的表示形式。

在 EOSIO 中,ABI 用于定义合约的接口和数据结构。为了方便存储和传输,ABI 需要被序列化为一种紧凑的二进制格式,以节省存储空间和网络带宽。

具体而言,一个典型的 ABI 包含以下字段:

version:ABI 的版本信息,用于标识 ABI 的兼容性和支持的特性

types:类型定义,用于描述合约中使用的自定义类型,如结构体、枚举等

structs:结构定义,描述合约中的数据结构,包括结构体的名称、字段和类型等

actions:操作定义,描述合约中可执行的操作,包括操作的名称、参数和返回类型等

tables:表格定义,描述合约中的数据表格,包括表格的名称、字段和索引等

当执行 setabi 操作时,合约的 ABI 数据可以以两种形式之一进行提供:二进制文件或 JSON 文件。二进制文件是指以二进制格式存储的 ABI 数据文件,而 JSON 文件则是指以 JSON 格式存储的文本文件。

setabi 操作需要能够处理这两种形式的 ABI 数据,并进行相应的转换。具体而言,它可以将二进制文件转换为 JSON 格式的 ABI 数据,或将 JSON 格式的 ABI 数据转换为二进制格式,即序列化和反序列化的过程。这样,合约开发人员可以选择以更适合他们的方式提供 ABI 数据,并将其转换为适合在区块链上存储和使用的形式。


END

用户头像

BSN研习社

关注

还未添加个人签名 2021-11-05 加入

还未添加个人简介

评论

发布
暂无评论
eosio.system智能合约介绍(四)合约部署介绍_BSN研习社_InfoQ写作社区