From 7df3be14d6d7e7eb665571babb6ba86ec28e6a39 Mon Sep 17 00:00:00 2001 From: imuge Date: Mon, 2 Aug 2021 17:24:59 +0800 Subject: [PATCH] update docs --- README.md | 141 +- .../src/main/resources/docs/api_doc_cn_1.3.MD | 1716 ---------- .../main/resources/docs/api_doc_cn_1.3.html | 2665 --------------- .../src/main/resources/docs/api_doc_cn_1.4.MD | 2619 --------------- .../src/main/resources/docs/code_example.MD | 361 -- .../docs/design_contract-dev-manual.md | 436 --- docs/api.md | 2924 +++++++++++++++++ docs/block.md | 80 + docs/cli/keys.md | 120 + docs/cli/participant.md | 219 ++ docs/cli/query.md | 914 ++++++ docs/cli/tx.md | 531 +++ docs/contract.md | 549 ++++ docs/data_account.md | 63 + docs/event.md | 185 ++ docs/gateway.md | 53 + docs/images/deployment.jpg | Bin 131011 -> 0 bytes docs/images/deployment.png | Bin 298018 -> 0 bytes docs/indexer.md | 15 + docs/jdchain_cli.md | 30 + docs/kvdb.md | 365 ++ docs/log.md | 19 + docs/participant.md | 253 ++ docs/project.md | 56 + docs/quick_start.md | 52 + docs/samples.md | 45 + docs/scripts/testnet.sh | 278 ++ docs/sdk.md | 295 ++ docs/structure.md | 200 ++ docs/transaction.md | 478 +++ docs/user.md | 129 + 31 files changed, 7893 insertions(+), 7898 deletions(-) delete mode 100644 deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.MD delete mode 100644 deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.html delete mode 100644 deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD delete mode 100644 deploy/deploy-gateway/src/main/resources/docs/code_example.MD delete mode 100644 deploy/deploy-gateway/src/main/resources/docs/design_contract-dev-manual.md create mode 100644 docs/api.md create mode 100644 docs/block.md create mode 100644 docs/cli/keys.md create mode 100644 docs/cli/participant.md create mode 100644 docs/cli/query.md create mode 100644 docs/cli/tx.md create mode 100644 docs/contract.md create mode 100644 docs/data_account.md create mode 100644 docs/event.md create mode 100644 docs/gateway.md delete mode 100644 docs/images/deployment.jpg delete mode 100644 docs/images/deployment.png create mode 100644 docs/indexer.md create mode 100644 docs/jdchain_cli.md create mode 100644 docs/kvdb.md create mode 100644 docs/log.md create mode 100644 docs/participant.md create mode 100644 docs/project.md create mode 100644 docs/quick_start.md create mode 100644 docs/samples.md create mode 100644 docs/scripts/testnet.sh create mode 100644 docs/sdk.md create mode 100644 docs/structure.md create mode 100644 docs/transaction.md create mode 100644 docs/user.md diff --git a/README.md b/README.md index e3d7ced6..9abdf8f5 100644 --- a/README.md +++ b/README.md @@ -1,128 +1,67 @@ -[TOC] -#JD区块链 +![logo](http://storage.jd.com/jd.block.chain/jdt-jdchain.png) +
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.jd.blockchain/sdk-pack/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.jd.blockchain/sdk-pack/) [![Build Status](https://travis-ci.com/blockchain-jd-com/jdchain.svg?branch=master)](https://travis-ci.org/blockchain-jd-com/jdchain) +
+一个面向企业应用场景的通用区块链框架系统,能够作为企业级基础设施,为业务创新提供高效、灵活和安全的解决方案。 +## 源码构建 ------------------------------------------------------------------------- +`JD Chain`源码通过`git`及`git submodule`进行管理,如下操作可快速构建: -## 一、项目介绍 -JD Chain 的目标是实现一个面向企业应用场景的通用区块链框架系统,能够作为企业级基础设施,为业务创新提供高效、灵活和安全的解决方案。 - - -## 二、部署模型 - -JD Chain 主要部署组件包括以下几种: - -- 共识节点 - - 共识节点即参与共识的节点,这是系统的核心组件,承担了运行共识协议、管理账本数据、运行智能合约的职责。 - - 一个区块链网络由多个共识节点组成,共识节点的数量范围由选择的共识协议决定。 - - 共识节点和账本是两个不同的概念,共识节点是个物理上的概念,账本是个逻辑上的概念。JD Chain 是一个多账本区块链系统,一个共识节点上可以装载运行多个账本。账本是数据维度的独立管理单元。共识节点和账本的关系,就像关系数据库系统中,数据库服务器和数据库实例的关系。 - - 共识节点通常都部署在参与方的内部网络中,通过由网络管理员指定的安全的网络出口与其它的共识节点建立通讯连接。 - - 共识节点在形态上是服务器中的一个处理进程,背后需要连接一个本地或者内网的NoSQL数据库系统作为账本的存储。当前版本,共识节点目前是单进程的,未来版本将实现多进程以及多服务器集群模式。 - -- 网关节点 - - 网关节点是负责终端接入的节点,负责终端连接、协议转换、交易准入、本地密码运算、密钥管理等职责。 - - 网关节点是一种轻量节点,需要绑定一个特定参与方的密钥对,连接到一个或多个共识节点。 - - 网关节点向共识节点的连接是需要通过认证的,绑定的参与方的密钥对必须事先已经注册到区块链账本中,且得到接入授权。 - -- 终端 - - 终端泛指可以提交交易的客户端,典型来说,包括人、自动化设备、链外的信息系统等。 - - 终端只能通过网关节点来提交交易。终端提交的交易需要用体现该终端身份的私钥来签署,产生一份电子签名。随后当交易提交给网关节点时,网关节点需要在把交易提交到共识节点之前,对交易请求以网关节点绑定的私钥追加一项“节点签名”。 - - -- 备份节点 - - 仅对账本数据提供备份,但不参与交易共识的节点。(注:目前版本中尚未实现,将在后续版本中提供) - - -![](docs/images/deployment.jpg) +```bash +$ git clone https://github.com/blockchain-jd-com/jdchain.git jdchain +$ cd jdchain -## 三、构建源代码 +# 此处仅以 master 分支为例,正常情况下 master 分支可无障碍构建成功 +# 不推荐使用 develop 分支,submodule 代码可能未对齐 +# 推荐切换到具体已发布的版本分支 +$ git checkout master -1. 安装 Maven 环境 +$ chmod +x build/*.sh - JD Chain 当前版本以 Java 语言开发,需要安装配置 JVM 和 Maven,JDK 版本不低于1.8 。(没有特殊要求,请按标准方法安装,此处不赘述) - -2. 安装 Git 工具 - - 为了能够执行 git clone 命令获取代码仓库。 (没有特殊要求,请按标准方法安装,此处不赘述) - -3. 项目库说明 +# 执行完整的构建,包括执行”集成测试“和”打包“两部分;提供两个参数: +# --skipTests :跳过集成测试部分; +# --update :从远程仓库更新子模块。注意,采用此参数会导致子模块本地仓库丢失尚未 commit 的代码。 +# 不附带此参数的情况下不会更新子模块仓库。 +$ build/build.sh --update -JD Chain 源代码包括 3 个代码仓库 +# 跳过子模块代码更新和集成测试,直接编译和打包; +$ build/build.sh --skipTests -- jdchain 项目库: - - URL:git@github.com:blockchain-jd-com/jdchain.git - - 说明:主项目库,包含说明文档、示例代码,用于集成构建和打包; - - #### `主项目库包含以下 6 个子模块仓库,通过执行脚本 <主项目库根目录>/build/build.sh 便可以一键完成子模块的下载和整体的编译、测试和打包操作.` +# 首次代码拉取,跳过继承测试编译打包可执行: +build/build.sh --update --skipTests +``` -- project 项目库: - - URL:git@github.com:blockchain-jd-com/jdchain-project.git - - 说明:公共的父项目,定义公共的依赖; -- framework 项目库: - - URL:git@github.com:blockchain-jd-com/jdchain-framework.git - - 说明:框架源码库,定义公共数据类型、框架、模块组件接口、SDK、SPI、工具; -- core 项目库: - - URL:git@github.com:blockchain-jd-com/jdchain-core.git - - 说明:模块组件实现的源码库; -- explorer 项目库: - - URL:git@github.com:blockchain-jd-com/explorer.git - - 说明:相关产品的前端模块的源码库; -- libs/bft-smart 项目库: - - URL:git@github.com:blockchain-jd-com/bftsmart.git - - 说明:BFT-SMaRT 共识算法的源码库; -- test 项目库: - - URL:git@github.com:blockchain-jd-com/jdchain-test.git - - 说明:集成测试用例的源码库; +构建完成后会在`deploy`模块,`deploy-gateway`和`deploy-peer`目录`target`中生成网关安装部署包(`jdchain-gateway-*.zip`)和共识节点安装部署包(`jdchain-peer-*.zip`)。 -4. 构建操作 +## 部署使用 +### 快速部署 -```sh -$ git clone git@github.com:blockchain-jd-com/jdchain.git jdchain +使用[源码构建](#源码构建)生成的部署安装包,或者下载[官方部署安装包](http://ledger.jd.com/downloadapps.html) 参照[快速部署文档](docs/quick_start.md)可快速部署运行`JD Chain`网络。 -$ cd jdchain +### 数据上链 -$ git checkout develop +1. 命令行工具 -$ chmod +x build/*.sh +`JD Chain` 命令行工具集,即[jdchain-cli](docs/jdchain_cli.md),提供密钥管理,实时交易,链上信息查询,离线交易,共识节点变更等操作。可快速执行数据上链和链上数据查询。 -# 执行完整的构建,包括执行”集成测试“和”打包“两部分;提供两个参数: -# --skipTests :跳过集成测试部分; -# --update :从远程仓库更新子模块。注意,采用此参数会导致子模块本地仓库丢失尚未 commit 的代码。 -# 不附带此参数的情况下不会更新子模块仓库。 -$ build/build.sh --update - -# 跳过集成测试,直接编译和打包; -$ build/build.sh --skipTests +2. SDK -# 只执行集成测试; -$ build/test.sh - -``` +`JD Chain`提供了`Java`和`Go`版本的`SDK`。实际项目开发中`Java`可参照[示例代码](https://github.com/blockchain-jd-com/jdchain/tree/master/samples),`Go`语言`SDK`参照[framework-go](https://github.com/blockchain-jd-com/framework-go)。 -5. jdchain 的安装包 +### 更多 -当编译完成后,安装包位于主项目库的 deploy 目录中: +`JD Chain`功能开发,使用问题等欢迎`issue`中探讨,也欢迎广大开发者积极参与`JD Chain`社区活动及代码开发~ -- 共识节点的安装包: - - <主项目库根目录>/deploy/deploy-peer/target/jdchain-peer-**.zip -- 网关节点的安装包: - - <主项目库根目录>/deploy/deploy-gateway/target/jdchain-gateway-**.zip \ No newline at end of file +- `JD Chain`官方网站:https://ledger.jd.com/ +- 文档:[wiki](https://github.com/blockchain-jd-com/jdchain/wiki),[docs](docs/) +- 京东智臻链官网:https://blockchain.jd.com/ +- 服务邮箱:jdchain-support@jd.com +- `FAQ`:https://github.com/blockchain-jd-com/jdchain/wiki/FAQ \ No newline at end of file diff --git a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.MD b/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.MD deleted file mode 100644 index 6ef57c60..00000000 --- a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.MD +++ /dev/null @@ -1,1716 +0,0 @@ -# 京东区块链浏览器API文档参考 V_1.3 - -## 1 API调用说明 - -该文档内的所有api的调用成功和失败均按照以下规则 - -### 1.1 成功 - -```json -{ - "data": ..., - "success": true -} -``` - -说明 - - - success 值为 true 表明api调用成功 - - data 为返回的数据,具体数据类型参考具体的api说明 - -### 1.2 失败 - -```json -{ - "error": { - "errorCode": 5000, - "errorMessage": "未预期的异常! --Unsupported access ledger[6Gw3cK4uazegy4HjoaM81ck9NgYLNoKyBMb7a1TK1jt3d] !" - }, - "success": false -} -``` - -说明 - - - success 值为 false 表明api调用成功 - - errorCode 为异常代码 - - errorMessage 为错误提示 - -## 2 账本 - -### 2.1 获取账本总数 - -```http -GET /ledgers/count -``` - -#### 参数 -无 - - -#### 请求实例 -```http -http://localhost/ledgers/count -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本总数| - - -### 2.2 获取账本列表 - -```http -GET /ledgers?fromIndex={start_index}&count={count} -``` - -#### 参数 -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|query|start_index|否|查询账本的起始序号,默认为0|数字 -|query|count|否|查询返回账本的数量限制,默认最大限制为100,小于0或大于100均返回最大可返回结果集|数字 - - -#### 请求实例 -```http -http://localhost/ledgers?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [ - { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - } - ], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本哈希列表| -|value|账户哈希| - -### 2.3 获取账本详细信息 - -```http -GET /ledgers/{ledger} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs -``` - -#### 返回实例 - -```json -{ - "data": { - "hash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "latestBlockHash": { - "value": "67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL" - }, - "latestBlockHeight": 66 - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本信息| -|hash.value|账本哈希| -|latestBlockHash.value|最新区块哈希 -|latestBlockHeight|账本高度 - - -### 2.4 获取账本成员总数 - -```http -GET /ledgers/{ledger}/participants/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/participants/count -``` - -#### 返回实例 - -```json -{ - "data": 4, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本成员总数| - - -### 2.5 获取账本成员列表 - -```http -GET /ledgers/{ledger}/participants?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询成员起始序号,默认为0|数字 -|query|count|否|查询成员返回数量,默认最大返回100,小于0或大于100均返回最大可返回结果集|数字 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/participants?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [ - { - "address": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522", - "name": "jd.com", - "id": 0, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - }, - { - "address": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha", - "name": "at.com", - "id": 1, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - }, - { - "address": "5SmMWsqV2kbgrRMjyQFtSq1wvYuPzeRVepHG", - "name": "bt.com", - "id": 2, - "pubKey": { - "value": "mb4AtiGAH7vtPufMDuap2oca2Ww9X6KTkp59Eh5nZjXA5H" - } - }, - { - "address": "5Sm5QFyvN1dVB4GHFxWhDCp8vsJbNkdx31Ds", - "name": "xt.com", - "id": 3, - "pubKey": { - "value": "mb7pGhmmjqYUhxrJJ57C1YxXr9h1AWXv8QVosETyuLhVvH" - } - } - ], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|id|成员唯一标识| -|name|成员名称| -|address|成员地址| -|pubKey.value|成员公钥| - -## 3 区块 - -### 3.1 获取最新区块 - -```http -GET /ledgers/{ledger}/blocks/latest -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/latest -``` - -#### 返回实例 - -```json -{ - "data": { - "ledgerHash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "previousHash": { - "value": "6EJZnMc9464DCSU2kgi96RyngEv8YeEfVoJNhH3yZ2v5T" - }, - "transactionSetHash": { - "value": "6LmZtDpMM7xE8FPChACEmLj1PLhfaoVM2rEHRsrV3ohPN" - }, - "userAccountSetHash": { - "value": "67jx7SctrwdSczxxuYjwBocA8fER7V8qcRZUzWamSav5p" - }, - "contractAccountSetHash": { - "value": "67ftaBhPDez24NEB9wiiTM3SNcn1XFz5rb7boYhpbbLXN" - }, - "adminAccountHash": { - "value": "69KEFp9m5iFyAiyGmJ2qPcVxuT79gMChMf9JkStBZe8aa" - }, - "dataAccountSetHash": { - "value": "6LB9gosVWEPG3uvWXkxTcWq22mcwMHVehbiXkavFtr5fZ" - }, - "hash": { - "value": "67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL" - }, - "height": 66 - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|hash|区块哈希| -|ledgerHash|账本哈希| -|previousHash|前置区块哈希| -|transactionSetHash|交易集哈希| -|userAccountSetHash|用户集哈希| -|contractAccountSetHash|合约集哈希| -|adminAccountHash|管理员集哈希| -|dataAccountSetHash|数据账户集哈希| - -### 3.2 根据区块哈希获取区块详细信息 - -```http -GET /ledgers/{ledger}/blocks/hash/{block_hash} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_hash|是|区块哈希|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL -``` - -#### 返回实例 - -[参考](#block-detail) - - -### 3.3 根据区块高度获取区块详细信息 - -```http -GET /ledgers/{ledger}/blocks/height/{block_height} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_height|是|区块高度|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66 -``` - -#### 返回实例 - -[参考](#block-detail) - - -### 3.4 根据哈希查询区块总数 - -```http - GET /ledgers/{ledger}/blocks/count/search?keyword={keyword} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 区块哈希的全部或者一部分|string| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/count/search?keyword=6D5M -``` - -#### 返回实例 - -```json -{ - "data": 26, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|查询到的区块总数| - -### 3.5 根据哈希查询区块 - -```http - GET /ledgers/{ledger}/blocks/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 区块哈希的全部或者一部分|string| -|**query**|**start_index**|否| 查询区块结果起始序号,默认为0|string| -|**query**|**count**|否| 查询区块结果返回数量,默认最大值为100,小于0或大于100均返回最大可返回结果集|string| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/search?keyword=6D5M&fromIndex=0&count=-1 -``` - - -#### 返回实例 - -```json -{ - "data": { - "blocks": [ - { - "hash": "6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb" - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|blocks|查询到的区块列表| -|hash|区块哈希值| -|height|区块高度| -|txCount|区块内交易数量| - -## 4 交易 - -### 4.1 获取账本交易总数 - -```http -GET /ledgers/{ledger}/txs/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/count -``` - -##### 返回实例 - -```json -{ - "data": 688, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|交易数量| - -### 4.2 根据区块高度查询区块内的交易数量 - -```http -GET /ledgers/{ledger}/blocks/height/{block_height}/txs/additional-count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_height|是|区块高度|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66/txs/additional-count - -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs/additional-count -``` - -#### 返回实例 - -```json -{ - "data": 86, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|交易数量| - - -### 4.3 根据区块哈希查询区块内的交易数量 - -```http -GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs/additional-count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_hash|是|区块哈希|字符串| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs/additional-count -``` - -#### 返回实例 - -```json -{ - "data": 86, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|交易数量| - - -### 4.4 获取指定高度的区块交易列表 - -```http -GET /ledgers/{ledger}/blocks/height/{height}/txs?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|height|是|区块高度|数字| -|query|start_index|否|查询交易的起始序号,默认为0|数字| -|query|count|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66/txs?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [ - { - "blockHeight": 1, - "executionState": "SUCCESS", - "transactionContent": { - "ledgerHash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "operations": [ - { - "userID": { - "address": { - "value": "5SmBgzsrnY6u9Y7DgSSkXfTkCgp83hiFin3v" - }, - "pubKey": { - "value": "mb5kukaqjWtXyAerfHU1JDtVwabSeBU5c3khMZbNh7R8VJ" - } - } - }, - { - "accountID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - }, - { - "contractID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - }, - "chainCode": "----------" - }, - { - "contractAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - }, - "event": "----------", - "args": "----------" - }, - { - "writeSet": [{ - "key": "jdchain", - "value": { - "type": "TEXT", - "value": { - "value": "----------" - } - }, - "expectedVersion": 0 - }], - "accountAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - ], - "hash": { - "value": "6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA" - } - }, - "endpointSignatures": [ - { - "digest": { - "value": "42pbfM5YKnf39Gitr4UsjTCzhhnJjwNyi8MnLFYgP4VKewTLzHitzArHEMrCt3hZYUe5ex9XvqtmiCoWpeAbdc31F" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ], - "nodeSignatures": [ - { - "digest": { - "value": "66SQ95SbDaApAJhN2NsFx5sfAQTxsWhMW26D5iPqXc1jZU9rJEhRnqT1nzt62ZAcCvsfrjEsay3MxqXYA5tWPoA2U" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ] - } - ], - "success": true -} -``` - - -说明 - -|名称|说明| -|---|---| -|executionState|交易执行结果| -|transactionContent.hash|交易的哈希| -|transactionContent.operations|交易的操作列表| -|endpointSignatures|终端签名列表| -|nodeSignatures|节点的签名列表| - -### 4.5 获取指定哈希的区块的交易列表 - -```http -GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|block_hash|是|区块哈希|字符串| -|query|start_index|否|查询交易的起始序号,默认为0|数字| -|query|count|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs?fromIndex=0&count=-1 -``` - -#### 返回实例 - -[参考](#tx-list) - - -### 4.6 获取交易详细信息 - -```http -GET /ledgers/{ledger}/txs/hash/{tx_hash} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|tx_hash|是|交易哈希|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/hash/6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA -``` - -#### 返回实例 - -```json -{ - "data": { - "blockHeight": 1, - "executionState": "SUCCESS", - "transactionContent": { - "ledgerHash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "operations": [ - { - "userID": { - "address": { - "value": "5SmBgzsrnY6u9Y7DgSSkXfTkCgp83hiFin3v" - }, - "pubKey": { - "value": "mb5kukaqjWtXyAerfHU1JDtVwabSeBU5c3khMZbNh7R8VJ" - } - } - }, - { - "accountID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - }, - { - "contractID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - }, - "chainCode": "----------" - }, - { - "contractAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - }, - "event": "----------", - "args": "----------" - }, - { - "writeSet": [{ - "key": "jdchain", - "value": { - "type": "TEXT", - "value": { - "value": "----------" - } - }, - "expectedVersion": 0 - }], - "accountAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - ], - "hash": { - "value": "6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA" - } - }, - "endpointSignatures": [ - { - "digest": { - "value": "42pbfM5YKnf39Gitr4UsjTCzhhnJjwNyi8MnLFYgP4VKewTLzHitzArHEMrCt3hZYUe5ex9XvqtmiCoWpeAbdc31F" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ], - "nodeSignatures": [ - { - "digest": { - "value": "66SQ95SbDaApAJhN2NsFx5sfAQTxsWhMW26D5iPqXc1jZU9rJEhRnqT1nzt62ZAcCvsfrjEsay3MxqXYA5tWPoA2U" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ] - }, - "success": true -} -``` - -说明 - -[参考](#tx-keyword) - - -### 4.7 根据哈希查询交易总数 - -```http - GET /ledgers/{ledgers}/txs/count/search?keyword={keyword} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledgers**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是|交易哈希,签名者公钥,或者节点公钥的全部或者部分的|string| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/search?keyword=6BLt -``` - -#### 返回实例 - -```json -{ - "data": 36, - "success": true -} -``` - - -说明 - -|名称|说明| -|---|---| -|data|指定交易数量| - - -### 4.8 根据哈希查询交易 - -```http - GET /ledgers/{ledgers}/txs/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledgers**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是|交易哈希,签名者公钥,或者节点公钥的全部或者部分的|string| -|**query**|**start_index**|否|查询交易的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/search?keyword=6BLt -``` - - -#### 返回 - -```json -{ - "data": { - "txs": [ - { - "hash": "6L3ehswCmC1jqBfvGJP9vaPx8qxkLsieu2aRgYepmkiw3" - } - ] - }, - "success": true -} -``` - -## 5 用户 - -### 5.1 获取用户总数 - -```http -GET /ledgers/{ledger}/users/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/count -``` - -#### 返回实例 - -```json -{ - "data": 4, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|用户总数| - - -### 5.2 获取用户列表 - -```http -GET /ledgers/{ledger}/users?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询用户的起始序号,默认为0|数字| -|query|count|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data":[{ - "address": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - }, - "rootHash": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|用户地址| -|pubKey.value|用户公钥| - - -### 5.3 获取用户详细信息 - -```http -GET /ledgers/{ledger}/users/address/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|用户地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/address/55SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522 -``` - -#### 返回实例 - -```json -{ - "data": { - "address": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - }, - "rootHash": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|用户地址| -|pubKey.value|用户公钥| -|rootHash.value|用户根Hash| - - -### 5.4 用户查询数量 - -```http - GET /ledgers/{ledger}/users/count/search?keyword={keyword} -``` - -#### 说明 - -用户有公钥和地址两个属性,可以通过公钥或者地址查找特定用户数量,也可以返回全部用户的数量 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 用户的公钥或者地址的全部或者部分|string| -|**query**|**start_index**|否|查询用户的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/count/search?keyword=5Sm -``` - -#### 返回实例 - -```json -{ - "data": 4, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|用户数量| - -### 5.5 用户查询 - -```http - GET /ledgers/{ledger}/users/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -用户有公钥和地址两个属性,可以通过公钥或者地址查找特定用户,也可以返回全部用户的列表 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 用户的公钥或者地址的全部或者部分|string| -|**query**|**start_index**|否|查询用户的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/search?keyword=5Sm&fromIndex=0&count=-1 -``` - - -#### 返回实例 - -```json -{ - "data": { - "users": [ - { - "address": { - "value": "5SmAGKgmXyj5VsVvJgHbYCJ67iTizwSkNpw1" - }, - "pubKey": { - "value": "mb97eG4bba2EjrgjXYiD9chAstjg4HaNuV5xgCtSHc5TeB" - } - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|用户地址| -|pubKey.value|用户公钥| -|rootHash.value|用户根Hash| - -## 6 数据账户 - -### 6.1 获取账户列表 - -```http -GET /ledgers/{ledger}/accounts?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询数据账户的起始序号,默认为0|数字| -|query|count|否|查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data":[{ - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - - -### 6.2 获取账户详细信息 - -```http -GET /ledgers/{ledger}/accounts/address/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa -``` - -#### 返回实例 - -```json -{ - "data": { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - - -### 6.3 获取账户总数 - -```http -GET /ledgers/{ledger}/accounts/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/count -``` - -#### 返回实例 - -```json -{ - "data": 18, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账户数量| - - -### 6.4 查询数据账户匹配的数量 - -```http -GET /ledgers/{ledger}/accounts/count/search?keyword={keyword} -``` - -#### 说明 - -通过账户的公钥和地址的全部或者部分查询特定账户的总数量,也可以通过KV值的Key来查询含有该Key的账户的总数量 - - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|字符串 -|**query**|**keyword**|是|数据账户的公钥或者地址的全部或者部分,或者是KV值的key|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/count/search?keyword=jd -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账户数量| - - -### 6.5 查询数据账户 - -```http - GET /ledgers/{ledger}/accounts/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -通过账户的公钥和地址的全部或者部分查询特定账户,也可以通过KV值的Key来查询含有该Key的账户 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 数据账户的公钥或者地址的全部或者部分,或者是KV值的key|string| -|**query**|**start_index**|否|查询数据账户的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/search?keyword=5Sm5V&fromIndex=0&count=-1 -``` - - -#### 返回实例 - -```json -{ - "data": { - "accounts": [ - { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|数据账户根Hash| - - -### 6.6 获取某数据账户KV总数 - -```http - GET /ledgers/{ledger}/accounts/address/{address}/entries/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries/count -``` - -#### 返回实例 - -```json -{ - "data": 66, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|KV总数| - - -### 6.7 获取某数据账户KV详情 - -```http - GET/POST /ledgers/{ledger}/accounts/address/{address}/entries?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 -|form|keys|是|key详细内容列表|字符串 -|query|start_index|否|查询数据账户对应KV的起始序号,默认为0|数字| -|query|count|否|查询返回数据账户对应KV的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -> keys说明: - 1)keys使用表单方式提交,且keys为需要查询Key的列表,列表中每个Key都需要为完整Key - 2)Key提交方式使用GET或POST均可 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries -``` - -说明:表单提交参数为keys={"jd", "jdchain"} - - -#### 返回实例 - -```json -{ - "data": [ - { - "key": "jd", - "version": 0, - "type": "TEXT", - "value": "www.jd.com" - }, - { - "key": "jdchain", - "version": 0, - "type": "TEXT", - "value": "www.blockchain.com" - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|key|键| -|version|版本号| -|type|value类型| -|value|值| - - - -## 7 搜索 - -### 7.1 搜索区块链 - -```http - GET /ledgers/{ledger}/all/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -通过关键字搜索区块数据,支持区块哈希,交易哈希,用户公钥和地址,合约公钥和地址,数据账户哈希和地址的搜索 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是|关键字|string| -|**query**|**start_index**|否|查询匹配结果的起始序号,默认为0|数字| -|**query**|**count**|否|查询匹配结果的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/all/search?keyword=5Sm5V&fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "message": "OK", - "code": 0, - "data": { - "blocks": ..., - "txs": ..., - "users": ..., - "accounts": ..., - "contracts": ..., - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|blocks|[参考](#query-blocks-result)| -|txs|[参考](#query-txs-result)| -|users|[参考](#query-users-result)| -|accounts|[参考](#query-accounts-result)| -|contracts|[参考](#query-contracts-result)| - -## 8 合约 - -### 8.1 获取合约列表 - -```http -GET /ledgers/{ledger}/contracts?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询合约的起始序号,默认为0|数字| -|query|count|否|查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [{ - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - - -### 8.2 获取合约详细信息 - -```http -GET /ledgers/{ledger}/contracts/address/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|合约地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa -``` - -#### 返回实例 - -```json -{ - "data": { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - -### 8.3 获取合约总数 - -```http -GET /ledgers/{ledger}/contracts/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/count -``` - -#### 返回实例 - -```json -{ - "data": 27, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|合约数量| - - -### 8.4 查询指定合约数量 - -```http -GET /ledgers/{ledger}/contracts/count/search?keyword={keyword} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是| 合约的公钥或者地址的全部或者一部分|string| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/count/search?keyword=5Sm2 -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|合约数量| - -### 8.5 合约查询 - -```http - GET /ledgers/{ledger}/contracts/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -合约有公钥和地址两个属性,可以通过合约的这两个属性查询特定合约,也可以返回一个当前所有合约的列表 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是| 合约的公钥或者地址的全部或者一部分|string| -|**query**|**start_index**|否|查询合约的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/earch?keyword=5Sm2&fromIndex=0&count=-1 -``` - - -#### 返回 - -```json -{ - "data": { - "contracts": [ - { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|合约地址| -|pubKey.value|合约公钥| -|rootHash|合约根Hash| diff --git a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.html b/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.html deleted file mode 100644 index 169ef8b7..00000000 --- a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.3.html +++ /dev/null @@ -1,2665 +0,0 @@ - - - - - api_doc_cn_1.3 - - -

京东区块链浏览器API文档参考 V_1.3

-

1 API调用说明

-

该文档内的所有api的调用成功和失败均按照以下规则

-

1.1 成功

-
{
  "data": ...,
  "success": true
}
-

说明

-
- success 值为 true 表明api调用成功
- data 为返回的数据,具体数据类型参考具体的api说明

1.2 失败

-
{
  "error": {
    "errorCode": 5000,
    "errorMessage": "未预期的异常! --Unsupported access ledger[6Gw3cK4uazegy4HjoaM81ck9NgYLNoKyBMb7a1TK1jt3d] !"
  },
  "success": false
}
-

说明

-
- success 值为 false 表明api调用成功
- errorCode 为异常代码
- errorMessage 为错误提示

2 账本

-

2.1 获取账本总数

-
GET /ledgers/count
-

参数

-

-

请求实例

-
http://localhost/ledgers/count
-

返回实例

-
{
  "data": 2,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data账本总数
-

2.2 获取账本列表

-
GET /ledgers?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
querystart_index查询账本的起始序号,默认为0数字
querycount查询返回账本的数量限制,默认最大限制为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers?fromIndex=0&count=-1
-

返回实例

-
{
  "data": [
    {
      "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs"
    }
  ],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - -
名称说明
data账本哈希列表
value账户哈希
-

2.3 获取账本详细信息

-
GET /ledgers/{ledger}
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs
-

返回实例

-
{
  "data": {
    "hash": {
      "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs"
    },
    "latestBlockHash": {
      "value": "67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL"
    },
    "latestBlockHeight": 66
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
data账本信息
hash.value账本哈希
latestBlockHash.value最新区块哈希
latestBlockHeight账本高度
-

2.4 获取账本成员总数

-
GET /ledgers/{ledger}/participants/count
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/participants/count
-

返回实例

-
{
  "data": 4,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data账本成员总数
-

2.5 获取账本成员列表

-
GET /ledgers/{ledger}/participants?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
querystart_index查询成员起始序号,默认为0数字
querycount查询成员返回数量,默认最大返回100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/participants?fromIndex=0&count=-1
-

返回实例

-
{
  "data": [
    {
      "address": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522",
      "name": "jd.com",
      "id": 0,
      "pubKey": {
        "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
      }
    },
    {
      "address": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha",
      "name": "at.com",
      "id": 1,
      "pubKey": {
        "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
      }
    },
    {
      "address": "5SmMWsqV2kbgrRMjyQFtSq1wvYuPzeRVepHG",
      "name": "bt.com",
      "id": 2,
      "pubKey": {
        "value": "mb4AtiGAH7vtPufMDuap2oca2Ww9X6KTkp59Eh5nZjXA5H"
      }
    },
    {
      "address": "5Sm5QFyvN1dVB4GHFxWhDCp8vsJbNkdx31Ds",
      "name": "xt.com",
      "id": 3,
      "pubKey": {
        "value": "mb7pGhmmjqYUhxrJJ57C1YxXr9h1AWXv8QVosETyuLhVvH"
      }
    }
  ],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
id成员唯一标识
name成员名称
address成员地址
pubKey.value成员公钥
-

3 区块

-

3.1 获取最新区块

-
GET /ledgers/{ledger}/blocks/latest
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/latest
-

返回实例

-
{
  "data": {
    "ledgerHash": {
      "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs"
    },
    "previousHash": {
      "value": "6EJZnMc9464DCSU2kgi96RyngEv8YeEfVoJNhH3yZ2v5T"
    },
    "transactionSetHash": {
      "value": "6LmZtDpMM7xE8FPChACEmLj1PLhfaoVM2rEHRsrV3ohPN"
    },
    "userAccountSetHash": {
      "value": "67jx7SctrwdSczxxuYjwBocA8fER7V8qcRZUzWamSav5p"
    },
    "contractAccountSetHash": {
      "value": "67ftaBhPDez24NEB9wiiTM3SNcn1XFz5rb7boYhpbbLXN"
    },
    "adminAccountHash": {
      "value": "69KEFp9m5iFyAiyGmJ2qPcVxuT79gMChMf9JkStBZe8aa"
    },
    "dataAccountSetHash": {
      "value": "6LB9gosVWEPG3uvWXkxTcWq22mcwMHVehbiXkavFtr5fZ"
    },
    "hash": {
      "value": "67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL"
    },
    "height": 66
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
hash区块哈希
ledgerHash账本哈希
previousHash前置区块哈希
transactionSetHash交易集哈希
userAccountSetHash用户集哈希
contractAccountSetHash合约集哈希
adminAccountHash管理员集哈希
dataAccountSetHash数据账户集哈希
-

3.2 根据区块哈希获取区块详细信息

-
GET /ledgers/{ledger}/blocks/hash/{block_hash}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathblock_hash区块哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL
-

返回实例

-

参考

-

3.3 根据区块高度获取区块详细信息

-
GET /ledgers/{ledger}/blocks/height/{block_height}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathblock_height区块高度数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66
-

返回实例

-

参考

-

3.4 根据哈希查询区块总数

-
  GET /ledgers/{ledger}/blocks/count/search?keyword={keyword}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
querykeyword区块哈希的全部或者一部分string
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/count/search?keyword=6D5M
-

返回实例

-
{
  "data": 26,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data查询到的区块总数
-

3.5 根据哈希查询区块

-
  GET /ledgers/{ledger}/blocks/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
querykeyword区块哈希的全部或者一部分string
querystart_index查询区块结果起始序号,默认为0string
querycount查询区块结果返回数量,默认最大值为100,小于0或大于100均返回最大可返回结果集string
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/search?keyword=6D5M&fromIndex=0&count=-1
-

-

返回实例

-
{
  "data": {
    "blocks": [
      {
        "hash": "6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb"
      }
    ]
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
blocks查询到的区块列表
hash区块哈希值
height区块高度
txCount区块内交易数量
-

4 交易

-

4.1 获取账本交易总数

-
GET /ledgers/{ledger}/txs/count
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/count
-
返回实例
-
{
  "data": 688,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data交易数量
-

4.2 根据区块高度查询区块内的交易数量

-
GET /ledgers/{ledger}/blocks/height/{block_height}/txs/additional-count
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathblock_height区块高度数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66/txs/additional-count
 
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs/additional-count
-

返回实例

-
{
  "data": 86,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data交易数量
-

4.3 根据区块哈希查询区块内的交易数量

-
GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs/additional-count
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathblock_hash区块哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs/additional-count
-

返回实例

-
{
  "data": 86,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data交易数量
-

4.4 获取指定高度的区块交易列表

-
GET /ledgers/{ledger}/blocks/height/{height}/txs?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathheight区块高度数字
querystart_index查询交易的起始序号,默认为0数字
querycount查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66/txs?fromIndex=0&count=-1
-

返回实例

-
{
  "data": [
    {
      "blockHeight": 1,
      "executionState": "SUCCESS",
      "transactionContent": {
        "ledgerHash": {
          "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs"
        },
        "operations": [
          {
            "userID": {
              "address": {
                "value": "5SmBgzsrnY6u9Y7DgSSkXfTkCgp83hiFin3v"
              },
              "pubKey": {
                "value": "mb5kukaqjWtXyAerfHU1JDtVwabSeBU5c3khMZbNh7R8VJ"
              }
            }
          },
          {
            "accountID": {
              "address": {
                "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha"
              },
              "pubKey": {
                "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
              }
            }
          },
          {
            "contractID": {
              "address": {
                "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha"
              },
              "pubKey": {
                "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
              }
            },
            "chainCode": "----------"
          },
          {
            "contractAddress": {
              "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
            },
            "event": "----------",
            "args": "----------"
          },
          {
            "writeSet": [{
              "key": "jdchain",
              "value": {
                "type": "TEXT",
                "value": {
                  "value": "----------"
                }
              },
              "expectedVersion": 0
            }],
            "accountAddress": {
              "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
            }
          }
        ],
        "hash": {
          "value": "6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA"
        }
      },
      "endpointSignatures": [
        {
          "digest": {
            "value": "42pbfM5YKnf39Gitr4UsjTCzhhnJjwNyi8MnLFYgP4VKewTLzHitzArHEMrCt3hZYUe5ex9XvqtmiCoWpeAbdc31F"
          },
          "pubKey": {
            "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
          }
        }
      ],
      "nodeSignatures": [
        {
          "digest": {
            "value": "66SQ95SbDaApAJhN2NsFx5sfAQTxsWhMW26D5iPqXc1jZU9rJEhRnqT1nzt62ZAcCvsfrjEsay3MxqXYA5tWPoA2U"
          },
          "pubKey": {
            "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
          }
        }
      ]
    }
  ],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
executionState交易执行结果
transactionContent.hash交易的哈希
transactionContent.operations交易的操作列表
endpointSignatures终端签名列表
nodeSignatures节点的签名列表
-

4.5 获取指定哈希的区块的交易列表

-
GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathblock_hash区块哈希字符串
querystart_index查询交易的起始序号,默认为0数字
querycount查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs?fromIndex=0&count=-1
-

返回实例

-

参考

-

4.6 获取交易详细信息

-
GET /ledgers/{ledger}/txs/hash/{tx_hash}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathtx_hash交易哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/hash/6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA
-

返回实例

-
{
  "data": {
    "blockHeight": 1,
    "executionState": "SUCCESS",
    "transactionContent": {
      "ledgerHash": {
        "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs"
      },
      "operations": [
        {
          "userID": {
            "address": {
              "value": "5SmBgzsrnY6u9Y7DgSSkXfTkCgp83hiFin3v"
            },
            "pubKey": {
              "value": "mb5kukaqjWtXyAerfHU1JDtVwabSeBU5c3khMZbNh7R8VJ"
            }
          }
        },
        {
          "accountID": {
            "address": {
              "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha"
            },
            "pubKey": {
              "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
            }
          }
        },
        {
          "contractID": {
            "address": {
              "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha"
            },
            "pubKey": {
              "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
            }
          },
          "chainCode": "----------"
        },
        {
          "contractAddress": {
            "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
          },
          "event": "----------",
          "args": "----------"
        },
        {
          "writeSet": [{
            "key": "jdchain",
            "value": {
              "type": "TEXT",
              "value": {
                "value": "----------"
              }
            },
            "expectedVersion": 0
          }],
          "accountAddress": {
            "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR"
          }
        }
      ],
      "hash": {
        "value": "6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA"
      }
    },
    "endpointSignatures": [
      {
        "digest": {
          "value": "42pbfM5YKnf39Gitr4UsjTCzhhnJjwNyi8MnLFYgP4VKewTLzHitzArHEMrCt3hZYUe5ex9XvqtmiCoWpeAbdc31F"
        },
        "pubKey": {
          "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
        }
      }
    ],
    "nodeSignatures": [
      {
        "digest": {
          "value": "66SQ95SbDaApAJhN2NsFx5sfAQTxsWhMW26D5iPqXc1jZU9rJEhRnqT1nzt62ZAcCvsfrjEsay3MxqXYA5tWPoA2U"
        },
        "pubKey": {
          "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
        }
      }
    ]
  },
  "success": true
}
-

说明

-

参考

-

4.7 根据哈希查询交易总数

-
  GET /ledgers/{ledgers}/txs/count/search?keyword={keyword}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledgers所要搜索的账本范围,需要完整的账本哈希string
querykeyword交易哈希,签名者公钥,或者节点公钥的全部或者部分的string
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/search?keyword=6BLt
-

返回实例

-
{
  "data": 36,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data指定交易数量
-

4.8 根据哈希查询交易

-
  GET /ledgers/{ledgers}/txs/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledgers所要搜索的账本范围,需要完整的账本哈希string
querykeyword交易哈希,签名者公钥,或者节点公钥的全部或者部分的string
querystart_index查询交易的起始序号,默认为0数字
querycount查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/search?keyword=6BLt
-

-

返回

-
{
  "data": {
    "txs": [
      {
        "hash": "6L3ehswCmC1jqBfvGJP9vaPx8qxkLsieu2aRgYepmkiw3"
      }
    ]
  },
  "success": true
}
-

5 用户

-

5.1 获取用户总数

-
GET /ledgers/{ledger}/users/count
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/count
-

返回实例

-
{
  "data": 4,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data用户总数
-

5.2 获取用户列表

-
GET /ledgers/{ledger}/users?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
querystart_index查询用户的起始序号,默认为0数字
querycount查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users?fromIndex=0&count=-1
-

返回实例

-
{
  "data":[{
    "address": {
      "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522"
    },
    "pubKey": {
      "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
    },
    "rootHash": {
      "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522"
    }
  }],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - -
名称说明
address.value用户地址
pubKey.value用户公钥
-

5.3 获取用户详细信息

-
GET /ledgers/{ledger}/users/address/{address}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathaddress用户地址字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/address/55SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522
-

返回实例

-
{
  "data": {
    "address": {
      "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522"
    },
    "pubKey": {
      "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS"
    },
    "rootHash": {
      "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522"
    }
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value用户地址
pubKey.value用户公钥
rootHash.value用户根Hash
-

5.4 用户查询数量

-
  GET /ledgers/{ledger}/users/count/search?keyword={keyword}
-

说明

-

用户有公钥和地址两个属性,可以通过公钥或者地址查找特定用户数量,也可以返回全部用户的数量

-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
querykeyword用户的公钥或者地址的全部或者部分string
querystart_index查询用户的起始序号,默认为0数字
querycount查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/count/search?keyword=5Sm
-

返回实例

-
{
  "data": 4,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data用户数量
-

5.5 用户查询

-
  GET /ledgers/{ledger}/users/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

说明

-

用户有公钥和地址两个属性,可以通过公钥或者地址查找特定用户,也可以返回全部用户的列表

-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
querykeyword用户的公钥或者地址的全部或者部分string
querystart_index查询用户的起始序号,默认为0数字
querycount查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/search?keyword=5Sm&fromIndex=0&count=-1
-

-

返回实例

-
{
  "data": {
    "users": [
      {
        "address": {
          "value": "5SmAGKgmXyj5VsVvJgHbYCJ67iTizwSkNpw1"
        },
        "pubKey": {
          "value": "mb97eG4bba2EjrgjXYiD9chAstjg4HaNuV5xgCtSHc5TeB"
        },
        "rootHash": {
          "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522"
        }
      }
    ]
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value用户地址
pubKey.value用户公钥
rootHash.value用户根Hash
-

6 数据账户

-

6.1 获取账户列表

-
GET /ledgers/{ledger}/accounts?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
querystart_index查询数据账户的起始序号,默认为0数字
querycount查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts?fromIndex=0&count=-1
-

返回实例

-
{
  "data":[{
    "address": {
      "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa"
    },
    "rootHash": {
      "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM"
    },
    "pubKey": {
      "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs"
    }
  }],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value账户地址
pubKey.value账户公钥
rootHash.value默克尔树根哈希
-

6.2 获取账户详细信息

-
GET /ledgers/{ledger}/accounts/address/{address}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathaddress账户地址字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa
-

返回实例

-
{
  "data": {
    "address": {
      "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa"
    },
    "rootHash": {
      "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM"
    },
    "pubKey": {
      "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs"
    }
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value账户地址
pubKey.value账户公钥
rootHash.value默克尔树根哈希
-

6.3 获取账户总数

-
GET /ledgers/{ledger}/accounts/count
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/count
-

返回实例

-
{
  "data": 18,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data账户数量
-

6.4 查询数据账户匹配的数量

-
GET /ledgers/{ledger}/accounts/count/search?keyword={keyword}
-

说明

-

通过账户的公钥和地址的全部或者部分查询特定账户的总数量,也可以通过KV值的Key来查询含有该Key的账户的总数量

-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希字符串
querykeyword数据账户的公钥或者地址的全部或者部分,或者是KV值的key字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/count/search?keyword=jd
-

返回实例

-
{
  "data": 2,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data账户数量
-

6.5 查询数据账户

-
  GET /ledgers/{ledger}/accounts/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

说明

-

通过账户的公钥和地址的全部或者部分查询特定账户,也可以通过KV值的Key来查询含有该Key的账户

-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
querykeyword数据账户的公钥或者地址的全部或者部分,或者是KV值的keystring
querystart_index查询数据账户的起始序号,默认为0数字
querycount查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/search?keyword=5Sm5V&fromIndex=0&count=-1
-

-

返回实例

-
{
  "data": {
    "accounts": [
      {
        "address": {
          "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa"
        },
        "rootHash": {
          "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM"
        },
        "pubKey": {
          "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs"
        }
      }
    ]
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value账户地址
pubKey.value账户公钥
rootHash.value数据账户根Hash
-

6.6 获取某数据账户KV总数

-
  GET /ledgers/{ledger}/accounts/address/{address}/entries/count
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathaddress账户地址字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries/count
-

返回实例

-
{
  "data": 66,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
dataKV总数
-

6.7 获取某数据账户KV详情

-
  GET/POST /ledgers/{ledger}/accounts/address/{address}/entries?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathaddress账户地址字符串
formkeyskey详细内容列表字符串
querystart_index查询数据账户对应KV的起始序号,默认为0数字
querycount查询返回数据账户对应KV的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-
-

keys说明: - 1)keys使用表单方式提交,且keys为需要查询Key的列表,列表中每个Key都需要为完整Key - 2)Key提交方式使用GET或POST均可

-
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries
-

说明:表单提交参数为keys={"jd", "jdchain"}

-

返回实例

-
{
  "data": [
  {
    "key": "jd",
    "version": 0,
    "type": "TEXT",
    "value": "www.jd.com"
  },
  {
    "key": "jdchain",
    "version": 0,
    "type": "TEXT",
    "value": "www.blockchain.com"
  }],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
key
version版本号
typevalue类型
value
-

6.8 查询某数据账户键数量

-
  GET /ledgers/{ledger}/accounts/address/{address}/keys/count/search?keyword={keyword}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
pathaddress所要搜索的数据账户地址,需要完整的数据账户地址string
querykeyword键的部分字符,空表示全部string
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/keys/count/search?keyword=j
-

返回实例

-
{
  "data": 66,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data条件查询键总数
-

6.9 查询某数据账户键

-
  GET /ledgers/{ledger}/accounts/address/{address}/keys/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
pathaddress所要搜索的数据账户地址,需要完整的数据账户地址string
querykeyword键的部分字符,空表示全部string
querystart_index查询数据账户对应Key的起始序号,默认为0数字
querycount查询返回数据账户对应Key的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/keys/search?keyword=j&fromIndex=0&count=-1
-

返回实例

-
{
  "data": [
  {
    "key": "jd"
  },
  {
    "key": "jdchain"
  }],
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
key
-

7 搜索

-

7.1 搜索区块链

-
  GET /ledgers/{ledger}/all/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

说明

-

通过关键字搜索区块数据,支持区块哈希,交易哈希,用户公钥和地址,合约公钥和地址,数据账户哈希和地址的搜索

-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本,需要完整的账本哈希string
querykeyword关键字string
querystart_index查询匹配结果的起始序号,默认为0数字
querycount查询匹配结果的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/all/search?keyword=5Sm5V&fromIndex=0&count=-1
-

返回实例

-
{
  "message": "OK",
  "code": 0,
  "data": {
    "blocks": ...,
    "txs": ...,
    "users": ...,
    "accounts": ...,
    "contracts": ...,
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
名称说明
blocks参考
txs参考
users参考
accounts参考
contracts参考
-

8 合约

-

8.1 获取合约列表

-
GET /ledgers/{ledger}/contracts?fromIndex={start_index}&count={count}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
querystart_index查询合约的起始序号,默认为0数字
querycount查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts?fromIndex=0&count=-1
-

返回实例

-
{
  "data": [{
    "address": {
      "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa"
    },
    "rootHash": {
      "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM"
    },
    "pubKey": {
      "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs"
    }
  }],
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value账户地址
pubKey.value账户公钥
rootHash.value默克尔树根哈希
-

8.2 获取合约详细信息

-
GET /ledgers/{ledger}/contracts/address/{address}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
pathaddress合约地址字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa
-

返回实例

-
{
  "data": {
    "address": {
      "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa"
    },
    "rootHash": {
      "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM"
    },
    "pubKey": {
      "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs"
    }
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value账户地址
pubKey.value账户公钥
rootHash.value默克尔树根哈希
-

8.3 获取合约总数

-
GET /ledgers/{ledger}/contracts/count
-

参数

- - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger账本哈希字符串
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/count
-

返回实例

-
{
  "data": 27,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data合约数量
-

8.4 查询指定合约数量

-
GET /ledgers/{ledger}/contracts/count/search?keyword={keyword}
-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本范围,需要完整的账本哈希string
querykeyword合约的公钥或者地址的全部或者一部分string
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/count/search?keyword=5Sm2
-

返回实例

-
{
  "data": 2,
  "success": true
}
-

说明

- - - - - - - - - - - - - -
名称说明
data合约数量
-

8.5 合约查询

-
  GET /ledgers/{ledger}/contracts/search?keyword={keyword}&fromIndex={start_index}&count={count}
-

说明

-

合约有公钥和地址两个属性,可以通过合约的这两个属性查询特定合约,也可以返回一个当前所有合约的列表

-

参数

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
请求类型名称是否必需说明数据类型
pathledger所要搜索的账本范围,需要完整的账本哈希string
querykeyword合约的公钥或者地址的全部或者一部分string
querystart_index查询合约的起始序号,默认为0数字
querycount查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集数字
-

请求实例

-
http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/earch?keyword=5Sm2&fromIndex=0&count=-1
-

-

返回

-
{
  "data": {
    "contracts": [
      {
        "address": {
          "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa"
        },
        "rootHash": {
          "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM"
        },
        "pubKey": {
          "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs"
        }
      }
    ]
  },
  "success": true
}
-

说明

- - - - - - - - - - - - - - - - - - - - - -
名称说明
address.value合约地址
pubKey.value合约公钥
rootHash合约根Hash
- diff --git a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD b/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD deleted file mode 100644 index 06fd228a..00000000 --- a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD +++ /dev/null @@ -1,2619 +0,0 @@ -# 京东区块链浏览器API文档参考 V_1.4 - -## 1 API调用说明 - -该文档内的所有api的调用成功和失败均按照以下规则 - -### 1.1 成功 - -```json -{ - "data": ..., - "success": true -} -``` - -说明 - - - success 值为 true 表明api调用成功 - - data 为返回的数据,具体数据类型参考具体的api说明 - -### 1.2 失败 - -```json -{ - "error": { - "errorCode": 5000, - "errorMessage": "未预期的异常! --Unsupported access ledger[6Gw3cK4uazegy4HjoaM81ck9NgYLNoKyBMb7a1TK1jt3d] !" - }, - "success": false -} -``` - -说明 - - - success 值为 false 表明api调用成功 - - errorCode 为异常代码 - - errorMessage 为错误提示 - -## 2 账本 - -### 2.1 获取账本总数 - -```http -GET /ledgers/count -``` - -#### 参数 -无 - - -#### 请求实例 -```http -http://localhost/ledgers/count -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本总数| - - -### 2.2 获取账本列表 - -```http -GET /ledgers?fromIndex={start_index}&count={count} -``` - -#### 参数 -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|query|start_index|否|查询账本的起始序号,默认为0|数字 -|query|count|否|查询返回账本的数量限制,默认最大限制为100,小于0或大于100均返回最大可返回结果集|数字 - - -#### 请求实例 -```http -http://localhost/ledgers?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [ - { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - } - ], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本哈希列表| -|value|账户哈希| - -### 2.3 获取账本详细信息 - -```http -GET /ledgers/{ledger} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs -``` - -#### 返回实例 - -```json -{ - "data": { - "hash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "latestBlockHash": { - "value": "67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL" - }, - "latestBlockHeight": 66 - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本信息| -|hash.value|账本哈希| -|latestBlockHash.value|最新区块哈希 -|latestBlockHeight|账本高度 - - -### 2.4 获取账本成员总数 - -```http -GET /ledgers/{ledger}/participants/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/participants/count -``` - -#### 返回实例 - -```json -{ - "data": 4, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账本成员总数| - - -### 2.5 获取账本成员列表 - -```http -GET /ledgers/{ledger}/participants?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询成员起始序号,默认为0|数字 -|query|count|否|查询成员返回数量,默认最大返回100,小于0或大于100均返回最大可返回结果集|数字 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/participants?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [ - { - "address": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522", - "name": "jd.com", - "id": 0, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - }, - { - "address": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha", - "name": "at.com", - "id": 1, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - }, - { - "address": "5SmMWsqV2kbgrRMjyQFtSq1wvYuPzeRVepHG", - "name": "bt.com", - "id": 2, - "pubKey": { - "value": "mb4AtiGAH7vtPufMDuap2oca2Ww9X6KTkp59Eh5nZjXA5H" - } - }, - { - "address": "5Sm5QFyvN1dVB4GHFxWhDCp8vsJbNkdx31Ds", - "name": "xt.com", - "id": 3, - "pubKey": { - "value": "mb7pGhmmjqYUhxrJJ57C1YxXr9h1AWXv8QVosETyuLhVvH" - } - } - ], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|id|成员唯一标识| -|name|成员名称| -|address|成员地址| -|pubKey.value|成员公钥| - - - -### 2.6 获取账本元数据信息 - -```http -GET /ledgers/{ledger}/metadata -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/metadata -``` - -#### 返回实例 - -```json -{ - "data": { - "participantsHash": { - "value": "j5hQErg4epzNh38FR3EABx8YJqPkLYZoY828giAyKpCXMd" - }, - "seed": "ky3+I/4jIy8oPzL63TKqdoMiyi9WI2zacTazIssyP/4=", - "setting": { - "consensusProvider": "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", - "cryptoSetting": { - "supportedProviders": [{ - "algorithms": [{}, {}, {}, {}, {}, {}, {}], - "name": "com.jd.blockchain.crypto.service.classic.ClassicCryptoService" - }, { - "algorithms": [{}, {}, {}], - "name": "com.jd.blockchain.crypto.service.sm.SMCryptoService" - }], - "autoVerifyHash": true, - "hashAlgorithm": 8216 - }, - "consensusSetting": { - "value": "112ky33NcTKBkV..." - } - } - }, - "success": true -} - -``` - -说明 - -|名称|说明| -|---|---| -|seed|账本生成种子| -|consensusSetting|共识配置,每种共识不同,需独立解析| - - - - -### 2.7 获取账本配置信息 - -```http -GET /ledgers/{ledger}/settings -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/settings -``` - -#### 返回实例 - -```json - -{ - "data": { - "consensusProtocol": "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", - "consensusSettings": { - "nodes": [{ - "address": "LdeNgXM4J1SybrdUn71KdPhwBYvJzZ6xUG5Rd", - "id": 0, - "networkAddress": { - "host": "127.0.0.1", - "port": 26000, - "secure": false - }, - "pubKey": { - "value": "7VeRMXAkf3zoqr4N2RgLZ83xAv7wurqu6Vxak1V1GHv4Kfe3" - } - }, { - "address": "LdeNwbLhiAHQCVxnXsyKLhgcmUi2fuwYd6jkh", - "id": 1, - "networkAddress": { - "host": "127.0.0.1", - "port": 26010, - "secure": false - }, - "pubKey": { - "value": "7VeRAt79WPnMQ7TsM5cfhy2ERwVLu8fXbDezfFb6bT9BgYaZ" - } - }, { - "address": "LdeNgVjFaUTzsSHySB3ZrBaLiEeZebLkkyWFP", - "id": 2, - "networkAddress": { - "host": "127.0.0.1", - "port": 26020, - "secure": false - }, - "pubKey": { - "value": "7VeR9rnFNzgECCYGF8V3G36xhF3X9rr6YzqfN8h6CojgLpEY" - } - }, { - "address": "LdeNgVAkBAAdKLD1z3Nb7n5vtGujfqWdhx8G7", - "id": 3, - "networkAddress": { - "host": "127.0.0.1", - "port": 26030, - "secure": false - }, - "pubKey": { - "value": "7VeRPkXMyHFvpPf2jayHjiLX8H7CAcTJpF9F1FARogiroSK2" - } - }], - "systemConfigs": [{ - "name": "system.bft", - "value": "true" - }, { - "name": "system.communication.defaultkeys", - "value": "true" - }, { - "name": "system.communication.inQueueSize", - "value": "500000" - }, { - "name": "system.communication.outQueueSize", - "value": "500000" - }, { - "name": "system.communication.useMACs", - "value": "1" - }, { - "name": "system.communication.useSenderThread", - "value": "true" - }, { - "name": "system.communication.useSignatures", - "value": "0" - }, { - "name": "system.debug", - "value": "0" - }, { - "name": "system.initial.view", - "value": "0,1,2,3" - }, { - "name": "system.servers.f", - "value": "1" - }, { - "name": "system.servers.num", - "value": "4" - }, { - "name": "system.shutdownhook", - "value": "true" - }, { - "name": "system.totalordermulticast.checkpoint_period", - "value": "1000" - }, { - "name": "system.totalordermulticast.checkpoint_to_disk", - "value": "false" - }, { - "name": "system.totalordermulticast.global_checkpoint_period", - "value": "120000" - }, { - "name": "system.totalordermulticast.highMark", - "value": "10000" - }, { - "name": "system.totalordermulticast.log", - "value": "true" - }, { - "name": "system.totalordermulticast.log_parallel", - "value": "false" - }, { - "name": "system.totalordermulticast.log_to_disk", - "value": "false" - }, { - "name": "system.totalordermulticast.maxbatchsize", - "value": "400" - }, { - "name": "system.totalordermulticast.nonces", - "value": "10" - }, { - "name": "system.totalordermulticast.revival_highMark", - "value": "10" - }, { - "name": "system.totalordermulticast.state_transfer", - "value": "true" - }, { - "name": "system.totalordermulticast.sync_ckp", - "value": "false" - }, { - "name": "system.totalordermulticast.sync_log", - "value": "false" - }, { - "name": "system.totalordermulticast.timeout", - "value": "2000" - }, { - "name": "system.totalordermulticast.timeout_highMark", - "value": "200" - }, { - "name": "system.totalordermulticast.verifyTimestamps", - "value": "false" - }, { - "name": "system.ttp.id", - "value": "7002" - }] - }, - "cryptoSetting": { - "autoVerifyHash": true, - "hashAlgorithm": 8216, - "supportedProviders": [{ - "algorithms": [{}, {}, {}, {}, {}, {}, {}], - "name": "com.jd.blockchain.crypto.service.classic.ClassicCryptoService" - }, { - "algorithms": [{}, {}, {}], - "name": "com.jd.blockchain.crypto.service.sm.SMCryptoService" - }] - }, - "participantNodes": [{ - "address": "LdeNgXM4J1SybrdUn71KdPhwBYvJzZ6xUG5Rd", - "id": 0, - "name": "a.com", - "pubKey": { - "value": "7VeRMXAkf3zoqr4N2RgLZ83xAv7wurqu6Vxak1V1GHv4Kfe3" - } - }, { - "address": "LdeNwbLhiAHQCVxnXsyKLhgcmUi2fuwYd6jkh", - "id": 1, - "name": "b.com", - "pubKey": { - "value": "7VeRAt79WPnMQ7TsM5cfhy2ERwVLu8fXbDezfFb6bT9BgYaZ" - } - }, { - "address": "LdeNgVjFaUTzsSHySB3ZrBaLiEeZebLkkyWFP", - "id": 2, - "name": "c.com", - "pubKey": { - "value": "7VeR9rnFNzgECCYGF8V3G36xhF3X9rr6YzqfN8h6CojgLpEY" - } - }, { - "address": "LdeNgVAkBAAdKLD1z3Nb7n5vtGujfqWdhx8G7", - "id": 3, - "name": "d.com", - "pubKey": { - "value": "7VeRPkXMyHFvpPf2jayHjiLX8H7CAcTJpF9F1FARogiroSK2" - } - }], - "participantsHash": { - "value": "j5hQErg4epzNh38FR3EABx8YJqPkLYZoY828giAyKpCXMd" - }, - "seed": "932dfe23-fe23232f-283f32fa-dd32aa76-8322ca2f-56236cda-7136b322-cb323ffe" - }, - "success": true -} - - -``` - -说明 - -|名称|说明| -|---|---| -|seed|账本种子信息| -|consensusProtocol|共识协议,以字符串方式显示| -|consensusSettings|共识配置,不同共识协议内容不同,上述示例为BFTSmart相关配置| -|cryptoSetting|密码相关配置| -|cryptoSetting.hashAlgorithm|Hash算法Code(8216代表SHA256)| -|cryptoSetting.autoVerifyHash|是否自动校验Hash| -|cryptoSetting.supportedProviders|支持的算法库| -|participantNodes|参与方列表信息| -|participantNodes.id|参与方序号| -|participantNodes.address|参与方地址| -|participantNodes.name|参与方名称| -|participantNodes.pubKey.value|参与方公钥信息| -|participantsHash.value|参与方根Hash| - - - -## 3 区块 - -### 3.1 获取最新区块 - -```http -GET /ledgers/{ledger}/blocks/latest -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/latest -``` - -#### 返回实例 - -```json -{ - "data": { - "ledgerHash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "previousHash": { - "value": "6EJZnMc9464DCSU2kgi96RyngEv8YeEfVoJNhH3yZ2v5T" - }, - "transactionSetHash": { - "value": "6LmZtDpMM7xE8FPChACEmLj1PLhfaoVM2rEHRsrV3ohPN" - }, - "userAccountSetHash": { - "value": "67jx7SctrwdSczxxuYjwBocA8fER7V8qcRZUzWamSav5p" - }, - "contractAccountSetHash": { - "value": "67ftaBhPDez24NEB9wiiTM3SNcn1XFz5rb7boYhpbbLXN" - }, - "adminAccountHash": { - "value": "69KEFp9m5iFyAiyGmJ2qPcVxuT79gMChMf9JkStBZe8aa" - }, - "dataAccountSetHash": { - "value": "6LB9gosVWEPG3uvWXkxTcWq22mcwMHVehbiXkavFtr5fZ" - }, - "hash": { - "value": "67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL" - }, - "height": 66 - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|hash|区块哈希| -|ledgerHash|账本哈希| -|previousHash|前置区块哈希| -|transactionSetHash|交易集哈希| -|userAccountSetHash|用户集哈希| -|contractAccountSetHash|合约集哈希| -|adminAccountHash|管理员集哈希| -|dataAccountSetHash|数据账户集哈希| - -### 3.2 根据区块哈希获取区块详细信息 - -```http -GET /ledgers/{ledger}/blocks/hash/{block_hash} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_hash|是|区块哈希|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/67XsKWgqZTBz1NsytKGpyNWHMbMRENWcBj8PEDYQnWiDL -``` - -#### 返回实例 - -[参考](#block-detail) - - -### 3.3 根据区块高度获取区块详细信息 - -```http -GET /ledgers/{ledger}/blocks/height/{block_height} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_height|是|区块高度|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66 -``` - -#### 返回实例 - -[参考](#block-detail) - - -### 3.4 根据哈希查询区块总数 - -```http - GET /ledgers/{ledger}/blocks/count/search?keyword={keyword} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 区块哈希的全部或者一部分|string| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/count/search?keyword=6D5M -``` - -#### 返回实例 - -```json -{ - "data": 26, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|查询到的区块总数| - -### 3.5 根据哈希查询区块 - -```http - GET /ledgers/{ledger}/blocks/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 区块哈希的全部或者一部分|string| -|**query**|**start_index**|否| 查询区块结果起始序号,默认为0|string| -|**query**|**count**|否| 查询区块结果返回数量,默认最大值为100,小于0或大于100均返回最大可返回结果集|string| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/search?keyword=6D5M&fromIndex=0&count=-1 -``` - - -#### 返回实例 - -```json -{ - "data": { - "blocks": [ - { - "hash": "6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb" - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|blocks|查询到的区块列表| -|hash|区块哈希值| -|height|区块高度| -|txCount|区块内交易数量| - -## 4 交易 - -### 4.1 获取账本交易总数 - -```http -GET /ledgers/{ledger}/txs/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/count -``` - -##### 返回实例 - -```json -{ - "data": 688, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|交易数量| - -### 4.2 根据区块高度查询区块内的交易数量 - -```http -GET /ledgers/{ledger}/blocks/height/{block_height}/txs/additional-count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_height|是|区块高度|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66/txs/additional-count - -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs/additional-count -``` - -#### 返回实例 - -```json -{ - "data": 86, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|交易数量| - - -### 4.3 根据区块哈希查询区块内的交易数量 - -```http -GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs/additional-count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|block_hash|是|区块哈希|字符串| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs/additional-count -``` - -#### 返回实例 - -```json -{ - "data": 86, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|交易数量| - - -### 4.4 获取指定高度的区块交易列表 - -```http -GET /ledgers/{ledger}/blocks/height/{height}/txs?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|height|是|区块高度|数字| -|query|start_index|否|查询交易的起始序号,默认为0|数字| -|query|count|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/height/66/txs?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [ - { - "blockHeight": 1, - "executionState": "SUCCESS", - "transactionContent": { - "ledgerHash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "operations": [ - { - "userID": { - "address": { - "value": "5SmBgzsrnY6u9Y7DgSSkXfTkCgp83hiFin3v" - }, - "pubKey": { - "value": "mb5kukaqjWtXyAerfHU1JDtVwabSeBU5c3khMZbNh7R8VJ" - } - } - }, - { - "accountID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - }, - { - "contractID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - }, - "chainCode": "----------" - }, - { - "contractAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - }, - "event": "----------", - "args": "----------" - }, - { - "writeSet": [{ - "key": "jdchain", - "value": { - "type": "TEXT", - "value": { - "value": "----------" - } - }, - "expectedVersion": 0 - }], - "accountAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - ], - "hash": { - "value": "6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA" - } - }, - "endpointSignatures": [ - { - "digest": { - "value": "42pbfM5YKnf39Gitr4UsjTCzhhnJjwNyi8MnLFYgP4VKewTLzHitzArHEMrCt3hZYUe5ex9XvqtmiCoWpeAbdc31F" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ], - "nodeSignatures": [ - { - "digest": { - "value": "66SQ95SbDaApAJhN2NsFx5sfAQTxsWhMW26D5iPqXc1jZU9rJEhRnqT1nzt62ZAcCvsfrjEsay3MxqXYA5tWPoA2U" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ] - } - ], - "success": true -} -``` - - -说明 - -|名称|说明| -|---|---| -|executionState|交易执行结果| -|transactionContent.hash|交易的哈希| -|transactionContent.operations|交易的操作列表| -|endpointSignatures|终端签名列表| -|nodeSignatures|节点的签名列表| - -### 4.5 获取指定哈希的区块的交易列表 - -```http -GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|block_hash|是|区块哈希|字符串| -|query|start_index|否|查询交易的起始序号,默认为0|数字| -|query|count|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/blocks/hash/6D5MJZnybT69bXET5QdCZdLGT16rZBJEjxLkANmDuykcb/txs?fromIndex=0&count=-1 -``` - -#### 返回实例 - -[参考](#tx-list) - - -### 4.6 获取交易详细信息 - -```http -GET /ledgers/{ledger}/txs/hash/{tx_hash} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|tx_hash|是|交易哈希|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/hash/6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA -``` - -#### 返回实例 - -```json -{ - "data": { - "blockHeight": 1, - "executionState": "SUCCESS", - "transactionContent": { - "ledgerHash": { - "value": "657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs" - }, - "operations": [ - { - "userID": { - "address": { - "value": "5SmBgzsrnY6u9Y7DgSSkXfTkCgp83hiFin3v" - }, - "pubKey": { - "value": "mb5kukaqjWtXyAerfHU1JDtVwabSeBU5c3khMZbNh7R8VJ" - } - } - }, - { - "accountID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - }, - { - "contractID": { - "address": { - "value": "5SmA98VknTbZ1Z7fmbNPHBuN2pbD89ogy8Ha" - }, - "pubKey": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - }, - "chainCode": "----------" - }, - { - "contractAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - }, - "event": "----------", - "args": "----------" - }, - { - "writeSet": [{ - "key": "jdchain", - "value": { - "type": "TEXT", - "value": { - "value": "----------" - } - }, - "expectedVersion": 0 - }], - "accountAddress": { - "value": "mbC8hzmYBz2SsLLqwoBXAJiGeHrCnByBEvcaUZWscAiPqR" - } - } - ], - "hash": { - "value": "6BLtM1agb7ERKoN5AJgZKiTjzdS7BpjgzQNYK8ZeDqotA" - } - }, - "endpointSignatures": [ - { - "digest": { - "value": "42pbfM5YKnf39Gitr4UsjTCzhhnJjwNyi8MnLFYgP4VKewTLzHitzArHEMrCt3hZYUe5ex9XvqtmiCoWpeAbdc31F" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ], - "nodeSignatures": [ - { - "digest": { - "value": "66SQ95SbDaApAJhN2NsFx5sfAQTxsWhMW26D5iPqXc1jZU9rJEhRnqT1nzt62ZAcCvsfrjEsay3MxqXYA5tWPoA2U" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - } - } - ] - }, - "success": true -} -``` - -说明 - -[参考](#tx-keyword) - - -### 4.7 根据哈希查询交易总数 - -```http - GET /ledgers/{ledgers}/txs/count/search?keyword={keyword} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledgers**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是|交易哈希,签名者公钥,或者节点公钥的全部或者部分的|string| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/search?keyword=6BLt -``` - -#### 返回实例 - -```json -{ - "data": 36, - "success": true -} -``` - - -说明 - -|名称|说明| -|---|---| -|data|指定交易数量| - - -### 4.8 根据哈希查询交易 - -```http - GET /ledgers/{ledgers}/txs/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledgers**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是|交易哈希,签名者公钥,或者节点公钥的全部或者部分的|string| -|**query**|**start_index**|否|查询交易的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/txs/search?keyword=6BLt -``` - - -#### 返回 - -```json -{ - "data": { - "txs": [ - { - "hash": "6L3ehswCmC1jqBfvGJP9vaPx8qxkLsieu2aRgYepmkiw3" - } - ] - }, - "success": true -} -``` - -## 5 用户 - -### 5.1 获取用户总数 - -```http -GET /ledgers/{ledger}/users/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/count -``` - -#### 返回实例 - -```json -{ - "data": 4, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|用户总数| - - -### 5.2 获取用户列表 - -```http -GET /ledgers/{ledger}/users?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询用户的起始序号,默认为0|数字| -|query|count|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data":[{ - "address": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - }, - "rootHash": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|用户地址| -|pubKey.value|用户公钥| - - -### 5.3 获取用户详细信息 - -```http -GET /ledgers/{ledger}/users/address/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|用户地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/address/55SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522 -``` - -#### 返回实例 - -```json -{ - "data": { - "address": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - }, - "pubKey": { - "value": "mb5kbwzACnhK9P1dVxgMPB2ySJLFyJKQbHpH7T9oRK3LpS" - }, - "rootHash": { - "value": "5SmFzgFtHtpbJwMCsmWTwjNGTk6SeMKU1522" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|用户地址| -|pubKey.value|用户公钥| -|rootHash.value|用户根Hash| - - -### 5.4 用户查询数量 - -```http - GET /ledgers/{ledger}/users/count/search?keyword={keyword} -``` - -#### 说明 - -用户有公钥和地址两个属性,可以通过公钥或者地址查找特定用户数量,也可以返回全部用户的数量 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 用户的公钥或者地址的全部或者部分|string| -|**query**|**start_index**|否|查询用户的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/count/search?keyword=5Sm -``` - -#### 返回实例 - -```json -{ - "data": 4, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|用户数量| - -### 5.5 用户查询 - -```http - GET /ledgers/{ledger}/users/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -用户有公钥和地址两个属性,可以通过公钥或者地址查找特定用户,也可以返回全部用户的列表 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 用户的公钥或者地址的全部或者部分|string| -|**query**|**start_index**|否|查询用户的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/users/search?keyword=5Sm&fromIndex=0&count=-1 -``` - - -#### 返回实例 - -```json -{ - "data": { - "users": [ - { - "address": { - "value": "5SmAGKgmXyj5VsVvJgHbYCJ67iTizwSkNpw1" - }, - "pubKey": { - "value": "mb97eG4bba2EjrgjXYiD9chAstjg4HaNuV5xgCtSHc5TeB" - } - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|用户地址| -|pubKey.value|用户公钥| -|rootHash.value|用户根Hash| - -## 6 数据账户 - -### 6.1 获取账户列表 - -```http -GET /ledgers/{ledger}/accounts?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询数据账户的起始序号,默认为0|数字| -|query|count|否|查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data":[{ - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - - -### 6.2 获取账户详细信息 - -```http -GET /ledgers/{ledger}/accounts/address/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa -``` - -#### 返回实例 - -```json -{ - "data": { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - - -### 6.3 获取账户总数 - -```http -GET /ledgers/{ledger}/accounts/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/count -``` - -#### 返回实例 - -```json -{ - "data": 18, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账户数量| - - -### 6.4 查询数据账户匹配的数量 - -```http -GET /ledgers/{ledger}/accounts/count/search?keyword={keyword} -``` - -#### 说明 - -通过账户的公钥和地址的全部或者部分查询特定账户的总数量,也可以通过KV值的Key来查询含有该Key的账户的总数量 - - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|字符串 -|**query**|**keyword**|是|数据账户的公钥或者地址的全部或者部分,或者是KV值的key|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/count/search?keyword=jd -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|账户数量| - - -### 6.5 查询数据账户 - -```http - GET /ledgers/{ledger}/accounts/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -通过账户的公钥和地址的全部或者部分查询特定账户,也可以通过KV值的Key来查询含有该Key的账户 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是| 数据账户的公钥或者地址的全部或者部分,或者是KV值的key|string| -|**query**|**start_index**|否|查询数据账户的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/search?keyword=5Sm5V&fromIndex=0&count=-1 -``` - - -#### 返回实例 - -```json -{ - "data": { - "accounts": [ - { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|数据账户根Hash| - - -### 6.6 获取某数据账户KV总数 - -```http - GET /ledgers/{ledger}/accounts/address/{address}/entries/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries/count -``` - -#### 返回实例 - -```json -{ - "data": 66, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|KV总数| - - -### 6.7 获取某数据账户KV详情 - -```http - GET/POST /ledgers/{ledger}/accounts/address/{address}/entries?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 -|form|keys|是|key详细内容列表|字符串 -|query|start_index|否|查询数据账户对应KV的起始序号,默认为0|数字| -|query|count|否|查询返回数据账户对应KV的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -> keys说明: - 1)keys使用表单方式提交,且keys为需要查询Key的列表,列表中每个Key都需要为完整Key - 2)Key提交方式使用GET或POST均可 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries -``` - -说明:表单提交参数为keys={"jd", "jdchain"} - - -#### 返回实例 - -```json -{ - "data": [ - { - "key": "jd", - "version": 0, - "type": "TEXT", - "value": "www.jd.com" - }, - { - "key": "jdchain", - "version": 0, - "type": "TEXT", - "value": "www.blockchain.com" - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|key|键| -|version|版本号| -|type|value类型| -|value|值| - - - - -### 6.8 获取某数据账户KV整个历史详情 - -```http - GET/POST /ledgers/{ledger}/accounts/{address}/entries-version -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|账户地址|字符串 -|form|KVInfoVO|是|Key相关信息|对象 - -KVInfoVO对应格式如下: - -```json - -{ - "data": [{ - "key": "zhangsan", - "version": [0, 1, 2] - }, { - "key": "lisi", - "version": [0, 1] - }] -} - -``` - -KVInfoVO说明: - + 1)支持多个Key作为入参; - - + 2)每个Key支持多个version; - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/entries-version -``` - - -#### 返回实例 - -```json -{ - "data": [ - { - "key": "jd", - "version": 0, - "type": "TEXT", - "value": "www.jd.com" - }, - { - "key": "jdchain", - "version": 0, - "type": "TEXT", - "value": "www.blockchain.com" - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|key|键| -|version|版本号| -|type|value类型| -|value|值| - -### 6.9 查询某数据账户键数量 -``` -GET /ledgers/{ledger}/accounts/address/{address}/keys/count/search?keyword={keyword} -``` -#### 参数 -请求类型 | 名称 | 是否必需 | 说明 | 数据类型 ---- | --- | --- | --- | --- -path | ledger | 是 | 所要搜索的账本,需要完整的账本哈希 | string -path | address | 是 | 所要搜索的数据账户地址,需要完整的数据账户地址 | string -query | keyword | 否 | 键的部分字符,空表示全部 | string - -#### 请求实例 -``` -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/keys/count/search?keyword=j -``` -#### 返回实例 -``` -{ "data": 66, "success": true } -``` -说明 - -名称 | 说明 ---- | --- -data | 条件查询键总数 - -### 6.10 查询某数据账户键 -``` -GET /ledgers/{ledger}/accounts/address/{address}/keys/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` -#### 参数 -请求类型 | 名称 | 是否必需 | 说明 | 数据类型 ---- | --- | --- | --- | --- -path | ledger | 是 | 所要搜索的账本,需要完整的账本哈希 | string -path | address | 是 | 所要搜索的数据账户地址,需要完整的数据账户地址 | string -query | keyword | 否 | 键的部分字符,空表示全部 | string -query | start_index | 否 | 查询数据账户对应Key的起始序号,默认为0 | 数字 -query | count | 否 | 查询返回数据账户对应Key的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集 | 数字 - -#### 请求实例 -``` -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/accounts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa/keys/search?keyword=j&fromIndex=0&count=-1 -``` -#### 返回实例 -``` -{ "data": [ { "key": "jd" }, { "key": "jdchain" }], "success": true } -``` -说明 - -名称 | 说明 ---- | --- -key | 键 - -## 7 搜索 - -### 7.1 搜索区块链 - -```http - GET /ledgers/{ledger}/all/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -通过关键字搜索区块数据,支持区块哈希,交易哈希,用户公钥和地址,合约公钥和地址,数据账户哈希和地址的搜索 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本,需要完整的账本哈希|string| -|**query**|**keyword**|是|关键字|string| -|**query**|**start_index**|否|查询匹配结果的起始序号,默认为0|数字| -|**query**|**count**|否|查询匹配结果的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/all/search?keyword=5Sm5V&fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "message": "OK", - "code": 0, - "data": { - "blocks": ..., - "txs": ..., - "users": ..., - "accounts": ..., - "contracts": ..., - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|blocks|[参考](#query-blocks-result)| -|txs|[参考](#query-txs-result)| -|users|[参考](#query-users-result)| -|accounts|[参考](#query-accounts-result)| -|contracts|[参考](#query-contracts-result)| - -## 8 合约 - -### 8.1 获取合约列表 - -```http -GET /ledgers/{ledger}/contracts?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|query|start_index|否|查询合约的起始序号,默认为0|数字| -|query|count|否|查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data": [{ - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - - -### 8.2 获取合约详细信息 - -```http -GET /ledgers/{ledger}/contracts/address/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 -|path|address|是|合约地址|字符串 - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/address/5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa -``` - -#### 返回实例 - -```json -{ - "data": { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| -|rootHash.value|默克尔树根哈希| - -### 8.3 获取合约总数 - -```http -GET /ledgers/{ledger}/contracts/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串 - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/count -``` - -#### 返回实例 - -```json -{ - "data": 27, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|合约数量| - - -### 8.4 查询指定合约数量 - -```http -GET /ledgers/{ledger}/contracts/count/search?keyword={keyword} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是| 合约的公钥或者地址的全部或者一部分|string| - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/count/search?keyword=5Sm2 -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|合约数量| - -### 8.5 合约查询 - -```http - GET /ledgers/{ledger}/contracts/search?keyword={keyword}&fromIndex={start_index}&count={count} -``` - -#### 说明 - -合约有公钥和地址两个属性,可以通过合约的这两个属性查询特定合约,也可以返回一个当前所有合约的列表 - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|**path**|**ledger**|是|所要搜索的账本范围,需要完整的账本哈希|string| -|**query**|**keyword**|是| 合约的公钥或者地址的全部或者一部分|string| -|**query**|**start_index**|否|查询合约的起始序号,默认为0|数字| -|**query**|**count**|否|查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts/earch?keyword=5Sm2&fromIndex=0&count=-1 -``` - - -#### 返回 - -```json -{ - "data": { - "contracts": [ - { - "address": { - "value": "5Sm4gWXrNpDWW9Boi4xZCzZMHboRvEDm29Fa" - }, - "rootHash": { - "value": "6GiAH2PBRLnoE724ia83bKVijkKsNuNU5danA4AAi5qMM" - }, - "pubKey": { - "value": "mavweXqvKGUAJzSxE9S15pV7c7qe9bgUn5R1HwpqmXVTUs" - } - } - ] - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|合约地址| -|pubKey.value|合约公钥| -|rootHash|合约根Hash| - -## 9 用户自定义事件 - -### 9.1 获取事件账户列表 - -```http -GET /ledgers/{ledger}/events/user/accounts?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|query|start_index|否|查询的起始序号,默认为0|数字| -|query|count|否|查询返回事件账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts?fromIndex=0&count=-1 -``` - -#### 返回实例 - -```json -{ - "data":[ - { - "address":{ - "value":"LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1" - }, - "pubKey":{ - "value":"7VeRBi3xDfT1E11vFs9q5Q9gFo23RR7SoobPzivqxw9Uubzq" - } - } - ], - "success":true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| - -### 9.2 获取事件账户 - -```http -GET /ledgers/{ledger}/events/user/accounts/{address} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|address|账户地址|是|事件账户地址|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1 -``` - -#### 返回实例 - -```json -{ - "data":[ - { - "address":{ - "value":"LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1" - }, - "pubKey":{ - "value":"7VeRBi3xDfT1E11vFs9q5Q9gFo23RR7SoobPzivqxw9Uubzq" - } - } - ], - "success":true -} -``` - -说明 - -|名称|说明| -|---|---| -|address.value|账户地址| -|pubKey.value|账户公钥| - -### 9.3 获取事件账户总数 - -```http -GET /ledgers/{ledger}/events/user/accounts/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/count -``` - -#### 返回实例 - -```json -{ - "data": 1, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|事件账户数量| - -### 9.4 获取事件名数量 - -```http -GET /ledgers/{ledger}/events/user/accounts/{address}/names/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|address|是|事件账户地址|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/count -``` - -#### 返回实例 - -```json -{ - "data": 2, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|事件名数量| - -### 9.5 获取事件名列表 - -```http -GET /ledgers/{ledger}/events/user/accounts/{address}/names?fromIndex={start_index}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|address|是|事件账户地址|字符串| -|query|start_index|否|查询的起始序号,默认为0|数字| -|query|count|否|查询返回事件账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names?fromIndex=0&count=100 -``` - -#### 返回实例 - -```json -{ - "data": ["test1", "test2"], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|事件名数量数组| - -### 9.6 获取最新事件 - -```http -GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}/latest -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|address|是|事件账户地址|字符串| -|path|event_name|是|事件名|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/test1/latest -``` - -#### 返回实例 - -```json -{ - "data": { - "sequence": 0, - "transactionSource": { - "value": "j5rENX3rsdEgi5toeNUUv7ycUUivjNxAUb9Fme6oLCU851" - }, - "blockHeight": 10, - "contractSource": "", - "eventAccount": { - "value": "LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1" - }, - "name": "test1", - "content": { - "nil": false, - "bytes": { - "value": "Ctt6Eur" - }, - "type": "TEXT", - "value": "imuge" - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|sequence|事件序列| -|transactionSource.value|交易哈希| -|blockHeight|时间产生区块高度| -|contractSource|合约地址| -|eventAccount.value|事件账户地址| -|name|事件名| -|content.nil|事件内容是否为空| -|content.bytes.value|事件内容字节| -|content.type|事件内容类型| -|content.value|事件内容| - -### 9.7 获取事件数量 - -```http -GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}/count -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|address|是|事件账户地址|字符串| -|path|event_name|是|事件名|字符串| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/test1/count -``` - -#### 返回实例 - -```json -{ - "data": 1, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|事件数量| - -### 9.8 获取事件列表 - -```http -GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}?fromSequence={from_sequence}&count={count} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型| -|---|---|---|---|---| -|path|ledger|是|账本哈希|字符串| -|path|address|是|事件账户地址|字符串| -|path|event_name|是|事件名|字符串| -|query|from_sequence|否|查询的起始序号,默认为0|数字| -|query|count|否|查询返回事件的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| - - -#### 请求实例 -```http -http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/test1?fromSequenct=0&count=100 -``` - -#### 返回实例 - -```json -{ - "data": [{ - "sequence": 0, - "transactionSource": { - "value": "j5rENX3rsdEgi5toeNUUv7ycUUivjNxAUb9Fme6oLCU851" - }, - "blockHeight": 10, - "contractSource": "", - "eventAccount": { - "value": "LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1" - }, - "name": "test1", - "content": { - "nil": false, - "bytes": { - "value": "Ctt6Eur" - }, - "type": "TEXT", - "value": "imuge" - } - }], - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|data|事件列表| -|sequence|事件序列| -|transactionSource.value|交易哈希| -|blockHeight|时间产生区块高度| -|contractSource|合约地址| -|eventAccount.value|事件账户地址| -|name|事件名| -|content.nil|事件内容是否为空| -|content.bytes.value|事件内容字节| -|content.type|事件内容类型| -|content.value|事件内容| - -## 10.权限对外提供的API接口使用 -### 10.1根据角色获取权限信息 -```http -GET /ledgers/{ledgerHash}/authorization/role/{roleName} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|get|ledger|是|账本哈希|字符串 -|--|roleName|是|角色名|字符串 - - -#### 请求实例 -```http -http://localhost:11000/ledgers/j5pSJLyVpS8QG2wL95fiDWHHnweh2YdqNhgmnb64SBMjUh/authorization/role/DEFAULT -``` - -#### 返回实例 - -```json -{ - "data": { - "roleName": "DEFAULT", - "transactionPrivilege": { - "privilege": [ - "DIRECT_OPERATION", - "CONTRACT_OPERATION" - ], - "permissionCount": 2 - }, - "ledgerPrivilege": { - "privilege": [ - "CONFIGURE_ROLES", - "AUTHORIZE_USER_ROLES", - "SET_CONSENSUS", - "SET_CRYPTO", - "REGISTER_PARTICIPANT", - "REGISTER_USER", - "REGISTER_DATA_ACCOUNT", - "REGISTER_CONTRACT", - "UPGRADE_CONTRACT", - "SET_USER_ATTRIBUTES", - "WRITE_DATA_ACCOUNT", - "APPROVE_TX", - "CONSENSUS_TX", - "REGISTER_EVENT_ACCOUNT", - "WRITE_EVENT_ACCOUNT" - ], - "permissionCount": 15 - }, - "version": 0 - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|roleName|角色名称| -|transactionPrivilege|交易权限| -|transactionPrivilege -> privilege|交易权限->权限类别| -|transactionPrivilege -> permissionCount|交易权限->权限总数| -|ledgerPrivilege|账本权限| -|ledgerPrivilege -> privilege|账本权限->权限类别| -|ledgerPrivilege -> permissionCount|账本权限->权限总数| - -### 10.2根据用户获取权限信息 - -```http -GET /ledgers/{ledgerHash}/authorization/user/{userAddress} -``` - -#### 参数 - -|请求类型|名称|是否必需|说明|数据类型 -|---|---|---|---|---| -|get|ledger|是|账本哈希|字符串 -|--|userAddress|是|用户地址|字符串 - - -#### 请求实例 -```http -http://localhost:11000/ledgers/j5pSJLyVpS8QG2wL95fiDWHHnweh2YdqNhgmnb64SBMjUh/authorization/user/LdeNwH71wxtbf1UM8ExRG8qbPnu17MdnRSVva -``` - -#### 返回实例 - -```json -{ - "data": { - "userAddress": { - "value": "LdeNwH71wxtbf1UM8ExRG8qbPnu17MdnRSVva" - }, - "transactionPrivilegesBitset": { - "privilege": [ - "DIRECT_OPERATION" - ], - "permissionCount": 1 - }, - "userRole": [ - "MANAGER1", - "MANAGER0" - ], - "ledgerPrivilegesBitset": { - "privilege": [ - "CONFIGURE_ROLES", - "REGISTER_USER" - ], - "permissionCount": 2 - } - }, - "success": true -} -``` - -说明 - -|名称|说明| -|---|---| -|userRole|用户角色| -|transactionPrivilegesBitset|交易权限集| -|ledgerPrivilegesBitset|账本权限集| diff --git a/deploy/deploy-gateway/src/main/resources/docs/code_example.MD b/deploy/deploy-gateway/src/main/resources/docs/code_example.MD deleted file mode 100644 index 2f429d3f..00000000 --- a/deploy/deploy-gateway/src/main/resources/docs/code_example.MD +++ /dev/null @@ -1,361 +0,0 @@ -# 1. maven坐标 -```java - - com.jd.blockchain - sdk-client - 1.4.0.RELEASE - - - com.jd.blockchain - contract-starter - 1.4.0.RELEASE - - - com.jd.blockchain - crypto-classic - 1.4.0.RELEASE - - - - com.jd.blockchain - crypto-sm - 1.4.0.RELEASE - -``` -# 2. 数据快速上链 -## 2.1. 服务连接 - -```java - //使用已注册用户信息进行连接; - String GW_PUB_KEY = "3snxxx"; - String GW_PRIV_KEY = "177xxx"; - String GW_PASSWORD = "xxx"; - PrivKey gwPrivkey0 = KeyGenUtils.decodePrivKey(GW_PRIV_KEY, GW_PASSWORD); - PubKey gwPubKey0 = KeyGenUtils.decodePubKey(GW_PUB_KEY); - BlockchainKeypair adminKey = new BlockchainKeypair(gwPubKey0, gwPrivkey0); - //创建服务代理 - final String GATEWAY_IP = "127.0.0.1"; - final int GATEWAY_PORT = 80; - final boolean SECURE = false; - GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, - adminKey); - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - HashDigest[] ledgerHashs = service.getLedgerHashs(); - // 获取当前账本Hash - HashDigest ledgerHash = ledgerHashs[0]; -``` -## 2.2. 用户注册 -```java - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - // 在本地定义注册账号的 TX; - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); - - txTemp.users().register(user.getIdentity()); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - // 使用私钥进行签名; - prepTx.sign(adminKey); - // 提交交易; - prepTx.commit(); -``` -## 2.3. 数据账户注册 -```java - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - // 在本地定义注册账号的 TX; - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); - - txTemp.dataAccounts().register(dataAccount.getIdentity()); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - // 使用私钥进行签名; - prepTx.sign(adminKey); - - // 提交交易; - prepTx.commit(); -``` -## 2.4. 写入数据 -```java - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - - // 在本地定义注册账号的 TX; - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - - // -------------------------------------- - // 将商品信息写入到指定的账户中; - // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; - String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; - txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", "value1", -1); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - - String txHash = Base64Utils.encodeToUrlSafeString(prepTx.getHash().toBytes()); - // 使用私钥进行签名; - prepTx.sign(adminKey); - - // 提交交易; - prepTx.commit(); -``` -## 2.5. 查询数据 - -> 注:详细的查询可参考模块sdk-samples中SDK_GateWay_Query_Test_相关测试用例 - -```java - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - - // 查询区块信息; - // 区块高度; - long ledgerNumber = service.getLedger(ledgerHash).getLatestBlockHeight(); - // 最新区块; - LedgerBlock latestBlock = service.getBlock(ledgerHash, ledgerNumber); - // 区块中的交易的数量; - long txCount = service.getTransactionCount(ledgerHash, latestBlock.getHash()); - // 获取交易列表; - LedgerTransaction[] txList = service.getTransactions(ledgerHash, ledgerNumber, 0, 100); - // 遍历交易列表 - for (LedgerTransaction ledgerTransaction : txList) { - TransactionContent txContent = ledgerTransaction.getTransactionContent(); - Operation[] operations = txContent.getOperations(); - if (operations != null && operations.length > 0) { - for (Operation operation : operations) { - operation = ClientResolveUtil.read(operation); - // 操作类型:数据账户注册操作 - if (operation instanceof DataAccountRegisterOperation) { - DataAccountRegisterOperation daro = (DataAccountRegisterOperation) operation; - BlockchainIdentity blockchainIdentity = daro.getAccountID(); - } - // 操作类型:用户注册操作 - else if (operation instanceof UserRegisterOperation) { - UserRegisterOperation uro = (UserRegisterOperation) operation; - BlockchainIdentity blockchainIdentity = uro.getUserID(); - } - // 操作类型:账本注册操作 - else if (operation instanceof LedgerInitOperation) { - - LedgerInitOperation ledgerInitOperation = (LedgerInitOperation)operation; - LedgerInitSetting ledgerInitSetting = ledgerInitOperation.getInitSetting(); - - ParticipantNode[] participantNodes = ledgerInitSetting.getConsensusParticipants(); - } - // 操作类型:合约发布操作 - else if (operation instanceof ContractCodeDeployOperation) { - ContractCodeDeployOperation ccdo = (ContractCodeDeployOperation) operation; - BlockchainIdentity blockchainIdentity = ccdo.getContractID(); - } - // 操作类型:合约执行操作 - else if (operation instanceof ContractEventSendOperation) { - ContractEventSendOperation ceso = (ContractEventSendOperation) operation; - } - // 操作类型:KV存储操作 - else if (operation instanceof DataAccountKVSetOperation) { - DataAccountKVSetOperation.KVWriteEntry[] kvWriteEntries = - ((DataAccountKVSetOperation) operation).getWriteSet(); - if (kvWriteEntries != null && kvWriteEntries.length > 0) { - for (DataAccountKVSetOperation.KVWriteEntry kvWriteEntry : kvWriteEntries) { - BytesValue bytesValue = kvWriteEntry.getValue(); - DataType dataType = bytesValue.getType(); - Object showVal = ClientResolveUtil.readValueByBytesValue(bytesValue); - System.out.println("writeSet.key=" + kvWriteEntry.getKey()); - System.out.println("writeSet.value=" + showVal); - System.out.println("writeSet.type=" + dataType); - System.out.println("writeSet.version=" + kvWriteEntry.getExpectedVersion()); - } - } - } - } - } - } - - // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; - HashDigest txHash = txList[0].getTransactionContent().getHash(); - Transaction tx = service.getTransactionByContentHash(ledgerHash, txHash); - // 获取数据; - String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; - String[] objKeys = new String[] { "x001", "x002" }; - TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys); - - long payloadVersion = kvData[0].getVersion(); - - // 获取数据账户下所有的KV列表 - TypedKVEntry[] kvDatas = service.getDataEntries(ledgerHash, commerceAccount, 0, 100); - if (kvData != null && kvData.length > 0) { - for (TypedKVEntry kvDatum : kvDatas) { - System.out.println("kvData.key=" + kvDatum.getKey()); - System.out.println("kvData.version=" + kvDatum.getVersion()); - System.out.println("kvData.type=" + kvDatum.getType()); - System.out.println("kvData.value=" + kvDatum.getValue()); - } - } -``` - -## 2.6. 合约发布 - -```java - - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - - // 在本地定义TX模板 - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - - // 合约内容读取 - byte[] contractBytes = FileUtils.readBytes(new File("CONTRACT_FILE")); - - // 生成用户 - BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate(); - - // 发布合约 - txTemp.contracts().deploy(contractKeyPair.getIdentity(), contractBytes); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - - // 使用私钥进行签名; - prepTx.sign(adminKey); - - // 提交交易; - TransactionResponse transactionResponse = prepTx.commit(); - - assertTrue(transactionResponse.isSuccess()); - - // 打印合约地址 - System.out.println(contractKeyPair.getIdentity().getAddress().toBase58()); -``` - -## 2.7. 合约执行 - -```java - - // 创建服务代理; - BlockchainService service = serviceFactory.getBlockchainService(); - - // 在本地定义TX模板 - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - - // 合约地址 - String contractAddress = ""; - - // 使用接口方式调用合约 - TransferContract transferContract = txTemp.contract(contractAddress, TransferContract.class); - - // 使用decode方式调用合约内部方法(create方法) - // 返回GenericValueHolder可通过get方法获取结果,但get方法需要在commit调用后执行 - String address = "address"; - String account = "fill account"; - long money = 100000000L; - GenericValueHolder result = ContractReturnValue.decode(transferContract.create(address, account, money)); - - PreparedTransaction ptx = txTemp.prepare(); - - ptx.sign(adminKey); - - TransactionResponse transactionResponse = ptx.commit(); - - String cotractExecResult = result.get(); - - // TransactionResponse也提供了可供查询结果的接口 - OperationResult[] operationResults = transactionResponse.getOperationResults(); - - // 通过OperationResult获取结果 - for (int i = 0; i < operationResults.length; i++) { - OperationResult opResult = operationResults[i]; - System.out.printf("Operation[%s].result = %s \r\n", - opResult.getIndex(), BytesValueEncoding.decode(opResult.getResult())); - } -``` - -## 2.8. 事件账户注册 -```java - BlockchainService service = serviceFactory.getBlockchainService(); - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - - BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate(); - txTemp.eventAccounts().register(eventAccount.getIdentity()); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - // 使用私钥进行签名; - prepTx.sign(adminKey); - - // 提交交易; - prepTx.commit(); -``` -## 2.9. 事件发布 -```java - BlockchainService service = serviceFactory.getBlockchainService(); - TransactionTemplate txTemp = service.newTransaction(ledgerHash); - - // 发布事件到指定的账户中; - String eventAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; - txTemp.eventAccount(eventAccount).publish("event_name", "string", -1) - .publish("event_name", 0, 0); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - - // 使用私钥进行签名; - prepTx.sign(adminKey); - - // 提交交易; - prepTx.commit(); -``` - -## 2.10. 事件监听 - -- 系统事件 -> 目前仅支持新区块产生事件 -```java - EventListenerHandle handler = blockchainService.monitorSystemEvent(ledgerHash, - SystemEvent.NEW_BLOCK_CREATED, 0, new SystemEventListener() { - @Override - public void onEvents(Event[] eventMessages, EventContext eventContext) { - for (Event eventMessage : eventMessages) { - BytesValue content = eventMessage.getContent(); - // content中存放的是当前链上最新高度 - System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); - } - - // 关闭监听的两种方式:1 - eventContext.getHandle().cancel(); - } - }); - - // 关闭监听的两种方式:2 - handler.cancel(); -``` - -- 用户自定义事件 -```java - EventListenerHandle handler = blockchainService.monitorUserEvent(ledgerHash, - eventAccount.getAddress().toBase58(), eventName, 0, new UserEventListener() { - @Override - public void onEvent(Event eventMessage, EventContext eventContext) { - BytesValue content = eventMessage.getContent(); - switch (content.getType()) { - case TEXT: - System.out.println(content.getBytes().toUTF8String()); - break; - case INT64: - System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); - break; - default: - break; - } - - // 关闭监听的两种方式:1 - eventContext.getHandle().cancel(); - } - }); - - // 关闭监听的两种方式:2 - handler.cancel(); -``` \ No newline at end of file diff --git a/deploy/deploy-gateway/src/main/resources/docs/design_contract-dev-manual.md b/deploy/deploy-gateway/src/main/resources/docs/design_contract-dev-manual.md deleted file mode 100644 index 676e1e77..00000000 --- a/deploy/deploy-gateway/src/main/resources/docs/design_contract-dev-manual.md +++ /dev/null @@ -1,436 +0,0 @@ -# 智能合约开发手册 -版本|修改时间|修改人 ----|:--:|---: -V1.0|2020-04-17|huanghaiquan - ---- - - - -### 1. 简介 - - JD Chain 智能合约系统由5个部分组成:合约代码语言、合约引擎、合约账户、合约开发框架、合约开发插件。 - - 合约代码语言是用来编写智能合约的编程语言,合约引擎是解释和执行合约代码的虚拟机。 - - JD Chain 账本中以合约账户的方式对合约代码进行管理。一份部署上链的合约代码需要关联到一个唯一的公钥上,并生成与公钥对应的区块链账户地址,在账本中注册为一个合约账户。在执行之前,系统从账本中读出合约代码并将其加载到合约引擎,由交易执行器调用合约引擎触发合约执行。 - - JD Chain 账本定义了一组标准的账本操作指令,合约代码的执行过程实质上是向账本输出一串操作指令序列,这些指令对账本中的数据产生了变更,形成合约执行的最终结果。 - - 合约开发框架定义了进行合约代码开发中需要依赖的一组编程接口和类库。合约开发插件提供了更方便与IDE集成的合约编译、部署工具,可以简化操作,并与持续集成过程结合。 - - JD Chain 以 Java 语言作为合约代码语言,合约引擎是基于 JVM 构建的安全沙盒。为了实现与主流的应用开发方式无缝兼容, JD Chain 支持以 Maven 来管理合约代码的工程项目,并提供相应的 maven 插件来简化合约的编译和部署。 - - >智能合约是一种可以由计算机执行的合同/协议。不同于现实生活中的合同是由自然语言来编写并约定相关方的权利和义务,智能合约是用合约代码语言来编写,以合约代码的形式存在和被执行。通过账本中的数据状态来表示合同/协议相关条款信息,合约代码的运行过程体现了合同/协议条款的执行,并记录相应的结果。 - -### 2. 快速入门 - - #### 2.1. 准备开发环境 - - 按照正常的 Java 应用开发环境要求进行准备,以 Maven 作为代码工程的构建管理工具,无其它特殊要求。 - - >检查 JDK 版本不低于 1.8 ,Maven 版本不低于 3.0。 - - #### 2.2. 创建合约代码工程 - 创建一个普通的 Java Maven 工程,打开 pom.xml 把 packaging 设为 contract . - - ``` xml - - - 4.0.0 - your.group.id - your.project - 0.0.1-SNAPSHOT - - contract - - - - - - - - - - - - - ``` - - > 注:合约代码工程也是一个普通的 Java Maven 工程,因此尽管不同 IDE 创建 Maven 工程有不同的操作方式,由于对于合约开发而言并无特殊要求,故在此不做详述。 - - #### 2.3. 加入合约开发依赖 - - 在合约代码工程 pom.xml 加入对合约开发 SDK 的依赖: - - ``` xml - - com.jd.blockchain - contract-starter - ${jdchain.version} - - ``` - - #### 2.4. 加入合约插件 - - 在合约代码工程的 pom.xml 加入 contract-maven-plugin 插件: - ``` xml - - com.jd.blockchain - contract-maven-plugin - ${jdchain.version} - true - - ``` - - 完整的 pom.xml 如下: - - ``` xml - - - - 4.0.0 - your.group.id - your.project - 0.0.1-SNAPSHOT - - contract - - - 1.2.0.RELEASE - - - - - - com.jd.blockchain - contract-starter - ${jdchain.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - UTF-8 - false - true - false - false - - - - - - com.jd.blockchain - contract-maven-plugin - ${jdchain.version} - true - - - - - - ``` - - #### 2.5. 编写合约代码 - - 2.5.1. **注意事项** - ``` - 1、不允许合约(包括合约接口和合约实现类)使用com.jd.blockchain开头的package; - 2、必须有且只有一个接口使用@Contract注解,且其中的event必须大于等于一个; - 3、使用@Contract注解的接口有且只有一个实现类; - 4、黑名单调用限制(具体黑名单可查看配置文件),需要注意的是,黑名单分析策略会递归分析类实现的接口和父类,也就是说调用一个实现了指定黑名单接口的类也是不允许的; - 目前设置的黑名单如下: - java.io.File - java.io.InputStream - java.io.OutputStream - java.io.DataInput - java.io.DataOutput - java.io.Reader - java.io.Writer - java.io.Flushable - java.nio.channels.* - java.nio.file.* - java.net.* - java.sql.* - java.lang.reflect.* - java.lang.Class - java.lang.ClassLoader - java.util.Random - java.lang.System-currentTimeMillis - java.lang.System-nanoTime - com.jd.blockchain.ledger.BlockchainKeyGenerator - ``` - - 2.5.2. **声明合约** - - ``` java - /** - * 声明合约接口; - **/ - @Contract - public interface AssetContract { - - @ContractEvent(name = "transfer") - String transfer(String address, String from, String to, long amount); - - } - ``` - - 2.5.3. **实现合约** - - ``` java - /** - * 实现合约; - * - * 实现 EventProcessingAware 接口是可选的,目的获得 ContractEventContext 上下文对象, - * 通过该对象可以进行账本操作; - */ - public class AssetContractImpl implements AssetContract, EventProcessingAware { - - // 合约事件上下文; - private ContractEventContext eventContext; - - /** - * 执行交易请求中对 AssetContract 合约的 transfer 调用操作; - */ - public String transfer(String address, String from, String to, long amount) { - //当前账本的哈希; - HashDigest ledgerHash = eventContext.getCurrentLedgerHash(); - //当前账本上下文; - LedgerContext ledgerContext = eventContext.getLedger(); - - //做操作; - // ledgerContext. - - //返回合约操作的结果; - return "success"; - } - - /** - * 准备执行交易中的合约调用操作; - */ - @Override - public void beforeEvent(ContractEventContext eventContext) { - this.eventContext = eventContext; - } - - /** - * 完成执行交易中的合约调用操作; - */ - @Override - public void postEvent(ContractEventContext eventContext, Exception error) { - this.eventContext = null; - } - } - ``` - #### 2.6. 编译打包合约代码 - - 合约代码工程的编译打包操作与普通的 maven 工程是相同的,在工程的根目录下输入以下命令: - - ``` bash - mvn clean package - ``` - - 执行成功之后,在 target 目录中输出合约代码文件 \.\.car 。 - - 如果合约代码加入了除 com.jd.blockchain:contract-starter 之外的其它依赖,默认配置下,第三方依赖包将与 .car 文件一起打包一起部署。(也可以把第三方依赖包独立打包,具体参见以下 “3. 合约插件详细配置” - - > 注意:合约代码虽然利用了 Java 语言,遵照 Java 语法进行编写,但本质上是作为一种运行于受限环境(合约虚拟机)的语言来使用,因而一些 Java 语法和 SDK 的 API 是不被允许使用的,在编译过程中将对此进行检查。 - - #### 2.7. 部署合约代码 - - ##### 2.7.1. 在项目中部署合约代码 - - 如果希望在构建打包的同时将合约代码部署到指定的区块链网络,可以在合约代码工程 pom.xml 的 contract-maven-plugin 插件配置中加入合约部署相关的信息(具体更详细的配置可以参考“3. 合约插件详细配置”)。 - - ``` xml - - com.jd.blockchain - contract-maven-plugin - 1.2.0.RELEASE - true - - - - - j5rpuGWVxSuUbU3gK7MDREfui797AjfdHzvAMiSaSzydu7 - - - - 192.168.10.10 - 8081 - - - - - 3snPdw7i7Po4fYcXFxS4QztR8Dm4kLBdBpjsemuGPZRyZRBmtn5Z5u - - - - - 7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq - 177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x - DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY - - - - - ``` - - 加入部署配置信息之后,对工程执行编译打包操作,输出的合约代码(.car)将自动部署到指定的区块链网络。 - - ``` bash - mvn clean deploy - ``` - ##### 2.7.2. 发布已编译好的car - 如果已经通过插件的打包方式,编译打包完成一个合约文件(.car),可通过命令行的方式进行发布,命令行要求与开发环境一致的Maven环境(包括环境变量及Setting都已配置完成)。 - - ``` bash - mvn com.jd.blockchain:contract-maven-plugin:${version}:deploy - -DcarPath= - -Dledger= - -DgatewayHost= - -DgatewayPort= - -DcontractPubKey= - -DcontractAddress= - -DsignerPubKey= - -DsignerPrivKey= - -DsignerPrivKeyPwd= - ``` - - 各参数说明如下: - - | 参数名 | 含义 |是否必填| - | ---- | ---- | ---- | - | ${version} | 合约插件的版本号 | 否,系统会自动选择发布的最新的RELEASE版本,SNAPSHOT版本必须填写 | - | carPath | 合约文件所在路径 | 是 | - | ledger | 账本Hash(Base58编码) | 否,会自动选择线上第一个账本| - | gatewayHost | 可访问的网关节点地址,域名或IP地址 | 是| - | gatewayPort | 网关节点监听端口 | 是 | - | contractPubKey | 合约账户的公钥(Base58编码)| 否,会自动创建 | - | contractAddress | 合约账户的地址(Base58编码)|否,会根据contractPubKey生成| - | signerPubKey | 合约签名公钥信息(Base58编码)|是| - | signerPrivKey | 合约签名私钥信息(Base58编码)|是| - | signerPrivKeyPwd | 合约签名私钥解密密钥(Base58编码)|是| - - -下面是一个示例,供参考: - -``` bash - mvn com.jd.blockchain:contract-maven-plugin:1.2.0.RELEASE:deploy \ - -DcarPath=/root/jdchain/contracts/contract-test-1.0-SNAPSHOT.car \ - -Dledger=j5tW5HUvMjEtm2yB7E6MHoSByoH1DXvMwvF2HurEgMSaLW \ - -DgatewayHost=127.0.0.1 \ - -DgatewayPort=11000 \ - -DcontractPubKey= 7VeRBsHM2nsGwP8b2ufRxz36hhNtSqjKTquzoa4WVKWty5sD \ - -DcontractAddress= LdeNt7sEmTirh9PmE7axKvA2txTrbB9kxz6KB \ - -DsignerPubKey=7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq \ - -DsignerPrivKey=177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x \ - -DsignerPrivKeyPwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY - ``` - - - > 重点说明: - 命令行中输入参数的优先级高于配置文件,就是说通过2.7.1方式发布合约时也可以采用命令行的参数(指-D相关配置),其优先级高于配置文件。 - -### 3. 合约插件详细配置 - - ``` xml - - com.jd.blockchain - contract-maven-plugin - 1.2.0.RELEASE - true - - - - - - false - - - - - 1 - - - MB - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - -
-
-
- ``` - -### 4. 最简化合约插件配置示例 - -在pom.xml中有部分配置是非必填项,下面是一份最简化的合约发布(deploy)配置示例,供参考: - - - ``` xml - - com.jd.blockchain - contract-maven-plugin - 1.2.0.RELEASE - true - - - - - - 127.0.0.1 - 8081 - - - - - 7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq - 177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x - DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY - - - - - ``` \ No newline at end of file diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 00000000..2c6822fe --- /dev/null +++ b/docs/api.md @@ -0,0 +1,2924 @@ +# 网关API + +[账本](#2-账本) +- [获取账本总数](#21-获取账本总数) +- [获取账本列表](#22-获取账本列表) +- [获取账本详细信息](#23-获取账本详细信息) +- [获取账本参与方总数](#24-获取账本参与方总数) +- [获取账本参与方列表](#25-获取账本参与方列表) +- [获取账本元数据信息](#26-获取账本元数据信息) +- [获取账本初始化配置信息](#27-获取账本初始化配置信息) +- [获取账本管理数据信息](#28-获取账本管理数据信息) + +[区块](#3-区块) +- [获取最新区块](#31-获取最新区块) +- [根据区块哈希获取区块详细信息](#32-根据区块哈希获取区块详细信息) +- [根据区块高度获取区块详细信息](#33-根据区块高度获取区块详细信息) + +[交易](#4-交易) +- [获取账本交易总数](#41-获取账本交易总数) +- [根据区块高度查询交易数量](#42-根据区块高度查询交易数量) +- [根据区块哈希查询交易数量](#43-根据区块哈希查询交易数量) +- [根据区块高度查询区块内的交易数量](#44-根据区块高度查询区块内的交易数量) +- [根据区块哈希查询区块内的交易数量](#45-根据区块哈希查询区块内的交易数量) +- [获取指定区块高度的交易列表](#46-获取指定区块高度的交易列表) +- [获取指定哈希的区块的交易列表](#47-获取指定哈希的区块的交易列表) +- [获取交易详细信息](#48-获取交易详细信息) + +[用户](#5-用户) +- [获取用户总数](#51-获取用户总数) +- [获取用户列表](#52-获取用户列表) +- [获取用户详细信息](#53-获取用户详细信息) +- [获取指定高度的区块的用户总数](#54-获取指定高度的区块的用户总数) +- [获取指定哈希的区块的用户总数](#55-获取指定哈希的区块的用户总数) +- [根据区块高度查询区块内的用户数量](#56-根据区块高度查询区块内的用户数量) +- [根据区块哈希查询区块内的用户数量](#57-根据区块哈希查询区块内的用户数量) +- [查询最新区块新增用户数量](#58-查询最新区块新增用户数量) + +[角色权限](#6-角色权限) +- [根据角色获取权限信息](#61-根据角色获取权限信息) +- [根据用户获取权限信息](#62-根据用户获取权限信息) + +[数据账户](#7-数据账户) +- [获取账户列表](#71-获取账户列表) +- [获取账户详细信息](#72-获取账户详细信息) +- [获取账户总数](#73-获取账户总数) +- [获取指定高度的区块的数据账户总数](#74-获取指定高度的区块的数据账户总数) +- [获取指定哈希的区块的数据账户总数](#75-获取指定哈希的区块的数据账户总数) +- [根据区块高度查询区块内的数据账户数量](#76-根据区块高度查询区块内的数据账户数量) +- [根据区块哈希查询区块内的数据账户数量](#77-根据区块哈希查询区块内的数据账户数量) +- [获取某数据账户KV总数](#78-获取某数据账户KV总数) +- [获取某数据账户KV详情](#79-获取某数据账户KV详情) +- [获取某数据账户KV详情](#710-获取某数据账户KV详情) +- [获取某数据账户KV整个历史详情](#711-获取某数据账户KV整个历史详情) + +[合约](#8-合约) +- [获取合约总数](#81-获取合约总数) +- [获取指定区块高度的合约总数](#82-获取指定区块高度的合约总数) +- [获取指定区块哈希的合约总数](#83-获取指定区块哈希的合约总数) +- [根据区块高度查询区块内的合约总数](#84-根据区块高度查询区块内的合约总数) +- [根据区块哈希查询区块内的合约总数](#85-根据区块哈希查询区块内的合约总数) +- [获取合约列表](#86-获取合约列表) +- [获取合约详细信息](#87-获取合约详细信息) + +[事件](#9-用户自定义事件) + +- [获取事件账户列表](#91-获取事件账户列表) +- [获取事件账户](#92-获取事件账户) +- [获取事件账户总数](#93-获取事件账户总数) +- [获取事件名数量](#94-获取事件名数量) +- [获取事件名列表](#95-获取事件名列表) +- [获取最新事件](#96-获取最新事件) +- [获取事件数量](#97-获取事件数量) +- [获取事件列表](#98-获取事件列表) + +## 1 API调用说明 + +该文档内的所有api的调用成功和失败均按照以下规则 + +### 1.1 成功 + +```json +{ + "data": ..., + "success": true +} +``` + +说明 + + - success 值为 true 表明api调用成功 + - data 为返回的数据,具体数据类型参考具体的api说明 + +### 1.2 失败 + +```json +{ + "error": { + "errorCode": 5000, + "errorMessage": "未预期的异常! --Unsupported access ledger[6Gw3cK4uazegy4HjoaM81ck9NgYLNoKyBMb7a1TK1jt3d] !" + }, + "success": false +} + +[comment]: <> (```) + +说明 + + - success 值为 false 表明api调用成功 + - errorCode 为异常代码 + - errorMessage 为错误提示 + +## 2 账本 + +### 2.1 获取账本总数 + +​```http +GET /ledgers/count +``` + +#### 参数 +无 + + +#### 请求实例 +```http +http://localhost:8080/ledgers/count +``` + +#### 返回实例 + +```json +{ + "data": 2, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|账本总数| + + +### 2.2 获取账本列表 + +```http +GET /ledgers +``` + +#### 参数 +无 + + +#### 请求实例 +```http +http://localhost:8080/ledgers +``` + +#### 返回实例 + +```json +{ + "data" : [ + "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp" + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|账本哈希列表| + +### 2.3 获取账本详细信息 + +```http +GET /ledgers/{ledger} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "hash" : "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp", + "latestBlockHeight" : 0, + "latestBlockHash" : "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp" + } +} +``` + +说明 + +|名称|说明| +|---|---| +|data|账本信息| +|hash|账本哈希| +|latestBlockHash | 最新区块哈希 | +|latestBlockHeight| 最新账本高度 | + + +### 2.4 获取账本参与方总数 + +```http +GET /ledgers/{ledger}/participants/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/participants/count +``` + +#### 返回实例 + +```json +{ + "data": 4, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|账本参与方总数| + + +### 2.5 获取账本参与方列表 + +```http +GET /ledgers/{ledger}/participants +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/participants +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "pubKey" : "7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6", + "participantNodeState" : "CONSENSUS", + "id" : 2, + "address" : { + "value" : "LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE" + }, + "name" : "2" + }, + { + "participantNodeState" : "CONSENSUS", + "pubKey" : "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "id" : 1, + "name" : "1", + "address" : { + "value" : "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY" + } + }, + { + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "participantNodeState" : "CONSENSUS", + "address" : { + "value" : "LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw" + }, + "name" : "0", + "id" : 0 + }, + { + "id" : 3, + "address" : { + "value" : "LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6" + }, + "name" : "3", + "pubKey" : "7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr", + "participantNodeState" : "CONSENSUS" + } + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|id|参与方唯一标识| +|name|参与方名称| +|address.value|参与方地址| +|pubKey|参与方公钥| +|participantNodeState|参与方状态| + +`ParticipantNodeState` 参与方状态: + +- `READY` 就绪,在此状态下,参与方的账户可以作为网关节点接入终端的交易请求 +- `CONSENSUS` 共识,在此状态下,参与方的账户可以作为共识节点参与共识,也可以作为网关节点接入终端的交易请求 +- `DEACTIVATED` 停用,在此状态下,参与方的账户既不能作为共识节点参与共识,也不能作为网关节点接入终端的交易请求 + +### 2.6 获取账本元数据信息 + +```http +GET /ledgers/{ledger}/metadata +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/metadata +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "participantsHash" : "j5qzkZgpGMczBDNKXRGJdyPTndkxPvB7Gdrfiqy6LvG7P5", + "userRolesHash" : "j5rggjQQtcjMTSwxFyDedcxPSxVVfjAB3khJDvgdiGFhiB", + "seed" : "NiSpjQVYRMMEA+1bnyU2eA==", + "settingsHash" : "j5iNkXJptLJrJcFL1YJpuvbJCh6H3iioBNJG7QKPESUUif", + "rolePrivilegesHash" : "j5hBCfTVv77mTyM5WHoGnw1cezgzB3QDqojqjhg5qmuECn", + "ledgerStructureVersion" : 0 + } +} +``` + +说明 + +|名称|说明| +|---|---| +|seed|账本生成种子| +|participantsHash|成员数据集哈希| +|userRolesHash|用户角色集哈希| +|settingsHash|配置数据集哈希| +|rolePrivilegesHash|角色权限数据集哈希| +|ledgerStructureVersion|账本结构版本| + + +### 2.7 获取账本初始化配置信息 + +```http +GET /ledgers/{ledger}/settings +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/settings +``` + +#### 返回实例 + +```json +{ + "data": { + "ledgerStructureVersion": 0, + "participantsHash": "j5qzkZgpGMczBDNKXRGJdyPTndkxPvB7Gdrfiqy6LvG7P5", + "seed": "3624a98d-055844c3-0403ed5b-9f253678", + "consensusProtocol": "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", + "consensusSettings": { + "systemConfigs": [ + { + "name": "system.bft", + "value": "true" + }, + { + "value": "true", + "name": "system.communication.defaultkeys" + }, + { + "value": "500000", + "name": "system.communication.inQueueSize" + }, + { + "value": "500000", + "name": "system.communication.outQueueSize" + }, + { + "name": "system.communication.send.retryCount", + "value": "100" + }, + { + "name": "system.communication.send.retryInterval", + "value": "2000" + }, + { + "name": "system.communication.useMACs", + "value": "1" + }, + { + "name": "system.communication.useSenderThread", + "value": "true" + }, + { + "value": "0", + "name": "system.communication.useSignatures" + }, + { + "value": "0", + "name": "system.debug" + }, + { + "value": "0,1,2,3", + "name": "system.initial.view" + }, + { + "name": "system.servers.f", + "value": "1" + }, + { + "value": "4", + "name": "system.servers.num" + }, + { + "value": "true", + "name": "system.shutdownhook" + }, + { + "name": "system.totalordermulticast.checkpoint_period", + "value": "1000" + }, + { + "name": "system.totalordermulticast.checkpoint_to_disk", + "value": "false" + }, + { + "value": "120000", + "name": "system.totalordermulticast.global_checkpoint_period" + }, + { + "name": "system.totalordermulticast.highMark", + "value": "10000" + }, + { + "name": "system.totalordermulticast.log", + "value": "true" + }, + { + "value": "false", + "name": "system.totalordermulticast.log_parallel" + }, + { + "name": "system.totalordermulticast.log_to_disk", + "value": "true" + }, + { + "name": "system.totalordermulticast.maxbatchsize", + "value": "2000" + }, + { + "value": "10", + "name": "system.totalordermulticast.nonces" + }, + { + "value": "10", + "name": "system.totalordermulticast.revival_highMark" + }, + { + "name": "system.totalordermulticast.state_transfer", + "value": "true" + }, + { + "name": "system.totalordermulticast.sync_ckp", + "value": "false" + }, + { + "value": "false", + "name": "system.totalordermulticast.sync_log" + }, + { + "value": "3000000", + "name": "system.totalordermulticast.timeTolerance" + }, + { + "name": "system.totalordermulticast.timeout", + "value": "60000" + }, + { + "name": "system.totalordermulticast.timeout_highMark", + "value": "200" + }, + { + "value": "false", + "name": "system.totalordermulticast.verifyTimestamps" + }, + { + "name": "system.ttp.id", + "value": "2001" + } + ], + "viewId": 0, + "nodes": [ + { + "id": 0, + "networkAddress": { + "host": "127.0.0.1", + "port": 10080, + "secure": false + }, + "pubKey": "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "address": "LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw" + }, + { + "pubKey": "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "address": "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY", + "id": 1, + "networkAddress": { + "host": "127.0.0.1", + "port": 10082, + "secure": false + } + }, + { + "id": 2, + "networkAddress": { + "host": "127.0.0.1", + "port": 10084, + "secure": false + }, + "address": "LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE", + "pubKey": "7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6" + }, + { + "networkAddress": { + "host": "127.0.0.1", + "port": 10086, + "secure": false + }, + "id": 3, + "pubKey": "7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr", + "address": "LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6" + } + ] + }, + "cryptoSetting": { + "supportedProviders": [ + { + "algorithms": [ + { + "name": "AES", + "code": -32230 + }, + { + "name": "ED25519", + "code": 16661 + }, + { + "code": 16662, + "name": "ECDSA" + }, + { + "name": "RSA", + "code": -16105 + }, + { + "name": "RIPEMD160", + "code": 8217 + }, + { + "name": "SHA256", + "code": 8216 + }, + { + "name": "JVM-SECURE-RANDOM", + "code": 4123 + } + ], + "name": "com.jd.blockchain.crypto.service.classic.ClassicCryptoService" + }, + { + "name": "com.jd.blockchain.crypto.service.sm.SMCryptoService", + "algorithms": [ + { + "code": -16126, + "name": "SM2" + }, + { + "name": "SM3", + "code": 8195 + }, + { + "name": "SM4", + "code": -32252 + } + ] + } + ], + "hashAlgorithm": 8216, + "autoVerifyHash": false + }, + "participantNodes": [ + { + "participantNodeState": "CONSENSUS", + "pubKey": "7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6", + "address": { + "value": "LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE" + }, + "name": "2", + "id": 2 + }, + { + "id": 1, + "participantNodeState": "CONSENSUS", + "pubKey": "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "address": { + "value": "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY" + }, + "name": "1" + }, + { + "id": 0, + "address": { + "value": "LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw" + }, + "name": "0", + "participantNodeState": "CONSENSUS", + "pubKey": "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn" + }, + { + "id": 3, + "participantNodeState": "CONSENSUS", + "pubKey": "7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr", + "address": { + "value": "LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6" + }, + "name": "3" + } + ] + }, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|ledgerStructureVersion|账本种子信息| +|participantsHash|参与方数据集哈希| +|seed|账本种子信息| +|consensusProtocol|共识协议,以字符串方式显示| +|consensusSettings|共识配置| +|cryptoSetting|加密算法配置| +|participantNodes|参与方节点信息| + +### 2.8 获取账本管理数据信息 + +```http +GET /ledgers/{ledger}/admininfo +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/admininfo +``` + +#### 返回实例 + +```json +{ + "data" : { + "participants" : [ + { + "id" : 2, + "pubKey" : "7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6", + "name" : "2", + "participantNodeState" : "CONSENSUS", + "address" : { + "value" : "LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE" + } + }, + { + "name" : "1", + "pubKey" : "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "id" : 1, + "participantNodeState" : "CONSENSUS", + "address" : { + "value" : "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY" + } + }, + { + "id" : 0, + "name" : "0", + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "address" : { + "value" : "LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw" + }, + "participantNodeState" : "CONSENSUS" + }, + { + "participantNodeState" : "CONSENSUS", + "address" : { + "value" : "LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6" + }, + "name" : "3", + "pubKey" : "7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr", + "id" : 3 + } + ], + "participantCount" : 4, + "metadata" : { + "ledgerStructureVersion" : 0, + "seed" : "NiSpjQVYRMMEA+1bnyU2eA==", + "userRolesHash" : "j5rggjQQtcjMTSwxFyDedcxPSxVVfjAB3khJDvgdiGFhiB", + "settingsHash" : "j5iNkXJptLJrJcFL1YJpuvbJCh6H3iioBNJG7QKPESUUif", + "participantsHash" : "j5qzkZgpGMczBDNKXRGJdyPTndkxPvB7Gdrfiqy6LvG7P5", + "rolePrivilegesHash" : "j5hBCfTVv77mTyM5WHoGnw1cezgzB3QDqojqjhg5qmuECn" + }, + "settings" : { + "cryptoSetting" : { + "supportedProviders" : [ + { + "algorithms" : [ + { + "name" : "AES", + "code" : -32230 + }, + { + "name" : "ED25519", + "code" : 16661 + }, + { + "code" : 16662, + "name" : "ECDSA" + }, + { + "name" : "RSA", + "code" : -16105 + }, + { + "name" : "RIPEMD160", + "code" : 8217 + }, + { + "name" : "SHA256", + "code" : 8216 + }, + { + "name" : "JVM-SECURE-RANDOM", + "code" : 4123 + } + ], + "name" : "com.jd.blockchain.crypto.service.classic.ClassicCryptoService" + }, + { + "name" : "com.jd.blockchain.crypto.service.sm.SMCryptoService", + "algorithms" : [ + { + "code" : -16126, + "name" : "SM2" + }, + { + "name" : "SM3", + "code" : 8195 + }, + { + "name" : "SM4", + "code" : -32252 + } + ] + } + ], + "hashAlgorithm" : 8216, + "autoVerifyHash" : false + }, + "consensusProvider" : "com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider", + "consensusSetting" : { + "value" : "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" + } + } + }, + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|participants|参与方列表| +|participantCount|参与方数量| +|metadata|元数据| +|settings|配置信息| +|consensusProvider|共识协议| +|consensusSetting|共识配置| + + +## 3 区块 + +### 3.1 获取最新区块 + +```http +GET /ledgers/{ledger}/blocks/latest +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串 | + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/latest +``` + +#### 返回实例 + +```json +{ + "data" : { + "timestamp" : 1615261725429, + "transactionSetHash" : "j5ssSG7LQC2CgU7fLbMCs2m2JtwN26j5kj2buE2u8F9miP", + "userAccountSetHash" : "j5hzkPPBJAqKs4rLWbEiFhbh1VW6Jc2xk878X5A6JywPnC", + "previousHash" : "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp", + "hash" : "j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23", + "adminAccountHash" : "j5maavFZShDorv36Sj5W8ijm1wkm2z9GtfdiVvUcfzvwv8", + "height" : 1, + "ledgerHash" : "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp", + "dataAccountSetHash" : "j5poz1Ced486LxYbcotGvihT42CTiQym98Mg1By8DHZBxJ" + }, + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|hash|区块哈希| +|height|区块高度| +|timestamp|区块创建时间戳| +|ledgerHash|账本哈希| +|previousHash|前置区块哈希| +|transactionSetHash|交易集哈希| +|userAccountSetHash|用户集哈希| +|contractAccountSetHash|合约集哈希| +|adminAccountHash|管理员集哈希| +|dataAccountSetHash|数据账户集哈希| + +### 3.2 根据区块哈希获取区块详细信息 + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型 | +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_hash|是|区块哈希|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23 +``` + +#### 返回实例 + +同 [3.1](3.1-获取最新区块) + + +### 3.3 根据区块高度获取区块详细信息 + +```http +GET /ledgers/{ledger}/blocks/height/{block_height} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_height|是|区块高度|数字| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/1 +``` + +#### 返回实例 + +同 [3.1](3.1-获取最新区块) + +## 4 交易 + +### 4.1 获取账本交易总数 + +```http +GET /ledgers/{ledger}/txs/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/txs/count +``` + +##### 返回实例 + +```json +{ + "data": 2, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|交易数量| + +### 4.2 根据区块高度查询交易数量 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledgerHash}/blocks/height/{block_height}/txs/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_height|是|区块高度|数字| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/66/txs/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|交易数量| + +### 4.3 根据区块哈希查询交易数量 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_hash|是|区块哈希|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23/txs/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|交易数量| + +### 4.4 根据区块高度查询区块内的交易数量 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{block_height}/txs/additional-count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_height|是|区块高度|数字| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/66/txs/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|交易数量| + +### 4.5 根据区块哈希查询区块内的交易数量 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs/additional-count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_hash|是|区块哈希|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23/txs/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|交易数量| + +### 4.6 获取指定区块高度的交易列表 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{height}/txs?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|height|是|区块高度|数字| +|query|fromIndex|否|查询交易的起始序号,默认为0|数字| +|query|count|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/66/txs?fromIndex=1&count=1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "request" : { + "transactionContent" : { + "timestamp" : 1615261725387, + "ledgerHash" : "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp", + "operations" : [ + { + "@type" : "com.jd.blockchain.ledger.DataAccountRegisterOperation", + "accountID" : { + "pubKey" : "7VeRBZLMWAxcgL9DTjGWn9FHWny54bzDzrgeAH6pCFvEJ5eT", + "address" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + } + } + }, + { + "writeSet" : [ + { + "value" : { + "type" : "TEXT", + "bytes" : { + "value" : "EMeAB7i" + } + }, + "expectedVersion" : -1, + "key" : "key" + } + ], + "@type" : "com.jd.blockchain.ledger.DataAccountKVSetOperation", + "accountAddress" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + } + } + ] + }, + "nodeSignatures" : [ + { + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "digest" : "SMJHE64z77GSkBkC8Zw45r8zRhCq3KWgyGMxRo7KXZ1JWjnBBj1WkPGBdS3AUAX3UoWK5ymGxeqaskjTVgHxGtC768" + } + ], + "transactionHash" : "j5siSjjv7H6s61zsMajkGfyhASFnKpthveNDptCrM2gmui", + "endpointSignatures" : [ + { + "digest" : "SMJHE64z77GSkBkC8Zw45r8zRhCq3KWgyGMxRo7KXZ1JWjnBBj1WkPGBdS3AUAX3UoWK5ymGxeqaskjTVgHxGtC768", + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn" + } + ] + }, + "result" : { + "executionState" : "SUCCESS", + "dataSnapshot" : { + "adminAccountHash" : "j5maavFZShDorv36Sj5W8ijm1wkm2z9GtfdiVvUcfzvwv8", + "userAccountSetHash" : "j5hzkPPBJAqKs4rLWbEiFhbh1VW6Jc2xk878X5A6JywPnC", + "dataAccountSetHash" : "j5poz1Ced486LxYbcotGvihT42CTiQym98Mg1By8DHZBxJ" + }, + "blockHeight" : 1, + "transactionHash" : "j5siSjjv7H6s61zsMajkGfyhASFnKpthveNDptCrM2gmui" + } + } + ], + "success" : true +} +``` + + +说明 + +|名称|说明| +|---|---| +|request|请求数据| +|request.transactionContent|交易内容| +|request.transactionContent.timestamp|交易时间戳,毫秒| +|request.transactionContent.ledgerHash|账本哈希| +|request.transactionContent.operations|操作列表| +|request.nodeSignatures|参与方签名列表| +|request.endpointSignatures|终端用户签名列表| +|request.transactionHash|交易哈希| +|result|交易结果| +|result.executionState|交易执行状态,SUCCESS(成功)| +|result.dataSnapshot|交易执行后数据快照| +|result.blockHeight|最新区块高度| +|result.transactionHash|交易哈希| + +### 4.7 获取指定哈希的区块的交易列表 + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/txs?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|block_hash|是|区块哈希|字符串| +|query|fromIndex|否|查询交易的起始序号,默认为0|数字| +|query|count|否|查询返回交易的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23/txs?fromIndex=1&count=1 +``` + +#### 返回实例 + +[同 4.4](#4.4-获取指定区块高度的交易列表) + + +### 4.8 获取交易详细信息 + +```http +GET /ledgers/{ledger}/txs/hash/{tx_hash} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|tx_hash|是|交易哈希|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/txs/hash/j5siSjjv7H6s61zsMajkGfyhASFnKpthveNDptCrM2gmui +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "result" : { + "dataSnapshot" : { + "dataAccountSetHash" : "j5poz1Ced486LxYbcotGvihT42CTiQym98Mg1By8DHZBxJ", + "userAccountSetHash" : "j5hzkPPBJAqKs4rLWbEiFhbh1VW6Jc2xk878X5A6JywPnC", + "adminAccountHash" : "j5maavFZShDorv36Sj5W8ijm1wkm2z9GtfdiVvUcfzvwv8" + }, + "transactionHash" : "j5siSjjv7H6s61zsMajkGfyhASFnKpthveNDptCrM2gmui", + "blockHeight" : 1, + "executionState" : "SUCCESS" + }, + "request" : { + "nodeSignatures" : [ + { + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "digest" : "SMJHE64z77GSkBkC8Zw45r8zRhCq3KWgyGMxRo7KXZ1JWjnBBj1WkPGBdS3AUAX3UoWK5ymGxeqaskjTVgHxGtC768" + } + ], + "endpointSignatures" : [ + { + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "digest" : "SMJHE64z77GSkBkC8Zw45r8zRhCq3KWgyGMxRo7KXZ1JWjnBBj1WkPGBdS3AUAX3UoWK5ymGxeqaskjTVgHxGtC768" + } + ], + "transactionHash" : "j5siSjjv7H6s61zsMajkGfyhASFnKpthveNDptCrM2gmui", + "transactionContent" : { + "timestamp" : 1615261725387, + "operations" : [ + { + "@type" : "com.jd.blockchain.ledger.DataAccountRegisterOperation", + "accountID" : { + "address" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + }, + "pubKey" : "7VeRBZLMWAxcgL9DTjGWn9FHWny54bzDzrgeAH6pCFvEJ5eT" + } + }, + { + "accountAddress" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + }, + "@type" : "com.jd.blockchain.ledger.DataAccountKVSetOperation", + "writeSet" : [ + { + "value" : { + "bytes" : { + "value" : "EMeAB7i" + }, + "type" : "TEXT" + }, + "expectedVersion" : -1, + "key" : "key" + } + ] + } + ], + "ledgerHash" : "j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp" + } + } + } +} +``` + +说明 + +[同 4.4](#4.4-获取指定区块高度的交易列表) + +## 5 用户 + +### 5.1 获取用户总数 + +```http +GET /ledgers/{ledger}/users/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/users/count +``` + +#### 返回实例 + +```json +{ + "data": 4, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|用户总数| + + +### 5.2 获取用户列表 + +```http +GET /ledgers/{ledger}/users?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|query|fromIndex|否|查询用户的起始序号,默认为0|数字| +|query|count|否|查询返回用户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/users?fromIndex=0&count=2 +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : [ + { + "pubKey" : "7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn", + "address" : { + "value" : "LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw" + } + }, + { + "pubKey" : "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "address" : { + "value" : "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY" + } + } + ] +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|用户地址| +|pubKey|用户公钥| + + +### 5.3 获取用户详细信息 + +```http +GET /ledgers/{ledger}/users/address/{address} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|用户地址|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/users/address/LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "pubKey" : "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "iD" : { + "pubKey" : "7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW", + "address" : { + "value" : "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY" + } + }, + "dataRootHash" : "j5uJfAqLw1ptaZYJyKVZm37zZybboqxMPpS6Mv59rNd4xF", + "headerRootHash" : "j5oYeBmoBJ4jLpijwi6eoKAqh4BsQ3RWHzxdBnTvvTqSK6", + "dataset" : { + "dataCount" : 0, + "updated" : false, + "readonly" : false, + "rootHash" : "j5uJfAqLw1ptaZYJyKVZm37zZybboqxMPpS6Mv59rNd4xF" + }, + "address" : { + "value" : "LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY" + } + } +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|用户地址| +|pubKey|用户公钥| +|dataset.rootHash|用户根Hash| + +### 5.4 获取指定高度的区块的用户总数 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{block_height}/users/count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ------------ | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_height | 是 | 区块高度 | 数字 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/users/height/1/users/count +``` + +#### 返回实例 + +```json +{ + "data": 4, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | ------------ | +| data | 数据账户数量 | + +### 5.5 获取指定哈希的区块的用户总数 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/users/count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ---------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_hash | 是 | 区块哈希 | 字符串 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5opzRbH2fB6YmjvEdMLQ8VHVeZoUuKyVWzExCtJF1wecw/users/count +``` + +#### 返回实例 + +```json +{ + "data": 4, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | ------------ | +| data | 数据账户数量 | + +### 5.6 根据区块高度查询区块内的用户数量 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{block_height}/users/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ------------ | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_height | 是 | 区块高度 | 数字 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/2/users/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 用户数量 | + +### 5.7 根据区块哈希查询区块内的用户数量 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/users/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ---------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_hash | 是 | 区块哈希 | 字符串 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23/users/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 用户数量 | + +### 5.8 查询最新区块新增用户数量 + +**仅包含最新区块数据** + +```http +GET /ledgers/{ledger}/blocks/users/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ------ | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/users/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 0, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 用户数量 | + +## 6 角色权限 + +有关用户/角色/权限说明参照[用户文档](user.md) + +### 6.1 根据角色获取权限信息 +```http +GET /ledgers/{ledger}/authorization/role/{roleName} +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | -------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | roleName | 是 | 角色名 | 字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5pSJLyVpS8QG2wL95fiDWHHnweh2YdqNhgmnb64SBMjUh/authorization/role/DEFAULT +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "roleName" : "DEFAULT", + "transactionPrivilege" : { + "privilege" : [ + "DIRECT_OPERATION", + "CONTRACT_OPERATION" + ], + "permissionCount" : 2 + }, + "version" : 0, + "ledgerPrivilege" : { + "privilege" : [ + "CONFIGURE_ROLES", + "AUTHORIZE_USER_ROLES", + "SET_CONSENSUS", + "SET_CRYPTO", + "REGISTER_PARTICIPANT", + "REGISTER_USER", + "REGISTER_DATA_ACCOUNT", + "REGISTER_CONTRACT", + "UPGRADE_CONTRACT", + "SET_USER_ATTRIBUTES", + "WRITE_DATA_ACCOUNT", + "APPROVE_TX", + "CONSENSUS_TX", + "REGISTER_EVENT_ACCOUNT", + "WRITE_EVENT_ACCOUNT" + ], + "permissionCount" : 15 + } + } +} +``` + +说明 + +| 名称 | 说明 | +| ------------------------------------ | ----------------- | +| roleName | 角色名称 | +| transactionPrivilege | 交易权限 | +| transactionPrivilege.privilege | 交易权限.权限类别 | +| transactionPrivilege.permissionCount | 交易权限.权限总数 | +| ledgerPrivilege | 账本权限 | +| ledgerPrivilege.privilege | 账本权限.权限类别 | +| ledgerPrivilege.permissionCount | 账本权限.权限总数 | + +### 6.2 根据用户获取权限信息 + +```http +GET /ledgers/{ledger}/authorization/user/{userAddress} +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ----------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | userAddress | 是 | 用户地址 | 字符串 | + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5pSJLyVpS8QG2wL95fiDWHHnweh2YdqNhgmnb64SBMjUh/authorization/user/LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6 +``` + +#### 返回实例 + +```json +{ + "data" : { + "userAddress" : { + "value" : "LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6" + }, + "userRole" : [ + "DEFAULT" + ], + "ledgerPrivilegesBitset" : { + "privilege" : [ + "CONFIGURE_ROLES", + "AUTHORIZE_USER_ROLES", + "SET_CONSENSUS", + "SET_CRYPTO", + "REGISTER_PARTICIPANT", + "REGISTER_USER", + "REGISTER_DATA_ACCOUNT", + "REGISTER_CONTRACT", + "UPGRADE_CONTRACT", + "SET_USER_ATTRIBUTES", + "WRITE_DATA_ACCOUNT", + "APPROVE_TX", + "CONSENSUS_TX", + "REGISTER_EVENT_ACCOUNT", + "WRITE_EVENT_ACCOUNT" + ], + "permissionCount" : 15 + }, + "transactionPrivilegesBitset" : { + "permissionCount" : 2, + "privilege" : [ + "DIRECT_OPERATION", + "CONTRACT_OPERATION" + ] + } + }, + "success" : true +} +``` + +说明 + +| 名称 | 说明 | +| --------------------------- | ---------- | +| userRole | 用户角色 | +| transactionPrivilegesBitset | 交易权限集 | +| ledgerPrivilegesBitset | 账本权限集 | + +> 请求链上不存在的用户地址,会返回DEFAULT角色权限列表 + +## 7 数据账户 + +### 7.1 获取账户列表 + +```http +GET /ledgers/{ledger}/accounts?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|query|fromIndex|否|查询数据账户的起始序号,默认为0|数字| +|query|count|否|查询返回数据账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts?fromIndex=0&count=-1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "address" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + }, + "pubKey" : "7VeRBZLMWAxcgL9DTjGWn9FHWny54bzDzrgeAH6pCFvEJ5eT" + } + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|账户地址| +|pubKey|账户公钥| + + +### 7.2 获取账户详细信息 + +```http +GET /ledgers/{ledger}/accounts/address/{address} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|账户地址|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts/address/LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn +``` + +#### 返回实例 + +```json +{ + "data" : { + "dataset" : { + "updated" : false, + "readonly" : false, + "dataCount" : 1, + "rootHash" : "j5vjKBpdFncVW9dYnjefiKgs858QKNc98XAvy5pFXmgLKp" + }, + "headerRootHash" : "j5jUf96A8678xdggUdAZUtADL43WFsFu76gWxT9KkknjLf", + "dataRootHash" : "j5vjKBpdFncVW9dYnjefiKgs858QKNc98XAvy5pFXmgLKp", + "pubKey" : "7VeRBZLMWAxcgL9DTjGWn9FHWny54bzDzrgeAH6pCFvEJ5eT", + "iD" : { + "pubKey" : "7VeRBZLMWAxcgL9DTjGWn9FHWny54bzDzrgeAH6pCFvEJ5eT", + "address" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + } + }, + "address" : { + "value" : "LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn" + } + }, + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|账户地址| +|pubKey|账户公钥| + + +### 7.3 获取账户总数 + +```http +GET /ledgers/{ledger}/accounts/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|账户数量| + +### 7.4 获取指定高度的区块的数据账户总数 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{block_height}/accounts/count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ------------ | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_height | 是 | 区块高度 | 数字 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/1/accounts/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | ------------ | +| data | 数据账户数量 | + +### 7.5 获取指定哈希的区块的数据账户总数 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/accounts/count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ---------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_hash | 是 | 区块哈希 | 字符串 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5opzRbH2fB6YmjvEdMLQ8VHVeZoUuKyVWzExCtJF1wecw/accounts/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | ------------ | +| data | 数据账户数量 | + +### 7.6 根据区块高度查询区块内的数据账户数量 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{block_height}/accounts/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ------------ | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_height | 是 | 区块高度 | 数字 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/1/accounts/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | ------------ | +| data | 数据账户数量 | + +### 7.7 根据区块哈希查询区块内的数据账户数量 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{block_hash}/accounts/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ---------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | block_hash | 是 | 区块哈希 | 字符串 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5irFH5SJBaCSa6R3QYhbWYMUA2Wos3gvXYUyDYAHVhG23/accounts/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | ------------ | +| data | 数据账户数量 | + +### 7.8 获取某数据账户KV总数 + +```http + GET /ledgers/{ledger}/accounts/address/{address}/entries/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|账户地址|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts/address/LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn/entries/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|KV总数| + + +### 7.9 获取某数据账户KV详情 + +```http +GET /ledgers/{ledger}/accounts/address/{address}/entries?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|账户地址|字符串| +|query|fromIndex|否|查询数据账户对应KV的起始序号,默认为0|数字| +|query|count|否|查询返回数据账户对应KV的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts/address/LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn/entries?fromIndex=0&count=1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "type" : "TEXT", + "version" : 0, + "key" : "key", + "value" : "value" + } + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|key|键| +|version|版本号| +|type|value类型| +|value|值| + +> 数据类型参照[数据账户](data_account.md)中描述。 + +### 7.10 获取某数据账户KV详情 + +```http +GET/POST /ledgers/{ledger}/accounts/{address}/entries?keys={keys} +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ------- | -------- | --------------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | address | 是 | 账户地址 | 字符串 | +| form | keys | 是 | key详细内容列表 | 字符串 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts/LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn/entries?keys=key,key1 +``` + + +#### 返回实例 + +```json +{ + "success" : true, + "data" : [ + { + "key" : "key", + "value" : 1024, + "version" : 2, + "type" : "INT64" + }, + { + "type" : "NIL", + "version" : -1, + "key" : "key1" + } + ] +} +``` + +说明 + +| 名称 | 说明 | +| ------- | --------- | +| key | 键 | +| version | 版本号 | +| type | value类型 | +| value | 值 | + + +### 7.11 获取某数据账户KV整个历史详情 + +```http + GET/POST /ledgers/{ledger}/accounts/{address}/entries-version +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|账户地址|字符串| +|body|kvInfoVO|是|Key相关信息|对象| + +KVInfoVO对应格式如下: + +```json + +{ + "data": [{ + "key": "key", + "version": [0, 1] + } +} + +``` + +kvInfoVO说明: + - 支持多个Key作为入参; + - 每个Key支持多个version; + + +#### 请求实例 +```curl +curl -H 'Content-Type:application/json' --data '{"data":[{"key":"key","version":[0,1]}]}' 'http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/accounts/LdeNscE3MP9a1vgyVUg9LgxQx6yzkUEUS65Rn/entries-version' +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "type" : "TEXT", + "key" : "key", + "value" : "value", + "version" : 0 + }, + { + "type" : "BYTES", + "version" : 1, + "value" : "Ynl0ZXM=", + "key" : "key" + } + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|key|键| +|version|版本号| +|type|value类型| +|value|值,BASE64编码| + +## 8 合约 + +### 8.1 获取合约总数 + +```http +GET /ledgers/{ledger}/contracts/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| + + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/contracts/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 合约数量 | + +### 8.2 获取指定区块高度的合约总数 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{blockHeight}/contracts/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|blockHeight|是|区块高度|数字| + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/7/contracts/count +``` + +#### 返回实例 + +```json +{ + "data": 2, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 合约数量 | + + + +### 8.3 获取指定区块哈希的合约总数 + +**包含当前区块以及之前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{blockHash}/contracts/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|blockHash|是|区块哈希|字符串| + + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5hhTQPyZQHqkvP5UBq3sAaqxq8QUda6asJLzZ2VFUhvQ8/contracts/count +``` + +#### 返回实例 + +```json +{ + "data": 2, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 合约数量 | + +### 8.4 根据区块高度查询区块内的合约总数 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/height/{blockHeight}/contracts/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | ----------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | blockHeight | 是 | 区块高度 | 数字 | + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/height/7/contracts/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 合约数量 | + + + +### 8.5 根据区块哈希查询区块内的合约总数 + +**仅包含当前区块数据** + +```http +GET /ledgers/{ledger}/blocks/hash/{blockHash}/contracts/additional-count +``` + +#### 参数 + +| 请求类型 | 名称 | 是否必需 | 说明 | 数据类型 | +| -------- | --------- | -------- | -------- | -------- | +| path | ledger | 是 | 账本哈希 | 字符串 | +| path | blockHash | 是 | 区块哈希 | 字符串 | + + +#### 请求实例 + +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/blocks/hash/j5hhTQPyZQHqkvP5UBq3sAaqxq8QUda6asJLzZ2VFUhvQ8/contracts/additional-count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +| 名称 | 说明 | +| ---- | -------- | +| data | 合约数量 | + +### 8.6 获取合约列表 + +```http +GET /ledgers/{ledger}/contracts?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|query|fromIndex|否|查询合约的起始序号,默认为0|数字| +|query|count|否|查询返回合约的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/contracts?fromIndex=0&count=-1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "pubKey" : "7VeRCfSaoBW3uRuvTqVb26PYTNwvQ1iZ5HBY92YKpEVN7Qht", + "address" : { + "value" : "LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye" + } + }, + { + "pubKey" : "7VeRALfcPigCTSEPHSwz7U7TDNLoet85z3nRfr5cYspUWLAR", + "address" : { + "value" : "LdeNwApbVMHqTCzNKuynUtJXH7vN2rG8gxHN5" + } + } + ], + "success" : true +} + +``` + +说明 + +|名称|说明| +|---|---| +|address.value|账户地址| +|pubKey|账户公钥| + + +### 8.7 获取合约详细信息 + +```http +GET /ledgers/{ledger}/contracts/address/{address} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|合约地址|字符串| + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/contracts/address/LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "dataRootHash" : "j5uJfAqLw1ptaZYJyKVZm37zZybboqxMPpS6Mv59rNd4xF", + "chainCode" : "package com.jdchain.samples.contract;\n\nimport com.jd.blockchain.contract.*;\nimport utils.*;\nimport com.jd.blockchain.crypto.*;\nimport com.jd.blockchain.ledger.*;\n\npublic class SampleContractImpl implements EventProcessingAware, SampleContract\n{\n private ContractEventContext eventContext;\n \n public void setKVWithVersion(final String address, final String key, final String value, final long version) {\n this.eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version);\n }\n \n public void setKV(final String address, final String key, final String value) {\n final TypedKVEntry[] entries = this.eventContext.getUncommittedLedger().getDataEntries(address, new String[] { key });\n long version = -1L;\n if (null != entries && entries.length > 0) {\n version = entries[0].getVersion();\n }\n this.eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version);\n }\n \n public String registerUser(final String seed) {\n final CryptoAlgorithm algorithm = Crypto.getAlgorithm(\"ed25519\");\n final SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm);\n final AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes());\n final BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());\n this.eventContext.getLedger().users().register(keypair.getIdentity());\n return keypair.getAddress().toBase58();\n }\n \n public String registerDataAccount(final String seed) {\n final CryptoAlgorithm algorithm = Crypto.getAlgorithm(\"ed25519\");\n final SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm);\n final AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes());\n final BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());\n this.eventContext.getLedger().dataAccounts().register(keypair.getIdentity());\n return keypair.getAddress().toBase58();\n }\n \n public String registerEventAccount(final String seed) {\n final CryptoAlgorithm algorithm = Crypto.getAlgorithm(\"ed25519\");\n final SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm);\n final AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes());\n final BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());\n this.eventContext.getLedger().eventAccounts().register(keypair.getIdentity());\n return keypair.getAddress().toBase58();\n }\n \n public void publishEventWithSequence(final String address, final String topic, final String content, final long sequence) {\n this.eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence);\n }\n \n public void publishEvent(final String address, final String topic, final String content) {\n final Event event = this.eventContext.getUncommittedLedger().getLatestEvent(address, topic);\n long sequence = -1L;\n if (null != event) {\n sequence = event.getSequence();\n }\n this.eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence);\n }\n \n public void beforeEvent(final ContractEventContext eventContext) {\n this.eventContext = eventContext;\n }\n \n public void postEvent(final ContractEventContext eventContext, final Exception error) {\n }\n}\n", + "address" : { + "value" : "LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye" + }, + "headerRootHash" : "j5r72A4PMdDrAU4zhniJNRWM5nKV8kAKMdt6naNrtjRp3A", + "chainCodeVersion" : 0, + "pubKey" : "7VeRCfSaoBW3uRuvTqVb26PYTNwvQ1iZ5HBY92YKpEVN7Qht" + } +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|账户地址| +|pubKey|账户公钥| +|chainCode|合约源代码| + + + +## 9 用户自定义事件 + +### 9.1 获取事件账户列表 + +```http +GET /ledgers/{ledger}/events/user/accounts?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|query|fromIndex|否|查询的起始序号,默认为0|数字| +|query|count|否|查询返回事件账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts?fromIndex=0&count=-1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "address" : { + "value" : "LdeNqYND7M82fxrej7ffRPXZwahQZEoUSoUzz" + }, + "pubKey" : "7VeRJe66QNfuacfSVPzTfXPooFcRmMJKXPYqkUsn4r9v8DqA" + }, + { + "pubKey" : "7VeRMwxWNcpMszstXtaxJ1fupauuJpwedB81nMJJQB93LiAJ", + "address" : { + "value" : "LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA" + } + } + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|账户地址| +|pubKey|账户公钥| + +### 9.2 获取事件账户 + +```http +GET /ledgers/{ledger}/events/user/accounts/{address} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|address|账户地址|是|事件账户地址|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/LdeNqYND7M82fxrej7ffRPXZwahQZEoUSoUzz +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "address" : { + "value" : "LdeNqYND7M82fxrej7ffRPXZwahQZEoUSoUzz" + }, + "pubKey" : "7VeRJe66QNfuacfSVPzTfXPooFcRmMJKXPYqkUsn4r9v8DqA" + } +} +``` + +说明 + +|名称|说明| +|---|---| +|address.value|账户地址| +|pubKey|账户公钥| + +### 9.3 获取事件账户总数 + +```http +GET /ledgers/{ledger}/events/user/accounts/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/count +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : 2 +} +``` + +说明 + +|名称|说明| +|---|---| +|data|事件账户数量| + +### 9.4 获取事件名数量 + +```http +GET /ledgers/{ledger}/events/user/accounts/{address}/names/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|事件账户地址|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA/names/count +``` + +#### 返回实例 + +```json +{ + "data" : 5, + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|事件名数量| + +### 9.5 获取事件名列表 + +```http +GET /ledgers/{ledger}/events/user/accounts/{address}/names?fromIndex={fromIndex}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|事件账户地址|字符串| +|query|fromIndex|否|查询的起始序号,默认为0|数字| +|query|count|否|查询返回事件账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA/names?fromIndex=0&count=-1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + "topic4", + "topic3", + "topic", + "topic1", + "topic2" + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|事件名数量数组| + +### 9.6 获取最新事件 + +```http +GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}/latest +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|事件账户地址|字符串| +|path|event_name|是|事件名|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA/names/topic/latest +``` + +#### 返回实例 + +```json +{ + "success" : true, + "data" : { + "sequence" : 0, + "blockHeight" : 8, + "transactionSource" : "j5p868BwtU4w5BxG7gnuhQCFqpAgddVzTWNEKMAzZ8bnrF", + "eventAccount" : { + "value" : "LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA" + }, + "name" : "topic", + "contractSource" : "", + "content" : { + "bytes" : { + "value" : "4mZ4ZZRGDZ" + }, + "nil" : false, + "value" : "content", + "type" : "TEXT" + } + } +} +``` + +说明 + +|名称|说明| +|---|---| +|sequence|事件序列| +|transactionSource|交易哈希| +|blockHeight|时间产生区块高度| +|contractSource|合约地址| +|eventAccount.value|事件账户地址| +|name|事件名| +|content.nil|事件内容是否为空| +|content.bytes.value|事件内容字节,BASE64编码| +|content.type|事件内容类型| +|content.value|事件内容| + +### 9.7 获取事件数量 + +```http +GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}/count +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|事件账户地址|字符串| +|path|event_name|是|事件名|字符串| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/topic/count +``` + +#### 返回实例 + +```json +{ + "data": 1, + "success": true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|事件数量| + +### 9.8 获取事件列表 + +```http +GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}?fromSequence={fromSequence}&count={count} +``` + +#### 参数 + +|请求类型|名称|是否必需|说明|数据类型| +|---|---|---|---|---| +|path|ledger|是|账本哈希|字符串| +|path|address|是|事件账户地址|字符串| +|path|event_name|是|事件名|字符串| +|query|fromSequence|否|查询的起始序号,默认为0|数字| +|query|count|否|查询返回事件的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字| + + +#### 请求实例 +```http +http://localhost:8080/ledgers/j5hQrVB8y78xXbDR9vB92WBjiJShH36G7YLdQYsxtRxkpp/events/user/accounts/LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA/names/topic?fromSequenct=0&count=-1 +``` + +#### 返回实例 + +```json +{ + "data" : [ + { + "content" : { + "value" : "content", + "nil" : false, + "type" : "TEXT", + "bytes" : { + "value" : "4mZ4ZZRGDZ" + } + }, + "eventAccount" : { + "value" : "LdeNiAPuZ5tpYZVrrbELJNjqdvB51PBpNd8QA" + }, + "contractSource" : "", + "name" : "topic", + "sequence" : 0, + "transactionSource" : "j5p868BwtU4w5BxG7gnuhQCFqpAgddVzTWNEKMAzZ8bnrF", + "blockHeight" : 8 + } + ], + "success" : true +} +``` + +说明 + +|名称|说明| +|---|---| +|data|事件列表| +|sequence|事件序列| +|transactionSource|交易哈希| +|blockHeight|时间产生区块高度| +|contractSource|合约地址| +|eventAccount.value|事件账户地址| +|name|事件名| +|content.nil|事件内容是否为空| +|content.bytes.value|事件内容字节,BASE64编码| +|content.type|事件内容类型| +|content.value|事件内容| \ No newline at end of file diff --git a/docs/block.md b/docs/block.md new file mode 100644 index 00000000..552f156c --- /dev/null +++ b/docs/block.md @@ -0,0 +1,80 @@ +## 区块 + +采用`BFT-SMaRt`共识协议,即时出块,单个区块交易数限制默认为`2000`(`bftsmart.config`中参数`system.totalordermulticast.maxbatchsize`) + +### 结构 + +- `LedgerBlock`: + +```java +@DataContract(code = DataCodes.BLOCK) +public interface LedgerBlock extends BlockBody { + + /** + * 区块哈希; + */ + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + HashDigest getHash(); + +} +``` + +- `BlockBody`: + +```java +@DataContract(code= DataCodes.BLOCK_BODY) +public interface BlockBody extends LedgerDataSnapshot{ + + // 上一个区块哈希 + @DataField(order=2, primitiveType = PrimitiveType.BYTES) + HashDigest getPreviousHash(); + + // 账本哈希 + @DataField(order=3, primitiveType = PrimitiveType.BYTES) + HashDigest getLedgerHash(); + + // 区块高度 + @DataField(order=4, primitiveType= PrimitiveType.INT64) + long getHeight(); + + // 交易数据集哈希 + @DataField(order=5, primitiveType = PrimitiveType.BYTES) + HashDigest getTransactionSetHash(); + + // 区块时间戳,毫秒 + @DataField(order=6, primitiveType = PrimitiveType.INT64) + long getTimestamp(); +} +``` + +- `LedgerDataSnapshot`: + +```java +@DataContract(code=DataCodes.DATA_SNAPSHOT) +public interface LedgerDataSnapshot { + + // 管理数据集哈希 + @DataField(order=1, primitiveType = PrimitiveType.BYTES) + HashDigest getAdminAccountHash(); + + // 用户集哈希 + @DataField(order=2, primitiveType = PrimitiveType.BYTES) + HashDigest getUserAccountSetHash(); + + // 数据账户集哈希 + @DataField(order=3, primitiveType = PrimitiveType.BYTES) + HashDigest getDataAccountSetHash(); + + // 合约集哈希 + @DataField(order=4, primitiveType = PrimitiveType.BYTES) + HashDigest getContractAccountSetHash(); + + // 系统事件集哈希 + @DataField(order=5, primitiveType = PrimitiveType.BYTES) + HashDigest getSystemEventSetHash(); + + // 用户事件集哈希 + @DataField(order=6, primitiveType = PrimitiveType.BYTES) + HashDigest getUserEventSetHash(); +} +``` \ No newline at end of file diff --git a/docs/cli/keys.md b/docs/cli/keys.md new file mode 100644 index 00000000..a3410b54 --- /dev/null +++ b/docs/cli/keys.md @@ -0,0 +1,120 @@ +### 密钥管理 + +`jdchain-cli`提供基于本地目录的密钥管理:[密钥对列表](#密钥对列表),[添加密钥对](#添加密钥对),[更新私钥密码](#更新私钥密码),[删除密钥对](#删除密钥对) + +```bash +:bin$ ./jdchain-cli.sh keys -h +Usage: git status [...] [--] [...] +List, create, update or delete keypairs. + -h, --help Show this help message and exit. + --home= Set the home directory. + Default: ../ + --pretty Pretty json print + -V, --version Print version information and exit. +Commands: + list List all the keypairs. + add Create a new keypair. + update Update privkey password. + delete Delete keypair. + help Displays help information about the specified command +``` + +#### 密钥对列表 +```bash +:bin$ ./jdchain-cli.sh keys list -h +List all the keypairs. +Usage: jdchain-cli keys list [-hV] [--pretty] [--home=] + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `home`,指定密钥存储相关目录,`${home}/config/keys` + +如: +```bash +:bin$ ./jdchain-cli.sh keys list +NAME ALGORITHM ADDRESS PUBKEY +``` +- `NAME`,名称 +- `ALGORITHM`,算法 +- `ADDRESS`,地址 +- `PUBKEY`,公钥 + +#### 添加密钥对 +```bash +:bin$ ./jdchain-cli.sh keys add -h +Create a new keypair. +Usage: jdchain-cli keys add [-hV] [--pretty] [-a=] [--home=] + -n= + -a, --algorithm= + Crypto algorithm + -h, --help Show this help message and exit. + --home= Set the home directory. + -n, --name= Name of the key + --pretty Pretty json print + -V, --version Print version information and exit. +``` + +- `a`/`algorithm`,密钥算法:`SM2`,`ED25519`等,默认`ED25519` +- `name`,密钥对名称 + +如: +```bash +:bin$ ./jdchain-cli.sh keys add -n k1 +please input password: > +// 输入私钥密码 +1 +NAME ALGORITHM ADDRESS PUBKEY +k1 ED25519 LdeP1iczD3zpmcayKAxTfSywict9y2r6Jpq6n 7VeRBamwPeMb7jzTNg3Ap2DscBiy3QE3PK5NqBvv9tUjQVk4 +``` + +#### 更新私钥密码 + +```bash +:bin$ ./jdchain-cli.sh keys update -h +Update privkey password. +Usage: jdchain-cli keys update [-hV] [--pretty] [--home=] -n= + -h, --help Show this help message and exit. + --home= Set the home directory. + -n, --name= Name of the key + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `name`,密钥对名称 + +如: +```bash +:bin$ ./jdchain-cli.sh keys update -n k1 +input the current password: > +// 输入当前密码 +1 +input new password: > +// 输入新密码 +2 +NAME ALGORITHM ADDRESS PUBKEY +k1 ED25519 LdeP1iczD3zpmcayKAxTfSywict9y2r6Jpq6n 7VeRBamwPeMb7jzTNg3Ap2DscBiy3QE3PK5NqBvv9tUjQVk4 +``` + +#### 删除密钥对 + +```bash +:bin$ ./jdchain-cli.sh keys delete -h +Delete keypair. +Usage: jdchain-cli keys delete [-hV] [--pretty] [--home=] -n= + -h, --help Show this help message and exit. + --home= Set the home directory. + -n, --name= Name of the key + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `name`,密钥对名称 + +如: +```bash +:bin$ ./jdchain-cli.sh keys delete -n k1 +input the current password: > +// 输入当前密码 +2 +[k1] deleted +``` \ No newline at end of file diff --git a/docs/cli/participant.md b/docs/cli/participant.md new file mode 100644 index 00000000..0d23df02 --- /dev/null +++ b/docs/cli/participant.md @@ -0,0 +1,219 @@ +### 共识节点变更 + +借助`BFT-SMaRt`共识提供的Reconfig操作元语,`JD Chain`实现了在不停机的情况下快速更新共识网络拓扑,实现添加共识节点,移除共识节点,更新共识信息 等功能。 +```bash +:bin$ ./jdchain-cli.sh participant -h +Usage: jdchain-cli participant [-hV] [--pretty] [--home=] [COMMAND] +Add, update or delete participant. + -h, --help Show this help message and exit. + --home= Set the home directory. + Default: ../ + --pretty Pretty json print + -V, --version Print version information and exit. +Commands: + register Register new participant. + active Active participant. + update Update participant. + inactive Inactive participant. + help Displays help information about the specified command +``` +- `register` [注册新节点](#注册新节点) +- `active` [激活节点](#激活节点) +- `active` [更新节点](#更新节点) +- `inactive` [移除节点](#移除节点) + +#### 注册新节点 + +```bash +:bin$ ./jdchain-cli.sh participant register -h +Register new participant. +Usage: jdchain-cli participant register [-hV] [--pretty] [--gw-host=] + [--gw-port=] [--home=] + --name= + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --name= Name of the participant + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `name`,新节点名称 + +注册新节点: +```bash +:bin$ ./jdchain-cli.sh participant register --name node4 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +// 选择账本 +> 0 +// 选择待注册节点公私钥(链上必须不存在此公私钥对应的用户) +select keypair to register, input the index: +0 k1 LdeNq3862vtUCeptww1T5mVvLbAeppYqVNdqD +1 1627618939 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +2 node4 LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T +2 +input password of the key: +> 1 +// 选择此交易签名用户(必须是链上存在的用户,且有相应操作权限) +select keypair to sign tx, input the index: +0 k1 LdeNq3862vtUCeptww1T5mVvLbAeppYqVNdqD +1 1627618939 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +2 node4 LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T +1 +input password of the key: +> 1 +register participant: [LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T] +``` +成功在账本`j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg`中注册了新的节点`LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T` + +可通过[共识节点列表](query.md#共识节点列表)查看新的账本列表: +```bash +:bin$ ./jdchain-cli.sh query participants +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +[{"address":"LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE","id":2,"name":"2","participantNodeState":"CONSENSUS","pubKey":"7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6"},{"address":"LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY","id":1,"name":"1","participantNodeState":"CONSENSUS","pubKey":"7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW"},{"address":"LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T","id":4,"name":"node4","participantNodeState":"READY","pubKey":"7VeRKiWHcHjNoYH9kJk2fxoJxgBrstVJ7bHRecKewJAKcvUD"},{"address":"LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw","id":0,"name":"0","participantNodeState":"CONSENSUS","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"},{"address":"LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6","id":3,"name":"3","participantNodeState":"CONSENSUS","pubKey":"7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr"}] +register participant: [LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T] +``` +可以看出`node4`注册成功,地址为`LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T` + +#### 激活节点 + +激活节点前请正确配置并启动新节点,以下以刚注册成功的`node4`为例 + +1. 配置`node4` + +解压`peer`压缩包,复制待加入账本其他节点中数据最新的节点数据库数据,然后修改`config/ledger-binding.conf`: +```bash +# Base58编码的账本哈希 +ledger.bindings=<账本hash> +# 账本名字,与账本相关的其他其他peer保持一致 +binding.<账本HASH>.name=<节点名称> +# peer4的名名称,与[向现有共识网络注册新的参与方]操作中保持一致 +binding.<账本hash>.parti.name=<节点名称> +# peer4的用户地址 +binding.<账本hash>.parti.address= +# 新参与方base58编码的私钥,与[向现有共识网络注册新的参与方]操作中保持一致 +binding.<账本hash>.parti.pk=<新参与方base58编码的私钥> +# 新参与方base58编码的私钥读取密码,与[向现有共识网络注册新的参与方]操作中保持一致 +binding.<账本hash>.parti.pwd=<新参与方base58编码的私钥读取密码> +# 新参与方对应的账本数据库连接uri,即peer4的账本数据库存放位置,参照其他peer修改,不可与其他peer混用 +binding.<账本hash>.db.uri=<账本数据库连接> +``` + +2. 启动`node4` +| **一定注意在启动新参与方节点进程之前确保完成了账本数据库的复制工作** + +执行`peer4`中`bin`目录下`peer-startup.sh`脚本启动启动新参与方`peer4`节点进程: +```bash +./peer-startup.sh +``` + +3. 激活新节点 +```bash +:bin$ ./jdchain-cli.sh participant active -h +Active participant. +Usage: jdchain-cli participant active [-hV] [--pretty] [--shutdown] + --consensus-port= + [--home=] --host= + --ledger= --port= + --syn-host= --syn-port= + --consensus-port= + Set the participant consensus port. + -h, --help Show this help message and exit. + --home= Set the home directory. + --host= Set the participant host. + --ledger= Set the ledger. + --port= Set the participant service port. + --pretty Pretty json print + --shutdown Restart the node server. + --syn-host= Set synchronization participant host. + --syn-port= Set synchronization participant port. + -V, --version Print version information and exit. +``` +- `ledger`,账本哈希 +- `host`,新节点地址 +- `port`,新节点服务端口 +- `consensus-port`,新节点共识端口 +- `syn-host`,数据同步节点地址 +- `syn-port`,数据同步节点服务端口 + +在账本`j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg`中激活`node4`(以步骤2中启动的服务地址和端口为`127.0.0.1`和`7084`例),共识端口设置为`10088`,同步节点地址和端口为`127.0.0.1`和`7080`为例: +```bash +./jdchain-cli.sh participant active --ledger j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg --host 127.0.0.1 --port 7084 --consensus-port 10088 --syn-host 127.0.0.1 --syn-port 7080 +participant activated +``` + +成功后可通过[共识节点列表](query.md#共识节点列表)查询最新共识节点列表状态,`node4`为`CONSENSUS` + +#### 更新节点 + +通过[激活节点](#激活节点)操作除了激活新增的节点外,还可以动态修改已经处于激活状态的共识节点的`IP`和`共识端口`信息,从而实现本机的共识端口变更,不同机器之间进行`账本迁移`。 + +| **在进行节点信息变更时,要求暂停向共识网络中发起新的业务数据上链请求** + +1. 变更共识端口 + +| **操作前请确保变更到的端口未被占用** + +如将`node4`共识端口由`10088`修改为`10188`,操作指令如下: + +```bash +./jdchain-cli.sh participant update --ledger j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg --host 127.0.0.1 --port 7084 --consensus-port 10188 --syn-host 127.0.0.1 --syn-port 7080 +participant updated +``` +指令成功执行后,`peer1`的共识端口将自动变更为`10188` + +2. 账本迁移 + +账本迁移指将一台机器(`IP`)上的共识节点迁移到另一台机器(`IP`)上,主要操作流程如下: + +| **操作前请确保变更到的端口未被占用** + +如将`node4`共识`IP`由`127.0.0.1`修改为`192.168.1.100`(另一台机器),操作指令如下: + +```bash +./jdchain-cli.sh participant update --ledger j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg --host 192.168.1.100 --port 7084 --consensus-port 10188 --syn-host 127.0.0.1 --syn-port 7080 -shutdown +participant updated +``` + +**特别注意**:`-shutdown`会停止当前运行的当前账本共识服务,为必填选项,否则可能将导致整个网络需要重启。 + +#### 移除节点 + +``` +:bin$ ./jdchain-cli.sh participant inactive -h +Inactive participant. +Usage: jdchain-cli participant inactive [-hV] [--pretty] --address=
+ [--home=] --host= + --ledger= --port= + --syn-host= + --syn-port= + --address=
Set the participant address. + -h, --help Show this help message and exit. + --home= Set the home directory. + --host= Set the participant host. + --ledger= Set the ledger. + --port= Set the participant service port. + --pretty Pretty json print + --syn-host= Set synchronization participant host. + --syn-port= Set synchronization participant port. + -V, --version Print version information and exit. +``` +- `ledger`,账本哈希 +- `address`,待移除节点共识端口 +- `host`,待移除节点服务地址 +- `port`,待移除节点服务端口 +- `syn-host`,数据同步节点地址 +- `syn-port`,数据同步节点服务端口 + +如移除`node4`: +```bash +:bin$ ./jdchain-cli.sh participant inactive --ledger j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg --address LdeNwG6ECEGz57o2ufhwSbnW4C35TvPqANK7T --host 127.0.0.1 --port 7084 --syn-host 127.0.0.1 --syn-port 7080 +participant inactivated +``` + +成功后可通过[共识节点列表](query.md#共识节点列表)查询最新共识节点列表状态,`node4`为`DEACTIVATED` \ No newline at end of file diff --git a/docs/cli/query.md b/docs/cli/query.md new file mode 100644 index 00000000..87e36020 --- /dev/null +++ b/docs/cli/query.md @@ -0,0 +1,914 @@ +### 链上信息查询 + +```bash +:bin$ ./jdchain-cli.sh query -h +Usage: jdchain-cli query [-hV] [--pretty] [--gw-host=] + [--gw-port=] [--home=] [COMMAND] +Query commands. + --gw-host= Set the gateway host. Default: 127.0.0.1 + Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + Default: ../ + --pretty Pretty json print + -V, --version Print version information and exit. +Commands: + ledgers Query ledgers. + ledger Query ledger. + participants Query participants. + block Query block. + txs-count Query transactions count. + txs Query transactions. + tx Query transaction. + users Query users. + users-count Query users count. + user Query user. + role-privileges Query role privileges. + user-privileges Query user privileges. + data-accounts-count Query data accounts count. + data-accounts Query data accounts. + data-account Query data account. + kvs-count Query key-values count. + kvs Query kvs. + kv Query kv. + user-event-accounts-count Query user event accounts count. + user-event-accounts Query user event accounts. + user-event-account Query user event account. + user-event-names-count Query user event names count. + user-event-names Query user event names. + user-events-count Query user events count. + user-events Query user events. + latest-user-event Query latest user event. + contracts-count Query contracts count. + contracts Query contracts. + contract Query contract. + help Displays help information about the specified command +``` +查询命令:[账本列表](#账本列表),[账本详情](#账本详情),[共识节点列表](#共识节点列表),[区块详情](#区块详情),[交易总数](#交易总数),[交易列表](#交易列表),[交易详情](#交易详情),[用户总数](#用户总数),[用户列表](#用户列表),[用户详情](#用户详情),[角色权限](#角色权限),[用户权限](#用户权限),[数据账户总数](#数据账户总数),[数据账户列表](#数据账户列表),[数据账户详情](#数据账户详情),[KV总数](#KV总数),[KV列表](#KV列表),[KV详情](#KV详情),[用户事件账户总数](#用户事件账户总数),[用户事件账户列表](#用户事件账户列表),[用户事件账户详情](#用户事件账户详情),[用户事件名总数](#用户事件名总数),[用户事件名列表](#用户事件名列表),[用户事件总数](#用户事件总数),[用户事件列表](#用户事件列表),[最新用户事件](#最新用户事件),[合约总数](#合约总数),[合约列表](#合约列表),[合约详情](#合约详情) + +#### 账本列表 + +```bash +:bin$ ./jdchain-cli.sh query ledgers +j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +``` +返回当前网关服务所有账本列表 + +#### 账本详情 + +选择账本,打印当前账本详细信息: +```bash +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"hash":"j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg","latestBlockHash":"j5n8KGMFsRM7jzf99XK1jDK342fauj3myKcdgPJyLYyxws","latestBlockHeight":18} +``` + +可添加`--pretty`格式化输出`json`数据 + +#### 共识节点列表 + +查询共识节点列表: +```bash +:bin$ ./jdchain-cli.sh query participants +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +[{"address":"LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE","id":2,"name":"2","participantNodeState":"CONSENSUS","pubKey":"7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6"},{"address":"LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY","id":1,"name":"1","participantNodeState":"CONSENSUS","pubKey":"7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW"},{"address":"LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw","id":0,"name":"0","participantNodeState":"CONSENSUS","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"},{"address":"LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6","id":3,"name":"3","participantNodeState":"CONSENSUS","pubKey":"7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr"}] +``` +账本`j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg`中有四个共识节点,均为`CONSENSUS`状态 + +#### 区块详情 + +```bash +:bin$ ./jdchain-cli.sh query block -h +Query block. +Usage: jdchain-cli query block [-hV] [--pretty] [--gw-host=] + [--gw-port=] [--hash=] + [--height=] [--home=] + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --hash= Block hash + --height= Block height. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `height`,区块高度,默认`-1`查询当前最高区块 + +如: +```bash +:bin$ ./jdchain-cli.sh query block --pretty +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{ + "adminAccountHash":"j5p5z4es9RPrQWFu2nSJBQFT68byeGqAdUDu63qa5xV8Df", + "contractAccountSetHash":"j5kbvGQ1tFH2GXgk8ThF1co7H2gCrFdeZn7Nibva7Md72P", + "dataAccountSetHash":"j5fSmQkk8tb9v9SYDmaAko3oJJqmCm54HGbQwgbV2nTCVk", + "hash":"j5n8KGMFsRM7jzf99XK1jDK342fauj3myKcdgPJyLYyxws", + "height":18, + "ledgerHash":"j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg", + "previousHash":"j5motWQdmckqTxkG3x8DcE6quv2oGteKzsHqoV89Lfo4Mj", + "timestamp":1627703544928, + "transactionSetHash":"j5rc9PV5p9C8mXDAt8p9MR4QY3VAr4wQNG7zC3MSvFpcGG", + "userAccountSetHash":"j5haZvthy9gGaJ8M3mEbwtpeUg9Z113ifZbcWtzAeQcQdu", + "userEventSetHash":"j5nke9ZAnVRf1Qgg4u9Ske8RoZFbFVzVrKQid14qcqXaAn" +} +``` +返回当前最高区块详情 + +#### 交易总数 + +```bash +:bin$ ./jdchain-cli.sh query txs-count -h +Query transactions count. +Usage: jdchain-cli query txs-count [-hV] [--in-block] [--pretty] + [--gw-host=] [--gw-port=] + --height= [--home=] + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --height= Block height. + --home= Set the home directory. + --in-block In the given block. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `height`,区块高度 +- `in-block`,是否只统计`height`参数指定区块数据 + +如查询高度`10`区块交易总数(会统计区块`0-10`内所有交易): +```bash +:bin$ ./jdchain-cli.sh query txs-count --height 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +11 +``` + +查询高度`10`区块内交易总数(仅统计区块`10`交易): +```bash +:bin$ ./jdchain-cli.sh query txs-count --height 10 --in-block +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +1 +``` + +#### 交易列表 + +```bash +:bin$ ./jdchain-cli.sh query txs -h +Query transactions. +Usage: jdchain-cli query txs [-hV] [--in-block] [--pretty] --count= + [--gw-host=] [--gw-port=] + [--height=] [--home=] --index= + --count= Transaction item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --height= Block height. + --home= Set the home directory. + --in-block In the given block. + --index= Transaction item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `height`,区块高度 +- `in-block`,是否只统计`height`参数指定区块数据 +- `index`,查询起始位置 +- `count`,最大返回 + +如查询高度`10`区块交易列表(会统计区块`0-10`内所有交易),从第`0`条开始,最大返回`1`条: +```bash +:bin$ ./jdchain-cli.sh query txs --height 10 --index 0 --count 1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +[{"request":{"endpointSignatures":[],"nodeSignatures":[{"digest":"SMHYntB7uTm3N4mReke4srWHhpDkjDFGRuz7Bis8quJt19igevwA4rEwNmZqFGGLMExgmrPvdGrxgRrhLhpxUo1KGW","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"},{"digest":"SMHbyCLcvds5sRKaWPptSjixxoaiwkQfM1noLGpLSvsmxwUSg4J55UhJtK1ZWiQp3rxy5FEMZpwHGkywexYuwXEWHo","pubKey":"7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW"},{"digest":"SMGP3a7GHW6qWbQY3ZXX5UBhHNFLrSkUzRLLfCFA9Gu6CJVoYVvBQjjCEzaYq9ox38DvyZJQFuLWPirV2G6VMeARqQ","pubKey":"7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6"},{"digest":"SMHGzmEVzZPKyvN3zC6nLbVypufWEfd6cFvnMMjuEXFk5WncLeUx4CyAohTnNLP21ksJ6r15usowbkRFeaUYQgJkre","pubKey":"7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr"}],"transactionContent":{"operations":[{"@type":"com.jd.blockchain.ledger.LedgerInitOperation","initSetting":{"consensusParticipants":[{"address":"LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw","id":0,"name":"0","participantNodeState":"CONSENSUS","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"},{"address":"LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY","id":1,"name":"1","participantNodeState":"CONSENSUS","pubKey":"7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW"},{"address":"LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE","id":2,"name":"2","participantNodeState":"CONSENSUS","pubKey":"7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6"},{"address":"LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6","id":3,"name":"3","participantNodeState":"CONSENSUS","pubKey":"7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr"}],"consensusProvider":"com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider","consensusSettings":"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","createdTime":1627618941000,"cryptoSetting":{"autoVerifyHash":true,"hashAlgorithm":8216,"supportedProviders":[{"algorithms":[{},{},{},{},{},{},{}],"name":"com.jd.blockchain.crypto.service.classic.ClassicCryptoService"},{"algorithms":[{},{},{}],"name":"com.jd.blockchain.crypto.service.sm.SMCryptoService"}]},"ledgerSeed":"kULN7uzXyZuC7rD9BMLIgA==","ledgerStructureVersion":-1}},{"@type":"com.jd.blockchain.ledger.UserRegisterOperation","userID":{"address":"LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"}},{"@type":"com.jd.blockchain.ledger.UserRegisterOperation","userID":{"address":"LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY","pubKey":"7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW"}},{"@type":"com.jd.blockchain.ledger.UserRegisterOperation","userID":{"address":"LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE","pubKey":"7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6"}},{"@type":"com.jd.blockchain.ledger.UserRegisterOperation","userID":{"address":"LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6","pubKey":"7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr"}},{"@type":"com.jd.blockchain.ledger.RolesConfigureOperation","roles":[{"disableLedgerPermissions":[],"disableTransactionPermissions":[],"enableLedgerPermissions":["CONFIGURE_ROLES","AUTHORIZE_USER_ROLES","SET_CONSENSUS","SET_CRYPTO","REGISTER_PARTICIPANT","REGISTER_USER","REGISTER_DATA_ACCOUNT","REGISTER_CONTRACT","UPGRADE_CONTRACT","SET_USER_ATTRIBUTES","WRITE_DATA_ACCOUNT","APPROVE_TX","CONSENSUS_TX","REGISTER_EVENT_ACCOUNT","WRITE_EVENT_ACCOUNT"],"enableTransactionPermissions":["DIRECT_OPERATION","CONTRACT_OPERATION"],"roleName":"DEFAULT"}]},{"@type":"com.jd.blockchain.ledger.UserAuthorizeOperation","userRolesAuthorizations":[{"authorizedRoles":[],"policy":"UNION","unauthorizedRoles":[],"userAddresses":["LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw"]}]},{"@type":"com.jd.blockchain.ledger.UserAuthorizeOperation","userRolesAuthorizations":[{"authorizedRoles":[],"policy":"UNION","unauthorizedRoles":[],"userAddresses":["LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY"]}]},{"@type":"com.jd.blockchain.ledger.UserAuthorizeOperation","userRolesAuthorizations":[{"authorizedRoles":[],"policy":"UNION","unauthorizedRoles":[],"userAddresses":["LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE"]}]},{"@type":"com.jd.blockchain.ledger.UserAuthorizeOperation","userRolesAuthorizations":[{"authorizedRoles":[],"policy":"UNION","unauthorizedRoles":[],"userAddresses":["LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6"]}]}],"timestamp":1627618941000},"transactionHash":"j5vJGDBQLi6Vo5Gxtsab1vyL2TFaf1NoXDi6Xv2uvCcj9T"},"result":{"blockHeight":0,"dataSnapshot":{"adminAccountHash":"j5u4gqeAkKb3DoELpXP9bDgAxCVRQgKsguPvE1Wc9re1UT","userAccountSetHash":"j5hzkPPBJAqKs4rLWbEiFhbh1VW6Jc2xk878X5A6JywPnC"},"executionState":"SUCCESS","transactionHash":"j5vJGDBQLi6Vo5Gxtsab1vyL2TFaf1NoXDi6Xv2uvCcj9T"}}] +``` + +查询高度`10`区块内交易列表(仅统计区块`10`交易),从第`0`条开始,最大返回`1`: +```bash +:bin$ ./jdchain-cli.sh query txs --height 10 --index 0 --count 1 --in-block +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +[{"request":{"endpointSignatures":[{"digest":"SMKgce34AxQ8JEDDZY3x7iMvbL5QymiC93XPWqSirUB2AN8rvx18ynDS9f1zFA6QyXQNowA1XNhaLWnArrt7JHHxhY","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"}],"nodeSignatures":[{"digest":"SMKgce34AxQ8JEDDZY3x7iMvbL5QymiC93XPWqSirUB2AN8rvx18ynDS9f1zFA6QyXQNowA1XNhaLWnArrt7JHHxhY","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"}],"transactionContent":{"ledgerHash":"j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg","operations":[{"@type":"com.jd.blockchain.ledger.DataAccountKVSetOperation","accountAddress":"LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC","writeSet":[{"expectedVersion":-1,"key":"k1","value":{"bytes":"djE=","type":"TEXT"}}]}],"timestamp":1627632026435},"transactionHash":"j5fo2aAwp2tsneHm4wE8AnWLV7CKyax7BLWJqJm2V3WsrD"},"result":{"blockHeight":10,"dataSnapshot":{"adminAccountHash":"j5p5z4es9RPrQWFu2nSJBQFT68byeGqAdUDu63qa5xV8Df","dataAccountSetHash":"j5fSmQkk8tb9v9SYDmaAko3oJJqmCm54HGbQwgbV2nTCVk","userAccountSetHash":"j5mwiewVaxPLYQciovrB9nShWD5nr7YYFopbmWx28jqiFH","userEventSetHash":"j5wf9v6ixDDSD2gRi47r3vomkmTaRCqSLNbaNxrKcVdtD7"},"executionState":"SUCCESS","transactionHash":"j5fo2aAwp2tsneHm4wE8AnWLV7CKyax7BLWJqJm2V3WsrD"}}] +``` + +#### 交易详情 + +```bash +e:bin$ ./jdchain-cli.sh query tx -h +Query transaction. +Usage: jdchain-cli query tx [-hV] [--pretty] [--gw-host=] + [--gw-port=] [--hash=] [--home=] + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --hash= Transaction hash + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `hash`,交易哈希 + +如查询交易`j5fo2aAwp2tsneHm4wE8AnWLV7CKyax7BLWJqJm2V3WsrD`详情: +```bash +:bin$ ./jdchain-cli.sh query tx --hash j5fo2aAwp2tsneHm4wE8AnWLV7CKyax7BLWJqJm2V3WsrD +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"request":{"endpointSignatures":[{"digest":"SMKgce34AxQ8JEDDZY3x7iMvbL5QymiC93XPWqSirUB2AN8rvx18ynDS9f1zFA6QyXQNowA1XNhaLWnArrt7JHHxhY","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"}],"nodeSignatures":[{"digest":"SMKgce34AxQ8JEDDZY3x7iMvbL5QymiC93XPWqSirUB2AN8rvx18ynDS9f1zFA6QyXQNowA1XNhaLWnArrt7JHHxhY","pubKey":"7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn"}],"transactionContent":{"ledgerHash":"j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg","operations":[{"@type":"com.jd.blockchain.ledger.DataAccountKVSetOperation","accountAddress":"LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC","writeSet":[{"expectedVersion":-1,"key":"k1","value":{"bytes":"djE=","type":"TEXT"}}]}],"timestamp":1627632026435},"transactionHash":"j5fo2aAwp2tsneHm4wE8AnWLV7CKyax7BLWJqJm2V3WsrD"},"result":{"blockHeight":10,"dataSnapshot":{"adminAccountHash":"j5p5z4es9RPrQWFu2nSJBQFT68byeGqAdUDu63qa5xV8Df","dataAccountSetHash":"j5fSmQkk8tb9v9SYDmaAko3oJJqmCm54HGbQwgbV2nTCVk","userAccountSetHash":"j5mwiewVaxPLYQciovrB9nShWD5nr7YYFopbmWx28jqiFH","userEventSetHash":"j5wf9v6ixDDSD2gRi47r3vomkmTaRCqSLNbaNxrKcVdtD7"},"executionState":"SUCCESS","transactionHash":"j5fo2aAwp2tsneHm4wE8AnWLV7CKyax7BLWJqJm2V3WsrD"}} +``` + +#### 用户总数 + +查询用户总数: +```bash +:bin$ ./jdchain-cli.sh query users-count +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +10 +``` +当前区块链网络共有`10`个用户 + +#### 用户列表 + +```bash +:bin$ ./jdchain-cli.sh query users -h +Query users. +Usage: jdchain-cli query users [-hV] [--pretty] --count= + [--gw-host=] [--gw-port=] + [--home=] --index= + --count= User item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= User item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `index`,起始位置 +- `count`,最大返回 + +如分页查询用户列表,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query users --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +ADDRESS PUBKEY +LdeP2ji8PR1DPsLt5NoFeiBnhpckrLHgCJge6 7VeRGE4V9MR7HgAqTrkxGvJvaaKRZ3fAjHUjYzpNBGcjfAvr +LdeNq3862vtUCeptww1T5mVvLbAeppYqVNdqD 7VeRGuwP2iUykAL4beftP1DuDTj7y2uFGEM6mx3Dy7YSm2j1 +LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC 7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk +LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw 7VeRJpb2XX8XKAaC7G5zQg9DbgKM8gmLhUBtGFmerFbhJTZn +LdeNwTWpyzqioLURrHQuoGcnwA6YLiFWn3LNn 7VeRH7BsRntvJmomjw7YvF5HZVsSMb48GKzPnAP7iekRCLGq +LdeNiXZbsBCsTc2ZGp1PGBX81aUxPekhwEwmY 7VeREmuT4fF9yRPEMbSSaNLKbLa3qoTpfGHRgwpnSWUn5tqW +LdeNisM5oTypwPYv9tnhFNosRjCyXzzViU4SA 7VeREyEcDcY85DRdWAEsmJ4Moh89eE21AU2LEDbYG3t3MrGo +LdeNqvSjL4izfpMNsGpQiBpTBse4g6qLxZ6j5 7VeRFd2LB8ZmYnVNc2pux5TwVqHv3pwT6JXoF3fzDon9bSXK +LdeNwsiuo7n6HULWhNKc87PBXJXAfGKFon9RE 7VeRFF1ednwhrFoe5cngKwPUJ2N4iFKD9Jt53GxSCc1MmPQ6 +LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB 7VeRMGBMMBQVoZQTU3mcJYGgbVcQzxXiq6NK69TaCjEoktLf +``` +返回`10`个用户的地址和公私钥信息 + +| 由于`JD Chain`网络并不保证用户(数据账户/事件账户/合约账户)按创建顺序排列,所以当有新的用户注册后,前后两次相同参数的查询数据可能不一致!!! + +#### 用户详情 + +```bash +:bin$ ./jdchain-cli.sh query user -h +Query user. +Usage: jdchain-cli query user [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] + [--home=] + --address=
User address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,用户地址 + +根据地址`LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB`查询用户详情: +```bash +:bin$ ./jdchain-cli.sh query user --address LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"address":"LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB","pubKey":"7VeRMGBMMBQVoZQTU3mcJYGgbVcQzxXiq6NK69TaCjEoktLf"} +``` + +#### 角色权限 + +```bash +:bin$ ./jdchain-cli.sh query role-privileges -h +Query role privileges. +Usage: jdchain-cli query role-privileges [-hV] [--pretty] [--gw-host=] + [--gw-port=] [--home=] --role= + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + --role= Role name + -V, --version Print version information and exit. +``` +- `role`,角色名称 + +查询角色`ROLE1`权限信息: +```bash +:bin$ ./jdchain-cli.sh query role-privileges --role ROLE1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"ledgerPrivilege":{"permissionCount":2,"privilege":["REGISTER_USER","REGISTER_DATA_ACCOUNT"]},"transactionPrivilege":{"permissionCount":2,"privilege":["DIRECT_OPERATION","CONTRACT_OPERATION"]}} +``` + +#### 用户权限 + +```bash +:bin$ ./jdchain-cli.sh query user-privileges -h +Query user privileges. +Usage: jdchain-cli query user-privileges [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] [--home=] + --address=
User address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,用户地址 + +查询用户`LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB`权限信息: +```bash +:bin$ ./jdchain-cli.sh query user-privileges --address LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"ledgerPrivilegesBitset":{"privilege":["CONFIGURE_ROLES","AUTHORIZE_USER_ROLES","SET_CONSENSUS","SET_CRYPTO","REGISTER_PARTICIPANT","REGISTER_USER","REGISTER_DATA_ACCOUNT","REGISTER_CONTRACT","UPGRADE_CONTRACT","SET_USER_ATTRIBUTES","WRITE_DATA_ACCOUNT","APPROVE_TX","CONSENSUS_TX","REGISTER_EVENT_ACCOUNT","WRITE_EVENT_ACCOUNT"]},"transactionPrivilegesBitset":{"privilege":["DIRECT_OPERATION","CONTRACT_OPERATION"]},"userAddress":"LdeNufGZewrvS7sE4VWC9m1SFkPqVwjBN87LB","userRole":["DEFAULT"]} +``` + +#### 数据账户总数 + +查询数据账户总数: +```bash +:bin$ ./jdchain-cli.sh query data-accounts-count +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +1 +``` +当前账本共有一个数据账户 + +#### 数据账户列表 + +```bash +:bin$ ./jdchain-cli.sh query data-accounts -h +Query data accounts. +Usage: jdchain-cli query data-accounts [-hV] [--pretty] --count= + [--gw-host=] + [--gw-port=] [--home=] + --index= + --count= Data account item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= Data account item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `index`,起始位置 +- `count`,最大返回 + +如分页查询数据账户列表,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query data-accounts --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +ADDRESS PUBKEY +LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC 7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk +``` +返回数据账户的地址和公私钥信息 + +#### 数据账户详情 + +```bash +:bin$ ./jdchain-cli.sh query data-account -h +Query data account. +Usage: jdchain-cli query data-account [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] + [--home=] + --address=
Data account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,数据账户地址 + +查询数据账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`详情: +```bash +:bin$ ./jdchain-cli.sh query data-account --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"address":"LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC","dataRootHash":"j5vyv6SmvSXQNKyjsEVCQJsyqXxKGZMBU62fKvtdJm2W4y","headerRootHash":"j5sA2KPgY9vidgTUCjCJiscn2CXapgSJsVnWe54xXKohej","pubKey":"7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk"} +``` + +#### KV总数 + +```bash +:bin$ ./jdchain-cli.sh query kvs-count -h +Query key-values count. +Usage: jdchain-cli query kvs-count [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] + [--home=] + --address=
Data account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,数据账户地址 + +查询数据账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`中`kv`数据总数: +```bash +:bin$ ./jdchain-cli.sh query kvs-count --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +1 +``` +共有一个`kv` + +#### KV列表 + +```bash +:bin$ ./jdchain-cli.sh query kvs -h +Query kvs. +Usage: jdchain-cli query kvs [-hV] [--pretty] --address=
+ --count= [--gw-host=] + [--gw-port=] [--home=] + --index= + --address=
Data account address + --count= KV item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= KV item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,数据账户地址 +- `index`,起始位置 +- `count`,最大返回 + +如分页查询数据账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`中`kv`列表,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query kvs --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"key":"k1","type":"TEXT","value":"v1","version":0} +``` + +#### KV详情 + +```bash +:bin$ ./jdchain-cli.sh query kv -h +Query kv. +Usage: jdchain-cli query kv [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] + [--home=] --key= + --address=
Data account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --key= Key + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,数据账户地址 +- `key`,`key` + +查询数据账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`中`k1`最新数据: +```bash +:bin$ ./jdchain-cli.sh query kv --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --key k1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"key":"k1","type":"TEXT","value":"v1","version":0} +``` + +#### 用户事件账户总数 + +查询数据账户总数: +```bash +:bin$ ./jdchain-cli.sh query user-event-accounts-count +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +4 +``` +当前账本共有`4`个数据账户 + +#### 用户事件账户列表 + +```bash +:bin$ ./jdchain-cli.sh query user-event-accounts -h +Query user event accounts. +Usage: jdchain-cli query user-event-accounts [-hV] [--pretty] --count= + [--gw-host=] [--gw-port=] [--home=] --index= + --count= Event account item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= Event account item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `index`,起始位置 +- `count`,最大返回 + +如分页查询用户事件账户列表,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query user-event-accounts --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +ADDRESS PUBKEY +LdeNhAxxXjbh56LqeB7xHpgZgHG6GDTZ45GgJ 7VeR82o3hZy1AVEjmxfNpHHW3d1zabbELmJUnijGkKJNDXu5 +LdeP33nxsYxYgaELQUkd8tBsTmwrkySiqnAVF 7VeRBA5zD2EDCiRtsiHzMQUEPf52hjKwhAi6PfNCgoiRQrSw +LdeNnDJyqYgxDernBf6Vh68CkM5FbJNYtQCPA 7VeRB71W3anhCBretEP2R9YjiFB7ne2o5qhsivPo3XmHZ7cJ +LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC 7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk +``` +返回用户事件账户的地址和公私钥信息 + +#### 用户事件账户详情 + +```bash +:bin$ ./jdchain-cli.sh query user-event-account -h +Query user event account. +Usage: jdchain-cli query user-event-account [-hV] [--pretty] + --address=
[--gw-host=] [--gw-port=] + [--home=] + --address=
Event account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,用户事件账户地址 + +查询事件账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`详情: +```bash +:bin$ ./jdchain-cli.sh query user-event-account --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"address":"LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC","pubKey":"7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk"} +``` + +#### 用户事件名总数 + +```bash +:bin$ ./jdchain-cli.sh query user-event-names-count -h +Query user event names count. +Usage: jdchain-cli query user-event-names-count [-hV] [--pretty] + --address=
[--gw-host=] [--gw-port=] + [--home=] + --address=
Event account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,用户事件账户地址 + +查询事件账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`事件名总数: +```bash +:bin$ ./jdchain-cli.sh query user-event-names-count --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +1 +``` + +#### 用户事件名列表 + +```bash +:bin$ ./jdchain-cli.sh query user-event-names -h +Query user event names. +Usage: jdchain-cli query user-event-names [-hV] [--pretty] --address=
+ --count= [--gw-host=] [--gw-port=] + [--home=] --index= + --address=
Event account address + --count= Event name item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= Event name item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,事件账户地址 +- `index`,起始位置 +- `count`,最大返回 + +如分页查询用户事件账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`事件名列表,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query user-event-names --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +t1 +``` +当前事件账户仅有一个事件名 + +#### 用户事件总数 + +```bash +:bin$ ./jdchain-cli.sh query user-events-count -h +Query user events count. +Usage: jdchain-cli query user-events-count [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] [--home=] --name= + --address=
Event account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --name= Event name + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,事件账户地址 +- `name`,事件名 + +查询事件账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`事件名`t1`中事件总数: +```bash +:bin$ ./jdchain-cli.sh query user-events-count --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --name t1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +1 +``` +当前事件名仅有一个事件 + +#### 用户事件列表 + +```bash +:bin$ ./jdchain-cli.sh query user-events -h +Query user events. +Usage: jdchain-cli query user-events [-hV] [--pretty] --address=
+ --count= [--gw-host=] + [--gw-port=] [--home=] + --index= --name= + --address=
Event account address + --count= Event name item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= Event name item index + --name= Event name + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,事件账户地址 +- `name`,事件名 +- `index`,起始位置 +- `count`,最大返回 + +分页查询用户事件账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`事件名`t1`中事件,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query user-events --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --name t1 --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"blockHeight":12,"content":{"bytes":"YzE=","type":"TEXT"},"contractSource":"","eventAccount":"LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC","name":"t1","sequence":0,"transactionSource":"j5jSszhiJUTbCGtFgxd6uBWyxj56CEHRyhDF6nAnUvJTp7"} +``` + +#### 最新用户事件 + +```bash +:bin$ ./jdchain-cli.sh query latest-user-event -h +Query latest user event. +Usage: jdchain-cli query latest-user-event [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] [--home=] --name= + --address=
Event account address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --name= Event name + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,时间账户地址 +- `name`,事件名 + +查询用户事件账户`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`事件名`t1`最新事件: +```bash +:bin$ ./jdchain-cli.sh query latest-user-event --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --name t1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +{"blockHeight":12,"content":{"bytes":"YzE=","type":"TEXT"},"contractSource":"","eventAccount":"LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC","name":"t1","sequence":0,"transactionSource":"j5jSszhiJUTbCGtFgxd6uBWyxj56CEHRyhDF6nAnUvJTp7"} +``` + +#### 合约总数 + +查询合约总数: +```bash +:bin$ ./jdchain-cli.sh query contracts-count +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +1 +``` +当前账本仅有一个合约 + +#### 合约列表 + +```bash +:bin$ ./jdchain-cli.sh query contracts -h +Query contracts. +Usage: jdchain-cli query contracts [-hV] [--pretty] --count= + [--gw-host=] [--gw-port=] + [--home=] --index= + --count= Contract item count + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --index= Contract item index + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `index`,起始位置 +- `count`,最大返回 + +分页查询合约,从第`0`个开始,最大返回`10`条: +```bash +:bin$ ./jdchain-cli.sh query contracts --index 0 --count 10 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +ADDRESS PUBKEY +LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH 7VeRFZEqSdXWQxaLUFaAgJVdVTssuwQdBg4KPGgCCTbrzqxA +``` +返回合约地址和公钥信息 + +#### 合约详情 + +```bash +e:bin$ ./jdchain-cli.sh query contract -h +Query contract. +Usage: jdchain-cli query contract [-hV] [--pretty] --address=
+ [--gw-host=] [--gw-port=] + [--home=] + --address=
Contract address + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,合约地址 + +查询合约`LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH`详情: +```bash +:bin$ ./jdchain-cli.sh query contract --address LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +package com.jdchain.samples.contract; + +import com.jd.blockchain.contract.*; +import utils.*; +import com.jd.blockchain.crypto.*; +import com.jd.blockchain.ledger.*; + +public class SampleContractImpl implements EventProcessingAware, SampleContract +{ + private ContractEventContext eventContext; + + public void setKVWithVersion(final String address, final String key, final String value, final long version) { + this.eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version); + } + + public void setKV(final String address, final String key, final String value) { + final TypedKVEntry[] entries = this.eventContext.getUncommittedLedger().getDataEntries(address, new String[] { key }); + long version = -1L; + if (null != entries && entries.length > 0) { + version = entries[0].getVersion(); + } + this.eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version); + } + + public String registerUser(final String seed) { + final CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); + final SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); + final AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); + final BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); + this.eventContext.getLedger().users().register(keypair.getIdentity()); + return keypair.getAddress().toBase58(); + } + + public String registerDataAccount(final String seed) { + final CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); + final SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); + final AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); + final BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); + this.eventContext.getLedger().dataAccounts().register(keypair.getIdentity()); + return keypair.getAddress().toBase58(); + } + + public String registerEventAccount(final String seed) { + final CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); + final SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); + final AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); + final BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); + this.eventContext.getLedger().eventAccounts().register(keypair.getIdentity()); + return keypair.getAddress().toBase58(); + } + + public void publishEventWithSequence(final String address, final String topic, final String content, final long sequence) { + this.eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence); + } + + public void publishEvent(final String address, final String topic, final String content) { + final Event event = this.eventContext.getUncommittedLedger().getLatestEvent(address, topic); + long sequence = -1L; + if (null != event) { + sequence = event.getSequence(); + } + this.eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence); + } + + public void beforeEvent(final ContractEventContext eventContext) { + this.eventContext = eventContext; + } + + public void postEvent(final ContractEventContext eventContext, final Exception error) { + } +} + +``` \ No newline at end of file diff --git a/docs/cli/tx.md b/docs/cli/tx.md new file mode 100644 index 00000000..a6bf3b74 --- /dev/null +++ b/docs/cli/tx.md @@ -0,0 +1,531 @@ +### 交易 + +```bash +:bin$ ./jdchain-cli.sh tx -h +Usage: git status [...] [--] [...] +Build, sign or send transaction. + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + Default: ../ + --pretty Pretty json print + -V, --version Print version information and exit. +Commands: + user-register Register new user. + role Create or config role. + authorization User role authorization. + data-account-register Register new data account. + kv Set key-value. + event Publish event. + contract-deploy Deploy or update contract. + contract Call contract method. + event-account-register Register event account. + sign Sign transaction. + send Send transaction. + help Displays help information about the specified command +``` + +参数: +- `export`,导出交易到指定位置,用于离线交易相关命令 +- `gw-host`,网关服务地址,默认`127.0.0.1` +- `gw-port`,网关服务端口,默认`8080` +- `home`,指定密钥存储相关目录,`${home}/config/keys` + +命令: +- `user-register`,[注册用户](#注册用户) +- `role`,[角色管理](#角色管理) +- `authorization`,[权限配置](#权限配置) +- `data-account-register`,[注册数据账户](#注册数据账户) +- `kv`,[KV设值](#KV设值) +- `event-account-register`,[注册事件账户](#注册事件账户) +- `event`,[发布事件](#发布事件) +- `contract-deploy`,[部署合约](#部署合约) +- `contract`,[合约调用](#合约调用) +- `sign`,[离线交易签名](#离线交易签名) +- `send`,[离线交易发送](#离线交易发送) + +#### 注册用户 + +```bash +:bin$ ./jdchain-cli.sh tx user-register -h +Register new user. +Usage: jdchain-cli tx user-register [-hV] [--pretty] [--export=] + [--gw-host=] [--gw-port=] + [--home=] + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. +``` +从`${home}/config/keys`目录下密钥对选择密钥注册到网关服务对应的区块链网络。 + +如: +```bash +:bin$ ./jdchain-cli.sh tx user-register +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +// 选择账本,当前网关服务只有上面一个可用账本 +> 0 +select keypair to register: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +// 选择公私钥对用于注册用户 +> 1 +input password of the key: +// 输入所选择公私钥对密钥密码 +> 1 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +// 选择链上已存在且有注册用户权限的用户所对应的公私钥对,用于交易签名 +> 0 +input password of the key: +// 输入签名私钥密码 +> 1 +register user: [LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC] +``` +会在链上注册地址为`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`的用户账户信息。 + + +#### 角色管理 +```bash +:bin$ ./jdchain-cli.sh tx role -h +Create or config role. +Usage: jdchain-cli tx role [-hV] [--pretty] [--export=] + [--gw-host=] [--gw-port=] + [--home=] --name= + [--disable-ledger-perms=[, + ...]]... + [--disable-transaction-perms=[,...]]... + [--enable-ledger-perms=[, + ...]]... + [--enable-transaction-perms= + [,...]]... + --disable-ledger-perms=[,...] + Disable ledger permissions + --disable-transaction-perms=[, + ...] + Disable transaction permissions + --enable-ledger-perms=[,...] + Enable ledger permissions + --enable-transaction-perms=[, + ...] + Enable transaction permissions + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --name= Role name + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `name`,角色名称,不存在则创建 +- `disable-ledger-perms`,禁用的账本权限列表,半角逗号分割 +- `disable-transaction-perms`,禁用的交易权限列表,半角逗号分割 +- `enable-ledger-perms`,的账本权限列表,半角逗号分割 +- `enable-transaction-perms`,禁用的交易权限列表,半角逗号分割 + +如: +```bash +:bin$ ./jdchain-cli.sh tx role --name ROLE1 --enable-ledger-perms REGISTER_USER,REGISTER_DATA_ACCOUNT --enable-transaction-perms DIRECT_OPERATION,CONTRACT_OPERATION +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +// 选择账本 +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +// 选择签名账户 +> 0 +input password of the key: +// 输入签名账户私钥密码 +> 1 +Role config success! +``` + +#### 权限配置 + +```bash +:bin$ ./jdchain-cli.sh tx authorization -h +User role authorization. +Usage: jdchain-cli tx authorization [-hV] [--pretty] --address=
+ [--export=] [--gw-host=] + [--gw-port=] [--home=] + [--policy=] + [--authorize=[, + ...]]... + [--unauthorize=[, + ...]]... + --address=
User address + --authorize=[,...] + Authorize roles + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --policy= Role policy + --pretty Pretty json print + --unauthorize=[,...] + Unauthorize roles + -V, --version Print version information and exit. +``` +- `address`,用户地址 +- `authorize`,赋予角色列表,半角逗号分割 +- `unauthorize`,移除角色列表,半角逗号分割 +- `policy`,角色策略,`UNION`/`INTERSECT`,默认`UNION`合并所有角色权限 + +如: +```bash +:bin$ ./jdchain-cli.sh tx authorization --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --authorize ROLE1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +Authorization config success! +``` + +#### 注册数据账户 + +```bash +:bin$ ./jdchain-cli.sh tx data-account-register -h +Register new data account. +Usage: jdchain-cli tx data-account-register [-hV] [--pretty] + [--export=] [--gw-host=] [--gw-port=] + [--home=] [--pubkey=] + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + --pubkey= The pubkey of the exist data account + -V, --version Print version information and exit. +``` +- `pubkey`,待注册数据账户私钥 + +如: +```bash +:bin$ ./jdchain-cli.sh tx data-account-register --pubkey 7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +register data account: [LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC] +``` +会在链上注册地址为`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`的数据账户信息。 + +#### KV设值 + +```bash +:bin$ ./jdchain-cli.sh tx kv -h +Set key-value. +Usage: jdchain-cli tx kv [-hV] [--pretty] --address=
+ [--export=] [--gw-host=] + [--gw-port=] [--home=] --key= + --value= [--ver=] + --address=
Data account address + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --key= Key to set + --pretty Pretty json print + -V, --version Print version information and exit. + --value= Value to set + --ver= Version of the key-value +``` +- `address`,数据账户地址 +- `key`,键 +- `value`,值 +- `ver`,版本 + +如向账户地址`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`写入`k1`:`v1`:`-1`键值对数据: +```bash +:bin$ ./jdchain-cli.sh tx kv --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --key k1 --value v1 --ver -1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +set kv success +``` + +#### 注册事件账户 + +```bash +:bin$ ./jdchain-cli.sh tx event-account-register -h +Register event account. +Usage: jdchain-cli tx event-account-register [-hV] [--pretty] + [--export=] [--gw-host=] [--gw-port=] + [--home=] [--pubkey=] + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + --pubkey= The pubkey of the exist event account + -V, --version Print version information and exit. +``` +- `pubkey`,待注册事件账户私钥 + +如: +```bash +:bin$ ./jdchain-cli.sh tx event-account-register --pubkey 7VeRFk4ANQHjWjAmAoL7492fuykTpXujihJeAgbXT2J9H9Yk +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +register event account: [LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC] +``` +会在链上注册地址为`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`的事件账户信息。 + +#### 发布事件 +```bash +:bin$ ./jdchain-cli.sh tx event -h +Publish event. +Usage: jdchain-cli tx event [-hV] [--pretty] --address=
+ --content= [--export=] + [--gw-host=] [--gw-port=] + [--home=] [--sequence=] + --name= + --address=
Contract address + --content= Event content + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + --sequence= Sequence of the event + --name= Event name + -V, --version Print version information and exit. +``` +- `address`,事件账户地址 +- `name`,事件名 +- `content`,事件内容 +- `sequence`,事件序号 + +如向账户地址`LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC`发布事件`n1`:`c1`:`-1`: +```bash +:bin$ ./jdchain-cli.sh tx event --address LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC --name n1 --content c1 --sequence -1 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +event publish success +``` + +#### 部署合约 + +```bash +:bin$ ./jdchain-cli.sh tx contract-deploy -h +Deploy or update contract. +Usage: jdchain-cli tx contract-deploy [-hV] [--pretty] --car= + [--export=] [--gw-host=] + [--gw-port=] [--home=] + [--pubkey=] + --car= The car file path + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + --pubkey= The pubkey of the exist contract + -V, --version Print version information and exit. +``` +- `pubkey`,合约公钥,更新合约时使用 +- `car`,合约`car`文件 + +如将`contract-samples-1.5.0.RELEASE.car`文件中的合约部署上链: +```bash +:bin$ ./jdchain-cli.sh tx contract-deploy --car /home/imuge/Desktop/jdchain-cli/1.5.0/contract-samples-1.5.0.RELEASE.car +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +deploy contract: [LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH] +``` +合约地址:`LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH` + +#### 合约调用 + +```bash +:bin$ ./jdchain-cli.sh tx contract -h +Call contract method. +Usage: jdchain-cli tx contract [-hV] [--pretty] --address=
+ [--export=] [--gw-host=] + [--gw-port=] [--home=] + --method= [--args=[,...]]... + --address=
Contract address + --args=[,...] + Method arguments + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --method= Contract method + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `address`,合约地址 +- `method`,合约方法 +- `args`,合约参数,半角逗号分割,命令行中会将所有参数处理为字符串,非字符串参数方法调用暂无法通过命令行工具调用 + +如调用合约`LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH`中`registerUser`方法,传参`ed386a148fcb48b281b325f66103c805`: +```bash +:bin$ ./jdchain-cli.sh tx contract --address LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH --method registerUser --args ed386a148fcb48b281b325f66103c805 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +call contract success +return string: LdeNqvSjL4izfpMNsGpQiBpTBse4g6qLxZ6j5 +``` +调用成功并返回了字符串:`LdeNqvSjL4izfpMNsGpQiBpTBse4g6qLxZ6j5` + + +#### 离线交易签名 + +1. 离线交易 + +执行以上所有交易时,若`export`参数不为空,则会执行交易写入本地操作,而非签名并发送交易,离线交易可以 + +如构造合约调用操作交易并保存到本地: +```bash +:bin$ ./jdchain-cli.sh tx contract --address LdeNyF6jdNry5iCqmHdAFTQPvC8UkbJ9avoXH --method registerUser --args ed386a148fcb48b281b325f66103c810 --export /txs +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +export transaction success: /txs/j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3 +``` +交易内容会被序列化报存在`/txs/j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3`中,其中`j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3`是该交易哈希。 + +2. 离线签名 + +```bash +:bin$ ./jdchain-cli.sh tx sign -h +Sign transaction. +Usage: jdchain-cli tx sign [-hV] [--pretty] [--export=] + [--gw-host=] [--gw-port=] + [--home=] [--tx=] + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --tx= Local transaction file + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `import`,离线交易路径 + +如对步骤1中创建的离线交易添加终端用户(此用户需是链上存在的且有相关权限的用户)签名: +```bash +:bin$ ./jdchain-cli.sh tx sign --tx /txs/j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3 +select keypair to sign tx: +INDEX KEY ADDRESS +0 peer0 LdeNyibeafrAQXgHjBxgQxoLbna6hL4BcXZiw +1 k1 LdeNwQWabrf6WSjZ35saFo52MfQFhVKvm11aC +> 0 +input password of the key: +> 1 +Sign transaction success! +``` + +#### 离线交易发送 + +发送本地已经签名完成的交易 +```bash +:bin$ ./jdchain-cli.sh tx send -h +Send transaction. +Usage: jdchain-cli tx send [-hV] [--pretty] [--export=] + [--gw-host=] [--gw-port=] + [--home=] [--tx=] + --export= Transaction export directory + --gw-host= Set the gateway host. Default: 127.0.0.1 + --gw-port= Set the gateway port. Default: 8080 + -h, --help Show this help message and exit. + --home= Set the home directory. + --tx= Local transaction file + --pretty Pretty json print + -V, --version Print version information and exit. +``` +- `import`,离线交易路径 + +如发送`/txs/j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3`中包含的交易数据: +```bash +:bin$ ./jdchain-cli.sh tx send --tx /home/imuge/Desktop/jdchain-cli/1.5.0/txs/j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3 +select ledger, input the index: +INDEX LEDGER +0 j5sB3sVTFgTqTYzo7KtQjBLSy8YQGPpJpvQZaW9Eqk46dg +> 0 +Send transaction success: j5xR8ty8YbujTYKNRshmbfMYsL4jfe3yRUtMparmeHppd3 +``` \ No newline at end of file diff --git a/docs/contract.md b/docs/contract.md new file mode 100644 index 00000000..fca1fa53 --- /dev/null +++ b/docs/contract.md @@ -0,0 +1,549 @@ +# 智能合约 + +### 1. 简介 + +JD Chain 智能合约系统由5个部分组成:合约代码语言、合约引擎、合约账户、合约开发框架、合约开发插件。 + +合约代码语言是用来编写智能合约的编程语言,合约引擎是解释和执行合约代码的虚拟机。 + +JD Chain 账本中以合约账户的方式对合约代码进行管理。一份部署上链的合约代码需要关联到一个唯一的公钥上,并生成与公钥对应的区块链账户地址,在账本中注册为一个合约账户。在执行之前,系统从账本中读出合约代码并将其加载到合约引擎,由交易执行器调用合约引擎触发合约执行。 + +JD Chain 账本定义了一组标准的账本操作指令,合约代码的执行过程实质上是向账本输出一串操作指令序列,这些指令对账本中的数据产生了变更,形成合约执行的最终结果。 + +合约开发框架定义了进行合约代码开发中需要依赖的一组编程接口和类库。合约开发插件提供了更方便与IDE集成的合约编译、部署工具,可以简化操作,并与持续集成过程结合。 + +JD Chain 以 Java 语言作为合约代码语言,合约引擎是基于 JVM 构建的安全沙盒。为了实现与主流的应用开发方式无缝兼容, JD Chain 支持以 Maven 来管理合约代码的工程项目,并提供相应的 maven 插件来简化合约的编译和部署。 + +>智能合约是一种可以由计算机执行的合同/协议。不同于现实生活中的合同是由自然语言来编写并约定相关方的权利和义务,智能合约是用合约代码语言来编写,以合约代码的形式存在和被执行。通过账本中的数据状态来表示合同/协议相关条款信息,合约代码的运行过程体现了合同/协议条款的执行,并记录相应的结果。 + +### 2. 快速入门 + +#### 2.1. 准备开发环境 + +按照正常的 Java 应用开发环境要求进行准备,以 Maven 作为代码工程的构建管理工具,无其它特殊要求。 + +>检查 JDK 版本不低于 1.8 ,Maven 版本不低于 3.0。 + +#### 2.2. 创建合约代码工程 +创建一个普通的 Java Maven 工程,打开 pom.xml 把 packaging 设为 contract . + +```xml + + 4.0.0 + your.group.id + your.project + 0.0.1-SNAPSHOT + + contract + + + + + + + + + + + +``` + +> 注:合约代码工程也是一个普通的 Java Maven 工程,因此尽管不同 IDE 创建 Maven 工程有不同的操作方式,由于对于合约开发而言并无特殊要求,故在此不做详述。 + +#### 2.3. 加入合约开发依赖 + +在合约代码工程 pom.xml 加入对合约开发 SDK 的依赖: + + ```xml + + com.jd.blockchain + contract-starter + ${jdchain.version} + + ``` + +#### 2.4. 加入合约插件 + +在合约代码工程的 pom.xml 加入 contract-maven-plugin 插件: + ```xml + + com.jd.blockchain + contract-maven-plugin + ${jdchain.version} + true + + ``` + +完整的 pom.xml 如下: + + ```xml + + 4.0.0 + your.group.id + your.project + 0.0.1-SNAPSHOT + + contract + + + 1.4.2.RELEASE + + + + + + com.jd.blockchain + contract-starter + ${jdchain.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + false + true + false + false + + + + + + com.jd.blockchain + contract-maven-plugin + ${jdchain.version} + true + + + + + ``` + +#### 2.5. 编写合约代码 + +2.5.1. **注意事项** + +1. 不允许合约(包括合约接口和合约实现类)使用com.jd.blockchain开头的package; +2. 必须有且只有一个接口使用@Contract注解,且其中的event必须大于等于一个; +3. 使用@Contract注解的接口有且只有一个实现类; +4. 黑名单调用限制(具体黑名单可查看配置文件),需要注意的是,黑名单分析策略会递归分析类实现的接口和父类,也就是说调用一个实现了指定黑名单接口的类也是不允许的; + + +目前设置的黑名单如下: +```conf +java.io.File +java.io.InputStream +java.io.OutputStream +java.io.DataInput +java.io.DataOutput +java.io.Reader +java.io.Writer +java.io.Flushable +java.nio.channels.* +java.nio.file.* +java.net.* +java.sql.* +java.lang.reflect.* +java.lang.Class +java.lang.ClassLoader +java.util.Random +java.lang.System-currentTimeMillis +java.lang.System-nanoTime +com.jd.blockchain.ledger.BlockchainKeyGenerator +``` + +2.5.2. **声明合约** + +```java +/** + * 声明合约接口; +**/ +@Contract +public interface AssetContract { + + @ContractEvent(name = "transfer") + String transfer(String address, String from, String to, long amount); + +} +``` + +2.5.3. **实现合约** + +```java +/** + * 实现合约; + * + * 实现 EventProcessingAware 接口是可选的,目的获得 ContractEventContext 上下文对象, + * 通过该对象可以进行账本操作; + */ +public class AssetContractImpl implements AssetContract, EventProcessingAware { + + // 合约事件上下文; + private ContractEventContext eventContext; + + /** + * 执行交易请求中对 AssetContract 合约的 transfer 调用操作; + */ + public String transfer(String address, String from, String to, long amount) { + //当前账本的哈希; + HashDigest ledgerHash = eventContext.getCurrentLedgerHash(); + //当前账本上下文; + LedgerContext ledgerContext = eventContext.getLedger(); + + //做操作; + // ledgerContext. + + //返回合约操作的结果; + return "success"; + } + + /** + * 准备执行交易中的合约调用操作; + */ + @Override + public void beforeEvent(ContractEventContext eventContext) { + this.eventContext = eventContext; + } + + /** + * 完成执行交易中的合约调用操作; + */ + @Override + public void postEvent(ContractEventContext eventContext, Exception error) { + this.eventContext = null; + } +} +``` + +**账本数据可见范围**: + +`ContractEventContext`中`getUncommittedLedger`方法可访问执行中的未提交区块数据,此方法的合理使用可以解决客户并发调用合约方法涉及数据版本/事件序列冲突的问题。 +```java +/** + * 当前包含未提交区块数据账本查询上下文; + */ +LedgerQueryService getUncommittedLedger(); +``` + +`ContractEventContext`中`getLedger`方法访问的是链上已提交的最新区块数据,不包含未提交交易,所以存在未提交交易中多个合约方法调用操作间数据不可见,导致并发时数据版本等冲突问题。 +```java +/** + * 账本操作上下文; + */ +LedgerContext getLedger(); +``` + +合约方法中对账本的操作通过调用`LedgerContext`中相关方法,可参照[示例合约](https://github.com/blockchain-jd-com/jdchain/tree/master/samples/contract-samples/src/main/java/com/jdchain/samples/contract) + +#### 2.6. 编译打包合约代码 + +合约代码工程的编译打包操作与普通的 maven 工程是相同的,在工程的根目录下输入以下命令: + +```bash +mvn clean package +``` + +执行成功之后,在 target 目录中输出合约代码文件 \.\.car 。 + +如果合约代码加入了除 com.jd.blockchain:contract-starter 之外的其它依赖,默认配置下,第三方依赖包将与 .car 文件一起打包一起部署。(也可以把第三方依赖包独立打包,具体参见以下 “3. 合约插件详细配置” + +> 注意:合约代码虽然利用了 Java 语言,遵照 Java 语法进行编写,但本质上是作为一种运行于受限环境(合约虚拟机)的语言来使用,因而一些 Java 语法和 SDK 的 API 是不被允许使用的,在编译过程中将对此进行检查。 + +#### 2.7. 部署合约代码 + +##### 2.7.1. 在项目中部署合约代码 + +如果希望在构建打包的同时将合约代码部署到指定的区块链网络,可以在合约代码工程 pom.xml 的 contract-maven-plugin 插件配置中加入合约部署相关的信息(具体更详细的配置可以参考“3. 合约插件详细配置”)。 + +```xml + + com.jd.blockchain + contract-maven-plugin + 1.2.0.RELEASE + true + + + + + j5rpuGWVxSuUbU3gK7MDREfui797AjfdHzvAMiSaSzydu7 + + + + 192.168.10.10 + 8081 + + + + + 7VeRMpXVeTY4cqPogUHeNoZNk86CGAejBh9Xbd5ndFZXNFj3 + + + + + 7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq + 177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x + DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY + + + + +``` + +加入部署配置信息之后,对工程执行编译打包操作,输出的合约代码(.car)将自动部署到指定的区块链网络。 + +```bash +mvn clean deploy +``` +##### 2.7.2. 发布已编译好的car +如果已经通过插件的打包方式,编译打包完成一个合约文件(.car),可通过命令行的方式进行发布,命令行要求与开发环境一致的Maven环境(包括环境变量及Setting都已配置完成)。 + +```bash +mvn com.jd.blockchain:contract-maven-plugin:${version}:deploy + -DcarPath= + -Dledger= + -DgatewayHost= + -DgatewayPort= + -DcontractPubKey= + -DcontractAddress= + -DsignerPubKey= + -DsignerPrivKey= + -DsignerPrivKeyPwd= +``` + +各参数说明如下: + +| 参数名 | 含义 |是否必填| +| ---- | ---- | ---- | +| ${version} | 合约插件的版本号 | 否,系统会自动选择发布的最新的RELEASE版本,SNAPSHOT版本必须填写 | +| carPath | 合约文件所在路径 | 是 | +| ledger | 账本Hash(Base58编码) | 否,会自动选择线上第一个账本| +| gatewayHost | 可访问的网关节点地址,域名或IP地址 | 是| +| gatewayPort | 网关节点监听端口 | 是 | +| contractPubKey | 合约账户的公钥(Base58编码)| 否,会自动创建 | +| contractAddress | 合约账户的地址(Base58编码)|否,会根据contractPubKey生成| +| signerPubKey | 合约签名公钥信息(Base58编码)|是| +| signerPrivKey | 合约签名私钥信息(Base58编码)|是| +| signerPrivKeyPwd | 合约签名私钥解密密钥(Base58编码)|是| + + +下面是一个示例,供参考: + +```bash +mvn com.jd.blockchain:contract-maven-plugin:1.2.0.RELEASE:deploy \ + -DcarPath=/root/jdchain/contracts/contract-test-1.0-SNAPSHOT.car \ + -Dledger=j5tW5HUvMjEtm2yB7E6MHoSByoH1DXvMwvF2HurEgMSaLW \ + -DgatewayHost=127.0.0.1 \ + -DgatewayPort=11000 \ + -DcontractPubKey= 7VeRBsHM2nsGwP8b2ufRxz36hhNtSqjKTquzoa4WVKWty5sD \ + -DcontractAddress= LdeNt7sEmTirh9PmE7axKvA2txTrbB9kxz6KB \ + -DsignerPubKey=7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq \ + -DsignerPrivKey=177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x \ + -DsignerPrivKeyPwd=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY +``` + +> 重点说明: +命令行中输入参数的优先级高于配置文件,就是说通过2.7.1方式发布合约时也可以采用命令行的参数(指-D相关配置),其优先级高于配置文件。 + +### 3. 合约插件详细配置 + +```xml + + com.jd.blockchain + contract-maven-plugin + 1.2.0.RELEASE + true + + + + + + false + + + + + 1 + + + MB + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + +
+
+
+``` + +### 4. 最简化合约插件配置示例 + +在pom.xml中有部分配置是非必填项,下面是一份最简化的合约发布(deploy)配置示例,供参考: + + +```xml + + com.jd.blockchain + contract-maven-plugin + 1.2.0.RELEASE + true + + + + + + 127.0.0.1 + 8081 + + + + + 7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq + 177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x + DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY + + + + +``` + +### 5. 合约SDK + +除上述使用 maven 命令方式部署合约外,JD Chain SDK 提供了 Java 和 Go 语言的合约部署/升级,合约调用等方法。 +以下以 Java SDK 为例讲述主要步骤,完整代码参照[JD Chain Samples](https://github.com/blockchain-jd-com/jdchain/tree/master/samples)合约部分。 + +#### 5.1 合约部署 + +```java +// 新建交易 +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); +// 生成合约账户 +BlockchainKeypair contractAccount = BlockchainKeyGenerator.getInstance().generate(); +System.out.println("合约地址:" + contractAccount.getAddress()); +// 部署合约 +txTemp.contracts().deploy(contractAccount.getIdentity(), FileUtils.readBytes("src/main/resources/contract-samples-1.4.2.RELEASE.car")); +``` + +#### 5.2 合约升级 + +```java +// 新建交易 +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); +// 解析合约身份信息 +BlockchainIdentity contractIdentity = new BlockchainIdentityData(KeyGenUtils.decodePubKey("7VeRCfSaoBW3uRuvTqVb26PYTNwvQ1iZ5HBY92YKpEVN7Qht")); +System.out.println("合约地址:" + contractIdentity.getAddress()); +// 指定合约地址,升级合约,如合约地址不存在会创建该合约账户 +txTemp.contracts().deploy(contractIdentity, FileUtils.readBytes("src/main/resources/contract-samples-1.4.2.RELEASE.car")); +``` + +#### 5.3 合约调用 + +5.3.1 动态代理方式 + +基于动态代理方式合约调用,需要依赖合约接口 + +```java +// 新建交易 +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); + +// 一次交易中可调用多个(多次调用)合约方法 +// 调用合约的 registerUser 方法 +SampleContract sampleContract = txTemp.contract("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye", SampleContract.class); +GenericValueHolder userAddress = ContractReturnValue.decode(sampleContract.registerUser(UUID.randomUUID().toString())); + +// 准备交易 +PreparedTransaction ptx = txTemp.prepare(); +// 交易签名 +ptx.sign(adminKey); +// 提交交易 +TransactionResponse response = ptx.commit(); +Assert.assertTrue(response.isSuccess()); + +// 获取返回值 +System.out.println(userAddress.get()); +``` + +5.3.2 非动态代理方式 + +不需要依赖合约接口及实现,传入参数构造合约调用操作 + +```java +// 新建交易 +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); + +ContractEventSendOperationBuilder builder = txTemp.contract(); + +// 一次交易中可调用多个(多次调用)合约方法 +// 调用合约的 registerUser 方法,传入合约地址,合约方法名,合约方法参数列表 +builder.send("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye", "registerUser", + new BytesDataList(new TypedValue[]{ + TypedValue.fromText(UUID.randomUUID().toString()) + }) +); +// 准备交易 +PreparedTransaction ptx = txTemp.prepare(); +// 交易签名 +ptx.sign(adminKey); +// 提交交易 +TransactionResponse response = ptx.commit(); +Assert.assertTrue(response.isSuccess()); + +Assert.assertEquals(1, response.getOperationResults().length); +// 解析合约方法调用返回值 +for (int i = 0; i < response.getOperationResults().length; i++) { + BytesValue content = response.getOperationResults()[i].getResult(); + switch (content.getType()) { + case TEXT: + System.out.println(content.getBytes().toUTF8String()); + break; + case INT64: + System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); + break; + case BOOLEAN: + System.out.println(BytesUtils.toBoolean(content.getBytes().toBytes()[0])); + break; + default: // byte[], Bytes + System.out.println(content.getBytes().toBase58()); + break; + } +} +``` \ No newline at end of file diff --git a/docs/data_account.md b/docs/data_account.md new file mode 100644 index 00000000..b27366cd --- /dev/null +++ b/docs/data_account.md @@ -0,0 +1,63 @@ +## 数据账户 + +`JD Chain`存放`KV`数据的数据结构。 + +### 1. 基本概念 + +可类比传统数据库的表的概念,上层应用需要保存的应用数据最终都应表现为`KV`类型数据写入到数据账户中。 + +写入`KV`数据之前,需要创建或使用已存在数据账户。 + +一个账本可以创建无限多个数据账户,一个数据账户中可以写入无限多个`KV`数据。 + +`KV`数据有`Version`(数据版本)的概念,以`KEY`作为唯一标识,`VALUE`的更新写入需要提供当前该`KEY`的最高版本,`KEY`不存在时为`-1`。 + +### 2. SDK + +以下只描述主要步骤,完整示例代码可参照[JD Chain Samples](samples.md)数据账户部分。 + +#### 2.1 注册数据账户 + +创建数据账户: +```java +BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); +System.out.println("数据账户地址:" + dataAccount.getAddress()); +// 注册数据账户 +txTemp.dataAccounts().register(dataAccount.getIdentity()); +``` + +从已存在数据账户公钥恢复: +```java +PubKey pubKey = KeyGenUtils.decodePubKey("7VeRLdGtSz1Y91gjLTqEdnkotzUfaAqdap3xw6fQ1yKHkvVq"); +BlockchainIdentity dataAccountIdentity = new BlockchainIdentityData(pubKey); +System.out.println("数据账户地址:" + dataAccountIdentity.getAddress()); +// 注册数据账户 +txTemp.dataAccounts().register(dataAccountIdentity); +``` + +#### 2.2 写入数据 + +```java +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); + +txTemp.dataAccount("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye") + .setText("key1", "value1", -1) + .setText("key1", "value1", 0) + .setInt64("key2", 1, -1) + .setJSON("key3", "{}", -1) + .setBytes("key4", Bytes.fromInt(2), -1); +``` + +支持写入数据类型: + +- `setText`,字符类型 +- `setInt64`,长整型 +- `setJSON`,`JSON`串 +- `setBytes`,字节数组 +- `setTimestamp`,时间戳,长整型 +- `setXML`,`XML`文本 +- `setImage`,图片字节数据 + +> 本质上仅支持`String/Long/[]byte`这三种数据类型,`JSON/XML/Image/Timestamp`等起标识作用,用于扩展差异化数据展示等场景需求 + +`setText("key1", "value1", -1)`中第三个参数即为数据版本,需要传入`JD Chain`网络中当前`key1`的最高数据版本,首次写入时传入`-1`。 \ No newline at end of file diff --git a/docs/event.md b/docs/event.md new file mode 100644 index 00000000..a753f7f5 --- /dev/null +++ b/docs/event.md @@ -0,0 +1,185 @@ +## 事件 + +`JD Chain`账本中设计了事件数据集,用以存储事件账户,事件数据。 + +`事件账户`与`用户`,`数据账户`,`合约账户`是相互独立的,所承载的数据也是相互隔离的。 + +`JD Chain`事件分为两类:[系统事件](#系统事件),[用户事件](#用户事件) + +`JD Chain SDK` 针对事件数据集开发了[事件发布](#事件发布),[事件监听](#事件监听)实现。 + +### 1. 系统事件 + +系统运行期间产生的事件,目前仅定义了`新区块产生`这一个: + +```java +/** + * 系统事件类型 + */ +public enum SystemEvent { + // 新区块 + NEW_BLOCK_CREATED("new_block_created"); +} +``` + +### 2. 用户事件 + +用户自定义事件类型,需要创建`事件账户`,用户自定义事件名 + +`事件账户`数量没有限制,一个事件账户内`Topic`(事件名)数量没有限制 + +同一个`事件账户`的同一个`Topic`所指向的`Content`(事件内容)有`Sequence`(事件序号)的概念,以`Topic`作为唯一标识,同一个`Topic`的更新发布需要提供当前该`Topic`的最高序号,`Topic`不存在时为`-1`。 + +### 3. 事件结构 + +```java +/** + * 事件; + * + */ +@DataContract(code = DataCodes.EVENT_MESSAGE) +public interface Event { + /** + * 事件名; + * + * @return + */ + @DataField(order = 1, primitiveType = PrimitiveType.TEXT) + String getName(); + + /** + * 事件序号; + * + * @return + */ + @DataField(order = 2, primitiveType = PrimitiveType.INT64) + long getSequence(); + + /** + * 事件内容; + * + * @return + */ + @DataField(order=3, refContract = true) + BytesValue getContent(); + + /** + * 产生事件的交易哈希;  + * + * @return + */ + @DataField(order = 4, primitiveType = PrimitiveType.BYTES) + HashDigest getTransactionSource(); + + /** + * 产生事件的合约地址; + * + * @return + */ + @DataField(order = 5, primitiveType = PrimitiveType.TEXT) + String getContractSource(); + + /** + * 产生事件的区块高度 + * + * @return + */ + @DataField(order = 6, primitiveType = PrimitiveType.INT64) + long getBlockHeight(); + + /** + * 事件账户地址,系统事件此字段为空 + * + * @return + */ + @DataField(order = 7, primitiveType = PrimitiveType.BYTES) + Bytes getEventAccount(); +} +``` + +### 4. SDK + +`JD Chain`事件监听是`SDK`端以`拉`的方式实现,消息可重复消费,需要使用者自行保存消费位置。 + +以下只描述主要步骤,完整示例代码可参照[JD Chain Samples](samples.md)事件相关部分。 + +#### 4.1 生成事件账户 + +> 用户事件才有事件账户 + +```java +// 新建交易 +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); +// 生成事件账户 +BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate(); +System.out.println("事件账户地址:" + eventAccount.getAddress()); +// 注册事件账户 +txTemp.eventAccounts().register(eventAccount.getIdentity()); +``` + +#### 4.2 事件发布 + +> 系统事件由系统运行期间自动产生,用户事件可通过SDK发布 + +```java +// 新建交易 +TransactionTemplate txTemp = blockchainService.newTransaction(ledger); + +txTemp.eventAccount(Bytes.fromBase58("LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye")) + .publish("topic1", "content1", -1) + .publish("topic1", "content2", 0) + .publish("topic1", "content3", 1) + .publish("topic2", "content", -1) + .publish("topic3", 1, -1) + .publish("topic4", Bytes.fromInt(1), -1); +``` + +支持发布数据类型: + +- `Text`,字符类型 +- `Int64`,长整型 +- `JSON`,`JSON`串 +- `Bytes`,字节数组 +- `Timestamp`,时间戳,长整型 +- `XML`,`XML`文本 +- `Image`,图片字节数据 + +> 本质上仅支持`String/Long/[]byte`这三种数据类型,`JSON/XML/Image/Timestamp`等起标识作用,用于扩展差异化数据展示等场景需求 + +`publish("topic1", "content1", -1)`中第三个参数即为事件序号,需要传入`JD Chain`网络中当前`topic1`的最高序号,首次写入时传入`-1`。 + +#### 4.3 事件监听 + +- 监听系统事件 +```java +// 目前仅有新区快产生事件 +blockchainService.monitorSystemEvent(ledger, + SystemEvent.NEW_BLOCK_CREATED, 0, (eventMessages, eventContext) -> { + for (Event eventMessage : eventMessages) { + // content中存放的是当前链上最新高度 + System.out.println("New block:" + eventMessage.getSequence() + ":" + BytesUtils.toLong(eventMessage.getContent().getBytes().toBytes())); + } + }); +``` + +- 监听用户事件: +```java +blockchainService.monitorUserEvent(ledger, "LdeNr7H1CUbqe3kWjwPwiqHcmd86zEQz2VRye", "sample-event", 0, (eventMessage, eventContext) -> { + + BytesValue content = eventMessage.getContent(); + switch (content.getType()) { + case TEXT: + case XML: + case JSON: + System.out.println(eventMessage.getName() + ":" + eventMessage.getSequence() + ":" + content.getBytes().toUTF8String()); + break; + case INT64: + case TIMESTAMP: + System.out.println(eventMessage.getName() + ":" + eventMessage.getSequence() + ":" + BytesUtils.toLong(content.getBytes().toBytes())); + break; + default: // byte[], Bytes + System.out.println(eventMessage.getName() + ":" + eventMessage.getSequence() + ":" + new String(content.getBytes().toBytes())); + break; + } +}); +``` \ No newline at end of file diff --git a/docs/gateway.md b/docs/gateway.md new file mode 100644 index 00000000..10574bc4 --- /dev/null +++ b/docs/gateway.md @@ -0,0 +1,53 @@ +## 网关服务 + +`JD Chain`的网关服务是应用的接入层。 +终端接入是`JD Chain`网关的基本功能,在确认终端身份的同时提供连接节点、转发消息和隔离共识节点与客户端等服务。网关确认客户端的合法身份,接收并验证交易;网关根据初始配置文件与对应的共识节点建立连接,并转发交易数据。 + +### 1. 配置 + +网关配置在文件`gateway.conf`中: + +```properties +#网关的HTTP服务地址; +http.host=0.0.0.0 +#网关的HTTP服务端口; +http.port=8080 +#网关的HTTP服务上下文路径,可选; +#http.context-path= + +#共识节点的服务地址(与该网关节点连接的Peer节点的IP地址); +peer.host=127.0.0.1 +#共识节点的服务端口(与该网关节点连接的Peer节点的端口,即在Peer节点的peer-startup.sh中定义的端口); +peer.port=7080 +#共识节点的服务是否启用安全证书; +peer.secure=false + +#是否存储共识拓扑信息,网关重启后若存储存在有效的拓扑信息可快速建立与拓扑中所有节点的连接 +topology.store=false + +#共识节点的服务提供解析器 +#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider +#简单消息共识Provider:com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider +peer.providers=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider + +#数据检索服务对应URL,格式:http://{ip}:{port},例如:http://127.0.0.1:10001 +#若该值不配置或配置不正确,则浏览器模糊查询部分无法正常显示 +data.retrieval.url= +schema.retrieval.url= + +#默认公钥的内容(Base58编码数据); +keys.default.pubkey= +#默认私钥的路径;在 pk-path 和 pk 之间必须设置其一; +keys.default.privkey-path= +#默认私钥的内容(加密的Base58编码数据);在 pk-path 和 pk 之间必须设置其一; +keys.default.privkey= +#默认私钥的解码密码; +keys.default.privkey-password= + +``` + +其中: + +- `data.retrieval.url`与`schema.retrieval.url`分别与[Argus(高级检索)](https://github.com/blockchain-jd-com/jdchain-indexer)中的[区块链基础数据检索服务](https://github.com/blockchain-jd-com/jdchain-indexer#%E5%90%AF%E5%8A%A8%E5%8C%BA%E5%9D%97%E9%93%BE%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%B4%A2%E5%BC%95%E6%A3%80%E7%B4%A2%E6%9C%8D%E5%8A%A1)和[`Schema`服务](https://github.com/blockchain-jd-com/jdchain-indexer#%E5%90%AF%E5%8A%A8value%E7%B4%A2%E5%BC%95%E6%9C%8D%E5%8A%A1)相对应,只有启动并正确配置了`Argus`,`JD Chain`浏览器才能正常使用搜索功能。 + +- `keys.default`几个参数代表接入`JD Chain`网络的身份信息,只有处于非停用(`DEACTIVATED`)状态的参与方身份才可作为此处的配置。 \ No newline at end of file diff --git a/docs/images/deployment.jpg b/docs/images/deployment.jpg deleted file mode 100644 index aec66f03d653931de983a14f49dc902983121449..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131011 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 z 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 z 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 JkM`%ce*p^~en$WR diff --git a/docs/images/deployment.png b/docs/images/deployment.png deleted file mode 100644 index a0b2e722c2060d15a6bfd3fe01ca94f306487112..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298018 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 diff --git a/docs/indexer.md b/docs/indexer.md new file mode 100644 index 00000000..da642c8f --- /dev/null +++ b/docs/indexer.md @@ -0,0 +1,15 @@ +# 高级检索 + +## Argus + +穿透式检索Argus提供JD Chain区块链基础数据索引,自定义键值索引服务 + +源码已开源,请参照[Argus](https://github.com/blockchain-jd-com/jdchain-indexer)首页说明安装使用。 + +## JD Chain + Argus + +修改JD Chain网关配置文件`gateway.conf`中: +- `data.retrieval.url` 对应`Argus`中区块链基础数据检索服务 +- `schema.retrieval.url` 对应`Argus`中`Schema`服务 + +重启网关后可在区块连浏览器中使用搜索功能 \ No newline at end of file diff --git a/docs/jdchain_cli.md b/docs/jdchain_cli.md new file mode 100644 index 00000000..dcab9053 --- /dev/null +++ b/docs/jdchain_cli.md @@ -0,0 +1,30 @@ +## JD Chain Cli + +JD Chain 命令行工具集,提供密钥管理,实时交易,链上信息查询,离线交易,共识节点变更等操作。 + +```bash +:bin$ ./jdchain-cli.sh -h +Usage: jdchain-cli [-hV] [--pretty] [--home=] [COMMAND] +JDChain Cli is a convenient tool to manage jdchain keys, sign and send +transactions to jdchain network, query data from jdchain network. + -h, --help Show this help message and exit. + --home= Set the home directory. + --pretty Pretty json print + -V, --version Print version information and exit. + +Commands: + +The most commonly used git commands are: + keys List, create, update or delete keypairs. + tx Build, sign or send transaction. + query Query commands. + participant Add, update or delete participant. + help Displays help information about the specified command + +See 'jdchain-cli help ' to read about a specific subcommand or concept. +``` + +- `keys` [密钥管理](cli/keys.md) +- `tx` [交易](cli/tx.md) +- `query` [链上信息查询](cli/query.md) +- `participant` [共识节点变更](cli/participant.md) \ No newline at end of file diff --git a/docs/kvdb.md b/docs/kvdb.md new file mode 100644 index 00000000..4774f20a --- /dev/null +++ b/docs/kvdb.md @@ -0,0 +1,365 @@ +## RocksDB as a server + +### 1.简介 + +`KVDB`是一个简单的`NoSQL`数据库,支持简单的“键值”读写操作。 + +`KVDB`包装了`RocksDB`作为数据库引擎,实现了单机部署和集群部署。 + +`KVDB`的集群是一个分布式的分片服务集群,每个分片节点是一个`KVDB`的数据库服务实例,采用对等模式部署,没有主节点。 + +### 2.安装 + +> java 版本>= 1.8 + +下载源代码,执行: +```bash +mvn clean package +``` +`kvdb-server`模块`target`下会生成`kvdb-***.zip`,解压缩安装包,结构如下: +```bash +bin # 脚本文件目录 + start # 启动本机的数据库服务的脚本文件 + stop # 停止本机的数据库服务的脚本文件 + kvdb-cli # 连接本机的数据库服务控制台的脚本文件 + kvdb-benchmark # 基准测试 +conf # 配置文件目录 + kvdb.conf # 本机的数据库服务配置 + cluster.conf # 数据库集群的配置 +libs # 数据库服务的代码库目录 +system # 系统数据目录 + dblist # 文件记录了本数据库服务实例装载的数据库列表 + pid # 文件记录了本数据库服务实例的运行进程ID;当服务实例运行时创建,服务实例退出后删除 +``` + +### 3.部署配置 + +#### 3.1 `kvdb.conf` + +```bash +# 数据库服务的本机监听地址; +server.host=0.0.0.0 + +# 数据库服务的本机监听端口; +server.port=7078 + +# 管理控制台的端口; +# 注:管理控制台总是绑定到环回地址 127.0.0.1,只允许本机访问; +manager.port=7060 + +# 数据库实例默认的根目录 +dbs.rootdir=/usr/kvdb/dbs + +# 数据库实例默认的本地分区数 +dbs.partitions=4 + +# 是否禁用WAL +wal.disable=false + +# WAL刷新机制,-1跟随系统,0实时刷新,n(n>0)秒刷新一次 +wal.flush=1 +``` + +> `WAL`写入成功,但`RocksDB`写入失败,服务器将在后续所有数据库读写操作前根据`WAL`进行重试操作,直至成功。 + +#### 3.2 `cluster.conf` +```bash +# 数据库集群的分片数,每一个分片都赋予唯一的编号,分片编号最小为 0,所有分片的编号必须连续递增 +# ‘’表示集群名称,只允许用字母、数字、下划线组成; +cluster..partitions=3 + +# 数据库集群 ‘’ 的第 1 个分片的数据库实例地址(URL格式); +cluster..0=kvdb://:/ + +# 数据库集群 ‘’ 的第 2 个分片的数据库实例地址(URL格式); +cluster..1=kvdb://:/ + +# 数据库集群 ‘’ 的第 3 个分片的数据库实例地址(URL格式); +cluster..2=kvdb://:/ + +# 指定多个不同的集群 +#cluster..partitions=3 +... +``` +> 一个数据库实例只能加入唯一的集群;一旦加入集群,则不能再被客户端以单库连接方式访问,对该库实例的连接自动转为集群连接。集群中配置的数据库必须在`dblist`中已存在且设置为`true` +> 所有`host`使用明确的可通畅连接的地址,不同服务器节点中同一集群配置必须完全一致 + +#### 3.3 `dblist` +```bash +# 是否激活数据库 ‘’ ;如果为`true`,则创建或加载该数据库并提供访问; +# ‘’表示数据库名称,只允许用字母、数字、下划线组成; +# db..enable=true + +# 数据库 的根目录;如果未配置,则从默认目录加载(由`conf/kvdb.conf`指定了默认配置${dbs.rootdir}/); +# db.test.rootdir= + +# 数据库 的本地分区数;如果未配置,则采用`conf/kvdb.conf`中指定的默认配置${dbs.partitions} +# db.test.partitions= +``` +> `dblist`中配置的数据库会在`kvdb-server`启动时自动创建。在`kvdb-server`启动完成后由管理工具执行`create database `创建数据库,创建成功的数据库会追加到`dblist`中。使用`kvdb-cli`命令行工具执行数据库实例更新操作。 + +#### 3.4 日志 + +1. `kvdb-server` + +修改`bin`目录下,`start.sh`文件: +```bash +LOG_SET="-Dlogging.path="$HOME/logs" -Dlogging.level=ERROR" +``` +默认日志路径:程序解压缩后主目录下`logs`目录 +默认日志等级:`ERROR` + +可配置日志等级:`ALL`,`TRACE`,`DEBUG`,`INFO`,`WARN`,`ERROR`,`FATAL`,`OFF` + +2. `kvdb-cli` + +修改`bin`目录下,`kvdb-cli.sh`文件: +```bash +LOG_SET="-Dlogging.path="$HOME/logs" -Dlogging.level.root=error" +``` +默认日志路径:程序解压缩后主目录下`logs`目录 +默认日志等级:`error` + +#### 3.5 启动 + +```bash +./start.sh +``` +#### 停止 +```bash +./stop.sh +``` + +### 4.SDK + +1. 依赖 +```maven + + com.jd.blockchain + kvdb-client + ${project.version} + +``` + +2. 创建客户端连接 +```java +// `host`、`port`为服务器地址和端口,`database`为数据库名称 +KVDBClient client = new KVDBClient("kvdb://:/"); +# KVDBClient client = new KVDBClient(new KVDBURI("kvdb://:/")); +# KVDBClient client = new KVDBClient(new ClientConfig(host, port, db)); +``` + +> 对于集群的连接,客户端将开启`WAL`,在`WAL`写入成功,部分服务器失败的情况下,客户端在执行后续所有操作前都将根据`WAL`日志执行重试操作,直至成功。 + +3. 操作 + +```java +/** + * 存在性查询 + * + * @param key + * @return + * @throws KVDBException + */ +boolean exists(Bytes key) throws KVDBException; + +/** + * 存在性查询,支持多个键值 + * + * @param keys + * @return + * @throws KVDBException + */ +boolean[] exists(Bytes... keys) throws KVDBException; + +/** + * 键值获取 + * + * @param key + * @return + * @throws KVDBException + */ +Bytes get(Bytes key) throws KVDBException; + +/** + * 键值获取,支持多个键值 + * + * @param keys + * @return + * @throws KVDBException + */ +Bytes[] get(Bytes... keys) throws KVDBException; + +/** + * 设置键值对 + * + * @param key + * @param value + * @return + * @throws KVDBException + */ +boolean put(Bytes key, Bytes value) throws KVDBException; + +/** + * 设置键值对 + * + * @param key + * @param value + * @param aSync + * @return + * @throws KVDBException + */ +boolean put(Bytes key, Bytes value, boolean aSync) throws KVDBException; + +/** + * 开启批处理 + * + * @return + * @throws KVDBException + */ +boolean batchBegin() throws KVDBException; + +/** + * 取消批处理 + * + * @return + * @throws KVDBException + */ +boolean batchAbort() throws KVDBException; + +/** + * 提交批处理,服务器掉线重连后会丢失未提交批处理数据 + *

+ * 未提交的`batch`对其他客户端连接不可见。 + * + * @return + * @throws KVDBException + */ +boolean batchCommit() throws KVDBException; + +/** + * 提交批处理 + * + * @param size 此次批处理操作去重后的key数量 + * @return + * @throws KVDBException + */ +boolean batchCommit(long size) throws KVDBException; + +/** + * 关闭 + */ +void close(); +``` + +### 5.管理工具 + +`kvdb-cli`是基于[`SDK`](#SDK)的命令行工具实现: + +```bash +./kvdb-cli.sh -h -p -db -t