diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/Blacklist.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/Blacklist.sol new file mode 100644 index 000000000..752a7b65b --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/Blacklist.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: SimPL-2.0 +pragma solidity>=0.4.24 <0.6.11; +pragma experimental ABIEncoderV2; + +import "./Table.sol"; +import "./DataFormat.sol"; + +contract Blacklist is DataFormat{ + event insertResult(int256 count); + event updateResult(int256 count); + event removeResult(int256 count); + + + TableFactory tableFactory; + + string constant BLACK_LIST_TABLE_NAME = "blacklist"; + + string[] allUserId; + + constructor() public { + // Set tableFactory address + tableFactory = TableFactory(0x1001); + + // + tableFactory.createTable(BLACK_LIST_TABLE_NAME, "userId", "userState"); + } + + + // 初始化用户账户状态表; 用户状态默认值 1 : 正常账户 + // 参数数据格式(userId) 返回值(插入数据条数) + function initUserState(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(BLACK_LIST_TABLE_NAME); + Entry entry = table.newEntry(); + + // Set Value + entry.set("userId", userId); + entry.set("userState", "1"); + + int256 count = table.insert(userId, entry); + emit insertResult(count); + + return count; + } + + // 更新用户账户状态, 正常 -> 拉黑 + // 参数数据格式(userId) 返回值(更新数据条数) + function changeUserState(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(BLACK_LIST_TABLE_NAME); + Entry entry = table.newEntry(); + + // 记录黑名单账户 + allUserId.push(userId); + + //已完成状态 0 + entry.set("userState", "0"); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + return count; + } + + + // 获得用户账户状态 + // 参数数据格式(userId) 返回值("1" -> 正常;"0" -> 拉黑) + function getUserState(string memory userId) + public + view + returns(string memory) + { + Table table = tableFactory.openTable(BLACK_LIST_TABLE_NAME); + string memory userState; + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entries entries = table.select(userId, condition); + if(0 == entries.size()) + { + return("该ID不存在"); + } + + Entry entry = entries.get(0); + + userState= entry.getString("userState"); + + return(userState); + } + + // 获取所有黑名单账户 + function getAllBlacklistUser() + public + view + returns(string[] memory, uint256) + { + uint256 blacklistNum = allUserId.length; + return(allUserId, blacklistNum); + } +} \ No newline at end of file diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/DataFormat.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/DataFormat.sol new file mode 100644 index 000000000..293c852f1 --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/DataFormat.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: SimPL-2.0 +pragma solidity>=0.4.24 <0.6.11; + +contract DataFormat{ + // string matching + function strMatching(string memory v1, string memory v2) + internal + pure + returns(bool) + { + return keccak256(bytes(v1)) == keccak256(bytes(v2)); + } + + // string catenate + function strCat(string memory v1, string memory v2) + internal + pure + returns (string memory){ + bytes memory v1Bytes = bytes(v1); + bytes memory v2Bytes = bytes(v2); + + string memory result = new string(v1Bytes.length + v2Bytes.length); + bytes memory resultBytes = bytes(result); + + uint k = 0; + uint i = 0; + for (i = 0; i < v1Bytes.length; i++){ + resultBytes[k++] = v1Bytes[i]; + } + for (i = 0; i < v2Bytes.length; i++) { + resultBytes[k++] = v2Bytes[i]; + } + + return string(resultBytes); + + } + + + function strCatWithSymbol(string memory v1, string memory v2) + internal + pure + returns (string memory) + { + if(true == strMatching("", v1)){ + v1 = v2; + } + else{ + v1 = strCat(v1, ","); + v1 = strCat(v1, v2); + } + return v1; + } +} \ No newline at end of file diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/FundingUser.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/FundingUser.sol new file mode 100644 index 000000000..c1bbf2159 --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/FundingUser.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: SimPL-2.0 +pragma solidity>=0.4.24 <0.6.11; +pragma experimental ABIEncoderV2; + +import "./Table.sol"; +import "./DataFormat.sol"; + +contract FundingUser is DataFormat{ + event insertResult(int256 count); + event updateResult(int256 count); + event removeResult(int256 count); + + TableFactory tableFactory; + + string constant FUNDING_USER_TABLE_NAME = "fundingUser"; + + constructor() public { + // Set tableFactory address + tableFactory = TableFactory(0x1001); + + //资助用户(allFundingNumStr, 对应allFundingUser的金额) + tableFactory.createTable(FUNDING_USER_TABLE_NAME, "userId", "allFundingUser, allFundingNumStr, fundingTime, score"); + } + + // 初始化用户资助表 + // 参数数据格式(userId) 返回值(插入数据条数) + function initFundingInfo(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(FUNDING_USER_TABLE_NAME); + Entry entry = table.newEntry(); + + // Set Value + entry.set("userId", userId); + entry.set("allFundingUser", ""); + entry.set("allFundingNumStr", ""); + entry.set("fundingTime", ""); + entry.set("score", int256(0)); + + int256 count = table.insert(userId, entry); + emit insertResult(count); + + return count; + } + + // 用户进行资助后,更新资助信息 + // 参数数据格式(userId,资助金额int,资助对象Id,资助金额string,资助时间) 返回值(更新数据条数) + // 测试数据 1."2" "200" "伍羽放" "200" "2020-10-12" 2."2" "500" "赵双" "500" "2021-10-12" + function updateFundingInfo(string memory userId, int256 fundsNumInt, string memory fundingId, string memory fundsNumStr, string memory fundingTime) + public + returns(int256) + { + Table table = tableFactory.openTable(FUNDING_USER_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + // Get current fundsSum + Entry entry = table.select(userId, condition).get(0); + + //资助者对象Id拼接 + string memory allFundingUser = entry.getString("allFundingUser"); + allFundingUser = strCatWithSymbol(allFundingUser, fundingId); + + // 每名资助者的金额 + // 资助金额拼接 + string memory allFundingNumStr = entry.getString("allFundingNumStr"); + allFundingNumStr = strCatWithSymbol(allFundingNumStr, fundsNumStr); + + //资助者时间拼接 + string memory allFundingTime = entry.getString("fundingTime"); + allFundingTime = strCatWithSymbol(allFundingTime, fundingTime); + + int256 score = entry.getInt("score"); + score = score + (fundsNumInt * 10); + + entry.set("allFundingUser", allFundingUser); + entry.set("allFundingNumStr", allFundingNumStr); + entry.set("fundingTime", allFundingTime); + entry.set("score", score); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + + return count; + } + + // 获得资助者当前资助数据 + // 参数数据格式(userId) 返回值(所有资助对象Id,所有资助对象金额,对应资助时间,总积分) + function getUserFundingInfo(string memory userId) + public + view + returns(string memory, string memory, string memory, int256) + { + Table table = tableFactory.openTable(FUNDING_USER_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entries entries = table.select(userId, condition); + if(0 == entries.size()) + { + return("","","",-1); + } + + Entry entry = entries.get(0); + //allFundingUser, allFundingNumStr, fundingTime, score + string memory allFundingUser = entry.getString("allFundingUser"); + string memory allFundingNumStr = entry.getString("allFundingNumStr"); + string memory fundingTime = entry.getString("fundingTime"); + int256 score = entry.getInt("score"); + + return(allFundingUser, allFundingNumStr, fundingTime, score); + } + +} \ No newline at end of file diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/FundsApplicationCipher.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/FundsApplicationCipher.sol new file mode 100644 index 000000000..f7c0375b5 --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/FundsApplicationCipher.sol @@ -0,0 +1,499 @@ +// SPDX-License-Identifier: SimPL-2.0 +pragma solidity>=0.4.24 <0.6.11; +pragma experimental ABIEncoderV2; + +import "./Table.sol"; +import "./DataFormat.sol"; + +contract FundsApplicationCipher is DataFormat{ + event insertResult(int256 count); + event updateResult(int256 count); + event removeResult(int256 count); + + TableFactory tableFactory; + + string constant APP_TABLE_NAME = "fundsApplication"; + string constant FUNDS_TABLE_NAME = "fundsCompute"; + string constant WITHDRAWAL_TABLE_NAME = "fundsWithdrawal"; + string constant DETAIL_TABLE_NAME = "fundsDetail"; + + string[] private allUserId; + //记录当前用户申请数 + uint256 private flag = 0; + //记录allUserId申请内存数 + uint256 private insertNum = 0; + + constructor() public{ + // Set tableFactory address + tableFactory = TableFactory(0x1001); + //资助申请表,fundsState默认为1 + tableFactory.createTable(APP_TABLE_NAME, "userId", "certificateData,certificateTemplate,fundsState"); + //资助统计表 + tableFactory.createTable(FUNDS_TABLE_NAME, "userId", "fundsSum, fundingId, fundingNum, fundingTime"); + //资助提现表 + tableFactory.createTable(WITHDRAWAL_TABLE_NAME, "userId", "withdrawalAmount, balance, withdrawalSum"); + //提现明细表 + tableFactory.createTable(DETAIL_TABLE_NAME, "userId", "costSum, detail, costStr"); + } + + // 资助申请块插入记录 + // 参数数据格式(userId, 验证密文,验证临时数据) 返回值(插入记录条数) + //"1" "asdfasdfdasfdas" "asdfasdhfasi" + //"2" "zxcvuioios" zxcvupoiui" + //"3" "qwerqwer" qweioruo" + function insertFundsInfo(string memory userId, string memory certificateData, string memory certificateTemplate) + public + returns(int256) + { + Table table = tableFactory.openTable(APP_TABLE_NAME); + + Entry entry = table.newEntry(); + int256 count; + // Set Value + entry.set("userId", userId); + entry.set("certificateData", certificateData); + entry.set("certificateTemplate", certificateTemplate); + //默认值 1 : 筹款未结束 + entry.set("fundsState", "1"); + + + for(uint i = 0; i < insertNum; i++) + { + if(strMatching(allUserId[i], "") == true) + { + allUserId[i] = userId; + flag = flag + 1; + count = table.insert(userId, entry); + emit insertResult(count); + return count; + } + } + allUserId.push(userId); + insertNum = insertNum + 1; + flag = flag + 1; + + count = table.insert(userId, entry); + emit insertResult(count); + + return count; + } + + // 获得求助者的求助信息 + // 参数数据格式(userId) 返回值(用户信息) + function getUserApplicationInfo(string memory userId) + public + view + returns(string memory, string memory, string memory, string memory) + { + Table table = tableFactory.openTable(APP_TABLE_NAME); + string memory certificateData; + string memory certificateTemplate; + string memory fundsState; + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entries entries = table.select(userId, condition); + if(0 == entries.size()) + { + return("该ID不存在", "", "", ""); + } + + Entry entry = entries.get(0); + + certificateData= entry.getString("certificateData"); + certificateTemplate= entry.getString("certificateTemplate"); + fundsState = entry.getString("fundsState"); + + return(userId, certificateData, certificateTemplate, fundsState); + } + + // 更新用户个人信息 + // 参数数据格式(userId,验证密文,验证临时数据) 返回值(更新数据条数) + function updateApplication(string memory userId, string memory certificateData, string memory certificateTemplate) + public + returns(int256) + { + Table table = tableFactory.openTable(APP_TABLE_NAME); + Entry entry = table.newEntry(); + + entry.set("certificateData", certificateData); + entry.set("certificateTemplate", certificateTemplate); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + + return count; + } + + // 更新用户筹款状态, 未完成 -> 已完成 + // 参数数据格式(userId) 返回值(更新数据条数) + function changeFundsState(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(APP_TABLE_NAME); + Entry entry = table.newEntry(); + + //已完成状态 0 + entry.set("fundsState", "0"); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + return count; + } + + + /**************************************资助统计块**************************************/ + // 初始化申请者统计表 + // 参数数据格式(userId) 返回值(插入数据条数) + function initFundsCompute(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(FUNDS_TABLE_NAME); + + Entry entry = table.newEntry(); + // Set Value + entry.set("userId", userId); + entry.set("fundsSum", int256(0)); + entry.set("fundingId", ""); + entry.set("fundingNum", ""); + entry.set("fundingTime", ""); + + int256 count = table.insert(userId, entry); + emit insertResult(count); + + return count; + } + + + // 用户进行资助后,更新筹款金额 + // 参数数据格式(userId,资助金额int,资助者Id,资助金额string,资助时间) 返回值(更新数据条数) + // 测试数据 1."1" "200" "伍羽放" "200" "2020-10-12" 2."1" "500" "赵双" "500" "2021-10-12" + function updateFundsCompute(string memory userId, int256 fundsSum, string memory fundingId, string memory fundsNum, string memory fundingTime) + public + returns(int256) + { + Table table = tableFactory.openTable(FUNDS_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + // Get current fundsSum + Entry entry = table.select(userId, condition).get(0); + + // 每名资助者的金额 + string memory fundingNum = entry.getString("fundingNum"); + fundingNum = strCatWithSymbol(fundingNum, fundsNum); + + entry.set("fundingNum", fundingNum); + + fundsSum += entry.getInt("fundsSum"); + + //资助者ID拼接 + string memory allFundingId = entry.getString("fundingId"); + allFundingId = strCatWithSymbol(allFundingId, fundingId); + + //资助者时间拼接 + string memory allFundingTime = entry.getString("fundingTime"); + allFundingTime = strCatWithSymbol(allFundingTime, fundingTime); + + entry.set("fundsSum", fundsSum); + entry.set("fundingId", allFundingId); + entry.set("fundingTime", allFundingTime); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + + return count; + } + + // 获得求助者当前筹款数额 + // 参数数据格式(userId) 返回值(筹款金额,资助者ID,对应资助金额,资助时间) + function getUserFundsInfo(string memory userId) + public + view + returns(int256, string memory, string memory, string memory) + { + Table table = tableFactory.openTable(FUNDS_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entries entries = table.select(userId, condition); + if(0 == entries.size()) + { + return(-1, "该用户不存在", "", ""); + } + + Entry entry = entries.get(0); + + int256 fundsSum = entry.getInt("fundsSum"); + string memory allFundingId = entry.getString("fundingId"); + string memory fundsNum = entry.getString("fundingNum"); + string memory fundingTime = entry.getString("fundingTime"); + + return(fundsSum, allFundingId, fundsNum, fundingTime); + } + + +/**************************************资助提现块**************************************/ + // 初始化申请者提现表 + // 参数数据格式(userId) 返回值(插入数据条数) + function initFundsWithdrawal(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(WITHDRAWAL_TABLE_NAME); + + Entry entry = table.newEntry(); + // Set Value + entry.set("userId", userId); + entry.set("withdrawalAmount", int256(0)); + entry.set("balance", int256(0)); + entry.set("withdrawalSum", int256(0)); + + int256 count = table.insert(userId, entry); + emit insertResult(count); + + return count; + } + + // 用户进行提现后,更新提现表 + // 参数数据格式(userId,提现金额) 返回值(更新数据条数) + // 测试数据 1."1" "50" 2."1" "20" + function updateFundsWithdrawal(string memory userId, int256 withdrawalAmount) + public + returns(int256) + { + Table table = tableFactory.openTable(WITHDRAWAL_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + // Get current fundsSum + Entry entry = table.select(userId, condition).get(0); + + entry.set("withdrawalAmount", withdrawalAmount); + int256 withdrawalSum = entry.getInt("withdrawalSum") + withdrawalAmount; + + int256 fundsSum; + (fundsSum,,,) = getUserFundsInfo(userId); + + int256 balance = fundsSum - withdrawalSum; + + entry.set("balance", balance); + entry.set("withdrawalSum", withdrawalSum); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + + return count; + } + + // 获得求助者当前提现数据 + // 参数数据格式(userId) 返回值(上次提现金额,剩余金额,提现金额总数) + function getUserFundsWithdrawal(string memory userId) + public + view + returns(int256, int256, int256) + { + Table table = tableFactory.openTable(WITHDRAWAL_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entries entries = table.select(userId, condition); + if(0 == entries.size()) + { + return(-1, -1, -1); + } + + Entry entry = entries.get(0); + if(0 == entry.getInt("withdrawalAmount")) + { + int256 initBalance; + (initBalance,,,) = getUserFundsInfo(userId); + return(0, initBalance, 0); + } + + + int256 withdrawalAmount = entry.getInt("withdrawalAmount"); + int256 balance = entry.getInt("balance"); + int256 withdrawalSum = entry.getInt("withdrawalSum"); + + return(withdrawalAmount, balance, withdrawalSum); + } + +/**************************************提现明细块**************************************/ + // 初始化申请者明细表 + // 参数数据格式(userId) 返回值(插入数据条数) + function initCostDetail(string memory userId) + public + returns(int256) + { + Table table = tableFactory.openTable(DETAIL_TABLE_NAME); + + Entry entry = table.newEntry(); + // Set Value + entry.set("userId", userId); + entry.set("costSum", int256(0)); + entry.set("detail", ""); + entry.set("costStr", ""); + + int256 count = table.insert(userId, entry); + emit insertResult(count); + + return count; + } + + // 用户提交明细后,更新明细表 + // 参数数据格式(userId,使用金额Int,使用明细, 使用金额string) 返回值(更新数据条数) + // 测试数据 1."1" "20" "花钱吃麦当劳" "20" 2."1" "40" "花钱吃第二顿麦当劳" "40" + function updateCostDetail(string memory userId, int256 cost, string memory detail, string memory costStr) + public + returns(int256) + { + Table table = tableFactory.openTable(DETAIL_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entry entry = table.select(userId, condition).get(0); + + cost += entry.getInt("costSum"); + + string memory allDetail = entry.getString("detail"); + allDetail = strCatWithSymbol(allDetail, detail); + + string memory allCostStr = entry.getString("costStr"); + allCostStr = strCatWithSymbol(allCostStr, costStr); + + entry.set("costSum", cost); + entry.set("detail", allDetail); + entry.set("costStr", allCostStr); + + int256 count = table.update(userId, entry, condition); + emit updateResult(count); + + return count; + } + + // 获得用户当前明细 + // 参数数据格式(userId) 返回值(使用总金额,使用明细,对应使用金额) + function getUserCostDetail(string memory userId) + public + view + returns(int256, string memory, string memory) + { + Table table = tableFactory.openTable(DETAIL_TABLE_NAME); + + Condition condition = table.newCondition(); + condition.EQ("userId", userId); + + Entries entries = table.select(userId, condition); + if(0 == entries.size()) + { + return(-1, "该ID不存在", "该ID不存在"); + } + + Entry entry = entries.get(0); + + int256 costSum = entry.getInt("costSum"); + string memory detail = entry.getString("detail"); + string memory costStr = entry.getString("costStr"); + + return(costSum, detail, costStr); + } + +/**************************************其余接口**************************************/ + // 删除用户求助信息 + // 参数数据格式(userId) 返回值(删除数据条数) + function removeAll(string memory userId) + public + returns (int256) + { + Table table1 = tableFactory.openTable(APP_TABLE_NAME); + Condition condition = table1.newCondition(); + condition.EQ("userId", userId); + + int256 count = table1.remove(userId, condition); + + Table table2 = tableFactory.openTable(FUNDS_TABLE_NAME); + count += table2.remove(userId, condition); + + Table table3 = tableFactory.openTable(WITHDRAWAL_TABLE_NAME); + count += table3.remove(userId, condition); + + Table table4 = tableFactory.openTable(DETAIL_TABLE_NAME); + count += table4.remove(userId, condition); + + for(uint256 i = 0; i < flag; i++) + { + if(strMatching(allUserId[i], userId) == true) + { + for(uint256 j = i; j < flag - 1 ; j++) + { + allUserId[j] = allUserId[j + 1]; + } + + allUserId[flag - 1] = ""; + flag = flag - 1; + //removeNum = removeNum + 1; + + break; + } + + } + + + emit removeResult(count); + + return count; + } + + // 获取全部求助信息 + // 返回值(string[]) (userId, certificateData, certificateTemplate, fundsState):用`分隔 + function getAllUserApplication() + public + view + returns(string[] memory) + { + string[] memory allUserInfo = new string[](flag); + Table table = tableFactory.openTable(APP_TABLE_NAME); + Condition condition = table.newCondition(); + + for(uint256 i = 0; i < flag; i++) + { + condition.EQ("userId", allUserId[i]); + Entries entries = table.select(allUserId[i], condition); + if(0 == entries.size()) + { + continue; + } + + Entry entry = entries.get(0); + + string memory userId = entry.getString("userId"); + string memory certificateData = entry.getString("certificateData"); + string memory certificateTemplate = entry.getString("certificateTemplate"); + string memory fundsState = entry.getString("fundsState"); + allUserInfo[i] = strCat(strCat(strCat(strCat(strCat(strCat(userId, "`"), certificateData), "`"),certificateTemplate), "`"), fundsState); + } + return(allUserInfo); + } + + // 查看当前用户数申请数 和 全部用户Id + function get() public view returns(uint, string[] memory) + { + return(flag, allUserId); + } + +} \ No newline at end of file diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/Medical.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/Medical.sol new file mode 100644 index 000000000..f0844a66d --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/Medical.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: SimPL-2.0 +pragma solidity>=0.4.24 <0.6.11; +pragma experimental ABIEncoderV2; + +import "./Table.sol"; +import "./DataFormat.sol"; + +contract Medical is DataFormat{ + event insertResult(int256 count); + event updateResult(int256 count); + + TableFactory tableFactory; + + string constant MEIDICAL_RECORD = "medicalRecord"; + + constructor() public { + tableFactory = TableFactory(0x1001); + + tableFactory.createTable(MEIDICAL_RECORD, "idNumber", "userName, userMedicalRecord"); + + Table table = tableFactory.openTable(MEIDICAL_RECORD); + Entry entry_1 = table.newEntry(); + Entry entry_2 = table.newEntry(); + Entry entry_3 = table.newEntry(); + Entry entry_4 = table.newEntry(); + Entry entry_5 = table.newEntry(); + + entry_1.set("idNumber", "110108199912121212"); + entry_1.set("userName", "Tom"); + entry_1.set("userMedicalRecord", "心脑血管-心肌梗死"); + + entry_2.set("idNumber", "410527199901010101"); + entry_2.set("userName", "Jerry"); + entry_2.set("userMedicalRecord", "感染病-病毒性肝炎"); + + entry_3.set("idNumber", "130528199902020202"); + entry_3.set("userName", "Bob"); + entry_3.set("userMedicalRecord", "血液恶性病-白血病"); + + entry_4.set("idNumber", "130224199903030303"); + entry_4.set("userName", "Kitty"); + entry_4.set("userMedicalRecord", "肿瘤-恶性肿瘤"); + + entry_5.set("idNumber", "452427199904040404"); + entry_5.set("userName", "Sammy"); + entry_5.set("userMedicalRecord", "心脑血管-冠心病"); + + table.insert("110108199912121212", entry_1); + table.insert("410527199901010101", entry_2); + table.insert("130528199902020202", entry_3); + table.insert("130224199903030303", entry_4); + table.insert("452427199904040404", entry_5); + } + + // 插入病历信息 + // 参数(身份证号,姓名,病历信息) + function insertMeidicalRecord(string memory idNumber, string memory userName, string memory userMedicalRecord) + public + returns(int256) + { + Table table = tableFactory.openTable(MEIDICAL_RECORD); + Entry entry = table.newEntry(); + int256 count; + + // Set Value + entry.set("idNumber", idNumber); + entry.set("userName", userName); + entry.set("userMedicalRecord", userMedicalRecord); + + count = table.insert(idNumber, entry); + emit insertResult(count); + + return count; + } + + // 查询用户病历信息 + // 参数(身份证号, 姓名, 病历信息) 返回值(bool, 错误信息) + function getUserMedicalRecord(string memory idNumber, string memory userName, string memory userMedicalRecord) + public + view + returns(bool, string memory) + { + Table table = tableFactory.openTable(MEIDICAL_RECORD); + + Condition condition = table.newCondition(); + condition.EQ("idNumber", idNumber); + + string memory userNameTemp; + string memory userMedicalRecordTemp; + + Entries entries = table.select(idNumber, condition); + if(0 == entries.size()) + { + return(false, "用户ID出错"); + } + + Entry entry = entries.get(0); + + userNameTemp = entry.getString("userName"); + userMedicalRecordTemp = entry.getString("userMedicalRecord"); + if(strMatching(userNameTemp, userName) != true) + { + return(false, "姓名错误"); + } + if(strMatching(userMedicalRecordTemp, userMedicalRecord) != true) + { + return(false, "病历信息错误"); + } + + return(true, ""); + } +} \ No newline at end of file diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/README.md b/2021-Shenzhen-FinTechathon3/Contracts/solidity/README.md new file mode 100644 index 000000000..c4e00aca8 --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/README.md @@ -0,0 +1,209 @@ +# 合约接口说明文档 +主要合约包括: + +1. FundsApplicationCipher合约:存储用户的求助信息,用户筹款信息以及多种方法。 +2. FundingUser合约:存储用户资助信息。 +3. Blacklist合约:存储黑名单用户。 +4. Medical合约:存储用户病历信息。 +5. UserAssetInfo合约:存储用户房车产信息。 +6. DataFormat合约:格式化合约。 + +## FundsApplicationCipher合约 +### insertFundsInfo +插入用户求助信息 +参数: +userId: String 用户id +certificateData: String 密文 +certificateTemplate: String 密文模板 +返回值: + 无 +### getUserApplicationInfo +查询用户求助信息 +参数: +userId: String 用户id +返回值: +userId: String 用户id +certificateData: String 密文 +certificateTemplate: String 密文模板 +fundState: String 筹款状态 +### updateApplication +更新用户个人信息 +参数: +userId: String 用户id +certificateData: String 密文 +certificateTemplate: String 密文模板 +返回值: + 无 +### changeFundsState +更改用户筹款状态 +参数: +userId: String 用户id +返回值: + 无 +### initFundsCompute +初始化用户筹款统计表 +参数: +userId: String 用户id +返回值: + 无 +### updateFundsCompute +更新用户筹款信息 +参数: +userId: String 用户id +fundSum: int 资助金额 +fundingId: String 资助人Id +fundsNum: String 资助金额 +fundingTime: String 资助时间 +返回值: + 无 +### getUserFundsInfo +获取求助者当前筹款金额 +参数: +userId: String 用户id +返回值: +fundSum: int 资助金额 +fundingId: String 资助人Id +fundsNum: String 资助金额 +fundingTime: String 资助时间 +### initFundsWithdrawl +初始化申请者提现表 +参数: +userId: String 用户id +返回值: + 无 +### updateFundsWithdrawal +更新用户提现信息 +参数: +userId: String 用户id +withdrawalAmount: int 提款金额 +返回值: + 无 +### getUserFundsWithdrawal +获取用户提现数据 +参数: +userId: String 用户id +返回值: +withdrawalAmount: int 上次取款金额 +balance: int 余额 +withdrawalSum: int 取款总额 +### initCostDetail +初始化用户花费明细表 +参数: +userId: String 用户id +withdrawalAmount: int 提款金额 +返回值: + 无 +### updateCostDetail +更新用户花费明细 +参数: +userId: String 用户id +cost: int 花费金额 +detail: String 花费明细 +costStr: String 花费金额 +返回值: + 无 +### getUserCostDetail +获取用户当前花费明细 +参数: +userId: String 用户id +返回值: +costSum: int 花费总金额 +detai: String 花费明细 +costStr: String 花费金额 +### removeAll +移除用户求助信息 +参数: +无 +返回值: +无 +### getAllUserApplication +获取全部用户求助信息 +参数: +无 +返回值: +无 + +## FundingUser合约 + +## initFundingInfo +初始化用户资助表 +参数: +userId: String 用户id +返回值: + 无 +## updateFundingInfo +更新用户资助信息 +参数: +userId: String 用户id +fundsNumInt: int 资助金额 +fundingId: String 捐款id +fundsNumStr: String 资助金额 +fundingTime: String 捐款时间 +返回值: + 无 +## getUserFundingInfo +获取资助者当前资助数据 +参数: +userId: String 用户id +返回值: +allFundingUser:String 资助id +allFundingNumStr:String 资助金额 +fundingTime:String 资助时间 +score:爱心值 +## Blacklist合约 + +### initUserState +初始化用户状态表 +参数: +userId: String 用户id +返回值: + 无 +### changeUserState +更改用户账户状态 +参数: +userId: String 用户id +返回值: + 无 +### getUserState +获取用户账户状态 +参数: +userId: String 用户id +返回值: +userState: String 用户状态 +## Medical合约 +### insertMedicalRecord +插入病历信息 +参数: +userId: String 用户id +userName:String 用户名字 +userMedicalRecord:String 用户病例 +返回值: + 无 +### getUserMedicalRecord +验证用户病历信息 +参数: +userId: String 用户id +返回值: +result: boolean 验证结果 +## UserAssetInfo合约 + +### insertUserAssetInfo +插入用户资产信息 +参数: +userId: String 用户id +userName:String 用户名字 +propertyValue:String 房产信息 +carValue:String 车产信息 +返回值: + 无 +### getUserAssetInfo +验证用户资产信息 +参数: +userId: String 用户id +userName:String 用户名字 +propertyValue:String 房产信息 +carValue:String 车产信息 +返回值: +result: boolean 验证结果 + + diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/Table.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/Table.sol new file mode 100644 index 000000000..adaac40a9 --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/Table.sol @@ -0,0 +1,67 @@ + +contract TableFactory { + function openTable(string memory) public view returns (Table) {} //open table + function createTable(string memory, string memory, string memory) public returns (int256) {} //create table +} + +//select condition +contract Condition { + function EQ(string memory, int256) public view{} + function EQ(string memory, string memory) public view{} + + function NE(string memory, int256) public view{} + function NE(string memory, string memory) public view{} + + function GT(string memory, int256) public view{} + function GE(string memory, int256) public view{} + + function LT(string memory, int256) public view{} + function LE(string memory, int256) public view{} + + function limit(int256) public view{} + function limit(int256, int256) public view{} +} + +//one record +contract Entry { + function getInt(string memory) public view returns (int256) {} + function getUInt(string memory) public view returns (uint256) {} + function getAddress(string memory) public view returns (address) {} + function getBytes64(string memory) public view returns (bytes1[64] memory) {} + function getBytes32(string memory) public view returns (bytes32) {} + function getString(string memory) public view returns (string memory) {} + + function set(string memory, int256) public {} + function set(string memory, uint256) public {} + function set(string memory, string memory) public {} + function set(string memory, address) public {} +} + +//record sets +contract Entries { + function get(int256) public view returns (Entry) {} + function size() public view returns (int256) {} +} + +//Table main contract +contract Table { + function select(string memory, Condition) public view returns (Entries) {} + function insert(string memory, Entry) public returns (int256) {} + function update(string memory, Entry, Condition) public returns (int256) {} + function remove(string memory, Condition) public returns (int256) {} + + function newEntry() public view returns (Entry) {} + function newCondition() public view returns (Condition) {} +} + +contract KVTableFactory { + function openTable(string memory) public view returns (KVTable) {} + function createTable(string memory, string memory, string memory) public returns (int256) {} +} + +//KVTable per permiary key has only one Entry +contract KVTable { + function get(string memory) public view returns (bool, Entry) {} + function set(string memory, Entry) public returns (int256) {} + function newEntry() public view returns (Entry) {} +} diff --git a/2021-Shenzhen-FinTechathon3/Contracts/solidity/UserAssetInfo.sol b/2021-Shenzhen-FinTechathon3/Contracts/solidity/UserAssetInfo.sol new file mode 100644 index 000000000..75abf230b --- /dev/null +++ b/2021-Shenzhen-FinTechathon3/Contracts/solidity/UserAssetInfo.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: SimPL-2.0 +pragma solidity>=0.4.24 <0.6.11; +pragma experimental ABIEncoderV2; + +import "./Table.sol"; +import "./DataFormat.sol"; + +contract UserAssetInfo is DataFormat{ + event insertResult(int256 count); + event updateResult(int256 count); + + TableFactory tableFactory; + + string constant ASSET_INFO = "assetInfo"; + + constructor() public { + tableFactory = TableFactory(0x1001); + + tableFactory.createTable(ASSET_INFO, "idNumber", "userName, propertyValue, carValue"); + + Table table = tableFactory.openTable(ASSET_INFO); + Entry entry_1 = table.newEntry(); + Entry entry_2 = table.newEntry(); + Entry entry_3 = table.newEntry(); + Entry entry_4 = table.newEntry(); + Entry entry_5 = table.newEntry(); + + entry_1.set("idNumber", "110108199912121212"); + entry_1.set("userName", "Tom"); + entry_1.set("propertyValue", int256(8000)); + entry_1.set("carValue", int256(2000)); + + entry_2.set("idNumber", "410527199901010101"); + entry_2.set("userName", "Jerry"); + entry_2.set("propertyValue", int256(10000)); + entry_2.set("carValue", int256(6000)); + + entry_3.set("idNumber", "130528199902020202"); + entry_3.set("userName", "Bob"); + entry_3.set("propertyValue", int256(50000)); + entry_3.set("carValue", int256(20000)); + + entry_4.set("idNumber", "130224199903030303"); + entry_4.set("userName", "Kitty"); + entry_4.set("propertyValue", int256(40000)); + entry_4.set("carValue", int256(30000)); + + entry_5.set("idNumber", "452427199904040404"); + entry_5.set("userName", "Sammy"); + entry_5.set("propertyValue", int256(30000)); + entry_5.set("carValue", int256(10000)); + + table.insert("110108199912121212", entry_1); + table.insert("410527199901010101", entry_2); + table.insert("130528199902020202", entry_3); + table.insert("130224199903030303", entry_4); + table.insert("452427199904040404", entry_5); + } + + // 插入资产信息 + // 参数(身份证号,姓名,房产,车产) + function insertUserAssetInfo(string memory idNumber, string memory userName, int256 propertyValue, int256 carValue) + public + returns(int256) + { + Table table = tableFactory.openTable(ASSET_INFO); + Entry entry = table.newEntry(); + int256 count; + + // Set Value + entry.set("idNumber", idNumber); + entry.set("userName", userName); + entry.set("propertyValue", propertyValue); + entry.set("carValue", carValue); + + count = table.insert(idNumber, entry); + emit insertResult(count); + + return count; + } + + // 查询用户资产信息 + // 参数(身份证号,姓名,房产,车产) 返回值(bool) + function getUserAssetInfo(string memory idNumber, string memory userName, int256 propertyValue, int256 carValue) + public + view + returns(bool, string memory) + { + Table table = tableFactory.openTable(ASSET_INFO); + + string memory userNameTemp; + int256 propertyValueTemp; + int256 carValueTemp; + + Condition condition = table.newCondition(); + condition.EQ("idNumber", idNumber); + + Entries entries = table.select(idNumber, condition); + if(0 == entries.size()) + { + return(false, "用户ID出错"); + } + + Entry entry = entries.get(0); + + userNameTemp = entry.getString("userName"); + propertyValueTemp = entry.getInt("propertyValue"); + carValueTemp = entry.getInt("carValue"); + + if(strMatching(userNameTemp, userName) != true) + { + return(false, "姓名错误"); + } + + if(propertyValue > (propertyValueTemp * 105 / 100) || propertyValue < (propertyValueTemp * 95 / 100)) + { + return(false, "房产金额错误"); + } + if(carValue > (carValueTemp * 105 / 100) || carValue < (carValueTemp * 95 / 100)) + { + return(false, "车产金额错误"); + } + + return(true, ""); + } +} \ No newline at end of file diff --git a/2021-Shenzhen-FinTechathon3/Document.docx b/2021-Shenzhen-FinTechathon3/Document.docx new file mode 100644 index 000000000..f23f6f16a Binary files /dev/null and b/2021-Shenzhen-FinTechathon3/Document.docx differ diff --git a/2021-Shenzhen-FinTechathon3/README.md b/2021-Shenzhen-FinTechathon3/README.md index 71aa516d7..2e3955447 100644 --- a/2021-Shenzhen-FinTechathon3/README.md +++ b/2021-Shenzhen-FinTechathon3/README.md @@ -1,11 +1,137 @@ -## 2021年微众银行第三届金融科技高校技术大赛参赛作品 -## 提交说明 - -1. 每个队伍请在本目录创建文件夹,文件夹中用于展示项目介绍、合约代码等。 -2. 如果需要提交图片或大于500KB文件,请使用[git-lfs](https://git-lfs.github.com/),由于git-lfs等组件对中文支持不友好,文件夹和文件名请使用英文。 -3. 参考格式 - + 项目类:项目简介、项目背景、项目目标、方案等 - + 工具类:项目说明、环境依赖、使用方法等 - -4. 参赛队伍可以在各自子目录`Contrcts`目录下提交Solidity合约。合约接口需要有说明文档,可提供通过[console](https://github.com/FISCO-BCOS/console)、[nodejs-sdk](https://github.com/FISCO-BCOS/nodejs-sdk)或[python-sdk](https://github.com/FISCO-BCOS/python-sdk)调用的操作截图。 -5. 参赛队伍可以在各自子目录`Project`目录下提交项目代码。项目代码要求提供运行指引且需要经过FISCO BCOS团队审核。项目代码要求安装步骤清晰、保证能运行和项目干净清晰。项目详细介绍请[参考这里的格式](../201907-Beijing/example_project/README.md)提交。 +# 亿点爱 + +团队名称:上园村小红果 +团队成员:伍羽放、刘煜昊、袁恩泽、赵双、周琳 +学校:北京交通大学 + +## 项目简介 + +近年来网络公益筹款平台层出不穷,但普遍存在监管制度不完善、个人隐私无法保护、个人行为无法约束等问题。因此本作品旨在通过区块链构建公益众筹平台,利用隐私保护技术实现安全可信存储,保护用户个人隐私的的同时有效防止虚假筹款和善款挪用,以此促进互联网公益众筹行业健康有序地发展。 + +## 项目背景 + +随着近些年来,公民参与社会公益的意识日益增强,科学信息技术不断发展,使得公益组织得到了迅速的发展。其中,各类众筹平台不断涌现,成为慈善、环境保护、扶贫等各个社会发展的领域中一股不可忽视的力量。公益众筹愈发活跃,频繁出现在人们的视野里,其不受空间、时间、地点的限制,信息交换具有互动性,成本低,更适合大众的需求。 + +目前公益众筹还存在如下问题: + +1. 法律制度不健全 + + 公益众筹在概念上同慈善募捐和公益慈善行为有根本的区别。我国公益众筹在法律上没有形成完整的信息监管体系,在发起人的准入资质、平台的审核、信息的公开上都出现了诸多问题。 + +2. 监管制度不完善 + + 简便的发起程序、松散的审核力度、象征性的抽查复核都增大了发起人发布虚假信息的可能性,也为事后的追责设置了困难。 + +3. 个人隐私无法保护 + + 信息公开制度存在争议,无法保护发起人的个人隐私信息可能对其造成困扰,一部分捐赠者会利用发起人的个人信息频繁骚扰受益人,无法保证发起人的合法权益。 + +4. 个人行为无法约束 + + 通过捏造或者夸大困境博得公众的同情,诈骗他人财物,消耗公众对于公益众筹的支持和信任度。因而,对发起人和捐赠者的行为缺乏约束会直接降低项目的质量,进而影响发起人和捐赠者之间的彼此信任。 + +## 项目目标 + +本作品旨在通过区块链构建公益众筹平台,利用智能合约、隐私保护等技术可信存储信息,保护了用户个人隐私的同时有效防止虚假筹款和善款挪用,以期促进互联网公益众筹行业健康有序的发展。 + +设计目标如下: + +1. 防止平台侵吞善款 + + 平台诚信问题在运行过程中饱受争议,民众的公益热情持续降低,对平台的不信任代替了爱心。将每一笔资金的来源和去向存储在区块链上,保证每一笔交易均可追溯,不可篡改。 + +2. 保护申请者个人隐私 + + 利用智能合约与加密技术,结合零知识证明、选择性披露等隐私保护方法,依据信息种类对其进行链上分类存储,将敏感信息、隐私信息等以密文形式存储,维护了发起人的合法权益。 + +3. 追踪善款去向 + + 将资金使用的明细上链,给捐赠者提供了方便的监督渠道,使得所有的慈善款去向清晰明了,提高公民对平台的信任感。 + +4. 自动化验证信息 + + 使用跨链技术,实现对用户所提交的个人病例信息与资产信息的自动化查询验证,提高平台的可靠性。 + +## 方案 + +### 技术概述 + +Web前端界面主要有信息公示、资助申请、我的资助、我的筹款四个功能模块,采用JavaScript + Vue + Element UI组件进行界面设计,根据用户的操作,发起相应请求到后端,执行对区块链数据的读写操作。 + +后端作为数据处理方,主要负责隐私保护模块以及数据的传输。在接收到前端传输的用户明文数据后,会向医院管理的病例信息存储链以及车管所、房管所管理的车房资产存储链发送查询认证请求,两条链完成验证后会返回验证结果,若结果为是,则会对数据进行选择性披露认证以及零知识证明认证,生成相应的认证数据及认证密钥,分别由区块链以及数据库保存,若结果为否,则返回错误信息,用户可再次填写重新提交,若提交错误达五次,则该用户将被拉入黑名单,不可再提交筹款申请。后端在收到查询用户详细信息请求后,会以同样的传输方式从区块链获取数据,并进行认证处理,最后选择性向查询者披露明文,保护用户隐私数据。 + +区块链模块本质上可以视为一个存储数据信息的分布式数据库,也可以作为一个系统内多方用户的共享公共账本。账本由多种区块共同构成,分别存放每一名用户的不同信息,隐私信息作为密文上链存储,需要公开展示的信息则作为明文进行存储,可以供所有用户随时查询。 + +### 隐私保护方案 + +为了保证用户的筹款明细以及使用善款的明细公开透明且防止恶意篡改,所以使用区块链系统作为数据存储的媒介,但是也正因为区块链系统的公开透明原则,导致了在链上存储的用户信息会发生泄漏。 + +因此,在亿点爱系统中使用了微众银行提供的WeDPR隐私保护模块,WeDPR是一系列即时可用场景式隐私保护高效解决方案套件和服务,通过该模块,系统在后端实现了对用户信息的认证并生成特定密文,将密文和用户ID存储在区块链上,保证用户的隐私。在需要对用户信息进行认证或披露的情况下,根据区块链上存储的密文以及用户所保存的私钥进行认证,最终披露出非敏感个人信息。 + +#### 加密模块 + +具体的加密流程如下图所示: + +![image-20211107091357670](https://i.loli.net/2021/11/07/U2nMeGQHz4Og7wC.png) + +为了最大程度的保护用户隐私数据,系统对用户所输入的全部个人信息进行加密处理,具体的加密流程如下: + +接收到用户发送的明文信息后,分别将汉字及英文字母转换为字节数组,从而将这两部分信息转化为十进制的数字。 + +因为负数不能作为加密模块的输入值,因此对所有的十进制编码信息统一加和一个固定数值,使所有数值转化为正三位数。 + +依据字段对获得的正三位数按原字段转化后的顺序依次拼接,再将各个字段最终生成的字符串作为SCD加密模块的输入进行信息认证处理。 + +SCD模块根据输入会输出的四个凭证值:认证数据、认证模版、混淆凭证以及认证私钥。其中认证数据、认证模版作为密文存储在区块链上,混淆凭证以及认证私钥则保存在用户手中。 + +#### 解密模块 + +解密认证流程如下图所示: + +![image-20211107085858230](https://i.loli.net/2021/11/07/9Irg51dVMT8ztHj.png) + +当资助用户需要查看求助用户的个人信息数据以及资产情况时,调用解密模块对用户信息进行披露,具体披露认证步骤如下: + +当资助者申请查看求助者筹款信息时,服务层分别向求助者和区块链提取四个凭证信息:认证数据、认证模版、混淆凭证以及认证私钥,并输入至SCD验证模块。 + +根据参数选择,对用户的非敏感信息进行选择性披露,对用户的资产情况进行零知识证明,给予用户资产等级证明,同时对用户的患病信息进行选择性披露,保证在可证明的情况下,保护申请者的个人隐私。 + +### 智能合约逻辑 + +在系统运行前,提前部署筹款申请者智能合约和资助者智能合约,初始化所需要的数据表。 + +#### 申请模块 + +当求助者从UI界面提交筹款申请后,调用资助申请块插入函数,将申请者的ID以及个人信息的密文数据存储在区块链上,后续由申请者本人或是资助者进行查询详情信息时,再将链上存储的密文数据发送至后端进行零知识认证以及选择性披露。 + +因为区块链公开透明的特性,导致了所有参与方都可以查看链上存储的数据,为实现保护申请者的个人隐私,因此采用零知识证明以及选择性披露这两种隐私计算方法,在保证数据可证明、可验证的情况下提供隐私性保障。 + +#### 资助模块 + +当用户在系统界面完成用户注册后,会调用资助模块的初始化函数,为所有注册用户生成一个记录自己捐助信息的空区块。 + +资助者在前端界面查看用户求助详情后,可进行捐助善款操作。在进行捐款时,通过调用资助统计块的更新合约,可根据被资助者的ID更新其当前已筹集的善款数,并记录资助者的ID以及对应资助金额及资助时间,以便后续追踪善款的来源。 + +在进行资助操作后,同时会调用资助模块的更新函数,以资助者自己的ID为参数更新区块数据,除去更新资助的基本信息外,同时会计算资助他人所获得的爱心积分值。当爱心积分值高于一定阈值时,会自动提高资助者本人作为申请者时发布求助信息的曝光率,同时也会提高其筹款时单次提现的最大限额。以此来激励人们积极参与筹款活动。 + +#### 提现模块 + +当求助者在收到他人捐献的善款后,可以在提现界面进行申请提现操作,与此同时会更新善款提现块的提现信息,包括本次提现金额、当前剩余金额以及提现总金额。 + +除此之外,系统会对用户单次提现的金额进行额度限制,用户第一次提现金额为总目标金额的20%,第二次提现额度为总目标金额的40%,以此来最大程度确保求助者不会侵吞善款。同时,当求助者完成一次提现后,需要提交本次提现金额的全部花费明细,才能进行下一次提现申请,通过这种方法来确保筹款金额花费的公开透明,让所有捐献者可以实时追踪到善款的去向以及用处。 + +### 跨链验证方案 + +本节我们针对本文提出的亿点爱众筹方案,结合区块链未来可能应用场景,基于WeCross模块,实现了下图所示的安全可信任的跨链验证方案。以解决众筹过程中可能存在的监管制度不完善、个人行为无法约束等问题。 + +![image-20211107090121932](https://i.loli.net/2021/11/07/Aw5pyfBqGSik1TU.png) + +#### 房车资产存储链 + +房车资产存储链由政府相关机构,如房管局、车管所等责任单位管理维护,如下图所示,该链中存储的信息包括姓名、身份证号、房产证明、车产证明等内容,用于证明发起众筹用户的房产、车产等资产情况。在保证用户资产情况真实可信的同时,实现了对用户资产的隐私保护,避免泄露的风险。 + +#### 病例信息存储链 + +病例信息存储链由医院等医疗单位负责维护,如下图所示,该链中存储的信息包括姓名、身份证号、病例信息等内容,用于证明用户曾经的患病信息,患病信息作为用户的敏感信息,急需得到相应的保护。本节我们采用的方案在实现准确验证用户病例信息的同时,实现了对病人病例信息的有效保护。 + +![image-20211107091421582](https://i.loli.net/2021/11/07/SUu6VqlvyXFnbDa.png) \ No newline at end of file diff --git "a/2021-Shenzhen-FinTechathon3/\346\231\272\"\346\203\240\"\345\271\263\345\217\260" "b/2021-Shenzhen-FinTechathon3/\346\231\272\"\346\203\240\"\345\271\263\345\217\260" deleted file mode 100644 index 4a4f41c28..000000000 --- "a/2021-Shenzhen-FinTechathon3/\346\231\272\"\346\203\240\"\345\271\263\345\217\260" +++ /dev/null @@ -1,10 +0,0 @@ -项目名称:智“惠”——基于区块链的群智感知数据交易平台 -团队宣言:链接世界,智“惠”你我 -作品介绍: - “智惠”——基于区块链的群智感知数据交易平台,使用了真值发现、随机矩阵、区块链、智能合约等技术,支持隐私保护的任 -务发布、用户选择、数据求真及报酬发放,保障参与用户的隐私及经济利益,促进数据高效流通,提升数据资源价值,规范数据公平交易。 -背景: -随着对大数据技术的探索与发展,越来越多的企业意识到大数据的重要性。企业通过大数据对客户的消费行为分析归类,可以更好地了解客户需求,为 -客户提供个性定制化服务。在零售业,依托大数据技术,可以使零售商获得大量用户的精准数据,对这些数据加以有效利用,不仅可以帮助商户提升用户的消费体验, -更好的满足消费需求,还能有助于商户制定合理的营销推广策略;在餐饮业,餐企的数字化能有效提升效率、降低成本,通过分析掌握的数据资源,可以及 -时有针对性的调整业务的发展方向;在互联网行业,企业大数据的处理能力,对企业体量能否做大有着至关重要的作用。