- 区块链
【免费下载链接】eos
An open source smart contract platform
本篇指南围绕 EOS 区块链的核心数据检索操作展开:通过命令行工具cleos查询链上智能合约存储的表(table)数据。文章从cleos get table ACCOUNT SCOPE TABLE这一最简命令出发,完整覆盖参数详解、分页与多索引查询实战、kv_table 查询,并结合当前仓库源码剖析命令从 cleos 到 nodeos 链插件的完整调用链,帮助开发者在开发调试、链上数据审计和 DApp 运维中熟练获取合约表信息。
前置准备:安装 cleos 并理解三个核心概念
在执行任何查询之前,需要满足以下前提条件(对应关联文档 how-to-get-tables-information.md 中的 "Before you begin" 部分):
- 安装当前受支持的
cleos版本:cleos是 EOS 官方提供的命令行客户端,与nodeos、keosd一同构建。可参考仓库中的构建脚本 eosio_build.sh 及各平台构建脚本(如 eosio_build_ubuntu.sh)完成从源码构建。 - 理解账户(account):账户是链上资源的持有主体,也是智能合约的部署主体。每个智能合约部署在某一个账户名下,查询表数据时首先需要知道这个"合约账户"。
- 理解表(table):EOS 智能合约通过
multi_index(多索引表)持久化业务数据,表结构由合约的 ABI(Application Binary Interface)定义。表名即合约 ABI 中声明的名称。 - 理解作用域(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 为eosio的accounts表(即 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, --limit | UINT | 返回的最大行数 | 10(源码uint32_t limit = 10;) |
-k, --key | TEXT | 指定按哪个键索引查询。已废弃(Deprecated),不再使用 | — |
-L, --lower | TEXT | 键下界的 JSON 表示,默认从第一个开始 | 首个键 |
-U, --upper | TEXT | 键上界的 JSON 表示,默认到最后一个结束 | 末个键 |
--index | TEXT | 索引号:1为主键(第一个),2为第二个次级索引(按 multi_index 定义顺序),以此类推;支持数字或名称,如secondary或2 | 1(主键) |
--key-type | TEXT | --index指向索引的键类型。主键仅支持i64;次级索引支持i64、i128、i256、float64、float128、ripemd160、sha256,特殊类型name表示账户名 | — |
--encode-type | TEXT | --key-type对应值的编码方式。dec用于i64、i128、float64、float128的十进制编码;i256同时支持dec与hex;ripemd160与sha256仅支持hex | dec(源码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 = 10、encode_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_type与encode_type选择对应的索引访问路径。从 plugins/chain_plugin/chain_plugin.cpp 的read_only::get_table_rows实现可以看到完整的类型分发逻辑:主键仅支持i64/name,次级索引按i64、i128、i256、float64、float128、sha256、ripemd160分别走不同的索引模板,且i256、sha256、ripemd160、float128支持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),返回行包含code、scope、table、payer、count五个字段。
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-type(bytes/string/dec/hex)编码选择,以及-r逆序、-l限制条数。分页时需注意:当"more": true时,应将返回的"next_key"以--encode-type bytes形式作为下一次查询的-L(正序)或-U(逆序)继续取数;范围语义上-L包含边界、-U不包含边界。完整的分页、边界与编码示例可参考 get/kv_table.md 中十余个逐步推进的实例。
源码视角:一条查询命令的完整链路
理解底层链路有助于排查问题:
- cleos 组装请求:
get table子命令回调把位置参数与选项打包为get_table_rows参数(programs/cleos/main.cpp),通过 HTTP 调用 nodeos 的chainAPI。 - 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)。 - 返回结果:最终结果以
get_table_rows_result结构返回(chain_plugin.hpp),包含rows、more、next_key、next_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
相关推荐
使用 AWS CLI 的 athena get-table-metadata 查询 Athena 表元数据:命令详解与源码解析
使用 AWS CLI 的 athena get table metadata 查询 Athena 表元数据:命令详解与源码解析 aws athena get t
开发工具云原生运维eos 节点验证:cleos get schedule 命令详解与生产者调度表(Producer Schedule)查询实战
eos 节点验证:cleos get schedule 命令详解与生产者调度表(Producer Schedule)查询实战 导读 在 EOSIO 智能合约平台
区块链Wand-Enhancer 使用教程:4 步免费解锁 WeMod 专业版
Wand Enhancer 使用教程:4 步免费解锁 WeMod 专业版 WeMod 专业版按月收费,付费墙后面是去广告界面、全部可用的作弊选项和可自定义的热键
桌面应用前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考