- Java 90.1%
- Shell 5.3%
- Python 2.3%
- TypeScript 2.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| backend | ||
| docker-deploy | ||
| front | ||
| mockgen | ||
| ShanxiAuditRepo | ||
| ShanxiCommon | ||
| ShanxiEndpointRepo | ||
| .gitignore | ||
| build.gradle | ||
| gradle.properties.template | ||
| process.png | ||
| README.md | ||
| READMEV2.md | ||
| settings.gradle | ||
| TODO.md | ||
防篡改说明
概念解释
- data表示原始数据
- originalDataHash为SM3.hash(data)。originalDataHash可用于验证data的正确性。
- doid表示数据的唯一标识
- dataHash为SM3.hash(doid+originalDataHash)。dataHash可用于验证doid与originalDataHash的正确性。
- merkelTree,其叶子节点是由dataHash组成,其树根为merkelRootHash。merkelRootHash可用于验证一组dataHash的正确性。
- repoId,用于区分数据来源于哪个数据源。可设计为一个矿端一个repoId,一个云端系统(需要调用registerDOID的)一个repoId。
执行流程
-
为数据分配标识。输入参数包括repoId和data。 分配标识过程中,标识解析系统会维护doid到originalDataHash的关系;shanxiProxy会计算dataHash,并按批量上链的策略,计算出merkelTree,并把merkelRootHash上链,维护ledgerHash到merkelRootHash的关系。
-
通过doid+data在shanxiProxy中,基于标识解析系统验证data和originalDataHash的正确性,并计算出dataHash。其次,会基于分布式账本验证merkelRootHash未被篡改,从而验证dataHash未被篡改,从而验证doid+originalDataHash未被篡改,从而证明data未被篡改。
假设某条数据产生之后,想修改这条数据,那么需要:
- 为修改后的数据分配一个新的标识。即产生一组有效的doid2、dataHash2、merkelRootHash2、ledgerHash2。
- 一般而言,数据会有产生的时间戳,根据数据产生的时间戳和ledgerHash2的时间戳,可验证该数据是否为重新生成的。
使用流程
- 通过createRepo接口,创建分配数字对象仓库ID,创建接口同时会返回token,用于registerDOID接口。
- 通过registerDOID接口注册标识,系统会返回dataHash。
- 通过verifyDataByDOID接口,可在标识解析系统和分布式账本中验证原始数据、doid和dataHash是否匹配。
参数说明
接口地址:http://39.104.208.223:18010/SCIDE/SCManager 接口支持get和post两种。 其中get参数为?key=val&key2=val2的形式 post参数为json格式,放在body里传入。 测试地址中无签名证验逻辑,因此,pubkey和signature可不传。 公共参数如下:
{
"action": "executeContract",
"contractID": "ShanxiProxy"
}
以下四个不同的函数有不同的operation和arg。
结果响应
Error handling
当code不为0时,为异常返回。
{
"code": 1,
"message": "Description message",
"innererror": {
"optional": "inner error"
}
}
APIs
createRepo
用于创建repo。需使用管理员权限创建(测试环境中权限控制已停用)。
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=createRepo&arg={"name":"ttttt2","suffix":"tt2"}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=304402203f613628191aa1d532c3866568edcbaa2434b3b7bf49d7e9cd4e4791fb578cfa02202570454fbe32515e7a4710ae827cfe86fb4a1c920fde759abb4b07dda3d4ad7a
http post是将query转为json对象放到body里。 body示例:
{
"action": "executeContract",
"contractID": "ShanxiProxy",
"operation": "createRepo",
"arg": {
"name": "ttttt2",
"suffix": "tt2"
}
}
返回结果示例
{
"code": 0,
"repoId": "shanxi.taiyuan.xiaodian/tt2",
"token": "2fbb0029-9b4d-44a1-b04f-94e9f6fba2f7"
}
createDataType
用于创建DataType。需使用管理员权限创建(测试环境中权限控制已停用)。
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=createDataType&arg={"repoId":"shanxi.taiyuan.xiaodian/tt2","info":{"name":"XXSensor"}}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=30440220784fccb258b2eaf6775005591d3391ca671100498452fcd5c35b43a2c6a877fa02204fad69e07227640964ab702161e7c2622407c48be054c170d20c79270fd61118
http post是将query转为json对象放到body里。 body示例:
{
"action": "executeContract",
"contractID": "ShanxiProxy",
"operation": "createDataType",
"arg": {
"repoId": "shanxi.taiyuan.xiaodian/tt2",
"info": {
"name": "XXSensor"
}
}
}
返回结果示例
{
"dataType": "shanxi.taiyuan.xiaodian/tt2/3a382523-eba6-45c2-bb8f-cb9d94ce0116",
"code": 0
}
registerDOID
用于注册doid和获取dataHash。 该接口适用于在网关端为即将上传的数据打标识。 也适用于在云端为"传感数据经二次处理后待入库的数据"打标识。 输入参数arg为json格式,其中data为string类型,为待标识的数据。 比如"{"key1":"val1"}"。
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=registerDOID&arg={"data":"abc","repoId":"shanxi.taiyuan.xiaodian/tt2","token":"2fbb0029-9b4d-44a1-b04f-94e9f6fba2f7","dataType":"shanxi.taiyuan.xiaodian/tt2/3a382523-eba6-45c2-bb8f-cb9d94ce0116"}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=30450221008db6fa9e0fa70744ab07fb408a4921a5a98aa67131dfb51675d8f8045a0a733b022011de9bb870532ac11c78ce9455632b984e739472f3ea5684fdd03220bff3f4a7
http post是将query转为json对象放到body里。 body示例:
{
"action": "executeContract",
"contractID": "ShanxiProxy",
"operation": "registerDOID",
"arg": {
"data": "abc",
"repoId": "shanxi.taiyuan.xiaodian/tt2",
"token": "2fbb0029-9b4d-44a1-b04f-94e9f6fba2f7",
"dataType": "shanxi.taiyuan.xiaodian/tt2/3a382523-eba6-45c2-bb8f-cb9d94ce0116"
}
}
返回结果示例
{
"doid": "shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7",
"code": 0,
"dataHash": "de73de9bcc293d1eabe898fd227f12d6d18e6468e6e83d9761fcd9fe7fda2fa0"
}
verifyDataByDOID
用于验证doid和data是否匹配。
该函数可在云端收到网关端的数据时调用。
参数arg为json格式,其中data为string类型,doid和dataHash为接口registerDOID的返回结果。
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=verifyDataByDOID&arg={"doid":"shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7","data":"abc"}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=304502203121806d349a37d596045a071abe9edb069edc22e01f8a99c20691c387a25bf5022100a5cb7183bebd3e1cb0d64d96bf3a6a5813a2260bb9fe9a67461e07ebb075d507
http post示例:
{
"action": "executeContract",
"contractID": "ShanxiProxy",
"operation": "verifyDataByDOID",
"arg": {
"doid": "shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7",
"data": "abc"
}
}
返回结果示例
{
"code": 0,
"message": "验证成功",
"doidResolved": true,
"repoId":"shanxi.taiyuan.xiaodian/tt2",
"repoName":"ttttt2",
"dataHashMatched": true,
"dataHash": "de73de9bcc293d1eabe898fd227f12d6d18e6468e6e83d9761fcd9fe7fda2fa0",
// 仅dataHashMatch为false时返回:
// "originalHash": "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
"verificationPageUrl": "http://127.0.0.1:18000?transactionHash=bffcd42431b1cfb96ad5611cb15b55fe92b43abe",
"transactionHash": "bffcd42431b1cfb96ad5611cb15b55fe92b43abe",
"dataType": "shanxi.taiyuan.xiaodian/tt2/3a382523-eba6-45c2-bb8f-cb9d94ce0116",
"dataTypeInfo": {
"name": "XXSensor"
}
}
verifyDataByDOIDAndLedger
用于验证doid和data是否匹配。包含账本信息验证
该函数可在云端收到网关端的数据时调用。
参数arg为json格式,其中data为string类型,doid和dataHash为接口registerDOID的返回结果。
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=verifyDataByDOIDAndLedger&arg={"doid":"shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7","data":"abc"}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=304502203121806d349a37d596045a071abe9edb069edc22e01f8a99c20691c387a25bf5022100a5cb7183bebd3e1cb0d64d96bf3a6a5813a2260bb9fe9a67461e07ebb075d507
http post示例:
{
"action": "executeContract",
"contractID": "ShanxiProxy",
"operation": "verifyDataByDOIDAndLedger",
"arg": {
"doid": "shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7",
"data": "abc"
}
}
返回结果示例
{
"code": 0,
"message": "验证成功",
"doidResolved": true,
"repoId":"shanxi.taiyuan.xiaodian/tt2",
"repoName":"ttttt2",
"dataHashMatched": true,
"dataHash": "de73de9bcc293d1eabe898fd227f12d6d18e6468e6e83d9761fcd9fe7fda2fa0",
// 仅dataHashMatch为false时返回:
// "originalHash": "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
"transactionHash": "bffcd42431b1cfb96ad5611cb15b55fe92b43abe",
"merkelRootHashFromLedger": "de73de9bcc293d1eabe898fd227f12d6d18e6468e6e83d9761fcd9fe7fda2fa0",
"merkelTree": {
"root": {
"val": "de73de9bcc293d1eabe898fd227f12d6d18e6468e6e83d9761fcd9fe7fda2fa0"
},
"childCount": 35
},
"blockHash": "91fb0d25322088f4703079c59ac39444f1856a3a",
"blockHeader": {
"creator": "QmPbZLPU2kqViz4Z411pgLBQqENm4tYtQNZfhvCHN592gK",
"creatorSignature": "AqpVJPaGHTrUVh1aqrpP8tko8RzaYkv2bhL6JXXhWc63ZYcuVhqktE8WsGJ1nzDfLz8gt6YUudAE2mheA7ZuMG2ZiiAghnJofNUTuapKKP11VKu3ARUdfyHR3fhpBgtHLuzf2VKqr7XwXuGcA9YxqB6DGYeqmnqPeUfjboDyicJjCfAZevBVLqM4bixxZWGywwuEsXvHv5jBJGvb66DvMgmtjiaqVoC4gKZ6pS4phS7x1uYgfhUmxnjNEupSZKLggDRU7Wix9yCCb2ze2gUjdpUGq9kSxm9MrbGwPo3rqgQcNUa85ZyFWZGV8dRCcRVf5SMWcqZyXLag5gErLrJbpr5A4oRmNU",
"witnesses": [
"QmURFbtfc7RYE3YZyJ5bSXYFTqkVkXRiP7ZZoViJhNThL4",
"QmTYhCQ9p1HAWqamu6b3U5BGh5emUxXG2NtFGraWeoavYB",
"QmfNq5iBTb3YjVegi6xVFp4h2wHpn5K7JUBnXoePny8emT"
],
"witnessSignatures": [
"",
"",
""
]
},
"index": 16,
"verificationPageUrl": "http://127.0.0.1:18000?transactionHash=bffcd42431b1cfb96ad5611cb15b55fe92b43abe",
"dataType": "shanxi.taiyuan.xiaodian/tt2/3a382523-eba6-45c2-bb8f-cb9d94ce0116",
"dataTypeInfo": {
"name": "XXSensor"
}
}
验证结果矩阵
| 情况 | code (finalResult没必要,直接看是否为0) | 前端展示 | doidResolved (标识解析成功) | dataHashMatched (数据哈希匹配) | chainRecordMatched (区块链存证记录匹配) | message (前端展示) |
|---|---|---|---|---|---|---|
| doid解析不到 | DOIDNotFound | 错误提示页面 | false | empty | empty | 标识解析系统里查无此标识 |
| data hash不匹配 | DataHashMismatch | 表格 | true | false | empty | 数据哈希与标识解析系统不匹配 |
| chainHash不存在 | NotRecordedOnBdledger | 表格 | true | true | empty | 没有找到数据哈希对应的链上事务哈希 (还未上链) |
| 账本上未查到事务哈希 | NotFoundOnBdledger (异常) | 表格 | true | true | empty | 账本上未查到事务哈希 |
| merkelHash头没找到对应的merkelTree | MerkelTreeNotFound (异常) | 表格 | true | true | empty | 账本存证的事务异常,未包含默克尔树根 |
| merkelHashTree里没找到对应的dataHash | DataHashNotInMerkelTree (异常) | 表格 | true | true | empty | 默克尔树未包含数据哈希 |
| 全部成功 | 0 | 表格 | true | true | true | 验证成功 |
empty表示还没走到那个阶段,并不是失败,因此前端不显示勾或叉,直接不显示该行
Error codes
| code | message | Description |
|---|---|---|
| 0 | - | 正常返回 |
| 1 | DataTypeNotFound | 标识解析系统里查无此数据类型 |
| 2 | DOIDNotFound | 标识解析系统里查无此标识 |
| 3 | FailToAllocateDOID | 标识解析系统分配标识失败 |
| 4 | DataHashMismatch | 标识解析系统里的originalHash和dataHash不一致 |
| 5 | NotRecordedOnBdledger | 没有找到dataHash对应的ledgerHash(还未上链) |
| 6 | NotFoundOnBdledger | 找到了dataHash对应的ledgerHash,但是账本返回 not enough response |
| 7 | MerkelHashNotRecordedOnBdledger | 账本返回没找见merkelHash头 |
| 8 | MerkelTreeNotFound | merkelHash头没找到对应的merkelTree |
| 9 | DataHashNotInMerkelTree | merkelHashTree里没找到对应的dataHash |
| 10 | RepoNotFound | 标识解析系统里查无此Repo |
| 11 | IllegalToken | 非法token |
| 12 | PermissionDenied | 权限不足 |
| 13 | InnerError | 内部错误 |
getGlobalDOCount
查询所有仓库的DO总数
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=getGlobalDOCount&arg=&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=30460221008d0816b33e1a9dabaecfaa2a493a682cddfd1349e20cb0b531e40e262527928d022100b975f1f609e1378abca32ae0b7b06fcae38e52e5cfeaa0a64ea68f7b21fdb29a
返回结果示例
{
"count": 0
}
getDOCountByRepo
根据repo获取DO数量
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=getDOCountByRepo&arg={"repoId":"shanxi.taiyuan.xiaodian/tt1"}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=30460221009eebf485bf3d7bc3e4d536f2347934cf76a6eabbbeafa550f351b490178ffeb4022100c3ef2cb9f618f39863da03b0d23e9d2d4fb026b3b21d240e5e2e0530f7e06984
http post示例:
{
"repoId": "shanxi.taiyuan.xiaodian/tt1"
}
返回结果示例
{
"count":0
}
getRepoDOCountRanking
DO数量降序排序,取前若干个
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=getRepoDOCountRanking&arg={"repoCount":5}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=3046022100f61517835efa3fba8733fd7cd93bf94bc4d042415a539763392280b5abc893dc022100cb9ea2cb4abdf1afa400f076dbaabaea30e86c348c8986e4e780c3e134f910e4
http post示例:
{
"repoCount": 5
}
返回结果示例
{
"list":[
{"repoId": "shanxi.taiyuan.xiaodian/tt1", "count": 5},
{"repoId": "shanxi.taiyuan.xiaodian/tt2", "count": 3}
]
}
getRecentVerificationFailures
获取若干个最近的错误
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=getRecentVerificationFailures&arg={"count":5}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=30440220513233872920b1451ba69bfa7130a56473c05f2fb8c9c0be4efec59e4c29a96702206dc0c459f15f3d3237bd0c69f799e6da4a663ee19a6e4d5a8c5b8a086c365f1f
http post示例:
{
"count": 5
}
返回结果示例
{
"list": [{
"doid": "shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7",
"repoId": "shanxi.taiyuan.xiaodian/tt2",
"repoName": "ttttt2",
"timestamp": 1670827419003,
"errorCode": {
"code": 6,
"message": "找到了dataHash对应的ledgerHash,但是账本返回 not enough response"
}
}, {
"doid": "shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7",
"repoId": "shanxi.taiyuan.xiaodian/tt2",
"repoName": "ttttt2",
"timestamp": 1670827291607,
"errorCode": {
"code": 6,
"message": "找到了dataHash对应的ledgerHash,但是账本返回 not enough response"
}
}, {
"doid": "shanxi.taiyuan.xiaodian/tt2/2497cf0a-03b6-425e-96d8-a3e3c81c13e7",
"repoId": "shanxi.taiyuan.xiaodian/tt2",
"repoName": "ttttt2",
"timestamp": 1670826936049,
"errorCode": {
"code": 6,
"message": "找到了dataHash对应的ledgerHash,但是账本返回 not enough response"
}
}, {
"doid": "shanxi.taiyuan.xiaodian/tt1/f39cefeb-1e40-40af-9d1e-46b31a6d051b",
"repoId": "shanxi.taiyuan.xiaodian/tt1",
"repoName": "name1",
"timestamp": 1670826877822,
"errorCode": {
"code": 4,
"message": "标识解析系统里的originalHash和dataHash不一致"
}
}, {
"doid": "shanxi.taiyuan.xiaodian/tt1/fe369076-15e9-48aa-ad56-eff0aec3cfa9",
"repoId": "shanxi.taiyuan.xiaodian/tt1",
"repoName": "name1",
"timestamp": 1670826865632,
"errorCode": {
"code": 5,
"message": "没有找到dataHash对应的ledgerHash(还未上链)"
}
}]
}
resolveVerificationFailure
\ TODO resolve的效果是清除错误日志? 目前DB不支持这个操作
输入参数示例
http get示例:
http://39.104.208.223:18010/SCIDE/SCManager?action=executeContract&contractID=ShanxiProxy&operation=resolveVerificationFailure&arg={"doid":"shanxi.taiyuan.xiaodian/tt1/fe369076-15e9-48aa-ad56-eff0aec3cfa9"}&pubkey=04303718771b9323c204e607639f14469f9a94e55b0964a408ad3b3864b0493b645d7070da0d550f0c54b934275a8e88dedc3024467b0566db5c1108b1baeaae27&signature=304402207577adf56db9f1707b84268d8dea8c367a0f19446377b4781ee45e5551e01f1802204cf6513b74ba28771e546ccada4c89e41e8702b8708352ec3c8521d2ba8be3c8
http post示例:
{
"doid":"shanxi.taiyuan.xiaodian/tt1/fe369076-15e9-48aa-ad56-eff0aec3cfa9"
}
返回结果示例
{
"data": [{
"doid": "shanxi.taiyuan.xiaodian/tt1/fe369076-15e9-48aa-ad56-eff0aec3cfa9",
"repoId": "shanxi.taiyuan.xiaodian/tt1",
"repoName": "name1",
"timestamp": 1670814861037,
"errorCode": {
"code": 5,
"message": "没有找到dataHash对应的ledgerHash(还未上链)"
}
}, {
"doid": "shanxi.taiyuan.xiaodian/tt1/fe369076-15e9-48aa-ad56-eff0aec3cfa9",
"repoId": "shanxi.taiyuan.xiaodian/tt1",
"repoName": "name1",
"timestamp": 1670814861038,
"errorCode": {
"code": 5,
"message": "没有找到dataHash对应的ledgerHash(还未上链)"
}
}]
}