feat: init; from commit c3adcb2e6bc94b46f4f34c03bc62abcce6c7e1a0 of BDContract

This commit is contained in:
Frank.R.Wu
2021-06-15 19:56:39 +08:00
commit c8758ecfdc
1120 changed files with 241041 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,439 @@
# 管理界面
- - -
## 合约节点管理界面
该界面的使用地址为:[NodePortal.html](/NodePortal.html)
### 用户管理菜单
用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。
#### 概览
![nodeUserManager](./_static/imgs/nodeUserManager.jpg)
节点用户管理页面一共有四个模块:用户情况、用户活跃统计、授权用户管理、未授权用户管理。
#### 用户类型分布
主要统计当前节点管理员所拥有的四种角色的数量:合约提供者、合约管理员、合约使用者
![userList](./_static/imgs/userList.jpg)
#### 用户活跃统计
![userActive](./_static/imgs/userActive.jpg)
统计30天之内**登录**、**授权**、**申请**的次数
#### 当前用户信息
![nodeInfo](./_static/imgs/nodeInfo.jpg)
* 在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录节点管理员界面,可以将自己的公私钥复制到这个文本框中。
* 将自己的公私钥复制完成之后要点击**导入公钥**,将公钥加入到节点管理员本地
* 然后在**本地公钥**中可以看见公钥的前五位,选择自己的公钥,将在**我的权限**中展示出当前选择的公钥的角色,如果是还没有在中心管理员认证的节点则默认为**Anonymous**
* 如果不是节点管理员,想要加入某个中心管理员的网络,那么要在中心管理员所在的用户管理中用自己的公私钥导入后进行认证。
* 如果想要行使更多关于合约的操作,则需要认证不同的角色:合约管理员、合约使用者、合约提供者,然后进行**角色认证**
#### 授权与非授权用户列表
![roleAuth](./_static/imgs/roleAuth.jpg)
在节点管理员认证角色之后,节点管理员登录会在**未授权角色管理**表格中看见带有公钥的申请信息,如果同意,则点击**授权**,如果不同意点击**忽略**就可以。
授权之后将在**授权角色管理**表格中看见授权后的节点列表。如果节点管理员想要移除某个节点的角色,则在授权角色管理列表中**删除**即可。
### 合约代码管理菜单
![codeManageMenu](./_static/imgs/codeManageMenu.png)
#### 合约文件
![codeManage1](./_static/imgs/codeManage1.png)
在合约代码管理菜单中,用户可以看到公共合约以及个人私有合约。
![codeManage1-1](./_static/imgs/codeManage1-1.png)
对于公共合约,节点管理员可以对其中文件进行删除和上传操作,可以对合约项目进行下载和删除操作。
![codeManage1-2](./_static/imgs/codeManage1-2.png)
对于私有合约,合约提供者可以对其中文件进行删除和上传操作,可以对合约项目进行下载、删除和传至公共合约目录操作。
以下是对合约文件进行操作的示例。
#### 上传文件
![codeManage6](./_static/imgs/codeManage6.png)
#### 删除
![codeManage5](./_static/imgs/codeManage5.png)
#### 传至公共
![codeManage7](./_static/imgs/codeManage7.png)
#### 下拉框
![codeManage2](./_static/imgs/codeManage2.png)
四个下拉框中,可以分别对合约状态保存模式、已启动合约实例、节点所在集群以及结果校验方式进行选择。
#### 按钮操作
![codeManage3](./_static/imgs/codeManage3.png)
#### 启动
在文件列表中选择合约文件之后,在合约运行模式中选择“单节点执行”,点击启动按钮,会启动指定文件,并在结果显示框中显示返回结果。
#### 启动P2P集群合约
在文件列表中选择合约文件之后,在合约运行模式中选择该可信合约运行的合约集群,点击启动按钮,会在该集群的所有节点上启动指定文件,并在结果显示框中显示返回结果。
#### 启动全部
在合约运行模式中选择“单节点执行”,点击启动全部按钮,会启动合约文件列表中所有合约。
#### 停止P2P集群合约
在已启动合约实例的下拉框中选择一个合约实例,在合约运行模式中选择该可信合约运行的合约集群,点击停止按钮,会在该集群的所有节点上终止这个合约进程。
#### 停止
在已启动合约实例的下拉框中选择一个合约实例,点击停止按钮,会终止这个合约进程。
#### 停止全部
点击停止全部按钮,会停止该节点上运行的所有合约实例。
#### 静态分析
在合约文件列表中选择合约文件,并在合约实例下拉框中选择合约实例,点击静态分析按钮,会对该合约进行静态分析,并在结果显示框中显示返回结果。
#### 分发合约
在合约文件列表中选择合约项目并在合约运行模式中选择一个集群点击分发合约按钮会将该合约项目打包为ypk分发给这个集群中的所有节点。
#### 返回结果
![codeManage4](./_static/imgs/codeManage4.png)
返回结果显示中显示一些操作的返回结果。
#### 合约权限配置
在启动合约之后如果当前用户的角色可以查看已经启动合约进程那么在选定查看合约进程时将会在右下方展示当前合约的IO权限。
![permissionShow](./_static/imgs/permissionShow.png)
如果选中的合约没有IO权限则在当前权限的展示框中提示**当前合约没有IO权限**
![nullPermission](./_static/imgs/nullPermission.png)
当前用户是合约管理员时可以对已有的合约IO权限进行修改。系统会提示修改后合约将有可能不会正常运行如果还是确定要取消那么点击**确定** 即可,反之点击**关闭**
![updatePermission](./_static/imgs/updatePermission.png)
点击关闭或者打开之后下一次查看同一个合约代码的进程将会默认显示最近一次修改之后的IO权限。
![closePermission](./_static/imgs/closePermission.png)
### 合约实例管理菜单
![nodeInstancesPage](./_static/imgs/nodeInstancesPage.png)
合约实例管理菜单显示了该节点当前的所有合约实例, 用户可查看合约实例的状态, 并对合约实例进行执行或状态迁移的操作.
#### 合约实例列表
![nodeInstancesList](./_static/imgs/nodeInstancesList.png)
该列表显示了当前节点的所有合约实例信息, 包括合约ID, 合约名称, 合约类型合约状态, 合约进程端口, 合约调用次数, 合约流量, 及合约占用内存, 集群合约的结果校验模式.
#### 合约实例执行
![chooseInstance](./_static/imgs/chooseInstance.png)
用户可在合约实例的选择下拉框中选择合约实例, 对该合约实例进行操作.
![intanceExecute](./_static/imgs/intanceExecute.png)
选择合约实例后, 用户可在"方法"的下拉框中选择该合约的方法名, 在"参数"输入框中输入方法的参数, 点击"执行".
用户还可点击"动态分析执行"进行带有动态分析结果的执行.
若该合约为单点合约, 则合约在单点执行; 若该合约为集群合约, 则该合约在该集群的所有节点上执行.
#### 合约实例执行结果
![executeResult](./_static/imgs/executeResult.png)
合约实例的执行完成后的结果显示在"执行结果"区域中, 包括该次执行的ID, 执行成功/失败, 执行时间, 及执行结果.
![analysisExecuteResult](./_static/imgs/analysisExecuteResult.png)
若该合约的执行方式为"动态分析执行", 则结果框内除执行结果, 还会显示该次执行的动态分析结果.
#### 合约状态迁移
![memoryDump](./_static/imgs/memoryDump.png)
对于支持用户手动迁移的合约实例, 用户可点击"本地状态保存"对合约实例的状态进行保存, 或从合约的TimeTravel列表中选择已保存的合约实例, 将合约状态迁移到对应时刻.
### 日志管理菜单
![logMenu](./_static/imgs/logMenu.png)
该菜单是对该节点本地节点日志以及合约日志的统计结果展示。
其中,节点管理员可以查看节点日志的相关数据;合约管理者及合约使用者可以查看该节点本地合约日志的相关数据。
#### 日志统计图
![log1](./_static/imgs/log1.png)
#### 各类平台操作百分比
该图默认显示近2日各类平台操作占比的饼图其中平台操作分为登陆类、用户类、日志类、合约类、维护类以及其他类这六类。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围修改之后各类平台操作百分比会同步更新。
#### 各类合约操作百分比
合约操作分为启动、终止、静态分析和执行这四类该图为近2日对各类合约操作占比的饼图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围修改之后各类合约操作百分比会同步更新。
#### 每日平台使用统计
该图为近2日平台操作次数统计的折线图。可在节点日志详情的右上角的时间范围框中填写想要查看的日志时间范围修改之后每日平台使用统计折线图会同步更新。
#### 每日合约使用统计
该图为近2日对该节点上合约的操作次数统计的折线图。可在合约日志详情的右上角的时间范围框中填写想要查看的日志时间范围修改之后每日合约使用统计折线图会同步更新。
#### 日志详情
#### 节点日志详情
![log2](./_static/imgs/log2.png)
节点日志详情表是对节点日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类平台操作百分比和每日平台使用统计会同步更新。
#### 合约日志详情
![log3](./_static/imgs/log3.png)
合约日志详情表是对合约日志中所有数据的展示。可以点击表格中相关按钮按使得日志数据按不同方式进行排序,并且可以在表格右上角输入关键词进行相关日志搜索。可在右上角的时间范围框中填写想要查看的日志时间范围,修改之后,各类合约操作百分比和每日合约使用统计会同步更新。
### 节点管理菜单
![nodeConfig](./_static/imgs/nodeConfig.png)
节点管理菜单显示了该节点的配置信息及所属可信执行集群信息.
#### 节点配置
![nodeConfigChange](./_static/imgs/nodeConfigChange.png)
节点管理员可查看该节点的配置信息, 包括节点名称, 节点YJS路径, 节点的网络中心节点, 节点管理员还可对以上配置进行修改.
若节点管理员修改了节点的网络中心, 该节点后重新想改节点连接, 整个页面刷新重载.
#### 节点可信执行集群列表
![nodeUnits](./_static/imgs/nodeUnits.png)
节点管理员可查看节点所属的可信执行集群信息, 包括集群创建者, 集群ID, 集群中节点数目, 集群中节点的信息.
- - -
#### 节点Licence配置
![nodeLicence](./_static/imgs/nodeLicence.png)
用户可以查看该节点的Licence及过期时间, 还可申请Licence, 上传Licence, 保存节点UUID.
## 智能合约在线编辑器
### 用户与账号
#### 创建账号
#### 申请授权
### 创建项目
#### 新建文件
#### 上传文件
### 启动合约
![contractMode](./_static/imgs/contractMode.png)
####正常模式
点击左侧启动按钮,以正常模式启动合约。
####debug模式
点击右侧debug按钮以debug模式启动合约。目前约定debug模式合约通过executeContract调用正常模式合约时返回正常模式合约文档中的返回结果示例。
### 调用合约
###生成文档
![genReadme](./_static/imgs/genReadme.png)
启动合约后点击"生成文档"按钮可以通过各export函数的@Description / @Param / @Result 对合约进行调用及结果返回,从而生成合约的说明文档。
- - -
## 路由准入管理界面
### 权限申请与授权
### 仪表盘
仪表盘为提供对准入节点中用户数量,合约数量,节点数量的概览。
### 整体视图
![dashboard](./_static/imgs/dashboard.jpg)
一共分为四个模块,一个模块是用户、合约、节点数量的概览,然后分别是这三个数量的详细分类的数据统计情况。
### 节点数目
![node](./_static/imgs/node.jpg)
当前在线和离线节点统计
### 用户类型分布
![userAll](./_static/imgs/userAll.jpg)
当前准入节点所在组网中的节点管理员、准入管理员的数量和申请中节点的数量
### 合约调用情况
![contract](./_static/imgs/contract.jpg)
当前准入节点所在组网中所有合约中事件、多点执行、ws调用、Http调用的折线统计图。
### 用户管理
用户管理为登录用户提供查看当前用户分布情况和用户活跃情况统计等。
### 概览
![centerManager](./_static/imgs/centerManager.jpg)
用户管理页面一共有四个模块。
### 用户类型分布
主要统计当前中心管理员所管理的网络中有多少节点管理员,多少个中心管理以及申请节点管理员的数量
![userList](./_static/imgs/userList.jpg)
### 30天内的申请情况统计
![userApplyGraph](./_static/imgs/userApplyGraph.jpg)
统计30天之内申请节点管理员的数量和授权成为节点管理员的数量
### 当前用户信息
![authNodeManager](./_static/imgs/authNodeManager.jpg)
* 在这个文本框中可以查看当前用户的公私钥,如果其他用户想要用自己的公私钥登录中心管理员界面,可以将自己的公私钥复制到这个文本框中。
* 将自己的公私钥复制完成之后要点击**导入公钥**,将公钥加入到中心管理员本地
* 然后在**本地公钥**中可以看见公钥的前五位,选择自己的公钥,将在**我的权限**中展示出当前选择的公钥的角色,如果是中心管理员则拥有中心管理员的一切权限。
* 如果不是中心管理员或者节点管理员,想要加入当前中心管理员的网络,那么可以在下面的选择框中选中节点管理员,进行**角色认证**。
### 授权与非授权用户列表
在中心管理员当前用户信息申请之后,中心管理员登录会在**未授权用户管理**表格中看见带有公钥的申请信息,如果同意,则点击**授权**,如果不同意点击**忽略**就可以,此时这个申请就无效。
![authMan](./_static/imgs/authMan.jpg)
授权之后将在**授权用户管理**表格中看见授权后的节点列表。如果中心管理员想要移除某个节点管理员的某项角色,则在授权用户管理列表中选择相应的角色,然后点击**删除**即可删除选中的角色。
![authMana](./_static/imgs/authMana.jpg)
### 节点管理
![centerNodePage](./_static/imgs/centerNodePage.png)
节点管理为Manager对连接到自己的Cluster节点进行管理的页面, 仅Manager管理员及合约管理者可见. Manager管理员及合约管理者可在本页面查看节点信息, 并管理可信执行集群.
### 概览
![centerNodePreview](./_static/imgs/centerNodePreview.png)
概览中显示了该Manager节点所管理的所有节点的统计信息, 包括总节点数量, 总合约数量, 总订阅事件数量, 及可信执行集群数量, 右侧的饼图则为节点的分别处于Online/Offline的数量统计.
### 节点列表
![centerNodeList](./_static/imgs/centerNodeList.png)
节点列表显示了用户有权限查看的节点信息(Manager管理员可查看全部节点, 合约管理者可查看自己负责管理的Online节点). 包括节点的名称, 状态, 合约数目, 订阅事件数目, 用于节点间P2P通信的PeerID, 用于节点间UDP通信的UDPID, 及节点公钥.
### 可信执行集群列表
![centerNodeUnits](./_static/imgs/centerNodeUnits.png)
可信执行集群列表显示了用户有权限查看的可信执行集群信息(Manager管理员可查看全部集群, 合约管理者可查看自己创建的集群). 包括集群的创建者, 集群ID, 集群中节点数目, 以及集群中节点的信息.
用户可点击列表表项的"删除"按钮, 将该集群删除.
### 创建可信执行集群
![centerNodeUnitCreate](./_static/imgs/centerNodeUnitCreate.png)
用户可以通过多选节点, 创建新的可信执行集群. 用户可以选择的节点为自己有权限查看的节点, 即Manager管理员从全部节点中选择, 合约管理者可从自己负责管理的Online节点中选择). 选择后点击提交, 即可看到创建成功的提示信息, 该集群将随即显示在可信执行集群列表中. 集群名称由创建者选取, 不能含有双引号, 该名称为合约管理者选择集群时的可见标识.
### 日志管理
日志管理主要展示准入节点的各项日志信息,一共分为六个模块。
### 概览
![log](./_static/imgs/log.jpg)
### 管理操作分类统计2日
![operator](./_static/imgs/operator.jpg)
两日内所有管理类操作的统计饼图,管理类操作主要分为登录类、日志类、维护类、用户类。
### 管理操作每日统计2日
![everyLog](./_static/imgs/everyLog.jpg)
两日内管理类所有的操作每日操作统计
### 合约操作分类统计2日
![contractLog](./_static/imgs/contractLog.jpg)
两日内合约操作分类统计饼图,合约操作主要分为连接类和状态更新类。
### 合约操作每日统计2日
![contracteveryLog](./_static/imgs/contracteveryLog.jpg)
两日内合约操作数量折线统计图。
### 管理操作日志列表
![opList](./_static/imgs/opList.jpg)
管理操作日志的详细信息列表。包括日志时间,管理操作名称,操作对应的节点公钥。默认展示范围是两天,可以自定义获取日志的天数。
### 合约操作日志列表
![contractList](./_static/imgs/contractList.jpg)
合约操作日志详细信息列表。包括日志产生时间,合约操作名称,合约操作节点公钥。默认展示范围是两天,可以自定义获取日志的天数。
### 设置
设置页面是节点证书的状态展示以及配置节点证书
### 概览
![set](./_static/imgs/set.jpg)
### 证书状态
![licence](./_static/imgs/licence.jpg)
证书状态主要包括许可到期时间和许可节点数量。
### 配置证书
![plicence](./_static/imgs/plicence.jpg)
配置证书模块可以下载节点ID文件或者输入证书信息进行提交。

View File

@@ -0,0 +1,190 @@
# 安装说明
- - -
## 依赖环境的安装
1.安装Java1.8环境。
例如在Ubuntu下使用apt-get进行安装
```bash
apt-get install openjdk-8-jre
```
在Centos环境下使用yum进行安装
```bash
yum install java-1.8.0-openjdk
```
如果是离线环境可先下载openjdk的安装包后进行离线安装。
Ubuntu下
```bash
dpkg -i jdk-8uxxxxx.deb
```
在Centos环境下使用yum进行离线安装
```bash
yum localinstall jdk-8u271-linux-xxx.rpm
```
2.安装wget与unzip。
例如在Ubuntu下使用apt-get进行安装
```bash
apt-get install unzip
apt-get install wget
```
- - -
## 网络拓扑说明
部署数瑞智能合约引擎最小仅需一个节点,此时可用作调试、测试,不能通过多节点模式来实现可信的计算。
单节点部署时,可通过配置账本实现"防抵赖"的计算,但不能实现"难篡改"的计算。
多节点部署时可参考下图,包含三种逻辑节点,同一虚拟机可安装一至三种节点。
1账本节点。即数瑞图式账本。
2合约节点。运行代码逻辑并通过内存缓存实现高响应的模块。与其他合约节点组成可信计算网络。
3路由节点。各个合约节点的路由信息。一般单个路由节点可支持最高1000合约节点。可视情况部署多个路由节点并在路由节点之间配置实现更大规模的节点组网。
一般地,同一虚拟机下,会部署**合约节点与账本节点**。
![deploytopology](_static/imgs/deploytopology.png)
- - -
## 智能合约节点安装
打开[安装包下载链接](https://public.internetapi.cn/?dir=releases/bdcontract/newest)
其中,下载`bdserver-lite.zip`或`bdserver.zip`,其中,`bdserver.zip`包含更多示例和文档。
下载之后解压并启动。
```bash
unzip -d ./bdserver bdserver-lite.zip
cd bdserver
chmod +x *.sh
sh cmstart.sh
```
- - -
## 路由准入节点安装
打开[安装包下载链接](https://public.internetapi.cn/?dir=releases/bdcontract/newest)
其中,下载`bdserver-cluster.zip`。
下载之后解压并启动。
```bash
unzip -d ./bdcluster bdserver-cluster.zip
cd bdcluster
chmod +x *.sh
sh ncstart.sh
```
- - -
## 文件说明
### 智能合约节点
![bdserver目录](_static/imgs/dirstructure.png)
该目录下的文件说明:
1.cmstart.sh 该脚本用于启动合约引擎。合约引擎默认监听8080端口可通过修改cmstart.sh来修改合约引擎的监听端口。
2.BDWareProjectDir 该目录存放了本节点的所有合约项目。
3.WebContent 该目录存放了本节点的前端代码。
4.cp, 该目录存放了yjs.jar为启动合约实例所需的jar。
5.bdserver.jar 对外提供http/websocket的服务器逻辑。
6.updateContract.sh 用于升级的脚本。
### 路由准入节点
安装脚本会自动下载安装并解压为bdcluster目录。
该目录下的文件说明:
1.ncstart.sh 该脚本用于启动节点准入中心。默认监听1718端口。可通过修改ncstart.sh来修改监听的端口。
2.WebContent 该目录存放了准入中心的前端代码。
3.bdcluster.jar 准入中心的后端。
- - -
## 升级流程
### 合约节点
在命令行中输入:
```bash
sh updateContract.sh
```
亦可通过[public.internetapi.cn](https://public.internetapi.cn/?dir=releases/bdcontract)下载最新文件单独升级yjs.zip/bdserver-jar.zip/AgentWebContent来升级。
### 路由准入节点
```bash
sh updateCluster.sh
```
亦可通过[public.internetapi.cn](https://public.internetapi.cn/?dir=releases/bdcontract)下载最新文件单独升级bdserver-cluster.zip/ClusterWebContent.zip来升级。
- - -
## 使用说明
### 通过参考界面使用
当保留了WebContent目录的情况下可使用浏览器进行配置。
更多请使用见左侧文档[BDContract参考界面使用说明](./IDEUsage.html)。
#### BDWare OnlineIDE
打开[BDWare OnlineIDE](../OnlineIDE.html)。
#### BDWare NodePortal
打开[BDWare NodePortal](../NodePortal.html)。
如需组网,使用跨节点功能,则需安装路由准入中心。并按以下步骤进行配置。涉及两组公私钥。
第一组公私钥为合约节点的、有NodeManager权限的公私钥。
第二组公私钥为路由准入节点的、有CenterManager权限的公私钥。
1.打开NodePortal.html复制该节点的NodeManager公私钥。
2.打开CenterPortal.html点击右上角将上述的NodeManager公私钥导入并选择"NodeManager"进行身份认证。
3.在CenterPortal.html中切换CenterManager的公私钥点左侧的"用户管理"通过NodeManager的认证请求。
4.使用NodeManager权限的公私钥打开NodePortal.html点击“节点管理”菜单并配置加入网络。
其中,加入网络的格式为:ws://centerportal的ip:端口+1。
![配置示例](_static/imgs/config.png)
### 通过SDK使用
#### 基础知识
[Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
[Sm2加密的使用](https://github.com/JuneAndGreen/sm-crypto)
#### SDK下载
1. Java版本的客户端下载[BDWareJavaClient](_static/BDWareJavaClient.zip)。具体使用说明请下载后解压查看README.md并参考[ContractAPI](./ContractAPI.html)。
2.Javascript版本的客户端下载:[BDWareWebClient](_static/BDWareWebClient.zip)。具体使用说明请下载后解压查看README.md并参考[ContractAPI](./ContractAPI.html)。
3.配置工具[BDWareConfigTool](_static/BDWareConfigTool.zip)。具体说明请下载后解压,使用以下命令查看帮助:
``` bash
java -jar java-client.jar -h
```

View File

@@ -0,0 +1,54 @@
# 北大数瑞介绍
- - -
## 什么是北大数瑞?
北大数瑞是面向大数据场景的数据资源、IoT资源、云资源的管理、调度平台。BDContract是一个可信计算框架计算逻辑以智能合约的方式表达。通过”随机“和”冗余计算“的方式实现智能合约的可信执行。BDContract在保证智能合约的可用性、可靠性的同时着重提升执行效率和安全性。
- - -
## 特点
0. 支持多种执行模式,权衡可用性、可靠性、正确性和效率。
1. 接入各种数据源。
2. 支持合约的细粒度监测。
3. 支持合约的状态。
4. 访问控制。
5. 支撑跨语言调用。
- - -
## 使用开源项目说明
BDWare项目站在了许多巨人的肩膀上感谢这些开源项目。
本项目的智能合约后端使用了以下开源库。
| 名称 | Licence类型 | 说明 |
| ------ | ---------- | ---- |
| [Project Nashorn](https://openjdk.java.net/projects/nashorn/) | [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | 使用了该项目的编译器可以将js函数编译为java字节码 |
| [ASM OW2](https://projects.ow2.org/view/asm/) | [BSD](https://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_(original_%22BSD_License%22)) with attribution | 基于asm的TreeAPI与VisitorAPI实现合约的静态分析框架 |
| [Netty](https://netty.io/) | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) | 使用netty作为Http/Websocket的服务端 |
| [gRPC](https://grpc.io/) | [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) | 使用gRPC与BDWareLedger通讯 |
| [RocksDB](https://github.com/facebook/rocksdb) | [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) | 后台数据库 |
| [ANTLR](https://github.com/antlr/antlr4) | [BSD](https://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_(original_%22BSD_License%22)) | 对合约脚本的词法分析与语法分析 |
| [SM2Java](https://github.com/PopezLotado/SM2Java) | [无](https://github.com/PopezLotado/SM2Java/blob/master/README.md) | 国密SM2 Java语言实现 |
本项目的智能合约前端使用了以下开源库。
| 名称 | Licence类型 | 说明 |
| ------ | ---------- | ---- |
| [Bootstrap](https://getbootstrap.com/) | [MIT](https://github.com/twbs/bootstrap/blob/master/LICENSE) | 前端的排版、样式 |
| [jQuery](https://jquery.org/) | [MIT](https://jquery.org/license/) | 用于操作DOM的javascript库 |
| [jQueryUI](https://jqueryui.com/) | [MIT](https://jquery.org/license/) | 前端UI构件库 |
| [DataTables](https://datatables.net/) | [MIT](https://datatables.net/license/mit) | 表格样式 |
| [CodeMirror](https://codemirror.net/) | [MIT](https://codemirror.net/LICENSE) | 代码编辑框样式 |
| [eCharts](https://echarts.apache.org/zh/index.html) | [ApacheV2](https://www.apache.org/licenses/) | 统计图表 |
| [sm-crypto](https://github.com/JuneAndGreen/sm-crypto) | [MIT](https://github.com/JuneAndGreen/sm-crypto/blob/master/LICENCE_MIT) | 国密SM2 javascript语言实现 |
本项目的文档使用[Sphinx](https://www.sphinx-doc.org/en/master/)生成,感谢[readthedocs](https://readthedocs.org/)提供文档样式。

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,281 @@
# YJS语法
- - -
## 概述
YJS源文件包括任意数量的**import声明**和一个**contract定义**。
- - -
## import声明
与JavaScriptES6类似YJS也支持import声明语句在全局层面开发者可以使用如下import声明来导入其他文件。
```
import "filename";
```
### 内容
import声明语句将包含在“filename”文件中的所有全局符号单元导入到当前文件且全局范围内有效。
### 路径
**filename**通常用**/**做目录分隔符来表示文件的路径,例如,从同一目录下导入**x.yjs**文件到当前文件,可以使用**import "x.yjs"**语句;从其他目录下导入**x.yjs**使用**import "lib/x.yjs"**语句。
- - -
## Contract定义
### 示例
以下是一个合约示例用于JSON处理此YJS源文件以合约名称命名。
```
contract ScoreAdder{
//arg = {"action":"main","arg":"[{\"score\":20},{\"score\":20}]"}
export function main(arg){
//JSON is a build-in object.
var point = JSON.parse(arg);
var s = 0;
print(point[0].score);
print(point.length);
for (var i=0;i<point.length;i++){
s+=point[i].score/1.0;
}
print("total score= "+s);
return s;
}
}
```
### 注释
YJS源文件支持以**//**)表示的单行注释和以(**/\*...\*/**)表示的多行注释,如下所示:
```
// 这是一个单行注释
/*
* 这是一个
* 多行注释
*/
```
### 注解
与Java类似YJS也支持注解声明合约和函数。
在YJS中有几种内建注解LogType、LogLocation、Access、Permission。
当然,可以自定义注解。
内建注解的详细使用方式可以通过YJS内置API文档查看。
开发者可以使用如下注解来声明合约和函数。
```
@LogType("Arg","Result","Branch")
@SelfDefinedAnntation("dad",1)
@Access
function xxx(){}
```
### 结构
YJS中的合约类似于Java中的类。每个合约都定义了一定数量的**变量**、**函数**和**事件**。
#### 变量
YJS中的变量类似于JavaScriptES6中的变量分为**全局变量**和**局部变量**。
全局变量:
```
judge = true;
```
局部变量:
```
var vs = "This is a string";
```
所有的变量都是**动态类型**因为变量的具体类型是根据变量值来决定的。如上示例中全局变量judge是bool类型局部变量vs是字符串类型。
#### 函数
函数是合约中的可执行单元。YJS中有两种类型的函数普通函数和用**export**关键字修饰的exported函数。
以下是exported函数和普通函数的区别
1. 只有exported函数能被其他合约调用。
2. exported函数只能有一个参数且参数类型必须为String。
3. exported函数的返回类型必须是String。
4. 内置对象requester请求者的公钥只能存在于exported函数或onCreate函数因为onCreate()虽然没被**export**关键字修饰但它自带requester对象且该函数可以自动执行。
#### 事件
YJS中的事件类似于Solidity中的事件。
**发布者**定义一个包含事件发布函数的事件,然后通过调用事件发布函数发布事件。
**订阅者**订阅并处理事件。
事件示例如下:
EventPuber.yjs
```
contract EventPuber{
event abcEvent;
export function pub(arg){
abcEvent(arg);
return "done!";
}
}
```
EventSuber.yjs
```
contract EventSuber{
export function init(arg){
YancloudUtil.subscribe("EventPuber","abcEvent",handler);
print("Handler:"+handler);
}
function handler(e){
var ret = "ReceiveEvent:"+(e.type)+" "+(e.content);
print(ret);
}
}
```
- - -
## YJS项目
除了只包含一个contract定义的YJS源文件YJS引擎还支持**YJS项目**。
每个YJS project包含了合约执行过程中需用到的各种文件包括yjs源文件**".yjs"**和其他资源文件,如**"mainfest.json"**, **".js"**, **".txt"**,**".jar"**, ...
### Manifest.json
每个YJS项目在项目的根目录下必须有一个**mainfest.json**文件此文件描述了合约对于YJS的编译工具YJS引擎所需的必要信息。
#### Manifest结构
manifest文件需包含以下信息
1. **main**: 项目中将要被执行的合约文件。
2. **type**: 合约的类型,如数据合约/算法合约...
3. **builder**: 构建YJS项目的开发者姓名。
4. **insnLimit**: 运行合约需要消耗的值。
5. **pyDependences**: 项目所需的Python依赖。
#### Manifest示例
```
{
"main": "contract.js",
"type": "Data",
"builder": "caihq",
"permissions": 0L,
"pyDependences": [
{
"name": "yjsexample",
"modules": [
{
"name": "sample"
}
]
}
]
}
```
### YJS-Java
Jar文件实现了YJS与其他编程语言间的**跨语言调用**如YJS-Java, YJS-Python, ... 通过将Java文件包成jar包的方式使得合约可直接调用Java中的方法。
Java class:
```java
package your.own.pkg;
public class HelloWorld {
public static int fun(String arg){
return arg.length;
}
public int fun2(String arg){
return arg.length;
}
}
```
InvokeJava.yjs
```javascript
contract InvokeJava{
export function main(arg){
var Hello = Java.type("your.own.package.HelloWorld");
var hello = new Hello();
return Hello.fun(arg)+hello.fun2(arg);
}
}
```
### YJS-前端
使用数瑞客户端来访问智能合约支持从智能合约中获取html/js/css等资源文件
并在[BDWareWebClient](./_static/BDWareWebClient.zip)中渲染。
首先在合约中import以下模块。
```javascript
module Viewable{
export function loadResource(arg){
return Global.Resources.loadAsString(arg);
}
export function needRender(arg){
return true;
}
}
```
同时import以后定义一个getMainFrame方法以便数瑞客户端识别主页
```javascript
export function getMainFrame(arg){
return "/html/main.html";
}
```
该方法的返回结果为一个资源文件的路径。
示例的资源文件"/html/main.html"如下:
```html
<div>
<button onclick="queryDataFromContract()">Hello,</button> Data from contract:
<span id="resultText"></span>
<script fromContract="/html/hello.js"></script>
<link fromContract="/html/hello.css"/>
</div>
```
示例的资源文件"/html/hello.js"如下:
```javascript
var queryDataFromContract = function(){
//第一个参数为函数名,第二个为参数,第三个参数为回调。
var data = executeCurrentContract("query","abc",function(argg){
$("#resultText")[0].innerHTML = argg.result;
});
}
```
参考示例:
### YJS-Python
TODO

View File

@@ -0,0 +1,594 @@
``` {.yaml}
type: google.api.Service
config_version: 3
http:
rules:
- selector: bdware.bdledger.api.Node.ClientVersion
get: /v0/node/version
- selector: bdware.bdledger.api.Ledger.CreateLedger
post: /v0/ledgers
body: "*"
- selector: bdware.bdledger.api.Ledger.GetLedgers
get: /v0/ledgers
- selector: bdware.bdledger.api.Ledger.SendTransaction
post: /v0/ledgers/{ledger}/transactions
body: "*"
- selector: bdware.bdledger.api.Query.GetBlockByHash
get: /v0/ledgers/{ledger}/block
- selector: bdware.bdledger.api.Query.GetBlocks
post: /v0/ledgers/{ledger}/blocks/query
body: "*"
- selector: bdware.bdledger.api.Query.CountBlocks
post: /v0/ledgers/{ledger}/blocks/count
body: "*"
- selector: bdware.bdledger.api.Query.GetRecentBlocks
get: /v0/ledgers/{ledger}/blocks/recent
- selector: bdware.bdledger.api.Query.GetTransactionByHash
get: /v0/ledgers/{ledger}/transaction
- selector: bdware.bdledger.api.Query.GetTransactionByBlockHashAndIndex
get: /v0/ledgers/{ledger}/block/transaction
- selector: bdware.bdledger.api.Query.GetTransactions
post: /v0/ledgers/{ledger}/transactions/query
body: "*"
- selector: bdware.bdledger.api.Query.CountTransactions
post: /v0/ledgers/{ledger}/transactions/count
body: "*"
```
> **Note**
>
> Request/Response data of **bytes** type should/will be encoded with
> [Base64](https://tools.ietf.org/html/rfc4648#section-4).
> **Note**
>
> When using hash strings in URL, they need to be encoded with
> [encodeURIComponent](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent).
Request Examples {#_request_examples}
================
Node.ClientVersion {#_node_clientversion}
------------------
Get BDLedger node version
GET http://{{IP}}:{{PORT}}/v0/node/version
**Response.**
``` {.json}
{
"version": "dev-210119.a88bf4eb"
}
```
Ledger.CreateLedger {#_ledger_createledger}
-------------------
Create a new ledger
POST http://{{IP}}:{{PORT}}/v0/ledgers
**Request body.**
``` {.json}
{
"name": "test"
}
```
**Response.**
``` {.json}
{
"ok": true
}
```
Ledger.GetLedgers {#_ledger_getledgers}
-----------------
Get all ledgers
GET http://{{IP}}:{{PORT}}/v0/ledgers
**Response.**
``` {.json}
{
"ledgers": [
"default",
"test"
]
}
```
Ledger.SendTransaction {#_ledger_sendtransaction}
----------------------
Send a new transaction
POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions
**Request body.**
``` {.json}
{
"transaction": {
"type": 0,
"from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
"nonce": 52,
"data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
}
}
```
**Response.**
``` {.json}
{
"hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE="
}
```
Query.GetBlockByHash {#_query_getblockbyhash}
--------------------
Get a block identified by its hash
GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block?hash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D
**hash** has to be encoded with
[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
**Response.**
``` {.json}
{
"block": {
"hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"creator": "",
"nonce": "0",
"parentHashes": [
"fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
"rk0DWMaUpRG82yVX+cFhbfhPFdw=",
"3XkwkuMBearq8uavN76Te7Zdpl8="
],
"witnesses": [],
"timestamp": "1611038043",
"size": "0",
"transactionCount": 1,
"transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"transactions": [
{
"blockHash": "",
"blockTimestamp": "0",
"index": 0,
"hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"type": "RECORD",
"from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
"nonce": "0",
"to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
}
],
"transactionHashes": [
"VQBeA5Ee0Y5hqEileoQuYMHbOSE="
]
}
}
```
Query.GetBlocks {#_query_getblocks}
---------------
Get blocks in a timestamp range
POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/query
``` {.protobuf}
enum IncludeTransactions {
NONE = 0; // Don't include transaction data
HASH = 1; // Include transactions hashes
FULL = 2; // Include full transactions
}
```
Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\]
If only **end\_timestamp** is not specified, or
asciimath:\[\"end\_timestamp\"-\"start\_timestamp\"\>\"query.maxDuration\"\],
then **end\_timestamp** will be set to
asciimath:\[\"start\_timestamp\"+\"query.maxDuration\"\].
If only **start\_timestamp** is not specified, then **start\_timestamp**
will be set to asciimath:\[\"end\_timestamp\"-\"query.maxDuration\"\].
In all cases, **start\_timestamp** will never be earlier than the
genesis block's timestamp, and **end\_timestamp** will never be later
than the current timestamp when the node process the query request.
**Request body 1.**
``` {.json}
{
"start_timestamp": 1611038000,
"end_timestamp": 1611039000,
"include_transactions": 0
}
```
**Response 1.**
``` {.json}
{
"blocks": [
{
"hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"creator": "",
"nonce": "0",
"parentHashes": [
"fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
"rk0DWMaUpRG82yVX+cFhbfhPFdw=",
"3XkwkuMBearq8uavN76Te7Zdpl8="
],
"witnesses": [],
"timestamp": "1611038043",
"size": "0",
"transactionCount": 1,
"transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"transactions": [],
"transactionHashes": []
}
],
"startTimestamp": "1611038043",
"endTimestamp": "1611038043"
}
```
**Request body 2.**
``` {.json}
{
"start_timestamp": 1611038000,
"end_timestamp": 1611039000,
"include_transactions": 1
}
```
**Response 2.**
``` {.json}
{
"blocks": [
{
"hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"creator": "",
"nonce": "0",
"parentHashes": [
"fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
"rk0DWMaUpRG82yVX+cFhbfhPFdw=",
"3XkwkuMBearq8uavN76Te7Zdpl8="
],
"witnesses": [],
"timestamp": "1611038043",
"size": "0",
"transactionCount": 1,
"transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"transactions": [],
"transactionHashes": [
"VQBeA5Ee0Y5hqEileoQuYMHbOSE="
]
}
],
"startTimestamp": "1611038043",
"endTimestamp": "1611038043"
}
```
**Request body 3.**
``` {.json}
{
"start_timestamp": 1611038000,
"end_timestamp": 1611039000,
"include_transactions": 2
}
```
**Response 3.**
``` {.json}
{
"blocks": [
{
"hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"creator": "",
"nonce": "0",
"parentHashes": [
"fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
"rk0DWMaUpRG82yVX+cFhbfhPFdw=",
"3XkwkuMBearq8uavN76Te7Zdpl8="
],
"witnesses": [],
"timestamp": "1611038043",
"size": "0",
"transactionCount": 1,
"transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"transactions": [
{
"blockHash": "",
"blockTimestamp": "0",
"index": 0,
"hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"type": "RECORD",
"from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
"nonce": "0",
"to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
}
],
"transactionHashes": [
"VQBeA5Ee0Y5hqEileoQuYMHbOSE="
]
}
],
"startTimestamp": "1611038043",
"endTimestamp": "1611038043"
}
```
Query.CountBlocks {#_query_countblocks}
-----------------
Count all blocks in a ledger, or blocks in a timestamp range
POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/count
Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\]
If neither **start\_timestamp** nor **end\_timestamp** is specified,
then count all blocks in the specified ledger.
If only **end\_timestamp** is not specified, then count all blocks with
timestamps later than **start\_timestamp**.
If only **start\_timestamp** is not specified, then count all blocks
with timestamps earlier than **end\_timestamp**.
In all cases, **start\_timestamp** will never be earlier than the
genesis block's timestamp, and **end\_timestamp** will never be later
than the current timestamp when the node process the query request.
**Request body 1.**
``` {.json}
{}
```
**Response 1.**
``` {.json}
{
"count": "5",
"startTimestamp": "0",
"endTimestamp": "1611039957"
}
```
**Request body 2.**
``` {.json}
{
"start_timestamp": 1611038000,
"end_timestamp": 1611039000
}
```
**Response 2.**
``` {.json}
{
"count": "1",
"startTimestamp": "1611038000",
"endTimestamp": "1611039000"
}
```
Query.GetRecentBlocks {#_query_getrecentblocks}
---------------------
Get recent **count** blocks (Only support IncludeTransactions=NONE for
now)
GET http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/recent?count=2
**Response.**
``` {.json}
{
"blocks": [
{
"hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"creator": "",
"nonce": "0",
"parentHashes": [
"fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
"rk0DWMaUpRG82yVX+cFhbfhPFdw=",
"3XkwkuMBearq8uavN76Te7Zdpl8="
],
"witnesses": [],
"timestamp": "1611038043",
"size": "0",
"transactionCount": 1,
"transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"transactions": [],
"transactionHashes": []
},
{
"hash": "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
"creator": "",
"nonce": "0",
"parentHashes": [
"fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
"3XkwkuMBearq8uavN76Te7Zdpl8=",
"8pZPR74OALIbps5XFb4dL/s0j0M="
],
"witnesses": [],
"timestamp": "1610968019",
"size": "0",
"transactionCount": 1,
"transactionsRoot": "LuxttCm/pSHVMOKF0sJExk+DJXc=",
"transactions": [],
"transactionHashes": []
}
],
"startTimestamp": "1610968019",
"endTimestamp": "1611038043"
}
```
Query.GetTransactionByHash {#_query_gettransactionbyhash}
--------------------------
Get a transaction identified by its hash
GET http://{{IP}}:{{PORT}}/v0/ledgers/test/transaction?hash=VQBeA5Ee0Y5hqEileoQuYMHbOSE%3D
**hash** has to be encoded with
[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
**Response.**
``` {.json}
{
"transaction": {
"blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"blockTimestamp": "1611038043",
"index": 0,
"hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"type": "RECORD",
"from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
"nonce": "0",
"to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
}
}
```
Query.GetTransactionByBlockHashAndIndex {#_query_gettransactionbyblockhashandindex}
---------------------------------------
Get a transaction identified by hash of the block it belongs to and its
index inside the block
GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block/transaction?blockHash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D&index=0
**blockHash** has to be encoded with
[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
**Response.**
``` {.json}
{
"transaction": {
"blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
"blockTimestamp": "1611038043",
"index": 0,
"hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"type": "RECORD",
"from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
"nonce": "0",
"to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
}
}
```
Query.GetTransactions {#_query_gettransactions}
---------------------
Get transactions in a timestamp range
POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/query
**start\_timestamp** and **end\_timestamp** follow the same requirements
and rules as in [???](#Query.GetBlocks).
**Request body.**
``` {.json}
{
"start_timestamp": 1611038000,
"end_timestamp": 1611039000
}
```
**Response.**
``` {.json}
{
"transactions": [
{
"blockHash": "",
"blockTimestamp": "0",
"index": 0,
"hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
"type": "RECORD",
"from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
"nonce": "0",
"to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
}
],
"startTimestamp": "1611038043",
"endTimestamp": "1611038043"
}
```
Query.CountTransactions {#_query_counttransactions}
-----------------------
Count all transactions in a ledger, or transactions in a timestamp range
POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/count
**start\_timestamp** and **end\_timestamp** follow the same requirements
and rules as in [???](#Query.CountBlocks).
**Request body 1.**
``` {.json}
{}
```
**Response 1.**
``` {.json}
{
"count": "4",
"startTimestamp": "0",
"endTimestamp": "1611039957"
}
```
**Request body 2.**
``` {.json}
{
"start_timestamp": 1611038000,
"end_timestamp": 1611039000
}
```
**Response 2.**
``` {.json}
{
"count": "1",
"startTimestamp": "1611038000",
"endTimestamp": "1611039000"
}
```