使用 cleos get table 查询 EOS 智能合约表数据:从入门到源码级解析
2026/9/23 14:27:03 网站建设 项目流程
  • 区块链

【免费下载链接】eos

An open source smart contract platform

项目地址:https://gitcode.com/gh_mirrors/eo/eos
点击查看免费下载

本篇指南围绕 EOS 区块链的核心数据检索操作展开:通过命令行工具cleos查询链上智能合约存储的表(table)数据。文章从cleos get table ACCOUNT SCOPE TABLE这一最简命令出发,完整覆盖参数详解、分页与多索引查询实战、kv_table 查询,并结合当前仓库源码剖析命令从 cleos 到 nodeos 链插件的完整调用链,帮助开发者在开发调试、链上数据审计和 DApp 运维中熟练获取合约表信息。

前置准备:安装 cleos 并理解三个核心概念

在执行任何查询之前,需要满足以下前提条件(对应关联文档 how-to-get-tables-information.md 中的 "Before you begin" 部分):

  1. 安装当前受支持的cleos版本cleos是 EOS 官方提供的命令行客户端,与nodeoskeosd一同构建。可参考仓库中的构建脚本 eosio_build.sh 及各平台构建脚本(如 eosio_build_ubuntu.sh)完成从源码构建。
  2. 理解账户(account):账户是链上资源的持有主体,也是智能合约的部署主体。每个智能合约部署在某一个账户名下,查询表数据时首先需要知道这个"合约账户"。
  3. 理解表(table):EOS 智能合约通过multi_index(多索引表)持久化业务数据,表结构由合约的 ABI(Application Binary Interface)定义。表名即合约 ABI 中声明的名称。
  4. 理解作用域(scope):同一张表可以按不同的scope划分数据空间。例如eosio.token合约的accounts表以每个用户账户作为 scope,从而隔离不同用户的余额数据。

基础用法:一条命令查询表数据

关联文档给出的核心命令原型极为简洁:

cleos get table ACCOUNT SCOPE TABLE

其中三个位置参数的含义如下:

位置参数说明
ACCOUNT拥有该表的合约账户,即部署了智能合约的账户名
SCOPE表数据所在的作用域,通常是一个账户名或合约定义的作用域值
TABLE表名,与合约 ABI 中声明的表名一致

这三个参数在 cleos 源码中均被标记为必填,见 programs/cleos/main.cpp:

auto getTable = get->add_subcommand( "table", localized("Retrieve the contents of a database table")); getTable->add_option( "account", code, localized("The account who owns the table") )->required(); getTable->add_option( "scope", scope, localized("The scope within the contract in which the table is found") )->required(); getTable->add_option( "table", table, localized("The name of the table as specified by the contract abi") )->required();

第一个实战示例:查询 eosio.token 的 accounts 表

查询eosio.token合约中、scope 为eosioaccounts表(即 eosio 账户的 Token 余额),对应官方命令参考 get/table.md:

cleos get table eosio.token eosio accounts

返回结果为 JSON:

{ "rows": [{ "balance": "999999920.0000 SYS" } ], "more": false }

返回结构解析:

  • rows:查询到的行数据数组。默认json=true时,每一行由 ABI 解释为 JSON 对象;-b模式下则为二进制十六进制字符串。
  • more:布尔值,true表示数据尚未取完,需要继续分页;false表示已取完。

完整参数详解:从默认值到高级选项

基础命令之外,cleos get table还支持一整套查询控制选项。这些选项在 cleos 源码中全部有明确声明(programs/cleos/main.cpp),并在命令参考文档 get/table.md 中有完整说明,汇总如下:

选项类型说明默认值
-l, --limitUINT返回的最大行数10(源码uint32_t limit = 10;
-k, --keyTEXT指定按哪个键索引查询。已废弃(Deprecated),不再使用
-L, --lowerTEXT键下界的 JSON 表示,默认从第一个开始首个键
-U, --upperTEXT键上界的 JSON 表示,默认到最后一个结束末个键
--indexTEXT索引号:1为主键(第一个),2为第二个次级索引(按 multi_index 定义顺序),以此类推;支持数字或名称,如secondary21(主键)
--key-typeTEXT--index指向索引的键类型。主键仅支持i64;次级索引支持i64i128i256float64float128ripemd160sha256,特殊类型name表示账户名
--encode-typeTEXT--key-type对应值的编码方式。dec用于i64i128float64float128的十进制编码;i256同时支持dechexripemd160sha256仅支持hexdec(源码string encode_type{"dec"};
-b, --binary标志直接返回二进制值,不再用 ABI 解释为 JSON关闭
-r, --reverse标志逆序遍历关闭
--show-payer标志显示每行数据的 RAM 付费方(RAM payer)关闭

这些选项在底层被逐字映射为 chain 插件的 RPC 请求参数。cleos 侧的回调代码(programs/cleos/main.cpp)将所有选项打包进get_table_rows请求:

getTable->callback([&] { auto result = call(get_table_func, fc::mutable_variant_object("json", !binary) ("code",code) ("scope",scope) ("table",table) ("table_key",table_key) // not used ("lower_bound",lower) ("upper_bound",upper) ("limit",limit) ("key_type",key_type) ("index_position", index_position) ("encode_type", encode_type) ("reverse", reverse) ("show_payer", show_payer) ); std::cout << fc::json::to_pretty_string(result) << std::endl; });

对应的服务端参数结构体定义在 plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp,其中同样给出默认值:limit = 10encode_type{"dec"},并注释了index_position的语义为"1 主键、2 次级索引、3 第三个索引……"。

进阶实战:分页、次级索引与逆序查询

分页拉取全部数据

当表行数超过--limit(默认 10)时,返回结果中more字段变为true。此时把上一页返回的最后一个键作为下一页的--lower下界继续查询。例如将--limit调大并配合--lower即可逐步取回全部行:

# 第一页:取前 10 行 cleos get table eosio.token eosio accounts -l 10 # 第二页:以上一页末尾键作为下界继续取 cleos get table eosio.token eosio accounts -l 10 -L "上一页末尾键"

按次级索引查询

当表定义了次级索引时,通过--index指定索引位置、--key-type声明键类型,并用-L/-U划定范围。例如查询某个以i128为次级索引的表:

cleos get table mycontract myuser mytable --index 2 --key-type i128 -L "100000000000000000000000000000000" -U "200000000000000000000000000000000"

服务端会根据key_typeencode_type选择对应的索引访问路径。从 plugins/chain_plugin/chain_plugin.cpp 的read_only::get_table_rows实现可以看到完整的类型分发逻辑:主键仅支持i64/name,次级索引按i64i128i256float64float128sha256ripemd160分别走不同的索引模板,且i256sha256ripemd160float128支持hex编码。若类型不匹配,会抛出contract_table_query_exception(错误码 3060003),提示"Invalid table type"或"key type required for non-primary index"。

逆序与显示 RAM 付费方

# 逆序查询,并显示每行数据的 RAM 付费方 cleos get table eosio.token eosio accounts -r --show-payer

--show-payer对排查"谁为这些数据支付了 RAM"非常实用,是链上资源审计的常用手段。

扩展能力:get scope 与 get kv_table

除了get table,cleos 的 get 命令组还提供了两个密切相关的能力(命令参考分别见 get/scope.md 与 get/kv_table.md):

get scope:查看合约拥有哪些作用域

cleos get scope CONTRACT返回一个合约下所有 scope 与表的清单,非常适合在不确定 scope 名称时先做侦查:

cleos get scope eosio.token

支持-t/--table按表名过滤、-L/-U限定 scope 范围、-l限制行数、-r逆序。服务端对应read_only::get_table_by_scope(参数结构体见 chain_plugin.hpp),返回行包含codescopetablepayercount五个字段。

get kv_table:查询 KV 表

针对新一代 KV 存储接口(kv表,见 contracts/enable-kv 启用说明),cleos 提供get kv_table子命令,位置参数为ACCOUNT TABLE INDEX_NAME(programs/cleos/main.cpp):

cleos get kv_table --encode-type name -i boba contr_acct kvtable primarykey -b

它支持-i/--index点查、-L/-U范围查询、--encode-typebytes/string/dec/hex)编码选择,以及-r逆序、-l限制条数。分页时需注意:当"more": true时,应将返回的"next_key"--encode-type bytes形式作为下一次查询的-L(正序)或-U(逆序)继续取数;范围语义上-L包含边界、-U不包含边界。完整的分页、边界与编码示例可参考 get/kv_table.md 中十余个逐步推进的实例。

源码视角:一条查询命令的完整链路

理解底层链路有助于排查问题:

  1. cleos 组装请求get table子命令回调把位置参数与选项打包为get_table_rows参数(programs/cleos/main.cpp),通过 HTTP 调用 nodeos 的chainAPI。
  2. chain_plugin 接收并执行:nodeos 侧read_only::get_table_rows首先通过get_abi读取合约 ABI(chain_plugin.cpp),再调用get_table_index_name判断是主键还是次级索引,随后按key_type分发到get_table_rows_ex(主键)或get_table_rows_by_seckey(次级索引,模板实现见 chain_plugin.hpp)。
  3. 返回结果:最终结果以get_table_rows_result结构返回(chain_plugin.hpp),包含rowsmorenext_keynext_key_bytes字段,其中next_key/next_key_bytes正是分页续取所需的游标。

值得注意的是,服务端结构体注释明确next_key的用法是"fill lower_bound with this value to fetch more rows"(将下界填充为该值以继续取数),这与上文分页示例完全对应。

常见错误与排查建议

错误信息含义与处理
Error 3060003: Contract Table Query Exception表查询异常。常见原因是表名/scope 拼写错误,或--key-type--encode-type与索引实际类型不匹配。应先用cleos get scope CONTRACT确认表与 scope 存在,再核对索引类型。
Invalid table type主键查询时 ABI 中的表类型不是i64/name可支持的类型,需检查合约 ABI。
key type required for non-primary index指定了非主键索引(--index非 1)却未提供--key-type,补齐即可。
Unsupported secondary index type--key-type传入的类型不在i64/i128/i256/float64/float128/ripemd160/sha256/name之列。

此外,查询结果为空时,rows数组为空但命令正常退出,这通常意味着 scope 或表名下确实没有数据,而非命令错误。

小结

cleos get table ACCOUNT SCOPE TABLE是 EOS 开发与运维中使用频率最高的数据检索命令之一。掌握其三个位置参数与--limit--lower/--upper--index/--key-type-b-r--show-payer等选项,再配合get scope侦查作用域、get kv_table查询 KV 表,即可覆盖绝大多数链上表数据检索场景。如需继续深入,可进一步阅读 cleos 命令参考索引、get table 完整参考,以及 eosio.token 合约测试 了解表数据在合约侧的写入与组织方式。

  • 区块链

【免费下载链接】eos

An open source smart contract platform

项目地址:https://gitcode.com/gh_mirrors/eo/eos
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询