支持增删改查等基本数据库功能(见示意图)。
可同时对多张表进行多项操作,类似数据库的事务功能(见示意图)。
ChainSQL的API提供事务操作的接口,可同时对一张表或多张表进行多项操作,若这些操作中有一个失败,则事务整体操作失败。
创建表的用户拥有此表的增删改查权限,并可将这些权限授权给其他用户(见示意图) 。
默认只有创建该表的用户才有此表的增删改查权限,建表人可将这些权限授权给其他用户,建表后也可对同一用户进行多次授权,重新授权会覆盖之前的权限。
可以对所有人进行授权,对个人授权>对所有人的授权
建表时可以对增删改查权限分别进行条件设置,只有满足条件的记录方可被操作,精确度到行(见示意图) 。
应用场景:在我们做业务的时候,经常会出现多个用户通过ChainSQL访问同一张表的情况,为了防止用户对表的数据随意修改,我们提出了行级控制的概念,通过在建表时指定操作条件,可以将对表的操作力度控制在行级。
目前支持的功能:
插入:
1.指定某列默认插入当前操作账户
2.指定某列默认插入交易的hash值
3.设置插入条数限制
更新:
1.设置可更新字段集合
2.设置更新条件
删除:设置删除条件(若设置了插入条数限制条件,删除条件中必须做相应的账户设置)
查询:设置查询条件
举例说明:
建表时指定行级控制规则如下:
{ "tx_json": { "TransactionType": "TableListSet", "Account": "zP8Mum8xaGSkypRgDHKRbN8otJSzwgiJ9M", "Tables":[ { "Table":{ "TableName":"tableWithRule" } } ], "OpType": 1, "Raw": [ {"field":"id","type":"int","length":11,"PK":1,"NN":1,"UQ":1}, {"field":"age","type":"int"}, {"field":"name","type":"varchar","length":32}, {"field":"account","type":"varchar","length":64}, {"field":"txid","type":"varchar","length":64} ], "OperationRule":{ "Insert":{ "Condition":{"account":"$account","txid":"$tx_hash"}, "Count":{"AccountField":"account","CountLimit":5} }, "Update":{ "Condition":{"$or":[{"age":{"$le":28}},{"id":2}]}, "Fields":["age"] }, "Delete":{ "Condition":{"account":"$account"} }, "Get":{ "Condition":{"id":{"$ge":3}} } } } }
以上命令中指定的增删改查条件如下:
插入:
1.account字段值为执行插入交易时的账户地址,不写会自动填充
2.Txid字段值为执行插入交易时的交易hash值,不写会自动填充
3.每个账户最多只能插入5条数据到表中
更新:
1.只能更新表中的age字段
2.只能更新age <=2 8 或 id=2的记录
删除: 删除记录A的账户必须与记录A中account字段的值一致(与插入条数对应)
查询:只有满足id >=3的记录才能被查询出来
注意事项: 使用行级控制功能的不能为加密表
案例:
百望发票项目:
“税务+区块链”应用采用API接口的方式进行集成。区块链接口满足的业务包括:
1. 创建wallet接口
2. 查询wallet ID接口
3. 发票写入接口
4. 发票读取接口
5. 发票状态维护接口
接口形式:Restful
信息流向:
1. from:baiwang
2. to1:消费者
3. to2:销货企业
4. to3:报销入账企业
项目应用的行级控制功能:
1.插入的限制条件to2字段值必须与插入账户相同:
{ "Insert":{ "Condition":{"to2":"$account"} } }
说明:Condition指定插入交易的账户地址("Account"的值)必须与交易中Raw字段的to2字段值值相同
2.更新目前可以限制更新字段与更新条件:
{ "Update":{ "Condition":{"$or":[{"to2":"$account"},{"to3":"$account"}]}, "Fields":["state"] } }
Condition指定更新满足的条件:to2的值等于当前交易(Update)的账户地址 或 to3的值等于当前交易(Update)的账户地址
Fields字段指定更新只能更新state字段
3.查询条件
{ "Condition":{"$or":[{"to1":"$account"},{"to2":"$account"},{"to3":"$account"}]} }
说明:只有to1/to2/to3指定的用户可以查询本条记录
最终OperationRule取值:
{ "Insert":{ "Condition":{"to2":"$account"} }, "Update":{ "Condition":{"$or":[{"to2":"$account"},{"to3":"$account"}]}, "Fields":["STATE"] }, "Get":{ "Condition":{"$or":[{"to1":"$account"},{"to2":"$account"},{"to3":"$account"}]} } }
可对整张表加密,也可对表中的某些字段加密,只有配有解密私钥的用户能解密出明文(见示意图)。
a. 整张表加密
这种加密方式是对整个表进行加密,没有对应解密私钥的用户无法同步该表
b. 字段级加密
可以对表里的某几个字段进行加密,精确度到某几行的某几个字段,没有解密私钥的用户只能看到字段名,无法看到该字段下的值
多人同时操作同一张表时,打开严格模式,可检测本地数据与链上最新数据是否一致,避免数据分叉(见示意图)。
数据库表的某些操作需要基于表的当前状态值进行,例如数据库表设计为 (帐户 :物品),当进行表插入操作insert into table (account , material) values (zhangsan, book) 时,会先判断数据库表中是否已经有(zhangsan : book),如果没有对应条目才进行插入操作。
在网络状态不稳定时,本地节点的区块有可能落后于整个ChainSQL网络的区块进度。新的ChainSQL网络的区块中已经有了(zhangsan : book),也就是说其它用户用另外一个帐号已经做了(zhangsan : book)的插入操作,但是从本地ChainSQL节点读取到的结果却没有这个记录,此时用户会再执行表插入操作,导致最终数据库中有多个(zhangsan : book)条目,造成数据库表的混乱。
严格模式是为了解决上述可能引起对数据库表误操作而设计的一种交易方式。
把对某张表的数据库操作设计成一个前向链表,数据库表的创建交易是链表的表头,对应的指针为hash(raw),即创建表操作的raw字段的哈希值作为该交易的指针。 此后每一个新的数据库表交易对应的指针值为hash( 前一个表操作指针值 + 本交易raw), 即将前一个交易里记录的指针值与本交易里的raw内容合并,再求哈希。
ChainSQL对每张表都会记录针对这张表的最新交易的指针值。
严格模式开启的情况下,在共识环节,各验证节点基于自己本地的ChainSQL网络状态,重新计算此交易对应的指针值,与交易里携带的指针值进行比较。若参加共识的各验证节点计算出来的指针值与交易里携带的结果一致,则交易成功;若共识节点读到的“前一个表操作指针值”与用户从自己连接的普通节点读到的“前一个表操作指针值”不一致,则交易失败。
在普通模式下,参加共识的各个验证节点并不去验证当前交易的链表指针是否有效,只要是对本数据表的操作都认为是有效操作。
可对数据表中的某些字段的增删改记录进行追踪溯源(见示意图)。
对数据库表的指定条目特定字段进行追根溯源,将所有影响了指定条目特定字段的数据库表操作都记录下来。
实现方式:通过Commandline方式进行操作。
命令形式:Chainsqld.exe t_aduit “para1” “para2” “para3”
Para1 : 与“数据库表的同步设置“保持一致。
Para2 : sql查询语句,表明指定条目特定字段,如“select name, salary from table1 where id=1”,代表审计数据库表table1中id=1的条目的name与salary字段,所有与对数据库表table1的操作中影响到id=1的条目中的name与salary字段的操作将被记录。
Para3 : 数据库表操作保存的目标路径。
例:Chainsqld.exe t_audit “zGutD9mnua27jYdcTqo7oGYnHzkAZq1VGJ table1 2000” “select name, salary from table1 where id=1” “/ChainSQL/table1.txt”
停止审计操作,命令如下:chainsqld.exe t_auditstop para1
可把链上某张表的操作日志以json的格式保存到本地txt文件中(见示意图)。
将数据库表的操作以文档的形式进行记录,可以分多次对同一张表进行dump。
实现方式:通过Commandline方式进行操作。
命令形式:Chainsqld.exe t_dump “para1” “para2”
Para1 : 与“数据库表的同步设置”保持一致。
Para2 : 数据库表操作保存的目标路径。
例:Chainsqld.exe t_dump “zGutD9mnua27jYdcTqo7oGYnHzkAZq1VGJ table1 2000” “/chainsql/table1.txt”
停止dump操作,命令如下:chainsqld.exe t_dumpstop para1
订阅某张表或某个交易后,对该表或该交易的操作日志会以事件的方式发送给订阅者(见示意图)。
一个交易是否通过共识被ChainSQL记录下来,是否已经写入本地数据库,通常需要客户在发送交易后主动去查询ChainSQL与数据库来确认。通过订阅功能,ChainSQL可以主动向用户发送交易或者表的状态。
订阅包括交易的订阅、表的订阅
交易的订阅:
接收ChainSQL发来的关于本交易在ChainSQL中共识及入库的状态,订阅命令:
{ "command": "subscribe", "transaction": "7EDDDED24811940E7253EB367EB572E67243292CFDF9C82ED8D8D3DCEAC5F41A" }
ChainSQL网络会监测交易在ChainSQL与数据库中的状态,通过事件的方式通知订阅方,状态包括:共识成功、共识失败、入库成功、入库失败。
返回结果:
{ "status":"validate_success", "transaction":{}, "type":"singleTransaction" }
{ "status":"db_success", "transaction":{}, "type":"singleTransaction" }
通过被动接收交易的执行情况,避免用户主动查询引起的资源浪费及复杂判断,简化的对交易结果判断的过程。
表的订阅
接收ChainSQL发来的关于订阅表的所有操作,命令:
{ "command": "subscribe", "owner": "zP8Mum8xaGSkypRgDHKRbN8otJSzwgiJ9M", "tablename": "hello" }
ChainSQL网络会监测订阅表的包含增删改及表的改名、授权、删除等一切操作,通过事件的方式通知订阅方。
返回结果:
{ "status":"validate_success", "transaction":{}, "type":"table" , "owner": "zP8Mum8xaGSkypRgDHKRbN8otJSzwgiJ9M", "tablename": "hello" }
{ "status":"db_success", "transaction":{}, "type":"table", "owner": "zP8Mum8xaGSkypRgDHKRbN8otJSzwgiJ9M", "tablename": "hello" }
表的最新操作都会通知给订阅方,订阅方可以及时了解到自己关心的表的最新动态。此功能可扩展为在ChainSQL的各个用户之间进行消息传递。
节点加入ChainSQL链后可同步链上存在的数据库表
节点在配置文件中指定要同步的表
同步方式:
未加密raw字段:表的发行帐户地址 + 表名
加密raw字段:表的发行帐户地址 + 表名 + 解密的私钥
跳过指定条件:表的发行帐户地址 + 表名 + 跳过指定条件(如跳过某个交易)
同步到指定条件之前:表的发行帐户地址 + 表名 + 同步到指定条件之前(如某个时间之前)
对数据库表的交易先在数据库中预执行,再发往区块链网络进行共识:如果共识成功,提交预执行;否则,撤销预执行(流程见下图)。
该功能默认处于打开状态,配置如下:
first_storage=1(打开状态)
first_storage=0(关闭状态)
指定一个时间点,该时间点的状态和该时间点之后的数据将保留链上,删除之前的数据,避免不断新增的数据占用磁盘空间(见示意图)。
可将一条或多条ChainSQL链上的数据上传到另一条ChainSQL链上(见示意图)。
场景:一个组织的各个分支机构都架设了各自的ChainSQL网络,分别记录了属于自己的私有数据,各个分支机构之间无权互相访问。组织的管理者也独立运行一个ChainSQL网络,在某些情况下下,管理者需要收集各分支机构的ChainSQL数据。
下图为某银行的组织机构图:
举例说明:
支行1(分支机构)要将本机构的ChainSQL网络(链A)数据上传到总行(管理机构)的ChainSQL网络(链B)上。
准备工作:在链B的上激活一个账户accountB用来上传A链的数据。
工具使用:peersafe提供的链间数据同步工具bcmutil。正确填写配置文件参数后,直接运行。
1.设置bcmutil的配置文件:
PullIpPort:链A中一个节点的websocket地址及端口,格式如192.168.0.112:5003
PushIpPort:链B中一个节点的websocket地址及端口, 格式如192.168.0.118:5003
PushAccount:链B上分配的账户accountB的地址
PushSecret:链B上分配的账户accountB的私钥
2.运行bcmutil程序
bcmutil运行原理:
1. 程序启动时,从链A获取最开始的交易,经过处理后发送到链B;
2. 若交易发送成功,则继续发送从链A获取到的交易;若发送失败,则返回下一个需要发送的交易hash,从链A获取对应交易后再发送
3. 交易同步到最新后,若长时间无交易产生,每隔一段时间向链B发送一个report交易,记录当前同步到链A中的区块高度
各分支机构用组织管理者分配的帐户,向上一级ChainSQL网络发送T_REPORT交易。
首先访问上级一级网络得到在自己网络查找交易的起点位置,然后按区块顺序查找所有ChainSQL交易。
读取机构ChainSQL交易中的raw字段,赋值给新的T_REPORT交易。记录原始交易的源帐户,以及原始交易所在的区块号。记录原始交易的哈希值及前一个ChainSQL交易的哈希值。
同一个帐户的T_REPORT交易通过前向哈希链表进行顺序串联,有助于查找整合的起点位置,同时防止交易的遗漏及重复上传。
目的:
1. 在组织独立运行的ChainSQL网络中可以查看到各分支构所建的各个数据库表。
2. 通过查看分配给特定机构的帐户交易详情,能够在机构所在的ChainSQL网络中查看到原始交易的详细信息。