支持增删改查等基本数据库功能(见示意图)。
可同时对多张表进行多项操作,类似数据库的事务功能(见示意图)。
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网络中查看到原始交易的详细信息。
区块链上采用不同的共识算法会对系统的共识效率、分布式程度产生不同影响。ChainSQL采用一种高效、支持拜占庭容错、具有自主知识产权的共识算法,同时共识算法支持可插拔,按照模块化的设计思路,将共识协议的各阶段进行封装、抽象出可扩展的接口。
ChainSQL采用自研的POP(Proof Of Peers)共识机制,整体来看可分为交易集共识、区块共识两个阶段。
在交易集共识阶段,每轮共识由全网唯一的leader节点(根据区块号轮换)对交易集提案,其它节点对这一提案进行投票最终达成共识。这样的优点是在交易量大时,使用leader提案的机制相比所有共识节点各自提案交易集然后解决分歧的机制更容易达成共识。
在区块共识阶段,每个节点在交易集达成共识后按顺序验证交易集中的每一笔交易,最终得到一个状态树根hash,并结合交易集构成的交易树根hash、区块号、时间戳等构造区块头信息,然后每个节点各自对自己生成的新区块投票并收集其它节点的投票,得票数超过阈值的区块被认为验证通过。由于每个节点在这一阶段已经达成一致的交易集,所以很容易达成共识。
ChainSQL中通过分片架构对共识性能进行提升,在对分片节点进行网络分片的基础上对交易进行分片,提高共识TPS。分片网络的整体性能随着分片数的增多而增大。
分片架构最上层为直接与客户端对接的节点和数据库组件,Lookup节点主要负责接收交易、分发交易到各分片,持久化、发布区块等。Sync节点作为ChainSQL表同步功能执行单元,可插件式灵活接入。
各分片主要执行交易以及共识。在这一层共识的结果主要是由各分片上的交易产生的状态变化而不是最终状态。分片节点主要负责执行交易,产生状态变化,并提交给最下面一层委员会。各个分片独立并行运行,互不依赖和干预,大大增加了整个网络的共识能力。
委员会合并所有分片共识的结果,并对最终区块进行共识。将区块分发到全网同步,分片网络中每个节点都具有全网状态。
在配置文件中配置共识算法及参数,可兼容更多共识算法。
在多链的设计中,通过主链的世界状态管理各子链;每条子链都有独立的P2P网络、交易池、共识、存储以及数据库模块。
主链:管理子链共享的数据。
子链:实现具体业务。
子链不继承主链任何状态,是一个全新的链;
子链只继承主链账户状态,需要锚定主链上的区块;
主链与子链共享账户余额,使用跨链的方式从主链向子链兑换积分。
先有主链:子链是在主链的基础上创建的,而且每个子链成员都需要同步主链数据;
分布式管理:通过主链上的世界状态对子链进行管理,子链的创建、子链节点的增删都需要通过智能合约;
存储隔离:每条子链之间的存储是隔离的,对于一个参与多条子链的节点来说,多条子链在磁盘上的存储是通过文件夹隔离的;
主链可继承:在创建子链时,可选择继承主链的账户状态,这样可以实现主链初始化一次,多条子链共享同一主链状态的效果;
治理多样化:子链中节点的增加与删除,可以通过指定的管理员进行中心化操作,也可以不指定管理员,通过多数节点投票的方式实现;
网络隔离:只有属于同一子链的节点才能收到主链相关的消息,不同子链的节点消息不互通,在网络层实现数据隔离。
扩展智能合约指令,打通了与ChainSQL中其它交易的调用,使合约数据与链元数据的交互成为可能。不仅可以通过区块链交易改变合约内部数据,还可根据合约的内部逻辑判断来影响合约外的区块链世界状态。同时提供智能合约检测工具,防止恶意的企图通过智能合约漏洞入侵用户数据的行为。
ChainSQL区块链系统国产自主可控。相继完成与中标麒麟高级服务器操作系统软件V7.0(X86-64)、人大金仓数据库管理系统KingbaseES V7和V8、华为技术有限公司TaiShan 200系列、银河麒麟高级服务器操作系统(飞腾版)V10和中标麒麟高级服务器操作系统软件(ARM64版)V7.0的兼容性测试,获得三项麒麟软件NeoCertify认证、人大金仓产品兼容性认证及华为技术认证书。
目前,ChainSQL已经完成自主可控认证的国产服务器、操作系统、数据库等,为从硬件到软件全部由国产自主可控厂商提供官方认证的区块链底层软件产品。
ChainSQL在2018年通过国家权威部门的测试,是最先取得国家密码管理局颁发的 “商用密码产品型号证书”的区块链底层框架,支持国内最快的软硬国密算法。并于同年完成了公安部针对计算机系统安全性测试,获得公安部网络安全保卫局颁发的“计算机信息系统安全专用产品销售许可证。
隐私计算集合了安全多方计算、同态加密和差分隐私等隐私保护技术的服务平台,平台提供一套针对隐私数据的计算接口,基于存储引擎、机器学习引擎、多种隐私计算算法来实现隐私数据计算。当接口被调用时,隐私计算平台首先会根据数据源配置去获取数据,将数据源进行预处理和加密,再根据具体接口分配不同任务、根据任务的参与方数量,将任务合理分片,调度给不同的参与方分别去执行。节点之间需要进行网络通信,以便传输计算结果。计算结束后,计算结果传递给确定的结果接收方,其他参与方不能获取任何计算过程中的数据和最后的计算结果,同时,结果接收方也无法获取其余参与方的任何数据。
在隐私计算平台中加入区块链模块,进一步实现数据的安全保护、合规管理、流程监督,使得数据的整个生命周期可控、可管、可审。
区块链中,用户身份一般不做限制,任何人只要有一个合法的钱包,就可以在链上发交易。但是在某些安全级别较高的应用场景中,只有某些授权用户才被允许在链上操作。
ChainSQL中通过给用户发证书(CA)的方式来实现用户身份准入机制,用户需要向链的管理方申请证书,并在发交易时附加证书。节点会配置它信任的根证书,只有交易中的证书是这些根证书签发的证书,交易才会被验证通过。
ChainSQL链之间,两者遵循一定协议,可以把子链上数据同步到主链上 同步数据需要同一账户进行数据的同步,数据同步不可逆。
区块链的存储空间是一大难题,因为区块链的机制,区块链在运行的过程中没有产生交易的情况下也会产生区块,由于区块链存在区块的结构信息,这样就会占用空间。ChainSQL对于空区块的产生可以进行控制,支持在没有交易的时候不产生空区块。另外对于落块的条件也进行了相应的设计,根据交易池数量、区块里交易数、共识时间来进行自行配置控制交易落块。