diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 6b4c86e0..4607f3af --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ | 依赖软件 | 说明 |备注| | --- | --- | --- | -| Solidity | 0.4.25 | | +| Solidity | 0.4.25-0.6.10 | | | Git | 下载需要使用Git | | ## 文档 diff --git a/contracts/base_type/BasicDemo.sol b/contracts/base_type/BasicDemo.sol old mode 100644 new mode 100755 diff --git a/contracts/base_type/LibAddress.sol b/contracts/base_type/LibAddress.sol old mode 100644 new mode 100755 diff --git a/contracts/base_type/LibConverter.sol b/contracts/base_type/LibConverter.sol old mode 100644 new mode 100755 diff --git a/contracts/base_type/LibSafeMathForFloatUtils.sol b/contracts/base_type/LibSafeMathForFloatUtils.sol new file mode 100755 index 00000000..5730156c --- /dev/null +++ b/contracts/base_type/LibSafeMathForFloatUtils.sol @@ -0,0 +1,94 @@ +pragma solidity^0.4.25; +import "./LibSafeMathForUint256Utils.sol"; + +library LibSafeMathForFloatUtils { + using LibSafeMathForUint256Utils for uint256; + + /* + fmul:浮点数乘法 + a:被乘数 + dA:被乘数a的精度,若a = 1234,dA=2,实际表示浮点型数为12.34 + b:乘数 + dB:乘数的精度 + 返回值:乘法后的结果,精度值(以被乘数精度为准) + 100.01 * 100.01 = 10000.0001 => 10000.00 + */ + function fmul(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals) { + decimals = dA; + c = a.mul(b).div(10 ** uint256(dB)); + } + + /* + fdiv:浮点数除法 + a:被除数 + dA:被除数a的精度,若a = 1234,decimalsA=2,实际表示浮点型数为12.34 + b:除数 + dB:除数的精度 + 返回值:除法后的结果,精度值(以被除数精度为准) + 10000.00 / 100.00 = 100.00 + */ + function fdiv(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals) { + decimals = dA; + if(dA == dB) { + c = a.mul(10 ** uint256(dA)).div(b); + } + else if(dA > dB) { + //第一个参数精度更大 + b = b.mul(10 **uint256(dA - dB) ); + c = a.mul(10 ** uint256(dA)).div(b); + } else { + //第2个参数精度更大 + b = b.div(10 ** uint256(dB - dA) ); + c = a.mul(10 ** uint256(dA)).div(b); + } + } + + /* + fadd:浮点数加法 + a:加数a + dA:加数a的精度,若a = 1234,decimalsA=2,实际表示浮点型数为12.34 + b:加数b + dB:加数b的精度 + 返回值:加法后的结果,精度值(以第1个参数精度为准) + */ + function fadd(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals) { + decimals = dA; + if(dA == dB) { + c = a.add(b); + } + else if(dA > dB) { + //第一个参数精度更大 + b = b.mul(10 **uint256(dA - dB) ); + c = a.add(b); + } else { + //第2个参数精度更大 + b = b.div(10 ** uint256(dB - dA) ); + c = a.add(b); + } + } + + /* + fsub:浮点数减法 + a:被减数 + dA:被减数a的精度,若a = 1234,decimalsA=2,实际表示浮点型数为12.34 + b:减数 + dB:减数b的精度 + 返回值:减法后的结果,精度值(以第1个参数精度为准) + */ + function fsub(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals) { + decimals = dA; + if(dA == dB) { + c = a.sub(b); + } else if (dA > dB) { + c = a.sub(b.mul(10 ** uint256(dA - dB))); + } else { + c = a.sub(b.div(10 ** uint256(dB - dA))); + } + + } + + +} + + + \ No newline at end of file diff --git a/contracts/base_type/LibSafeMathForUint256Utils.sol b/contracts/base_type/LibSafeMathForUint256Utils.sol old mode 100644 new mode 100755 diff --git a/contracts/base_type/ArrayDemo.sol b/contracts/base_type/array/ArrayDemo.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/base_type/ArrayDemo.sol rename to contracts/base_type/array/ArrayDemo.sol diff --git a/contracts/base_type/array/Lib2DArrayForUint256.sol b/contracts/base_type/array/Lib2DArrayForUint256.sol new file mode 100755 index 00000000..d88f403a --- /dev/null +++ b/contracts/base_type/array/Lib2DArrayForUint256.sol @@ -0,0 +1,115 @@ +pragma solidity ^0.4.25; +/** +* @author wpzczbyqy +* @title uint256类型 二维数组操作 +* 提供二维数组的操作,增加新元素,删除元素,修改值,查找值,合并扩展数组等 +**/ + +library Lib2DArrayForUint256 { + /** + *@dev 二维数组中增加一个数组元素 + *@param array uint256类型二维数组 + *@param value uint256类型一维数组 + **/ + function addValue(uint256[][] storage array,uint256[] value) internal{ + require(value.length > 0, "Empty Array: can not add empty array"); + array.push(value); + } + + /** + *@dev 查找二维数组中指定位置的值 + *@param array uint256类型二维数组 + *@param row 值所在的行 + *@param col 值所在的列 + *@return uint256 返回查找的值 + **/ + function getValue(uint256[][] storage array, uint256 row, uint256 col) internal returns (uint256) { + if(array.length == 0){ + return 0; + } + require(row < array.length,"Row: index out of bounds"); + require(col < array[row].length, "Col: index out of bounds"); + return array[row][col]; + } + + /** + *@dev 修改二维数组中指定位置的值 + *@param array uint256类型二维数组 + *@param row 值所在的行 + *@param col 值所在的列 + *@param val 修改指定位置的值为val + *@return uint256[][] 返回修改后的数组 + **/ + function setValue(uint256[][] storage array, uint256 row, uint256 col, uint256 val) internal returns (uint256[][]) { + if(array.length == 0){ + return; + } + + require(row < array.length,"Row: index out of bounds"); + require(col < array[row].length, "Col: index out of bounds"); + array[row][col] = val; + return array; + } + + /** + *@dev 修改二维数组中指定位置的值 + *@param array uint256类型二维数组 + *@param row 值所在的行 + *@param col 值所在的列 + *@param val 修改指定位置的值为val + *@return uint256[][] 返回修改后的数组 + **/ + function firstIndexOf(uint256[][] storage array, uint256 val) internal returns (bool, uint256, uint256) { + uint256 row; + uint256 col; + if (array.length == 0) { + return (false, 0, 0); + } + for(uint256 i = 0; i < array.length; i++) { + for(uint256 j = 0; j < array[i].length; j++) { + if(array[i][j] == val){ + row = i; + col = j; + return (true, row, col); + } + } + } + return (false, 0, 0); + } + + /** + *@dev 删除二维数组中的某个数组元素 + *@param array uint256类型二维数组 + *@param index 删除第index个数组元素 + *@return uint256[][] 返回修改后的数组 + **/ + function removeByIndex(uint256[][] storage array, uint256 index) internal returns(uint256[][]) { + require(index < array.length, "Index: index out of bounds"); + delete array[index]; + + while(index < array.length -1) { + delete array[index]; + for(uint256 i = 0; i < array[index + 1].length; i++){ + array[index].push(array[index + 1][i]); + } + index++; + } + array.length--; + return array; + } + + /** + *@dev 合并两个二维数组 + *@param array1 uint256类型二维数组 + *@param array2 uint256类型二维数组 + *@return uint256[][] 返回合并后的数组 + **/ + function extend(uint256[][] storage array1, uint256[][] storage array2) internal returns(uint256[][]){ + require(array2.length > 0, "Extend: can not extend empty array"); + + for(uint256 i = 0; i < array2.length; i++){ + array1.push(array2[i]); + } + return array1; + } +} \ No newline at end of file diff --git a/contracts/base_type/LibArrayForUint256Utils.sol b/contracts/base_type/array/LibArrayForUint256Utils.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/base_type/LibArrayForUint256Utils.sol rename to contracts/base_type/array/LibArrayForUint256Utils.sol diff --git a/contracts/base_type/array/TwoDArrayDemo.sol b/contracts/base_type/array/TwoDArrayDemo.sol new file mode 100755 index 00000000..c9f9703c --- /dev/null +++ b/contracts/base_type/array/TwoDArrayDemo.sol @@ -0,0 +1,57 @@ +pragma solidity ^0.4.25; +pragma experimental ABIEncoderV2; + +import "./Lib2DArrayForUint256.sol"; + +contract TwoDArrayDemo { + + uint256[][] private array; + uint256[][] private array2; + uint256[] val = [1,2]; + uint256[] val2 = [3, 4, 5]; + uint256[] val3 = [6, 7, 8, 9]; + + function addAndGetValue(uint256 row, uint256 col) public view returns (uint256) { + array = new uint256[][](0); + Lib2DArrayForUint256.addValue(array,val); + Lib2DArrayForUint256.addValue(array,val2); + // (1,1) => expected Return values:(4) + return Lib2DArrayForUint256.getValue(array,row,col); + } + + function firstIndexOf(uint256 key) public view returns (bool, uint256, uint256) { + array = new uint256[][](0); + Lib2DArrayForUint256.addValue(array,val); + // (2) => expected Return values:(true, 0, 0) + return Lib2DArrayForUint256.firstIndexOf(array,key); + } + + + function setValue(uint256 row, uint256 col, uint256 key) public view returns (uint256[][]) { + array = new uint256[][](0); + Lib2DArrayForUint256.addValue(array,val); + Lib2DArrayForUint256.addValue(array,val2); + // (1, 0, 9) => expected Return values:([[1, 2] [9, 4, 5] ] ) + return Lib2DArrayForUint256.setValue(array,row,col,key); + } + + function removeByIndex(uint256 index) public view returns (uint256[][]) { + array = new uint256[][](0); + Lib2DArrayForUint256.addValue(array,val); + Lib2DArrayForUint256.addValue(array,val2); + Lib2DArrayForUint256.addValue(array,val3); + // 1 => expected Return values:([[1, 2] [6, 7, 8, 9] ] ) + return Lib2DArrayForUint256.removeByIndex(array,index); + + } + + function extend() public view returns (uint256[][]) { + array = new uint256[][](0); + array2 = new uint256[][](0); + Lib2DArrayForUint256.addValue(array,val); + Lib2DArrayForUint256.addValue(array,val2); + Lib2DArrayForUint256.addValue(array2,val3); + // expected Return values:([[1, 2] [3, 4, 5] [6, 7, 8, 9] ] ) + return Lib2DArrayForUint256.extend(array,array2); + } +} \ No newline at end of file diff --git a/contracts/base_type/bits/LibBitOperationForByte.sol b/contracts/base_type/bits/LibBitOperationForByte.sol new file mode 100755 index 00000000..921386e8 --- /dev/null +++ b/contracts/base_type/bits/LibBitOperationForByte.sol @@ -0,0 +1,107 @@ +pragma solidity ^0.4.25; + +/** +* @author wpzczbyqy +* @description byte类型位操作 +* 提供solidity内置函数不包括的位操作方法,例如按位非、移位、取前/后n位等方法 +**/ + +library LibBitOperationForByte { + + /** + *按位非 + *@param a byte类型参数 + *@return byte + **/ + function invert(byte a) internal pure returns (byte) { + return a ^ 0xff; + } + + /** + *向左移动n位 + *@param a byte类型参数 + *@param n 向左移动的位数 + *@return byte + * 例如:0xa1向左移动2位,为0x84 + **/ + function leftShift(byte a, uint n) internal pure returns (byte) { + uint shifted = uint(a) * 2 ** n; + return byte(shifted); + } + + /** + *向右移动n位 + *@param a byte类型参数 + *@param n 向右移动的位数 + *@return byte + * 例如:0xa1向右移动2位,为0x28 + **/ + function rightShift(byte a, uint n) internal pure returns (byte) { + uint shifted = uint(a) / 2 ** n; + return byte(shifted); + } + + /** + *获取前n位 + *@param a byte类型参数 + *@param n 获取的位数长度 + *@return byte + * 例如:0xa1获取前2位,为0x80 + **/ + function getFirstN(byte a, uint8 n) internal pure isValidLength(n) returns (byte) { + byte nbits = byte(2 ** n - 1); + byte mask = leftShift(nbits, 8 - n);//constrcut the mask,e.g when n == 4, mask is 1111 0000 + return a & mask; + } + + /** + *获取后n位 + *@param a byte类型参数 + *@param n 获取的位数长度 + *@return byte + * 例如:0xa1获取后2位,为0x01 + **/ + function getLastN(byte a, uint8 n) internal pure isValidLength(n) returns (byte) { + if(n == 8) { + return a; + } + uint8 lastN = uint8(a) % (2 ** n); + return byte(lastN); + } + + /** + *获取第n个位置上的bit + *@param a byte类型参数 + *@param n 第n位 + *@return uint8,第n位的值0/1 + **/ + function getBitAtPositionN(byte a, uint8 n) internal pure isValidPosition(n) returns (uint8) { + bool val = a & leftShift(0x01, n) != 0; + if(val == true){ + return 1; + } + return 0; + } + + /** + *将第n个位置上的bit取反 + *@param a byte类型参数 + *@param n 第n位 + *@return byte + **/ + function invertBitAtPositionN(byte a, uint8 n) internal pure isValidPosition(n) returns (byte) { + return a ^ leftShift(0x01, n); + } + + /*校验长度*/ + modifier isValidLength(uint8 n) { + require(n < 9, "Invalid Length: byte is 8 bits"); + _; + } + + /*校验位置*/ + modifier isValidPosition(uint8 n) { + require(n < 8, "Invalid Position: n start with 0, n < 8"); + _; + } +} \ No newline at end of file diff --git a/contracts/base_type/bits/LibBits.sol b/contracts/base_type/bits/LibBits.sol new file mode 100755 index 00000000..698ddb91 --- /dev/null +++ b/contracts/base_type/bits/LibBits.sol @@ -0,0 +1,100 @@ +pragma solidity ^0.4.25; + +library LibBits { + function and(bytes1 a, bytes1 b) internal pure returns (bytes1) { + return a & b; + } + + function or(bytes1 a, bytes1 b) internal pure returns (bytes1) { + return a | b; + } + + function xor(bytes1 a, bytes1 b) internal pure returns (bytes1) { + return a ^ b; + } + + /** + *按位非 + *@param a byte类型参数 + *@return byte + **/ + function invert(byte a) internal pure returns (byte) { + return a ^ 0xff; + } + + function negate(bytes1 a) internal pure returns (bytes1) { + return a ^ allOnes(); + } + + function shiftLeft(bytes1 a, uint8 n) internal pure returns (bytes1) { + var shifted = uint8(a) << n; + return bytes1(shifted); + } + + function shiftRight(bytes1 a, uint8 n) internal pure returns (bytes1) { + var shifted = uint8(a) >> n; + return bytes1(shifted); + } + + // get the high bit data and keep it on high + function getFirstN(bytes1 a, uint8 n) internal pure isValidLength(n) returns (bytes1) { + var nOnes = bytes1(2**n - 1); + var mask = shiftLeft(nOnes, 8 - n); // Total 8 bits + return a & mask; + } + + function getLastN(bytes1 a, uint8 n) internal pure isValidLength(n) returns (bytes1) { + var lastN = uint8(a) % 2**n; + return bytes1(lastN); + } + + // Sets all bits to 1 + function allOnes() internal pure returns (bytes1) { + return bytes1(-1); // 0 - 1, since data type is unsigned, this results in all 1s. + } + + // Get bit value at position + function getBit(bytes1 a, uint8 n) + internal + pure + isValidPosition(n) + returns (bool) + { + n--; + return a & shiftLeft(0x01, n) != 0; + } + + // Set bit value at position + function setBit(bytes1 a, uint8 n) + internal + pure + isValidPosition(n) + returns (bytes1) + { + n--; + return a | shiftLeft(0x01, n); + } + + // Set the bit into state "false" + function clearBit(bytes1 a, uint8 n) + internal + pure + isValidPosition(n) + returns (bytes1) + { + n--; + bytes1 mask = negate(shiftLeft(0x01, n)); + return a & mask; + } + + modifier isValidPosition(uint8 n) { + require(n < 9 && n > 0, "Invalid Position: n start with 1, n <= 8"); + _; + } + + /*校验长度*/ + modifier isValidLength(uint8 n) { + require(n < 9, "Invalid Length: byte is 8 bits"); + _; + } +} diff --git a/contracts/base_type/bits/TestBits.sol b/contracts/base_type/bits/TestBits.sol new file mode 100644 index 00000000..98b3cc24 --- /dev/null +++ b/contracts/base_type/bits/TestBits.sol @@ -0,0 +1,72 @@ +pragma solidity >=0.4.24 <0.6.11; + +import "./LibBits.sol"; + +contract TestBits { + + function testAnd() public view returns(bytes1 ){ + bytes1 a = 1; + bytes1 b = 5; + bytes1 result = LibBits.and(a, b);//Expected to be 1 + return result; + } + + function testOr() public view returns(bytes1 ){ + bytes1 a = 2; // 0x010 + bytes1 b = 5; // 0x101 + bytes1 result = LibBits.or(a, b);//Expected to be 7, 0x111 + return result; + } + + function testXor() public view returns(bytes1 ){ + byte a = 3; // 0x011 + byte b = 5; // 0x101 + bytes1 result = LibBits.xor(a, b); //Expected to be 6, 0x110 + return result; + } + + function testNegate() public view returns(bytes1){ + bytes1 r = LibBits.negate(5);//Expected to be -6 0x00000101 -> 0x11111010 + return r; + } + + function testShiftLeft() public view returns(bytes1){ + bytes1 r = LibBits.shiftLeft(2,3);//Expected to be 16, 0x00000010 -> 0x00010000 + return r; + } + + function testShiftRight() public view returns(bytes1){ + bytes1 r = LibBits.shiftRight(15,3);//Expected to be 1, 0x00001111 -> 0x00000001 + return r; + } + + function testGetLastN() public view returns(bytes1){ + bytes1 r = LibBits.getLastN(60,3);//Expected to be 4 0x00111100 -> 0x00000100 + return r; + } + + function getFirstN() public view returns(bytes1){ + byte r = LibBits.getFirstN(60,3);//Expected to be 32, 0x00111100 -> 0x00100000 + return r; + } + + function testAllOnes() public view returns(bytes1){ + byte r = LibBits.allOnes();//Expected to be 255 + return r; + } + + function testGetBit() public view returns(bool){ + bool r = LibBits.getBit(3,2);//Expected to be 1 + return r; + } + + function testSetBit() public view returns(bytes1){ + byte r = LibBits.setBit(17,2);//Expected to be 19, 0x00010001 -> 0x00010011 + return r; + } + + function testClearBit() public view returns(bytes1){ + byte r = LibBits.clearBit(17,5);//Expected to be 1 + return r; + } +} \ No newline at end of file diff --git a/contracts/base_type/LibString.sol b/contracts/base_type/string/LibString.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/base_type/LibString.sol rename to contracts/base_type/string/LibString.sol diff --git a/contracts/base_type/StringDemo.sol b/contracts/base_type/string/StringDemo.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/base_type/StringDemo.sol rename to contracts/base_type/string/StringDemo.sol diff --git a/contracts/business_template/bill/BillController.sol b/contracts/business_template/bill/BillController.sol new file mode 100755 index 00000000..1c40e639 --- /dev/null +++ b/contracts/business_template/bill/BillController.sol @@ -0,0 +1,84 @@ +pragma solidity ^0.4.25; +pragma experimental ABIEncoderV2; + +import "./utils/Ownable.sol"; +import "./utils/LibString.sol"; +import "./service/BillStorage.sol"; + +contract BillController is Ownable { + + using LibString for string; + + BillStorage private billStorage; + + event IssueResult(int256); + event EndorseResult(bool); + event EcceptResult(bool); + event EcceptReject(bool); + + //日志打印 + event LogMessage(string _m); + function _log(bool _b , string memory _m) private { + if(_b){ + emit LogMessage(_m); + } + } + + constructor() public { + billStorage = new BillStorage(); + } + + /**发布票据 */ + function issue(string _s) external onlyOwner returns(int256){ + int256 count = billStorage.insert(_s); + emit IssueResult(count); + return count; + } + + /**批量查询当前持票人的票据 */ + function queryBills(string _holdrCmID) external returns(string[] memory){ + string[] memory result = billStorage.selectListByHoldrCmID(_holdrCmID); + return result; + } + + /**根据票据号码查询票据详情 */ + function queryBillByNo(string _infoID) external returns(string){ + return billStorage.getDetail(_infoID); + } + + /**发起背书请求 */ + function endorse(string _infoID, string _waitEndorseCmID, string _waitEndorseAcct) external onlyOwner returns(bool){ + string memory _holdrCmID = billStorage.getHoldrCmID(_infoID); + _log(_holdrCmID.empty(), "BillController: holdrCmID is empty"); + //require, false时执行 + require(!_holdrCmID.empty(), "BillController: holdrCmID is empty"); + // 待背书人不能是当前持票人 + require(!_holdrCmID.equal(_waitEndorseCmID), "BillController: waitEndorseCmID != holdrCmID"); + + int256 count = billStorage.updateEndorse(_infoID, _waitEndorseCmID, _waitEndorseAcct); + emit EndorseResult(count > int256(0)); + return count > int256(0); + } + + /**查询待背书票据列表 */ + function queryWaitBills(string _waitEndorseCmID) external returns(string[] memory){ + string[] memory result = billStorage.selectListByWaitEndorseCmID(_waitEndorseCmID); + return result; + } + + /**背书签收 */ + function accept(string _infoID, string _holdrCmID, string _holdrAcct) external onlyOwner returns(bool){ + + int256 count = billStorage.updateEccept(_infoID, _holdrCmID, _holdrAcct); + emit EcceptResult(count > int256(0)); + return count > int256(0); + } + + /**拒绝背书 */ + function reject(string _infoID, string _rejectEndorseCmID, string _rejectEndorseAcct) external onlyOwner returns(bool){ + int256 count = billStorage.updateReject(_infoID, _rejectEndorseCmID, _rejectEndorseAcct); + emit EcceptReject(count > int256(0)); + return count > int256(0); + } + +} \ No newline at end of file diff --git a/contracts/business_template/bill/service/BillStorage.sol b/contracts/business_template/bill/service/BillStorage.sol new file mode 100755 index 00000000..44a95b87 --- /dev/null +++ b/contracts/business_template/bill/service/BillStorage.sol @@ -0,0 +1,342 @@ +pragma solidity ^0.4.25; +pragma experimental ABIEncoderV2; + +import "../utils/Ownable.sol"; +import "../utils/Table.sol"; +import "../utils/LibString.sol"; +import "./MapStorage.sol"; + +contract BillStorage is Ownable { + + using LibString for string; + + MapStorage private mapStorage; + + event InsertResult(int256); + event UpdateEndorseResult(int256); + event UpdateEcceptResult(int256); + event UpdateRejectResult(int256); + + TableFactory tf; + string constant TABLE_NAME = "tx_bill"; + + string constant BillInfo_State_NewPublish = "NewPublish"; // 票据新发布状态 + string constant BillInfo_State_EndorseWaitSign = "EndorseWaitSign"; // 待背书状态 + string constant BillInfo_State_EndorseSigned = "EndorseSigned"; // 票据背书成功状态 + string constant BillInfo_State_EndorseReject = "EndorseReject"; // 票据背书拒绝状态 + + string constant BillInfo_holdrCmID = "holdrCmID_"; // 当前持票人证件号码,票据号码集前缀 + string constant BillInfo_waitEndorseCmID = "waitEndorseCmID_"; + + /** + * 创建票据表 + * +----------------------+------------------------+-------------------------+ + * | Field | Type | Desc | + * +----------------------+------------------------+-------------------------+ + * | info_id | string | 票据号码,全局唯一 | + * | info_amt | string | 票据金额 | + * | info_type | string | 票据类型 | + * | info_isse_date | string | 出票日期 | + * | info_due_date | string | 到期日期 | + * | drwr_acct | string | 出票人名称 | + * | drwr_cm_id | string | 出票人证件号码 | + * | accptr_acct | string | 承兑人名称 | + * | accptr_cm_id | string | 承兑人证件号码 | + * | pyee_acct | string | 收款人名称 | + * | pyee_cm_id | string | 收款人证件号码 | + * | holdr_acct | string | 当前持票人名称 | + * | holdr_cm_id | string | 当前持票人证件号码 | + * | wait_endorse_acct | string | 待背书人名称 | + * | wait_endorse_cm_id | string | 待背书人证件号码 | + * | reject_endorse_acct | string | 拒绝背书人名称 | + * | reject_endorse_cm_id | string | 拒绝背书人证件号码 | + * | state | string | 票据状态 | + * +----------------------+------------------------+-------------------------+ + */ + constructor() public { + tf = TableFactory(0x1001); + tf.createTable(TABLE_NAME, "info_id", "info_amt,info_type,info_isse_date,info_due_date,drwr_acct,drwr_cm_id,accptr_acct,accptr_cm_id,pyee_acct,pyee_cm_id,holdr_acct,holdr_cm_id,wait_endorse_acct,wait_endorse_cm_id,reject_endorse_acct,reject_endorse_cm_id,state"); + + mapStorage = new MapStorage(); + } + + /** + * BOC103,3000,11,20110101,20110105,11,11,11,11,11,11,BBB,BID + * 插入数据 + */ + function insert(string memory _s) public onlyOwner returns(int) { + + string[] memory ss = _s.split(","); + //创建空数组 + HistoryItem[] memory historys = new HistoryItem[](0); + Bill memory _bill = Bill(ss[0],ss[1],ss[2],ss[3],ss[4],ss[5],ss[6],ss[7],ss[8],ss[9],ss[10],ss[11],ss[12],"","","","",BillInfo_State_NewPublish,historys); + + Table table = tf.openTable(TABLE_NAME); + require(!_isInfoIDExist(table, _bill.infoID), "BillStorage: current info_id has already exist"); + + Entry entry = table.newEntry(); + + // entry.set("info_id", _bill.infoID); + entry.set("info_amt", _bill.infoAmt); + entry.set("info_type", _bill.infoType); + entry.set("info_isse_date", _bill.infoIsseDate); + entry.set("info_due_date", _bill.infoDueDate); + entry.set("drwr_acct", _bill.drwrAcct); + entry.set("drwr_cm_id", _bill.drwrCmID); + entry.set("accptr_acct", _bill.accptrAcct); + entry.set("accptr_cm_id", _bill.accptrCmID); + entry.set("pyee_acct", _bill.pyeeAcct); + entry.set("pyee_cm_id", _bill.pyeeCmID); + entry.set("holdr_acct", _bill.holdrAcct); + entry.set("holdr_cm_id", _bill.holdrCmID); + entry.set("wait_endorse_acct", _bill.waitEndorseAcct); + entry.set("wait_endorse_cm_id", _bill.waitEndorseCmID); + entry.set("reject_endorse_acct", _bill.rejectEndorseAcct); + entry.set("reject_endorse_cm_id", _bill.rejectEndorseCmID); + entry.set("state", _bill.state); + + int256 count = table.insert(_bill.infoID, entry); + if(count > int256(0)){ + string memory key = BillInfo_holdrCmID; + key = key.concat(_bill.holdrCmID); + mapStorage.put(key, _bill.infoID); + } + + emit InsertResult(count); + return count; + } + + /** 通过infoID查询数据 */ + function getDetail(string memory _infoID) public view returns(string memory _json){ + Entry entry = select(_infoID); + _json = _returnData(entry); + } + + /** 通过infoID获取HoldrCmID */ + function getHoldrCmID(string memory _infoID) public view returns(string memory _holdrCmID){ + Entry entry = select(_infoID); + _holdrCmID = entry.getString("holdr_cm_id"); + } + + /** 更新背书人信息 */ + function updateEndorse(string memory _infoID, string memory _waitEndorseCmID, string memory _waitEndorseAcct) public onlyOwner returns(int256) { + // 更改票据状态, 票据待背书人信息, 删除拒绝背书人信息 + Table table = tf.openTable(TABLE_NAME); + Entry entry = table.newEntry(); + entry.set("state", BillInfo_State_EndorseWaitSign); + entry.set("wait_endorse_cm_id", _waitEndorseCmID); + entry.set("wait_endorse_acct", _waitEndorseAcct); + entry.set("reject_endorse_cm_id", ""); + entry.set("reject_endorse_acct", ""); + Condition condition = table.newCondition(); + int256 count = table.update(_infoID, entry, condition); + if(count > int256(0)){ + string memory key = BillInfo_waitEndorseCmID; + key = key.concat(_waitEndorseCmID); + mapStorage.put(key, _infoID); + } + emit UpdateEndorseResult(count); + return count; + } + + /** 更新持票人信息 */ + function updateEccept(string memory _infoID, string memory _holdrCmID, string memory _holdrAcct) public onlyOwner returns(int256) { + // 更改票据信息: 票据状态, 当前持票人信息, 待背书人信息 + Table table = tf.openTable(TABLE_NAME); + Entry entry = table.newEntry(); + entry.set("state", BillInfo_State_EndorseSigned); + entry.set("holdr_cm_id", _holdrCmID); + entry.set("holdr_acct", _holdrAcct); + entry.set("wait_endorse_cm_id", ""); + entry.set("wait_endorse_acct", ""); + Condition condition = table.newCondition(); + int256 count = table.update(_infoID, entry, condition); + emit UpdateEcceptResult(count); + return count; + } + + /** 更新待背书人信息 */ + function updateReject(string memory _infoID, string memory _rejectEndorseCmID, string memory _rejectEndorseAcct) public onlyOwner returns(int256) { + // 修改票据信息: 票据状态, 待背书人信息, 拒绝背书人信息 + Table table = tf.openTable(TABLE_NAME); + Entry entry = table.newEntry(); + entry.set("state", BillInfo_State_EndorseReject); + entry.set("reject_endorse_cm_id", _rejectEndorseCmID); + entry.set("reject_endorse_acct", _rejectEndorseAcct); + entry.set("wait_endorse_acct", ""); + entry.set("wait_endorse_cm_id", ""); + Condition condition = table.newCondition(); + int256 count = table.update(_infoID, entry, condition); + emit UpdateRejectResult(count); + return count; + } + + /** 通过holdrCmID查询数据 */ + function selectListByHoldrCmID(string memory _holdrCmID) public view returns(string[]){ + string memory key = BillInfo_holdrCmID; + key = key.concat(_holdrCmID); + string[] memory infoIDs = mapStorage.get(key); + + Table table = tf.openTable(TABLE_NAME); + Condition condition = table.newCondition(); + condition.EQ("holdr_cm_id", _holdrCmID); + string[] memory result = new string[](uint256(infoIDs.length)); + for(uint256 i = uint256(0); i < infoIDs.length; i++){ + Entry entry = table.select(infoIDs[uint256(i)], condition).get(int(0)); + result[uint256(i)] = _returnData(entry); + } + + return result; + } + + /** 通过waitEndorseCmID查询数据 */ + function selectListByWaitEndorseCmID(string memory _waitEndorseCmID) public view returns(string[]){ + string memory key = BillInfo_waitEndorseCmID; + key = key.concat(_waitEndorseCmID); + string[] memory infoIDs = mapStorage.get(key); + + Table table = tf.openTable(TABLE_NAME); + Condition condition = table.newCondition(); + condition.EQ("wait_endorse_cm_id", _waitEndorseCmID); + string[] memory result = new string[](uint256(infoIDs.length)); + for(uint256 i = uint256(0); i < infoIDs.length; i++){ + Entry entry = table.select(infoIDs[uint256(i)], condition).get(int(0)); + result[uint256(i)] = _returnData(entry); + } + + return result; + } + + /** 通过infoID获取实体 */ + function select(string memory _infoID) private view returns(Entry _entry){ + Table table = tf.openTable(TABLE_NAME); + require(_isInfoIDExist(table, _infoID), "BillStorage: current infoID not exist"); + + Condition condition = table.newCondition(); + _entry = table.select(_infoID, condition).get(int(0)); + } + + function _isInfoIDExist(Table _table, string memory _id) internal view returns(bool) { + Condition condition = _table.newCondition(); + return _table.select(_id, condition).size() != int(0); + } + + //拼接成json数据 + function _returnData(Entry _entry) internal view returns(string){ + + string memory _json = "{"; + + _json = _json.concat("'infoID':'"); + _json = _json.concat(_entry.getString("info_id")); + _json = _json.concat("',"); + + _json = _json.concat("'infoAmt':'"); + _json = _json.concat(_entry.getString("info_amt")); + _json = _json.concat("',"); + + _json = _json.concat("'infoType':'"); + _json = _json.concat(_entry.getString("info_type")); + _json = _json.concat("',"); + + _json = _json.concat("'infoIsseDate':'"); + _json = _json.concat(_entry.getString("info_isse_date")); + _json = _json.concat("',"); + + _json = _json.concat("'infoDueDate':'"); + _json = _json.concat(_entry.getString("info_due_date")); + _json = _json.concat("',"); + + _json = _json.concat("'drwrAcct':'"); + _json = _json.concat(_entry.getString("drwr_acct")); + _json = _json.concat("',"); + + _json = _json.concat("'drwrCmID':'"); + _json = _json.concat(_entry.getString("drwr_cm_id")); + _json = _json.concat("',"); + + _json = _json.concat("'accptrAcct':'"); + _json = _json.concat(_entry.getString("accptr_acct")); + _json = _json.concat("',"); + + _json = _json.concat("'accptrCmID':'"); + _json = _json.concat(_entry.getString("accptr_cm_id")); + _json = _json.concat("',"); + + _json = _json.concat("'pyeeAcct':'"); + _json = _json.concat(_entry.getString("pyee_acct")); + _json = _json.concat("',"); + + _json = _json.concat("'pyeeCmID':'"); + _json = _json.concat(_entry.getString("pyee_cm_id")); + _json = _json.concat("',"); + + _json = _json.concat("'holdrAcct':'"); + _json = _json.concat(_entry.getString("holdr_acct")); + _json = _json.concat("',"); + + _json = _json.concat("'holdrCmID':'"); + _json = _json.concat(_entry.getString("holdr_cm_id")); + _json = _json.concat("',"); + + _json = _json.concat("'waitEndorseAcct':'"); + _json = _json.concat(_entry.getString("wait_endorse_acct")); + _json = _json.concat("',"); + + _json = _json.concat("'waitEndorseCmID':'"); + _json = _json.concat(_entry.getString("wait_endorse_cm_id")); + _json = _json.concat("',"); + + _json = _json.concat("'rejectEndorseAcct':'"); + _json = _json.concat(_entry.getString("reject_endorse_acct")); + _json = _json.concat("',"); + + _json = _json.concat("'rejectEndorseCmID':'"); + _json = _json.concat(_entry.getString("reject_endorse_cm_id")); + _json = _json.concat("',"); + + _json = _json.concat("'state':'"); + _json = _json.concat(_entry.getString("state")); + _json = _json.concat("'"); + + _json = _json.concat("}"); + + return _json; + + } + + struct Bill { + string infoID; // 票据号码 + string infoAmt; // 票据金额 + string infoType; // 票据类型 + + string infoIsseDate; // 出票日期 + string infoDueDate; // 到期日期 + + string drwrAcct; // 出票人名称 + string drwrCmID; // 出票人证件号码 + + string accptrAcct; // 承兑人名称 + string accptrCmID; // 承兑人证件号码 + + string pyeeAcct; // 收款人名称 + string pyeeCmID; // 收款人证件号码 + + string holdrAcct; // 当前持票人名称 + string holdrCmID; // 当前持票人证件号码 + + string waitEndorseAcct; // 待背书人名称 + string waitEndorseCmID; // 待背书人证件号码 + + string rejectEndorseAcct; // 拒绝背书人名称 + string rejectEndorseCmID; // 拒绝背书人证件号码 + + string state; // 票据状态 + HistoryItem[] historys; // 当前票据的历史流转记录 + } + + struct HistoryItem { + string txId; + Bill bill; + } + +} diff --git a/contracts/business_template/bill/service/MapStorage.sol b/contracts/business_template/bill/service/MapStorage.sol new file mode 100755 index 00000000..ee892091 --- /dev/null +++ b/contracts/business_template/bill/service/MapStorage.sol @@ -0,0 +1,67 @@ +pragma solidity ^0.4.25; +pragma experimental ABIEncoderV2; + +import "../utils/Ownable.sol"; +import "../utils/LibString.sol"; +import "../utils/Table.sol"; + +contract MapStorage is Ownable { + + using LibString for string; + + event PutResult(int count); + + TableFactory tf; + string constant TABLE_NAME = "tx_map"; + + /** + * @notice map表 + * +----------------------+------------------------+-------------------------+ + * | Field | Type | Desc | + * +----------------------+------------------------+-------------------------+ + * | key | string | key | + * | value | string | value | + * +----------------------+------------------------+-------------------------+ + */ + constructor() public { + tf = TableFactory(0x1001); + tf.createTable(TABLE_NAME, "key", "value"); + } + + /** + * @notice 插入数据,已有数据不添加 + */ + function put(string memory _key, string memory _value) public onlyOwner returns(int) { + int count = int(0); + Table table = tf.openTable(TABLE_NAME); + if(!_key.empty() && !_value.empty() && !_isExist(table, _key, _value)){ + Entry entry = table.newEntry(); + entry.set("value", _value); + count = table.insert(_key, entry); + } + emit PutResult(count); + return count; + } + + /** + * @notice 通过key获取value,可以存在多个value + */ + function get(string memory _key) public view returns(string[] memory){ + Table table = tf.openTable(TABLE_NAME); + Condition condition = table.newCondition(); + Entries entries = table.select(_key, condition); + string[] memory value_list = new string[](uint256(entries.size())); + for (int256 i = 0; i < entries.size(); ++i) { + Entry entry = entries.get(i); + value_list[uint256(i)] = entry.getString("value"); + } + return value_list; + + } + + function _isExist(Table _table, string memory _key, string memory _value) internal view returns(bool) { + Condition condition = _table.newCondition(); + condition.EQ("value", _value); + return _table.select(_key, condition).size() > int(0); + } +} \ No newline at end of file diff --git a/contracts/business_template/bill/utils/Console.sol b/contracts/business_template/bill/utils/Console.sol new file mode 100755 index 00000000..45145aee --- /dev/null +++ b/contracts/business_template/bill/utils/Console.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.4.25; + +//通过log函数重载,对不同类型的变量trigger不同的event,实现solidity打印效果,使用方法为:log(string name, var value) +contract Console { + + event LogString(string, string); + function log(string s , string x) internal { + emit LogString(s, x); + } + + event LogUint(string, uint); + function log(string s , uint x) internal { + emit LogUint(s, x); + } + + event LogInt(string, int); + function log(string s , int x) internal { + emit LogInt(s, x); + } + + event LogBytes(string, bytes); + function log(string s , bytes x) internal { + emit LogBytes(s, x); + } + + event LogBytes32(string, bytes32); + function log(string s , bytes32 x) internal { + emit LogBytes32(s, x); + } + + event LogAddress(string, address); + function log(string s , address x) internal { + emit LogAddress(s, x); + } + + event LogBool(string, bool); + function log(string s , bool x) internal { + emit LogBool(s, x); + } +} \ No newline at end of file diff --git a/contracts/business_template/bill/utils/LibString.sol b/contracts/business_template/bill/utils/LibString.sol new file mode 100755 index 00000000..2f28cd6f --- /dev/null +++ b/contracts/business_template/bill/utils/LibString.sol @@ -0,0 +1,357 @@ +/* + * Copyright 2014-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ + +pragma solidity ^0.4.25; + +library LibString{ + + + function lenOfChars(string memory src) internal pure returns(uint){ + uint i=0; + uint length = 0; + bytes memory string_rep = bytes(src); + //UTF-8 skip word + while (i b2) return 1; + if(b1 < b2) return -1; + } + //and length + if(selfb.length > otherb.length) return 1; + if(selfb.length < otherb.length) return -1; + return 0; + } + + function compareNocase(string memory self, string memory other) internal pure returns(int8){ + bytes memory selfb = bytes(self); + bytes memory otherb = bytes(other); + for(uint i=0;i= 'a' && ch1 <= 'z' && ch2 >= 'a' && ch2 <= 'z'){ + if(ch1 > ch2) return 1; + if(ch1 < ch2) return -1; + } + else{ + if(b1 > b2) return 1; + if(b1 < b2) return -1; + } + } + + if(selfb.length > otherb.length) return 1; + if(selfb.length < otherb.length) return -1; + return 0; + } + + function toUppercase(string memory src) internal pure returns(string memory){ + bytes memory srcb = bytes(src); + for(uint i=0;i= 'a' && b <= 'z'){ + b &= byte(0xDF);// -32 + srcb[i] = b ; + } + } + return src; + } + + function toLowercase(string memory src) internal pure returns(string memory){ + bytes memory srcb = bytes(src); + for(uint i=0;i= 'A' && b <= 'Z'){ + b |= 0x20; + srcb[i] = b; + } + } + return src; + } + + /** + * Index Of + * + * Locates and returns the position of a character within a string + * + * @param src When being used for a data type this is the extended object + * otherwise this is the string acting as the haystack to be + * searched + * @param value The needle to search for, at present this is currently + * limited to one character + * @return int The position of the needle starting from 0 and returning -1 + * in the case of no matches found + */ + function indexOf(string memory src, string memory value) + internal + pure + returns (int) { + return indexOf(src, value, 0); + } + + /** + * Index Of + * + * Locates and returns the position of a character within a string starting + * from a defined offset + * + * @param src When being used for a data type this is the extended object + * otherwise this is the string acting as the haystack to be + * searched + * @param value The needle to search for, at present this is currently + * limited to one character + * @param offset The starting point to start searching from which can start + * from 0, but must not exceed the length of the string + * @return int The position of the needle starting from 0 and returning -1 + * in the case of no matches found + */ + function indexOf(string memory src, string memory value, uint offset) + internal + pure + returns (int) { + bytes memory srcBytes = bytes(src); + bytes memory valueBytes = bytes(value); + + assert(valueBytes.length == 1); + + for (uint i = offset; i < srcBytes.length; i++) { + if (srcBytes[i] == valueBytes[0]) { + return int(i); + } + } + + return -1; + } + + function split(string memory src, string memory separator) + internal + pure + returns (string[] memory splitArr) { + bytes memory srcBytes = bytes(src); + + uint offset = 0; + uint splitsCount = 1; + int limit = -1; + while (offset < srcBytes.length - 1) { + limit = indexOf(src, separator, offset); + if (limit == -1) + break; + else { + splitsCount++; + offset = uint(limit) + 1; + } + } + + splitArr = new string[](splitsCount); + + offset = 0; + splitsCount = 0; + while (offset < srcBytes.length - 1) { + + limit = indexOf(src, separator, offset); + if (limit == - 1) { + limit = int(srcBytes.length); + } + + string memory tmp = new string(uint(limit) - offset); + bytes memory tmpBytes = bytes(tmp); + + uint j = 0; + for (uint i = offset; i < uint(limit); i++) { + tmpBytes[j++] = srcBytes[i]; + } + offset = uint(limit) + 1; + splitArr[splitsCount++] = string(tmpBytes); + } + return splitArr; + } + + //------------HELPER FUNCTIONS---------------- + + function utf8CharBytesLength(bytes memory stringRep, uint ptr) internal pure returns(uint){ + + if ((stringRep[ptr]>>7)==byte(0)) + return 1; + if ((stringRep[ptr]>>5)==byte(0x06)) + return 2; + if ((stringRep[ptr]>>4)==byte(0x0e)) + return 3; + if ((stringRep[ptr]>>3)==byte(0x1e)) + return 4; + return 1; + } + + function memcpy(uint dest, uint src, uint len) private { + // Copy word-length chunks while possible + for(; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + // Copy remaining bytes + uint mask = 256 ** (32 - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + +} \ No newline at end of file diff --git a/contracts/business_template/bill/utils/Ownable.sol b/contracts/business_template/bill/utils/Ownable.sol new file mode 100755 index 00000000..1a4e0736 --- /dev/null +++ b/contracts/business_template/bill/utils/Ownable.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.4.25; + +contract Ownable { + address private _owner; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor () internal { + _owner = msg.sender; + emit OwnershipTransferred(address(0), _owner); + } + + /** + * @return the address of the owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(isOwner(), "Ownable: not authorized"); + _; + } + + /** + * @return true if `msg.sender` is the owner of the contract. + */ + function isOwner() public view returns (bool) { + return msg.sender == _owner; + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + _transferOwnership(newOwner); + } + + /** + * @dev Transfers control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function _transferOwnership(address newOwner) internal { + require(newOwner != address(0), "Ownable: newOwner not be zero"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} diff --git a/contracts/business_template/bill/utils/Table.sol b/contracts/business_template/bill/utils/Table.sol new file mode 100755 index 00000000..172e3b1e --- /dev/null +++ b/contracts/business_template/bill/utils/Table.sol @@ -0,0 +1,65 @@ +pragma solidity ^0.4.24; + +contract TableFactory { + function openTable(string) public constant returns (Table); // 打开表 + function createTable(string,string,string) public returns(int); // 创建表 +} + +// 查询条件 +contract Condition { + //等于 + function EQ(string, int) public; + function EQ(string, string) public; + + //不等于 + function NE(string, int) public; + function NE(string, string) public; + + //大于 + function GT(string, int) public; + //大于或等于 + function GE(string, int) public; + + //小于 + function LT(string, int) public; + //小于或等于 + function LE(string, int) public; + + //限制返回记录条数 + function limit(int) public; + function limit(int, int) public; +} + +// 单条数据记录 +contract Entry { + function getInt(string) public constant returns(int); + function getAddress(string) public constant returns(address); + function getBytes64(string) public constant returns(byte[64]); + function getBytes32(string) public constant returns(bytes32); + function getString(string) public constant returns(string); + + function set(string, int) public; + function set(string, string) public; + function set(string, address) public; +} + +// 数据记录集 +contract Entries { + function get(int) public constant returns(Entry); + function size() public constant returns(int); +} + +// Table主类 +contract Table { + // 查询接口 + function select(string, Condition) public constant returns(Entries); + // 插入接口 + function insert(string, Entry) public returns(int); + // 更新接口 + function update(string, Entry, Condition) public returns(int); + // 删除接口 + function remove(string, Condition) public returns(int); + + function newEntry() public constant returns(Entry); + function newCondition() public constant returns(Condition); +} \ No newline at end of file diff --git a/contracts/business_template/CarbonFrugalEvidence/Address.sol b/contracts/business_template/carbon_frugal_evidence/Address.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/CarbonFrugalEvidence/Address.sol rename to contracts/business_template/carbon_frugal_evidence/Address.sol diff --git a/contracts/business_template/CarbonFrugalEvidence/AuthUsersRepository.sol b/contracts/business_template/carbon_frugal_evidence/AuthUsersRepository.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/CarbonFrugalEvidence/AuthUsersRepository.sol rename to contracts/business_template/carbon_frugal_evidence/AuthUsersRepository.sol diff --git a/contracts/business_template/CarbonFrugalEvidence/CarbonFrugalEvidence.sol b/contracts/business_template/carbon_frugal_evidence/CarbonFrugalEvidence.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/CarbonFrugalEvidence/CarbonFrugalEvidence.sol rename to contracts/business_template/carbon_frugal_evidence/CarbonFrugalEvidence.sol diff --git a/contracts/business_template/CarbonFrugalEvidence/ECDSA.sol b/contracts/business_template/carbon_frugal_evidence/ECDSA.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/CarbonFrugalEvidence/ECDSA.sol rename to contracts/business_template/carbon_frugal_evidence/ECDSA.sol diff --git a/contracts/business_template/CarbonFrugalEvidence/EvidencesRepository.sol b/contracts/business_template/carbon_frugal_evidence/EvidencesRepository.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/CarbonFrugalEvidence/EvidencesRepository.sol rename to contracts/business_template/carbon_frugal_evidence/EvidencesRepository.sol diff --git a/contracts/business_template/CarbonFrugalEvidence/SafeMath.sol b/contracts/business_template/carbon_frugal_evidence/SafeMath.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/CarbonFrugalEvidence/SafeMath.sol rename to contracts/business_template/carbon_frugal_evidence/SafeMath.sol diff --git a/contracts/business_template/Evidence/Authentication.sol b/contracts/business_template/evidence/Authentication.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/Evidence/Authentication.sol rename to contracts/business_template/evidence/Authentication.sol diff --git a/contracts/business_template/Evidence/EvidenceController.sol b/contracts/business_template/evidence/EvidenceController.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/Evidence/EvidenceController.sol rename to contracts/business_template/evidence/EvidenceController.sol diff --git a/contracts/business_template/Evidence/EvidenceRepository.sol b/contracts/business_template/evidence/EvidenceRepository.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/Evidence/EvidenceRepository.sol rename to contracts/business_template/evidence/EvidenceRepository.sol diff --git a/contracts/business_template/Evidence/RequestRepository.sol b/contracts/business_template/evidence/RequestRepository.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/Evidence/RequestRepository.sol rename to contracts/business_template/evidence/RequestRepository.sol diff --git a/contracts/business_template/evidence_plus/EvidenceFactory.sol b/contracts/business_template/evidence_plus/EvidenceFactory.sol old mode 100644 new mode 100755 diff --git a/contracts/business_template/evidence_plus/evidence.sol b/contracts/business_template/evidence_plus/evidence.sol old mode 100644 new mode 100755 diff --git a/contracts/business_template/Role_operation/Character.sol b/contracts/business_template/marriage_evidence/Character.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/Role_operation/Character.sol rename to contracts/business_template/marriage_evidence/Character.sol diff --git a/contracts/business_template/marriage_evidence/Evidence.sol b/contracts/business_template/marriage_evidence/Evidence.sol new file mode 100755 index 00000000..0a954216 --- /dev/null +++ b/contracts/business_template/marriage_evidence/Evidence.sol @@ -0,0 +1,89 @@ +pragma solidity ^0.4.25; + +contract EvidenceSignersDataABI +{ + //验证是否是合法地址 + function verify(address addr)public constant returns(bool){} + //根据索引值返回签名者地址 + function getSigner(uint index)public constant returns(address){} + //返回签名人数 + function getSignersSize() public constant returns(uint){} +} + +contract Evidence{ + + string evidence; //存证信息 + address[] signers;//储存合法签名者地址 + address public factoryAddr;//工厂合约地址 + //返回事件信息,查看log->判断正确或错误的信息 + event addSignaturesEvent(string evi); + event newSignaturesEvent(string evi, address addr); + event errorNewSignaturesEvent(string evi, address addr); + event errorAddSignaturesEvent(string evi, address addr); + event addRepeatSignaturesEvent(string evi); + event errorRepeatSignaturesEvent(string evi, address addr); + //查看此地址是否为合法签名者地址 + function CallVerify(address addr) public constant returns(bool) { + return EvidenceSignersDataABI(factoryAddr).verify(addr); + } + //初始化,创建存证合约 + constructor(string evi, address addr) { + factoryAddr = addr; + //tx.origin =>启动交易的原始地址(其实就是部署者的地址) + //如果是外部调用,在此可以理解为函数调用者地址 + if(CallVerify(tx.origin)) + { + evidence = evi; + signers.push(tx.origin); + newSignaturesEvent(evi,addr); + } + else + { + errorNewSignaturesEvent(evi,addr); + } + } + //返回签名信息,合约签名者地址,当前签名者地址 + function getEvidence() public constant returns(string,address[],address[]){ + uint length = EvidenceSignersDataABI(factoryAddr).getSignersSize(); + address[] memory signerList = new address[](length); + for(uint i= 0 ;iuint256) balances; + // A->B = 100 A->C 200 + mapping(address=>mapping(address=>uint256)) allows; + + constructor(string memory n, string memory s) public { + pointName = n; + pointSymbol = s; + owner = msg.sender; + } + + function mint(address _to, uint256 _value) external returns (bool success) { + require(_value > 0, "_value must > 0"); + require(address(0) != _to, "to must a valid address"); + require(msg.sender == owner, "only owner can do"); + + + balances[_to] = balances[_to].add(_value); + pointTotalSupply = pointTotalSupply.add(_value); + emit Transfer(address(0), _to, _value); + success = true; + } + + function name() override external view returns (string memory) { + return pointName; + } + function symbol() override external view returns (string memory) { + return pointSymbol; + } + function totalSupply() override external view returns (uint256) { + return pointTotalSupply; + } + function balanceOf(address _owner) override external view returns (uint256 balance) { + return balances[_owner]; + } + function transfer(address _to, uint256 _value) override external returns (bool success) { + require(_value > 0, "_value must > 0"); + require(address(0) != _to, "to must a valid address"); + require(balances[msg.sender] >= _value, "user's balance must enough"); + + //balances[msg.sender] -= _value; + balances[msg.sender] = balances[msg.sender].sub(_value); + //balances[_to] += _value; + balances[_to] = balances[_to].add(_value); + + emit Transfer(msg.sender, _to, _value); + return true; + } + function approve(address _spender, uint256 _value) override external returns (bool success) { + success = false; + require(_value > 0, "_value must > 0"); + require(address(0) != _spender, "_spender must a valid address"); + require(balances[msg.sender] >= _value, "user's balance must enough"); + + allows[msg.sender][_spender] = _value; + + emit Approval(msg.sender, _spender, _value); + success = true; + return true; + } + function transferFrom(address _from, address _to, uint256 _value) override external returns (bool success) { + require(_value > 0, "_value must > 0"); + require(address(0) != _to, "to must a valid address"); + require(balances[_from] >= _value, "user's balance must enough"); + + //balances[_from] -= _value; + balances[_from] = balances[_from].sub(_value); + //balances[_to] += _value; + balances[_to] = balances[_to].add(_value); + //allows[_from][msg.sender] -= _value; + allows[_from][msg.sender] = allows[_from][msg.sender].sub(_value); + + success = true; + emit Transfer(_from, _to, _value); + } + function allowance(address _owner, address _spender) override external view returns (uint256 remaining) { + return allows[_owner][_spender]; + } + +} \ No newline at end of file diff --git a/contracts/business_template/redpacket/proxy.sol b/contracts/business_template/red_packet/proxy.sol old mode 100644 new mode 100755 similarity index 99% rename from contracts/business_template/redpacket/proxy.sol rename to contracts/business_template/red_packet/proxy.sol index c199c873..4569ba86 --- a/contracts/business_template/redpacket/proxy.sol +++ b/contracts/business_template/red_packet/proxy.sol @@ -41,4 +41,5 @@ interface IPoint { function approve(address _spender, uint256 _value) external returns (bool success); function transferFrom(address _from, address _to, uint256 _value) external returns (bool success); function allowance(address _owner, address _spender) external view returns (uint256 remaining); + } \ No newline at end of file diff --git a/contracts/business_template/red_packet/redpacket.sol b/contracts/business_template/red_packet/redpacket.sol new file mode 100755 index 00000000..dc3b72ba --- /dev/null +++ b/contracts/business_template/red_packet/redpacket.sol @@ -0,0 +1,95 @@ +pragma solidity^0.6.0; + +import "./IERC20.sol"; +import "./SafeMath.sol"; + + +//定义接口 +contract mytoken is IERC20 { + using SafeMath for uint256; + //定义name + string tokenName; + string tokenSymbol; + uint256 tokenTotalSupply; + address owner; + //user's balance + mapping(address=>uint256) balances; + // A->B = 100 A->C 200 + mapping(address=>mapping(address=>uint256)) allows; + + constructor(string memory n, string memory s) public { + tokenName = n; + tokenSymbol = s; + owner = msg.sender; + } + + function mint(address _to, uint256 _value) external returns (bool success) { + require(_value > 0, "_value must > 0"); + require(address(0) != _to, "to must a valid address"); + require(msg.sender == owner, "only owner can do"); + + //balances[_to] += _value; + balances[_to] = balances[_to].add(_value); + //tokenTotalSupply += _value; + tokenTotalSupply = tokenTotalSupply.add(_value); + emit Transfer(address(0), _to, _value); + success = true; + } + + function name() override external view returns (string memory) { + return tokenName; + } + function symbol() override external view returns (string memory) { + return tokenSymbol; + } + function totalSupply() override external view returns (uint256) { + return tokenTotalSupply; + } + function balanceOf(address _owner) override external view returns (uint256 balance) { + return balances[_owner]; + } + function transfer(address _to, uint256 _value) override external returns (bool success) { + require(_value > 0, "_value must > 0"); + require(address(0) != _to, "to must a valid address"); + require(balances[msg.sender] >= _value, "user's balance must enough"); + + //balances[msg.sender] -= _value; + balances[msg.sender] = balances[msg.sender].sub(_value); + //balances[_to] += _value; + balances[_to] = balances[_to].add(_value); + + emit Transfer(msg.sender, _to, _value); + return true; + } + function approve(address _spender, uint256 _value) override external returns (bool success) { + success = false; + require(_value > 0, "_value must > 0"); + require(address(0) != _spender, "_spender must a valid address"); + require(balances[msg.sender] >= _value, "user's balance must enough"); + + allows[msg.sender][_spender] = _value; + + emit Approval(msg.sender, _spender, _value); + success = true; + return true; + } + function transferFrom(address _from, address _to, uint256 _value) override external returns (bool success) { + require(_value > 0, "_value must > 0"); + require(address(0) != _to, "to must a valid address"); + require(balances[_from] >= _value, "user's balance must enough"); + + //balances[_from] -= _value; + balances[_from] = balances[_from].sub(_value); + //balances[_to] += _value; + balances[_to] = balances[_to].add(_value); + //allows[_from][msg.sender] -= _value; + allows[_from][msg.sender] = allows[_from][msg.sender].sub(_value); + + success = true; + emit Transfer(_from, _to, _value); + } + function allowance(address _owner, address _spender) override external view returns (uint256 remaining) { + return allows[_owner][_spender]; + } + +} diff --git a/contracts/business_template/redpacket/redpacket.sol b/contracts/business_template/redpacket/redpacket.sol deleted file mode 100644 index 7c98df09..00000000 --- a/contracts/business_template/redpacket/redpacket.sol +++ /dev/null @@ -1,70 +0,0 @@ -pragma solidity ^0.4.25; -import "./SafeMath.sol"; -import "./Proxy.sol"; - -contract RedPacket { - //定义土豪 - address theRich; - //定义红包的数据 - uint256 public totalAmount;//红包金额 - uint256 public leftAmount;//剩余金额 - uint256 public count;//红包数量 - bool isEqual;//是否等额 - Proxy proxyContract;//红包的合约地址 - using SafeMath for uint256; - //抢过了不能再抢 - mapping(address=>bool) isGrabed; - - //构造函数:土豪执行,顺带将红包也发了 - constructor() public { - proxyContract = new Proxy();//创建代理合约对象 - - } - - //调用前,用户需要先调用积分合约的授权给本合约 - function sendRedPacket(uint256 c, bool ok, address addr, uint256 amount) public { - require(count == 0, "the red packet already exists"); - require(address(0) != addr, "addr is 0"); - require(amount > 0, "amount is 0"); - require(c > 0, "c is 0"); - isEqual = ok; - count = c; - proxyContract.setPointAddr(addr);//绑定要发送的积分合约地址 - require(proxyContract.balanceOf(msg.sender) > 0, "user's balance not enough"); - leftAmount = totalAmount = amount; - theRich = msg.sender; - } - - //抢红包 - function grabRedpacket() public { - require(count > 0, "count must > 0"); - require(leftAmount > 0, "leftAmount must > 0"); - require(!isGrabed[msg.sender], "msg.sender must has not grabed"); - isGrabed[msg.sender] = true; - - //如果是最后一个红包-- 直接拿走 - if(count == 1) { - proxyContract.transfer(theRich, msg.sender, leftAmount); - leftAmount = 0; - } else { - //是否为等额 - if(isEqual) { - uint256 transferAmount = leftAmount / count; - leftAmount = leftAmount.sub(amount); - proxyContract.transfer(theRich, msg.sender, amount); - } else { - //计算一个10以内的随机值 - uint256 random = uint256(keccak256(abi.encode(msg.sender, theRich, count, leftAmount, now))) % 8 + 1; - uint256 amount = totalAmount * random / 10; - proxyContract.transfer(theRich, msg.sender, amount); - leftAmount = leftAmount.sub(amount); - - } - } - count --; - } - - function getProxy() public view returns (address) { - return proxyContract.addr(); - } -} \ No newline at end of file diff --git a/contracts/business_template/RewardPoint/Admin.sol b/contracts/business_template/reward_point/Admin.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/Admin.sol rename to contracts/business_template/reward_point/Admin.sol diff --git a/contracts/business_template/RewardPoint/BasicAuth.sol b/contracts/business_template/reward_point/BasicAuth.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/BasicAuth.sol rename to contracts/business_template/reward_point/BasicAuth.sol diff --git a/contracts/business_template/RewardPoint/IssuerRole.sol b/contracts/business_template/reward_point/IssuerRole.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/IssuerRole.sol rename to contracts/business_template/reward_point/IssuerRole.sol diff --git a/contracts/business_template/RewardPoint/LibRoles.sol b/contracts/business_template/reward_point/LibRoles.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/LibRoles.sol rename to contracts/business_template/reward_point/LibRoles.sol diff --git a/contracts/business_template/RewardPoint/LibSafeMath.sol b/contracts/business_template/reward_point/LibSafeMath.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/LibSafeMath.sol rename to contracts/business_template/reward_point/LibSafeMath.sol diff --git a/contracts/business_template/RewardPoint/RewardPointController.sol b/contracts/business_template/reward_point/RewardPointController.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/RewardPointController.sol rename to contracts/business_template/reward_point/RewardPointController.sol diff --git a/contracts/business_template/RewardPoint/RewardPointData.sol b/contracts/business_template/reward_point/RewardPointData.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/RewardPoint/RewardPointData.sol rename to contracts/business_template/reward_point/RewardPointData.sol diff --git a/contracts/business_template/simple_point/SimplePointDemo.sol b/contracts/business_template/simple_point/SimplePointDemo.sol new file mode 100755 index 00000000..a17a309a --- /dev/null +++ b/contracts/business_template/simple_point/SimplePointDemo.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.25; + +contract PointDemo{ + + address public minter; + + mapping(address => uint) public balances; + + event Sent(address from,address to,uint amount); + constructor() public{ + minter = msg.sender; + } + function mint(address receiver,uint amount) public{ + require(msg.sender == minter); + balances[receiver] += amount; + } + + function send(address receiver,uint amount) public{ + require(amount <= balances[msg.sender]); + balances[msg.sender] -= amount; + balances[receiver] += amount; + emit Sent(msg.sender,receiver,amount); + } +} \ No newline at end of file diff --git a/contracts/business_template/Traceability/Goods.sol b/contracts/business_template/traceability/Goods.sol old mode 100644 new mode 100755 similarity index 72% rename from contracts/business_template/Traceability/Goods.sol rename to contracts/business_template/traceability/Goods.sol index c5e488c6..6785bf7e --- a/contracts/business_template/Traceability/Goods.sol +++ b/contracts/business_template/traceability/Goods.sol @@ -16,14 +16,14 @@ contract Goods{ constructor(uint64 goodsId) public{ _goodsId = goodsId; - _traceData.push(TraceData({addr:msg.sender, status:0, timestamp:now, remark:"create"})); - emit newStatus(msg.sender, 0, now, "create"); + _traceData.push(TraceData({addr:tx.origin, status:0, timestamp:now, remark:"create"})); + emit newStatus(tx.origin, 0, now, "create"); } function changeStatus(int16 goodsStatus, string memory remark) public { _status = goodsStatus; - _traceData.push(TraceData({addr:msg.sender, status:goodsStatus, timestamp:now, remark:remark})); - emit newStatus(msg.sender, goodsStatus, now, remark); + _traceData.push(TraceData({addr:tx.origin, status:goodsStatus, timestamp:now, remark:remark})); + emit newStatus(tx.origin, goodsStatus, now, remark); } function getStatus()public view returns(int16){ @@ -33,4 +33,4 @@ contract Goods{ function getTraceInfo()public view returns(TraceData[] memory _data){ return _traceData; } -} \ No newline at end of file +} diff --git a/contracts/business_template/Traceability/Traceability.sol b/contracts/business_template/traceability/Traceability.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/Traceability/Traceability.sol rename to contracts/business_template/traceability/Traceability.sol diff --git a/contracts/business_template/Traceability/TraceabilityFactory.sol b/contracts/business_template/traceability/TraceabilityFactory.sol old mode 100644 new mode 100755 similarity index 93% rename from contracts/business_template/Traceability/TraceabilityFactory.sol rename to contracts/business_template/traceability/TraceabilityFactory.sol index 083a66c5..885d84a5 --- a/contracts/business_template/Traceability/TraceabilityFactory.sol +++ b/contracts/business_template/traceability/TraceabilityFactory.sol @@ -48,4 +48,8 @@ contract TraceabilityFactory{ Traceability category = getTraceability(goodsGroup); return category.getGoods(goodsId); } -} \ No newline at end of file + + function getGoodsGroup(string memory name) public pure returns (bytes32) { + return keccak256(abi.encode(name)); + } +} diff --git a/contracts/common_tools/DateTimeContract.sol b/contracts/common_tools/DateTimeContract.sol new file mode 100644 index 00000000..583f8c3e --- /dev/null +++ b/contracts/common_tools/DateTimeContract.sol @@ -0,0 +1,154 @@ +pragma solidity >=0.4.25 <=0.6.10; + +///-------------------------------------------------------------------------------------------- +/// DateTimeContract v1.0 +/// 算法参考自https://mp.weixin.qq.com/s/bcUCYW6bt0fuLKYp4EqgNw +/// @title 时间操作合约 +/// @author jianglong,wei +/// @dev 基于block.timestamp 时间戳计算当前的日期,提供年份、月份、日期、小时、分钟、秒的计算函数 +///--------------------------------------------------------------------------------------------- +contract DateTimeContract { + uint256[] flat_year_month_day = [ + 0, + 31, + 28, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 + ]; + uint256[] leap_year_month_day = [ + 0, + 31, + 29, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 + ]; + + uint256 constant SECONDS_PER_FOUR_YEAR = 126230400; + uint256 constant SECONDS_PER_DAY = 24 * 60 * 60; + uint256 constant SECONDS_PER_HOUR = 60 * 60; + uint256 constant SECONDS_PER_MINUTE = 60; + uint256 constant SECONDS_PER_YEAR_FLAT = 31536000; + uint256 constant SECONDS_PER_YEAR_LEAP = 31622400; + uint256 constant UNIX_TIME_YEAR = 1970; + uint256 constant LEAP_YEAR = 0; + uint256 constant FLAT_YEAR = 1; + uint256 constant HOUR_OFFSET = 8; + + function getYear(uint256 timestamp) public view returns (uint256 _year) { + (_year, , , , , ) = timestampToDate(timestamp); + } + + function getMonth(uint256 timestamp) public view returns (uint256 _month) { + (, _month, , , , ) = timestampToDate(timestamp); + } + + function getDay(uint256 timestamp) public view returns (uint256 _day) { + (, , _day, , , ) = timestampToDate(timestamp); + } + + function getHour(uint256 timestamp) public view returns (uint256 _hour) { + (, , , _hour, , ) = timestampToDate(timestamp); + } + + function getMinute(uint256 timestamp) + public + view + returns (uint256 _minute) + { + (, , , , _minute, ) = timestampToDate(timestamp); + } + + function getSecond(uint256 timestamp) + public + view + returns (uint256 _second) + { + (, , , , , _second) = timestampToDate(timestamp); + } + + ///get date time according to timestamp(like block.timestamp) + function timestampToDate(uint256 timestamp) + public + view + returns ( + uint256 _year, + uint256 _month, + uint256 _days, + uint256 _hours, + uint256 _minute, + uint256 _second + ) + { + _second = timestamp % SECONDS_PER_MINUTE; + _minute = (timestamp % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE; + while (timestamp >= SECONDS_PER_FOUR_YEAR) { + _year++; + timestamp -= SECONDS_PER_FOUR_YEAR; + } + _year = UNIX_TIME_YEAR + (4 * _year); + if (timestamp >= SECONDS_PER_YEAR_FLAT) { + _year++; + timestamp -= SECONDS_PER_YEAR_FLAT; + if (timestamp >= SECONDS_PER_YEAR_FLAT) { + _year++; + timestamp -= SECONDS_PER_YEAR_FLAT; + if (timestamp >= SECONDS_PER_YEAR_LEAP) { + _year++; + timestamp -= SECONDS_PER_YEAR_LEAP; + if (timestamp >= SECONDS_PER_YEAR_FLAT) { + _year++; + timestamp -= SECONDS_PER_YEAR_FLAT; + } + } + } + } + uint256 isLeapOrFlatYear; + if (((_year % 4 == 0) && (_year % 100 != 0)) || (_year % 400 == 0)) { + isLeapOrFlatYear = LEAP_YEAR; + } else { + isLeapOrFlatYear = FLAT_YEAR; + } + + // compute days left + _days = timestamp / SECONDS_PER_DAY; + + // compute hours + _hours = + (timestamp - _days * SECONDS_PER_DAY) / + SECONDS_PER_HOUR + + HOUR_OFFSET; + _month = 1; + + // compute month + for (uint256 i = 0; i < 12; i++) { + if (isLeapOrFlatYear == FLAT_YEAR) { + if (_days >= flat_year_month_day[i + 1]) { + _month++; + _days -= flat_year_month_day[i + 1]; + } + } else if (isLeapOrFlatYear == LEAP_YEAR) { + if (_days >= leap_year_month_day[i + 1]) { + _month++; + _days -= leap_year_month_day[i + 1]; + } + } + } + _days += 1; + } +} diff --git a/contracts/common_tools/privacy_computation/DGHV-HE/DGHV_Homomorphic_Encryption.sol b/contracts/common_tools/privacy_computation/DGHV-HE/DGHV_Homomorphic_Encryption.sol new file mode 100755 index 00000000..7cd50f6c --- /dev/null +++ b/contracts/common_tools/privacy_computation/DGHV-HE/DGHV_Homomorphic_Encryption.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.4.16 < 0.9.0; + +import './LibSafeMathForUint256Utils.sol'; + +contract DGHV_Homomorphic_Encryption { + + // 随机数参数 + uint private m = 100; // 线性求余迭代次数 + uint private k = 3877; // 乘数 + uint private b = 29573; // 增量 + + // DGHV参数 + uint256 private eta; // 安全参数 + uint256 private q; + uint256 private p; // 密钥 + + constructor(uint _eta, uint _q, uint _p) public { + require(_p % 2 == 1); // 密钥必须是一个大奇数 + eta = _eta; + q = _q; + p = _p; + } + + // 使用线性求余的随机数生成器 + function randomGen(uint range, uint seed) private view returns (uint) { + require(range > 0); + uint LCG_random_num = LCG(seed, range); + return uint(keccak256(abi.encodePacked(block.timestamp, LCG_random_num))) % range; + } + + function LCG(uint _seed, uint range) private view returns(uint) { + uint val = _seed; + for (uint256 index = 0; index < m; index++) { + //TODO 内联汇编优化计算 + val = (LibSafeMathForUint256Utils.add(LibSafeMathForUint256Utils.mul(k, val), b)) % range; + } + return val; + } + + // 同态加密 + function encrypto(uint8 _m) public view returns (uint) { + require(_m == 0 || _m == 1); + // 生成随机数r + uint r = randomGen(8, block.timestamp%1000); + return LibSafeMathForUint256Utils.add(LibSafeMathForUint256Utils.add(_m, 2*r), LibSafeMathForUint256Utils.mul(p, q)); + } + + // 同态解密 + function decrypto(uint _c) public view returns (uint) { + return LibSafeMathForUint256Utils.mod(LibSafeMathForUint256Utils.mod(_c, p), 2); + } + + // 同态加法 + function HE_Add(uint _c1, uint _c2) public view returns(uint) { + return decrypto(LibSafeMathForUint256Utils.add(_c1, _c2)); + } + + // 同态乘法(可能会溢出) + function HE_Mul(uint _c1, uint _c2) public view returns(uint){ + return decrypto(LibSafeMathForUint256Utils.mul(_c1, _c2)); + } + + +} diff --git a/contracts/common_tools/privacy_computation/DGHV-HE/LibSafeMathForUint256Utils.sol b/contracts/common_tools/privacy_computation/DGHV-HE/LibSafeMathForUint256Utils.sol new file mode 100755 index 00000000..f79907f8 --- /dev/null +++ b/contracts/common_tools/privacy_computation/DGHV-HE/LibSafeMathForUint256Utils.sol @@ -0,0 +1,77 @@ +/* + * Copyright 2014-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * */ + +pragma solidity ^0.4.25; + +library LibSafeMathForUint256Utils { + + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMathForUint256: addition overflow"); + return c; + } + + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(b <= a, "SafeMathForUint256: subtraction overflow"); + uint256 c = a - b; + return c; + } + + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + if (a == 0 || b == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMathForUint256: multiplication overflow"); + return c; + } + + function div(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMathForUint256: division by zero"); + uint256 c = a / b; + return c; + } + + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + require(b != 0, "SafeMathForUint256: modulo by zero"); + return a % b; + } + + function power(uint256 a, uint256 b) internal pure returns (uint256){ + + if(a == 0) return 0; + if(b == 0) return 1; + + uint256 c = 1; + for(uint256 i = 0; i < b; i++){ + c = mul(c, a); + } + } + + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return a >= b ? a : b; + } + + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + function average(uint256 a, uint256 b) internal pure returns (uint256) { + return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); + } + +} diff --git a/contracts/common_tools/privacy_computation/DGHV-HE/syn_DGHV.go b/contracts/common_tools/privacy_computation/DGHV-HE/syn_DGHV.go new file mode 100755 index 00000000..f23e6c30 --- /dev/null +++ b/contracts/common_tools/privacy_computation/DGHV-HE/syn_DGHV.go @@ -0,0 +1,127 @@ +package main + +import ( + "fmt" + "math" + "math/big" + "math/rand" + "os" + "strconv" + "time" +) + +var ( + eta int // 安全参数η + p uint64 // 对称密钥 + q *big.Int // 参数 +) + +func main() { + if len(os.Args) <= 1 { + panic("Please input parameters η") + } + // 为了防止q的溢出,q是64位则η<=4,q是256位则η<=6 (η^3 < 位数) + eta, _ = strconv.Atoi(os.Args[1]) // 测试得出: η >= 9 加法、乘法计算稳定 + fmt.Println("η = ", eta) + fmt.Printf("p range is [%d, %d)\n", int(math.Pow(float64(2), float64(eta-1))), int(math.Pow(float64(2), float64(eta)))) + for i := 0; i < 100; i++ { + rand.Seed(time.Now().UnixNano() + int64(i)) + // 生成密钥 + fmt.Println("p = ", genKey_p()) + // 生成参数q + fmt.Printf("q = %d\n", genPara_q()) + //genPara_q() + // 加密测试 + m0, m1 := uint(0), uint(1) + fmt.Printf("m0 = %d, m1 = %d\n", m0, m1) + c0 := Encrypto(m0) + c1 := Encrypto(m1) + //fmt.Printf("c0 = %d, c1 = %d\n", c0, c1) + // 解密 + n0, n1 := Decrypto(c0), Decrypto(c1) + fmt.Printf("解密结果:n0 = %d, n1 = %d\n", n0, n1) + // 评估 + // 加法测试 + fmt.Printf("加法测试:%d + %d , %v\n", m0, m1, EvaluateAdd(m0, m1, c0, c1)) + fmt.Printf("加法测试:%d + %d , %v\n", m0, m0, EvaluateAdd(m0, m0, c0, c0)) + fmt.Printf("加法测试:%d + %d , %v\n", m1, m1, EvaluateAdd(m1, m1, c1, c1)) + fmt.Printf("加法测试:%d + %d , %v\n", m1, m0, EvaluateAdd(m1, m0, c1, c0)) + fmt.Println("==============================================") + // 乘法测试 + fmt.Printf("乘法测试:%d * %d , %v\n", m0, m1, EvaluateMul(m0, m1, c0, c1)) + fmt.Printf("乘法测试:%d * %d , %v\n", m0, m0, EvaluateMul(m0, m0, c0, c0)) + fmt.Printf("乘法测试:%d * %d , %v\n", m1, m1, EvaluateMul(m1, m1, c1, c1)) + fmt.Printf("乘法测试:%d * %d , %v\n", m1, m0, EvaluateMul(m1, m0, c1, c0)) + fmt.Println("==============================================") + } +} + +func genKey_p() uint64 { + // p ∈ [2^(η−1), 2^η) and odd + for { + randomP := int(math.Pow(float64(2), float64(eta-1))) + rand.Intn(int(math.Pow(float64(2), float64(eta-1)))) + if randomP % 2 == 1 { + p = uint64(randomP) + return p + } + } +} + +func genPara_r() int64 { + // |2r| < p/2 + // r ≈ 2^(√η) + goal := int(math.Pow(2, math.Sqrt(float64(eta)))) + r := 2 + randr := goal - r + 2 * rand.Intn(r) + for int(math.Abs(float64(2 * randr))) >= int(p) / 2 { + rand.Seed(time.Now().UnixNano()) + randr = goal - r + 2 * rand.Intn(r) + } + //fmt.Println("r = ", randr) + return int64(randr) +} + +func genPara_q() *big.Int { + // q ≈ 2^(η^3) + goal := big.NewInt(1) + for i := 0; i < int(math.Pow(float64(eta), 3)); i++ { + goal.Mul(goal, big.NewInt(2)) + } + r := 100 + goal.Sub(goal, big.NewInt(int64(r))) + goal.Add(goal, big.NewInt(int64(2 * rand.Intn(r)))) + q = goal + return q +} + +func Encrypto(m uint) *big.Int { + r := genPara_r() + c := big.NewInt(int64(m) + 2*r) + mul := q.Mul(q, big.NewInt(int64(p))) + c.Add(c, mul) + return c +} + +func Decrypto(c *big.Int) uint64 { + mod := &big.Int{} + mod = mod.Mod(c, big.NewInt(int64(p))) + mod.Mod(mod, big.NewInt(2)) + return mod.Uint64() +} + +func EvaluateAdd(m0, m1 uint, c0, c1 *big.Int) bool { + c := &big.Int{} + c.Add(c0, c1) + n := Decrypto(c) + if m0 == 1 && m1 == 1 { + return n == 0 + } + return n == uint64(m0 + m1) +} + +func EvaluateMul(m0, m1 uint, c0, c1 *big.Int) bool { + c := &big.Int{} + c.Mul(c0, c1) + n := Decrypto(c) + return n == uint64(m0 * m1) +} \ No newline at end of file diff --git a/contracts/business_template/privacy_computation/Fiat-Shamir-ZK/FiatShamir.sol b/contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/FiatShamir.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/privacy_computation/Fiat-Shamir-ZK/FiatShamir.sol rename to contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/FiatShamir.sol diff --git a/contracts/business_template/privacy_computation/Fiat-Shamir-ZK/contract_step1.py b/contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/contract_step1.py old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/privacy_computation/Fiat-Shamir-ZK/contract_step1.py rename to contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/contract_step1.py diff --git a/contracts/business_template/privacy_computation/Fiat-Shamir-ZK/contract_step2.py b/contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/contract_step2.py old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/privacy_computation/Fiat-Shamir-ZK/contract_step2.py rename to contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/contract_step2.py diff --git a/contracts/business_template/privacy_computation/Fiat-Shamir-ZK/contract_step45.py b/contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/contract_step45.py old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/privacy_computation/Fiat-Shamir-ZK/contract_step45.py rename to contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/contract_step45.py diff --git a/contracts/business_template/privacy_computation/Fiat-Shamir-ZK/fiat_shamir_1.py b/contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/fiat_shamir_1.py old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/privacy_computation/Fiat-Shamir-ZK/fiat_shamir_1.py rename to contracts/common_tools/privacy_computation/Fiat-Shamir-ZK/fiat_shamir_1.py diff --git a/contracts/common_tools/role/RBAC/Example.sol b/contracts/common_tools/role/RBAC/Example.sol new file mode 100755 index 00000000..25362973 --- /dev/null +++ b/contracts/common_tools/role/RBAC/Example.sol @@ -0,0 +1,41 @@ +pragma solidity ^0.6.10; + +import "./Ownable.sol"; +import "./RBAC.sol"; + +/** + * @author SomeJoker + * @title 例子 + */ +contract Example is Ownable,RBAC{ + string constant private ADD = "ADD"; + string constant private SUB = "SUB"; + string constant private MUL = "MUL"; + string constant private DIV = "DIV"; + + function setRole(address addr,string memory _role) public onlyOwner{ + addRole(addr, _role); + } + + function resetRole(address addr,string memory _role) public onlyOwner{ + removeRole(addr, _role); + } + + function add(uint a,uint b) public view onlyRole(ADD) returns(uint){ + return a+b; + } + + function sub(uint a,uint b) public view onlyRole(SUB) returns(uint){ + return a-b; + } + + function mul(uint a,uint b) public view onlyRole(MUL) returns(uint){ + return a*b; + } + + function div(uint a,uint b) public view onlyRole(DIV) returns(uint){ + return a/b; + } + + +} \ No newline at end of file diff --git a/contracts/common_tools/role/RBAC/Ownable.sol b/contracts/common_tools/role/RBAC/Ownable.sol new file mode 100755 index 00000000..8f36db92 --- /dev/null +++ b/contracts/common_tools/role/RBAC/Ownable.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.6.10; + + +/** + * @author SomeJoker + * @title Ownable + */ +contract Ownable{ + address public owner; + + event OwnershipRenounced(address indexed lastOwner); + event OwnershipTransfer(address indexed lastOwner,address indexed currentOwner); + + constructor() public{ + owner = msg.sender; + } + + modifier onlyOwner{ + require(msg.sender == owner, "msg.sender is not owner"); + _; + } + + function renounceOwnership() public onlyOwner{ + emit OwnershipRenounced(owner); + owner = address(0); + } + + function transferOwnership(address _newOwner) public onlyOwner { + require(_newOwner != address(0),"_newOwner Can't be Zero address"); + emit OwnershipTransfer(owner,_newOwner); + owner = _newOwner; + } +} \ No newline at end of file diff --git a/contracts/common_tools/role/RBAC/RBAC.sol b/contracts/common_tools/role/RBAC/RBAC.sol new file mode 100755 index 00000000..b8325468 --- /dev/null +++ b/contracts/common_tools/role/RBAC/RBAC.sol @@ -0,0 +1,38 @@ +pragma solidity ^0.6.10; +import "./Roles.sol"; + +/** + * @author SomeJoker + * @title RBAC + */ +contract RBAC{ + using Roles for Roles.Role; + + mapping (string => Roles.Role) private roles; + + event RoleAdded(address indexed operater,string role); + event RoleRemoved(address indexed operater,string role); + + function addRole(address _operater, string memory _role) internal{ + roles[_role].addRole(_operater); + emit RoleAdded(_operater,_role); + } + + function removeRole(address _operater, string memory _role) internal{ + roles[_role].removeRole(_operater); + emit RoleRemoved(_operater,_role); + } + + function hasRole(address _operater, string memory _role) public view returns(bool){ + return roles[_role].hasRole(_operater); + } + + function checkRole(address _operater, string memory _role) public view{ + roles[_role].checkRole(_operater); + } + + modifier onlyRole(string memory _role){ + checkRole(msg.sender, _role); + _; + } +} \ No newline at end of file diff --git a/contracts/common_tools/role/RBAC/Roles.sol b/contracts/common_tools/role/RBAC/Roles.sol new file mode 100755 index 00000000..d7c5ffcf --- /dev/null +++ b/contracts/common_tools/role/RBAC/Roles.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.6.10; +/** + * @author SomeJoker + * @title 角色 + */ +library Roles{ + + struct Role{ + mapping(address => bool) bearer; + } + + function addRole(Role storage role ,address addr) internal{ + role.bearer[addr] = true; + } + + function removeRole(Role storage role,address addr) internal{ + role.bearer[addr] = false; + } + + function hasRole(Role storage role,address addr) internal view returns(bool){ + return role.bearer[addr]; + } + + function checkRole(Role storage role,address addr) public view{ + require(hasRole(role, addr)); + } + +} \ No newline at end of file diff --git a/contracts/common_tools/role/role_operation/Character.sol b/contracts/common_tools/role/role_operation/Character.sol new file mode 100755 index 00000000..61b743ec --- /dev/null +++ b/contracts/common_tools/role/role_operation/Character.sol @@ -0,0 +1,86 @@ +pragma solidity^0.4.25; + +import "./Roles.sol"; + +contract Character{ + using Roles for Roles.Role; + Roles.Role private _character; + + event characterAdded(address amount,string summary); + event characterRemoved(address amount); + event characterRevised(address amount,string summary); + event characterSeeked(address amount); + + address owner; + address[] characters; + + + constructor()public{ + owner = msg.sender; + } + + modifier onlyOwner(){ + require(owner == msg.sender,"Only owner can call"); + _; + } + + function isCharacter(address amount)public view returns(bool){ + return _character.has(amount); + } + + function _addCharacter(address amount,string _summary)internal{ + _character.add(amount,_summary); + characters.push(amount); + emit characterAdded(amount,_summary); + } + + function _removeCharacter(address amount)internal{ + _character.remove(amount); + emit characterRemoved(amount); + } + + function _reviseCharacter(address amount,string _summary)internal{ + _character.revise(amount,_summary); + emit characterRevised(amount,_summary); + } + + function _seekCharacter(address amount)internal view returns(string){ + return _character.seek(amount); + emit characterSeeked(amount); + } + + function _removeCharacterByAddress(address amount)internal{ + for (uint i = 0; i < characters.length; i++) { + if (amount == characters[i]) + for (uint j = i; j < characters.length-1; j++) + characters[j] = characters[j+1]; + characters.length--; + } + } + + function addCharacter(address amount,string _summary)public onlyOwner{ + require(!isCharacter(amount),"The character already exist"); + _addCharacter(amount,_summary); + } + + function removeCharacter(address amount)public onlyOwner{ + require(isCharacter(amount),"The character does not exist"); + _removeCharacter(amount); + _removeCharacterByAddress(amount); + } + + function reviseCharacter(address amount,string _summary)public onlyOwner{ + require(isCharacter(amount),"The character does not exist"); + _reviseCharacter(amount,_summary); + } + + function seekCharacter(address amount)public view returns(string) { + require(isCharacter(amount),"The character does not exist"); + return _seekCharacter(amount); + } + + function getAllCharater()public view returns(address[]){ + return characters; + } + +} diff --git a/contracts/common_tools/role/role_operation/Roles.sol b/contracts/common_tools/role/role_operation/Roles.sol new file mode 100755 index 00000000..26de0d6d --- /dev/null +++ b/contracts/common_tools/role/role_operation/Roles.sol @@ -0,0 +1,35 @@ +pragma solidity^0.4.25; + +library Roles{ + struct Role{ + mapping(address=>bool) bearer; + mapping(address=>string) summary; + } + //判断角色 + function has(Role storage role,address amount)internal view returns(bool){ + require(amount!=address(0),"Address is zero address"); + return role.bearer[amount]; + } + //添加角色 + function add(Role storage role,address amount,string _summary)internal{ + require(!has(role,amount),"Address already exists"); + role.bearer[amount] = true; + role.summary[amount] = _summary; + } + //删除角色 + function remove(Role storage role,address amount)internal{ + require(has(role,amount),"Address does not exist"); + role.bearer[amount] = false; + } + //修改角色 + function revise(Role storage role,address amount,string _summary)internal { + require(has(role,amount),"Address does not exist"); + role.summary[amount] = _summary; + } + //查询角色 + function seek(Role storage role,address amount)internal view returns(string){ + require(has(role,amount),"Address does not exist"); + return role.summary[amount]; + } + +} \ No newline at end of file diff --git a/contracts/common_tools/role/white_list/SafeRole.sol b/contracts/common_tools/role/white_list/SafeRole.sol new file mode 100755 index 00000000..d6af855a --- /dev/null +++ b/contracts/common_tools/role/white_list/SafeRole.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.25; + + +library SafeRole { + struct Role { + mapping (address => bool) bearer; + } + + /** + * 给账户赋予角色. + */ + function add(Role storage role, address account) internal { + require(!has(role, account), "Roles: account already has role"); + role.bearer[account] = true; + } + + /** + * 账户移除角色 + */ + function remove(Role storage role, address account) internal { + require(has(role, account), "Roles: account does not have role"); + role.bearer[account] = false; + } + + /** + * 判断账户是否有此角色 + */ + function has(Role storage role, address account) internal view returns (bool) { + require(account != address(0), "Roles: account is the zero address"); + return role.bearer[account]; + } +} \ No newline at end of file diff --git a/contracts/common_tools/role/white_list/WhitelistAdminRole.sol b/contracts/common_tools/role/white_list/WhitelistAdminRole.sol new file mode 100755 index 00000000..257caaa3 --- /dev/null +++ b/contracts/common_tools/role/white_list/WhitelistAdminRole.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.4.25; + +import "./SafeRole.sol"; + + +contract WhitelistAdminRole { + using SafeRole for SafeRole.Role; + + event WhitelistAdminAdded(address indexed account); + event WhitelistAdminRemoved(address indexed account); + + SafeRole.Role private _whitelistAdmins; + + /** + * 构造器 + */ + constructor () internal { + _addWhitelistAdmin(msg.sender); + } + /** + * 白名单管理员权限修饰符 + */ + modifier onlyWhitelistAdmin() { + require(isWhitelistAdmin(msg.sender), "WhitelistAdminRole: caller does not have the WhitelistAdmin role"); + _; + } + /** + * 判断是否是白名单管理员 + */ + function isWhitelistAdmin(address account) public view returns (bool) { + return _whitelistAdmins.has(account); + } + /** + * 添加白名单管理员 + */ + function addWhitelistAdmin(address account) public onlyWhitelistAdmin { + _addWhitelistAdmin(account); + } + /** + * 移除白名单管理员 + */ + function renounceWhitelistAdmin() public { + _removeWhitelistAdmin(msg.sender); + } + + function _addWhitelistAdmin(address account) internal { + _whitelistAdmins.add(account); + emit WhitelistAdminAdded(account); + } + + function _removeWhitelistAdmin(address account) internal { + _whitelistAdmins.remove(account); + emit WhitelistAdminRemoved(account); + } +} \ No newline at end of file diff --git a/contracts/common_tools/role/white_list/WhitelistedRole.sol b/contracts/common_tools/role/white_list/WhitelistedRole.sol new file mode 100755 index 00000000..cb83c917 --- /dev/null +++ b/contracts/common_tools/role/white_list/WhitelistedRole.sol @@ -0,0 +1,45 @@ +pragma solidity ^0.4.25; + +import "./SafeRole.sol"; +import "./WhitelistAdminRole.sol"; + + +contract WhitelistedRole is WhitelistAdminRole { + using SafeRole for SafeRole.Role; + + event WhitelistedAdded(address indexed account); + event WhitelistedRemoved(address indexed account); + + SafeRole.Role private _whitelisteds; + + modifier onlyWhitelisted() { + require(isWhitelisted(msg.sender), "WhitelistedRole: caller does not have the Whitelisted role"); + _; + } + + function isWhitelisted(address account) public view returns (bool) { + return _whitelisteds.has(account); + } + + function addWhitelisted(address account) public onlyWhitelistAdmin { + _addWhitelisted(account); + } + + function removeWhitelisted(address account) public onlyWhitelistAdmin { + _removeWhitelisted(account); + } + + function renounceWhitelisted() public { + _removeWhitelisted(msg.sender); + } + + function _addWhitelisted(address account) internal { + _whitelisteds.add(account); + emit WhitelistedAdded(account); + } + + function _removeWhitelisted(address account) internal { + _whitelisteds.remove(account); + emit WhitelistedRemoved(account); + } +} \ No newline at end of file diff --git a/contracts/data_structure/LibDeque.sol b/contracts/data_structure/LibDeque.sol old mode 100644 new mode 100755 diff --git a/contracts/data_structure/LibQueue.sol b/contracts/data_structure/LibQueue.sol old mode 100644 new mode 100755 diff --git a/contracts/data_structure/LibStack.sol b/contracts/data_structure/LibStack.sol old mode 100644 new mode 100755 diff --git a/contracts/data_structure/LibMaxHeapUint256.sol b/contracts/data_structure/heap/LibMaxHeapUint256.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibMaxHeapUint256.sol rename to contracts/data_structure/heap/LibMaxHeapUint256.sol diff --git a/contracts/data_structure/LibMinHeapUint256.sol b/contracts/data_structure/heap/LibMinHeapUint256.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibMinHeapUint256.sol rename to contracts/data_structure/heap/LibMinHeapUint256.sol diff --git a/contracts/data_structure/LibLinkedList.sol b/contracts/data_structure/list/LibLinkedList.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibLinkedList.sol rename to contracts/data_structure/list/LibLinkedList.sol diff --git a/contracts/data_structure/LibSingleList.sol b/contracts/data_structure/list/LibSingleList.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibSingleList.sol rename to contracts/data_structure/list/LibSingleList.sol diff --git a/contracts/data_structure/LibBytesMap.sol b/contracts/data_structure/map/LibBytesMap.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibBytesMap.sol rename to contracts/data_structure/map/LibBytesMap.sol diff --git a/contracts/data_structure/MapDemo.sol b/contracts/data_structure/map/LibBytesMapDemo.sol old mode 100644 new mode 100755 similarity index 74% rename from contracts/data_structure/MapDemo.sol rename to contracts/data_structure/map/LibBytesMapDemo.sol index 818db9d1..b603edec --- a/contracts/data_structure/MapDemo.sol +++ b/contracts/data_structure/map/LibBytesMapDemo.sol @@ -1,12 +1,13 @@ pragma solidity ^0.4.25; import "./LibBytesMap.sol"; -contract MapDemo { +contract LibBytesMapDemo { using LibBytesMap for LibBytesMap.Map; LibBytesMap.Map private map; event Log(bytes key, uint256 index); + function f() public { string memory k1 = "k1"; string memory k2 = "k2"; @@ -14,13 +15,13 @@ contract MapDemo { string memory v1 = "v1"; string memory v2 = "v2"; string memory v3 = "v3"; - map.put(bytes(k1),bytes(v1)); - map.put(bytes(k2),bytes(v2)); - map.put(bytes(k3),bytes(v3)); + map.put(bytes(k1), bytes(v1)); + map.put(bytes(k2), bytes(v2)); + map.put(bytes(k3), bytes(v3)); uint256 i = map.iterate_start(); - while(map.can_iterate(i)){ + while (map.can_iterate(i)) { emit Log(map.getKeyByIndex(i), i); i = map.iterate_next(i); } diff --git a/contracts/data_structure/LibMerkleTree.sol b/contracts/data_structure/merkle_tree/LibMerkleTree.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibMerkleTree.sol rename to contracts/data_structure/merkle_tree/LibMerkleTree.sol diff --git a/contracts/data_structure/MerkleTreeDemo.sol b/contracts/data_structure/merkle_tree/MerkleTreeDemo.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/MerkleTreeDemo.sol rename to contracts/data_structure/merkle_tree/MerkleTreeDemo.sol diff --git a/contracts/data_structure/AddressSetDemo.sol b/contracts/data_structure/set/AddressSetDemo.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/AddressSetDemo.sol rename to contracts/data_structure/set/AddressSetDemo.sol diff --git a/contracts/data_structure/set/Bytes32SetDemo.sol b/contracts/data_structure/set/Bytes32SetDemo.sol new file mode 100755 index 00000000..6020d076 --- /dev/null +++ b/contracts/data_structure/set/Bytes32SetDemo.sol @@ -0,0 +1,113 @@ +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo { + using LibBytes32Set for LibBytes32Set.Bytes32Set; + + LibBytes32Set.Bytes32Set private bytesSet; + + function add() public view returns (bool) { + return + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF + ); + } + + function contains() public view returns (bool) { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF + ); + return + bytesSet.contains( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF + ); + } + + function getAll() public view returns (bytes32[]) { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + return bytesSet.getAll(); + } + + function remove(bytes32 del) public view returns (bytes32[]) { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + bytesSet.remove(del); + return bytesSet.getAll(); + } + + function removeAndAtPositon(bytes32 del, bytes32 key) + public + view + returns (bool, uint256) + { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + bytesSet.remove(del); + return bytesSet.atPosition(key); + } + + function getSize() public view returns (uint256) { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + return bytesSet.getSize(); + } + + function getByIndex(uint256 index) public view returns (bytes32) { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + return bytesSet.getByIndex(index); + } + + function atPosition() public view returns (bool, uint256) { + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB + ); + bytesSet.add( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + return + bytesSet.atPosition( + 0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC + ); + } +} diff --git a/contracts/data_structure/LibAddressSet.sol b/contracts/data_structure/set/LibAddressSet.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/data_structure/LibAddressSet.sol rename to contracts/data_structure/set/LibAddressSet.sol diff --git a/contracts/data_structure/set/LibBytes32Set.sol b/contracts/data_structure/set/LibBytes32Set.sol new file mode 100755 index 00000000..dd7c0a80 --- /dev/null +++ b/contracts/data_structure/set/LibBytes32Set.sol @@ -0,0 +1,112 @@ +pragma solidity ^0.4.25; +/** +* @author wpzczbyqy +* @title bytes32类型集合操作 +* 提供bytes32集合类型操作,包括新增元素,删除元素,获取元素等 +**/ + +library LibBytes32Set { + + struct Bytes32Set { + bytes32[] values; + mapping(bytes32 => uint256) indexes; + } + + /** + *@dev byte32集合是否包含某个元素 + *@param set bytes32类型集合 + *@param val 待验证的值 + *@return bool 是否包含该元素,true 包含;false 不包含 + **/ + function contains(Bytes32Set storage set, bytes32 val) internal view returns (bool) { + return set.indexes[val] != 0; + } + + /** + *@dev byte32集合,增加一个元素 + *@param set bytes32类型集合 + *@param val 待增加的值 + *@return bool 是否成功添加了元素 + **/ + function add(Bytes32Set storage set, bytes32 val) internal view returns (bool) { + + if(!contains(set, val)){ + set.values.push(val); + set.indexes[val] = set.values.length; + return true; + } + return false; + } + + /** + *@dev byte32集合,删除一个元素 + *@param set bytes32类型集合 + *@param val 待删除的值 + *@return bool 是否成功删除了元素 + **/ + function remove(Bytes32Set storage set, bytes32 val) internal view returns (bool) { + + uint256 valueIndex = set.indexes[val]; + + if(contains(set,val)){ + uint256 toDeleteIndex = valueIndex - 1; + uint256 lastIndex = set.values.length - 1; + + if(toDeleteIndex != lastIndex){ + bytes32 lastValue = set.values[lastIndex]; + set.values[toDeleteIndex] = lastValue; + set.indexes[lastValue] = valueIndex; + } + + delete set.values[lastIndex]; + delete set.indexes[val]; + set.values.length--; + + return true; + } + + return false; + } + + /** + *@dev 获取集合中的所有元素 + *@param set bytes32类型集合 + *@return bytes32[] 返回集合中的所有元素 + **/ + function getAll(Bytes32Set storage set) internal view returns (bytes32[] memory) { + return set.values; + } + + /** + *@dev 获取集合中元素的数量 + *@param set bytes32类型集合 + *@return uint256 集合中元素数量 + **/ + function getSize(Bytes32Set storage set) internal view returns (uint256) { + return set.values.length; + } + + /** + *@dev 某个元素在集合中的位置 + *@param set bytes32类型集合 + *@param val 待查找的值 + *@return bool,uint256 是否存在此元素与该元素的位置 + **/ + function atPosition (Bytes32Set storage set, bytes32 val) internal view returns (bool, uint256) { + if(contains(set, val)){ + return (true, set.indexes[val]-1); + } + return (false, 0); + } + + /** + *@dev 根据索引获取集合中的元素 + *@param set bytes32类型集合 + *@param index 索引 + *@return bytes32 查找到的元素 + **/ + function getByIndex(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + require(index < set.values.length,"Index: index out of bounds"); + return set.values[index]; + } +} \ No newline at end of file diff --git a/contracts/data_structure/set/LibUint256Set.sol b/contracts/data_structure/set/LibUint256Set.sol new file mode 100755 index 00000000..ee85b451 --- /dev/null +++ b/contracts/data_structure/set/LibUint256Set.sol @@ -0,0 +1,113 @@ +pragma solidity ^0.4.25; + +/** +* @author wpzczbyqy +* @title uint256类型集合操作 +* 提供uint256集合类型操作,包括新增元素,删除元素,获取元素等 +**/ + +library LibUint256Set { + + struct Uint256Set { + uint256[] values; + mapping(uint256 => uint256) indexes; + } + + /** + *@dev uint256集合是否包含某个元素 + *@param set uint256类型集合 + *@param val 待验证的值 + *@return bool 是否包含该元素,true 包含;false 不包含 + **/ + function contains(Uint256Set storage set, uint256 val) internal view returns (bool) { + return set.indexes[val] != 0; + } + + /** + *@dev uint256集合,增加一个元素 + *@param set uint256类型集合 + *@param val 待增加的值 + *@return bool 是否成功添加了元素 + **/ + function add(Uint256Set storage set, uint256 val) internal view returns (bool) { + + if(!contains(set, val)){ + set.values.push(val); + set.indexes[val] = set.values.length; + return true; + } + return false; + } + + /** + *@dev uint256集合,删除一个元素 + *@param set uint256类型集合 + *@param val 待删除的值 + *@return bool 是否成功删除了元素 + **/ + function remove(Uint256Set storage set, uint256 val) internal view returns (bool) { + + uint256 valueIndex = set.indexes[val]; + + if(contains(set,val)){ + uint256 toDeleteIndex = valueIndex - 1; + uint256 lastIndex = set.values.length - 1; + + if(toDeleteIndex != lastIndex){ + uint256 lastValue = set.values[lastIndex]; + set.values[toDeleteIndex] = lastValue; + set.indexes[lastValue] = valueIndex; + } + + delete set.values[lastIndex]; + delete set.indexes[val]; + set.values.length--; + + return true; + } + + return false; + } + + /** + *@dev 获取集合中的所有元素 + *@param set uint256类型集合 + *@return uint256[] 返回集合中的所有元素 + **/ + function getAll(Uint256Set storage set) internal view returns (uint256[] memory) { + return set.values; + } + + /** + *@dev 获取集合中元素的数量 + *@param set uint256类型集合 + *@return uint256 集合中元素数量 + **/ + function getSize(Uint256Set storage set) internal view returns (uint256) { + return set.values.length; + } + + /** + *@dev 某个元素在集合中的位置 + *@param set uint256类型集合 + *@param val 待查找的值 + *@return bool,uint256 是否存在此元素与该元素的位置 + **/ + function atPosition (Uint256Set storage set, uint256 val) internal view returns (bool, uint256) { + if(contains(set, val)){ + return (true, set.indexes[val]-1); + } + return (false, 0); + } + + /** + *@dev 根据索引获取集合中的元素 + *@param set uint256类型集合 + *@param index 索引 + *@return uint256 查找到的元素 + **/ + function getByIndex(Uint256Set storage set, uint256 index) internal view returns (uint256) { + require(index < set.values.length,"Index: index out of bounds"); + return set.values[index]; + } +} \ No newline at end of file diff --git a/contracts/data_structure/set/Uint256SetDemo.sol b/contracts/data_structure/set/Uint256SetDemo.sol new file mode 100755 index 00000000..0e2a0355 --- /dev/null +++ b/contracts/data_structure/set/Uint256SetDemo.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo { + using LibUint256Set for LibUint256Set.Uint256Set; + + LibUint256Set.Uint256Set private uintSet; + + function add() public view returns (bool) { + return uintSet.add(1); + } + + function contains() public view returns (bool) { + uintSet.add(1); + return uintSet.contains(1); + } + + function getAll() public view returns (uint256[]) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.getAll(); + } + + function remove(uint256 del) public view returns (bool, uint256[]) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + bool b = uintSet.remove(del); + return (b, uintSet.getAll()); + } + + function removeAndAtPositon(uint256 del, uint256 key) + public + view + returns (bool, uint256) + { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + uintSet.remove(del); + return uintSet.atPosition(key); + } + + function getSize() public view returns (uint256) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.getSize(); + } + + function getByIndex(uint256 index) public view returns (uint256) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.getByIndex(index); + } +} diff --git a/contracts/data_structure/table/DataTable.sol b/contracts/data_structure/table/DataTable.sol new file mode 100755 index 00000000..af1308db --- /dev/null +++ b/contracts/data_structure/table/DataTable.sol @@ -0,0 +1,64 @@ +pragma solidity ^0.4.25; + +import "./Map.sol"; + +//数据行,定义为list的数据节点 +contract DataRow is DataItem, Map{ + +} + +//二维数据表 +contract DataTable{ + Map _map; + + constructor(){ + _map = new Map(); + } + + function insertItem(bytes32 rowId, bytes32 colId, DataItem item) public { + if(!_map.isExists(rowId)){ + _map.insert(rowId, new DataRow()); + } + DataRow row = DataRow(_map.getValue(rowId)); + row.insert(colId, item); + } + function getItem(bytes32 rowId, bytes32 colId) public view returns(DataItem){ + require(_map.isExists(rowId), "the item is not exists"); + DataRow row = DataRow(_map.getValue(rowId)); + return row.getValue(colId); + } + + function getRow(bytes32 rowId) public view returns(DataRow){ + require(_map.isExists(rowId), "the row is not exists"); + DataRow row = DataRow(_map.getValue(rowId)); + return row; + } + + function isExists(bytes32 rowId, bytes32 colId) public view returns(bool){ + if(!_map.isExists(rowId)){ + return false; + } + DataRow row = DataRow(_map.getValue(rowId)); + return row.isExists(colId); + } + + function isExists(bytes32 rowId) public view returns(bool){ + return _map.isExists(rowId); + } + + function rowCount()public view returns(uint256){ + return _map.getSize(); + } + + function iterate_start() public view returns(Pair){ + return _map.iterate_start(); + } + + function iterate_next(Pair iter) public view returns(Pair){ + return _map.iterate_next(iter); + } + + function can_iterate(Pair iter) public view returns(bool){ + return _map.can_iterate (iter); + } +} \ No newline at end of file diff --git a/contracts/data_structure/table/Map.sol b/contracts/data_structure/table/Map.sol new file mode 100755 index 00000000..b5fd47ea --- /dev/null +++ b/contracts/data_structure/table/Map.sol @@ -0,0 +1,80 @@ +pragma solidity ^0.4.25; + +import "./LibLinkedList.sol"; + + + +interface DataItem{ +} + +contract EndNode is DataItem{ +} + +contract Pair is DataItem{ + bytes32 key; + DataItem value; + constructor(bytes32 k, DataItem v){ + key = k; + value = v; + } + + function getKey() public returns(bytes32){ + return key; + } + + function getValue()public returns(DataItem){ + return value; + } + +} + +//map +contract Map{ + address constant private NULLADDR = address(0x0); + + using LibLinkedList for LibLinkedList.LinkedList; + LibLinkedList.LinkedList _list; + + mapping(bytes32=>Pair) _nodeSet; + constructor(){ + _nodeSet[bytes32(0)] = new Pair(bytes32(0), new EndNode()); + } + + function insert(bytes32 key, DataItem value)public { + require(_nodeSet[key] == NULLADDR, "the item is already exists"); + Pair pair = new Pair(key, value); + _list.addNode(key); + _nodeSet[key] = pair; + } + + function getValue(bytes32 key)public view returns(DataItem){ + require(_nodeSet[key] != NULLADDR, "the item is not exists"); + return _nodeSet[key].getValue(); + } + + + function getSize()public view returns(uint256){ + return _list.getSize(); + } + + function isEmpty() public view returns(bool){ + return _list.getSize() == 0; + } + + function isExists(bytes32 key) public view returns(bool){ + return _nodeSet[key] != NULLADDR; + } + + function iterate_start() public view returns(Pair){ + return _nodeSet[_list.iterate_start()]; + } + + function iterate_next(Pair iter) public view returns(Pair){ + require(_nodeSet[iter.getKey()] != NULLADDR, "the iter is not exists"); + return _nodeSet[_list.iterate_next(iter.getKey())]; + } + + function can_iterate(Pair iter) public view returns(bool){ + return _list.can_iterate(iter.getKey()); + } +} \ No newline at end of file diff --git a/contracts/data_structure/table/StudentsGradesDemo.sol b/contracts/data_structure/table/StudentsGradesDemo.sol new file mode 100755 index 00000000..c293efc2 --- /dev/null +++ b/contracts/data_structure/table/StudentsGradesDemo.sol @@ -0,0 +1,151 @@ +pragma solidity ^0.4.25; +pragma experimental ABIEncoderV2; + +//学生成绩管理系统示例 +//分三个维度记录, 分别为 年份、班级、学号 + +import "./DataTable.sol"; + +//学生成绩 +contract Grades is DataItem{ + struct gradeNode{ + bytes32 subject; + int16 score; + } + gradeNode[] grades; + + function add(bytes32 subj, int16 sc) public { + grades.push(gradeNode({subject:subj, score:sc})); + } + function getGrades()public view returns(gradeNode[] memory){ + return grades; + } +} + +contract Class is DataItem, Map{ + +} + + +contract StudentsGradesDemo{ + DataTable schoolGrades; + + event newStudentEvent(bytes32 studentId); + event newClassEvent(bytes32 classId); + + event logAddr(address addr); + event logVal(bytes32 val); + event logScore(int16 score); + + constructor(){ + schoolGrades = new DataTable(); + } + //添加成绩 + function addGrades(bytes32 year, bytes32 classId, bytes32 studentId, bytes32 subject, int16 score) public { + Class class; + if(schoolGrades.isExists(year, classId)){ + class = Class(schoolGrades.getItem(year, classId)); + } else { + class = new Class(); + schoolGrades.insertItem(year, classId, class); + emit newClassEvent(classId); + } + if(class.isExists(studentId)){ + Grades gds = Grades(class.getValue(studentId)); + gds.add(subject, score); + } else { + Grades gd = new Grades(); + gd.add(subject, score); + class.insert(studentId, gd); + emit newStudentEvent(studentId); + } + } + //查询学生所有科目的成绩 + function select(bytes32 year, bytes32 classId, bytes32 studentId) public returns(Grades.gradeNode[] memory){ + require(schoolGrades.isExists(year, classId), "The year class is not exists" ); + Class class = Class(schoolGrades.getItem(year, classId)); + emit logAddr(class); + require(class.isExists(studentId), "The student is not exists" ); + Grades gd = Grades(class.getValue(studentId)); + return gd.getGrades(); + } + + //查询总分 + function selectTotal(bytes32 year, bytes32 classId, bytes32 studentId) public returns(int16 totalScore){ + Grades.gradeNode[] memory gdList = select(year, classId, studentId); + for(var i = 0; i < gdList.length; i++){ + totalScore += gdList[i].score; + } + return totalScore; + } + //查询班上总分最高的学生 + function selectClassFirst(bytes32 year, bytes32 classId) public returns(bytes32, int16){ + require(schoolGrades.isExists(year, classId), "The year class is not exists" ); + Class class = Class(schoolGrades.getItem(year, classId)); + int16 nScore = 0; + bytes32 strudentId; + + + for(Pair item = class.iterate_start(); class.can_iterate(item);item = class.iterate_next(item)){ + emit logVal(item.getKey()); + + var totalScore = selectTotal(year, classId, item.getKey()); + emit logScore(totalScore); + + if(totalScore > nScore){ + nScore = totalScore; + strudentId = item.getKey(); + } + } + return (strudentId,nScore); + } + + //查询年级总分最高的学生 + function selectYearFirst(bytes32 year) public returns(bytes32, bytes32, int16){ + var row = schoolGrades.getRow(year); + int16 bScore = 0; + bytes32 classId; + bytes32 strudentId; + for(Pair classIt = row.iterate_start(); row.can_iterate(classIt); classIt = row.iterate_next(classIt)){ + Class class = Class(classIt.getValue()); + for(Pair it = class.iterate_start(); class.can_iterate(it); it = class.iterate_next(it)){ + var totalScore = selectTotal(year, classIt.getKey(), it.getKey()); + if(totalScore > bScore){ + bScore = totalScore; + strudentId = it.getKey(); + classId = classIt.getKey(); + } + } + } + return (classId,strudentId,bScore); + } + + function testAdd() public { + addGrades(bytes32("2021"), bytes32("101"), bytes32("20210101"), bytes32("ch"), 120); + addGrades(bytes32("2021"), bytes32("101"), bytes32("20210101"), bytes32("en"), 110); + addGrades(bytes32("2021"), bytes32("101"), bytes32("20210101"), bytes32("math"), 130); + + addGrades(bytes32("2021"), bytes32("101"), bytes32("20210102"), bytes32("ch"), 140); + addGrades(bytes32("2021"), bytes32("101"), bytes32("20210102"), bytes32("en"), 100); + addGrades(bytes32("2021"), bytes32("101"), bytes32("20210102"), bytes32("math"), 110); + + addGrades(bytes32("2021"), bytes32("102"), bytes32("20210201"), bytes32("ch"), 140); + addGrades(bytes32("2021"), bytes32("102"), bytes32("20210201"), bytes32("en"), 110); + addGrades(bytes32("2021"), bytes32("102"), bytes32("20210201"), bytes32("math"), 130); + + addGrades(bytes32("2020"), bytes32("102"), bytes32("20210201"), bytes32("ch"), 130); + addGrades(bytes32("2020"), bytes32("102"), bytes32("20210201"), bytes32("en"), 140); + addGrades(bytes32("2020"), bytes32("102"), bytes32("20210201"), bytes32("math"), 120); + + } + + function testSelect() public returns(int16) { + return selectTotal(bytes32("2021"), bytes32("101"), bytes32("20210101")); + } + function testClassFirst() public returns(bytes32, int16) { + return selectClassFirst(bytes32("2021"), bytes32("101")); + } + function testYearFirst() public returns(bytes32, bytes32, int16) { + return selectYearFirst(bytes32("2021")); + } +} \ No newline at end of file diff --git a/contracts/default/HelloWorld.sol b/contracts/default/HelloWorld.sol old mode 100644 new mode 100755 diff --git a/contracts/default/crypto/Crypto.sol b/contracts/default/crypto/Crypto.sol old mode 100644 new mode 100755 diff --git a/contracts/default/crypto/LibCryptoHash.sol b/contracts/default/crypto/LibCryptoHash.sol old mode 100644 new mode 100755 diff --git a/contracts/default/crypto/LibDecode.sol b/contracts/default/crypto/LibDecode.sol old mode 100644 new mode 100755 diff --git a/contracts/default/crypto/ShaTest.sol b/contracts/default/crypto/ShaTest.sol old mode 100644 new mode 100755 diff --git a/contracts/default/Table/KVTableTest.sol b/contracts/default/embeded_table/KVTableTest.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/default/Table/KVTableTest.sol rename to contracts/default/embeded_table/KVTableTest.sol diff --git a/contracts/default/Table/Table.sol b/contracts/default/embeded_table/Table.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/default/Table/Table.sol rename to contracts/default/embeded_table/Table.sol diff --git a/contracts/default/Table/TableTest.sol b/contracts/default/embeded_table/TableTest.sol old mode 100644 new mode 100755 similarity index 100% rename from contracts/default/Table/TableTest.sol rename to contracts/default/embeded_table/TableTest.sol diff --git a/contracts/default/internal_function/InternalFunction.sol b/contracts/default/internal_function/InternalFunction.sol new file mode 100755 index 00000000..8c164dc9 --- /dev/null +++ b/contracts/default/internal_function/InternalFunction.sol @@ -0,0 +1,82 @@ +pragma solidity ^0.6.10; + +/** + * @author SomeJoker + * @title solidity 内置函数转换 + */ +contract InternalFunction{ + /** + * @notice 根据指定的区块号获取hash(仅支持最近256个区块,且不包含当前区块) + * @param uint256 blockNumber + * @return bytes32 区块的hash值 + */ + function getBlockhash(uint256 blockNumber) view public returns(bytes32){ + return blockhash(blockNumber); + } + + /** + * @notice 获取当前区块的区块高度 + * @return uint256 区块高度 + */ + function getBlockNumber() view public returns(uint256){ + return block.number; + } + + /** + * @notice 获取当前区块的时间戳 + * @return uint256 时间戳 + */ + function getTimestamp() view public returns(uint256){ + return now; + } + + /** + * @notice 判断地址是否是合约地址 + */ + function isContract(address addr) view public returns (bool){ + uint256 size; + assembly { + size := extcodesize(addr) + } + return size > 0; + } + + /** + * @notice 获取合约的代码节码 + */ + function getCodeByAddress(address addr) public view returns (bytes memory) { + require(isContract(addr) , "addr is not a contract"); + bytes memory o_code; + assembly { + // 获取代码大小,这需要汇编语言 + let size := extcodesize(addr) + // 分配输出字节数组 – 这也可以不用汇编语言来实现 + // 通过使用 o_code = new bytes(size) + o_code := mload(0x40) + // 包括补位在内新的“memory end” + mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + // 把长度保存到内存中 + mstore(o_code, size) + // 实际获取代码,这需要汇编语言 + extcodecopy(addr, add(o_code, 0x20), 0, size) + } + return o_code; + } + + /** + * @notice 根据字节码计算合约地址 + */ + function computeAddress(bytes32 salt, bytes32 bytecodeHash) public view returns (address) { + return computeAddress(salt, bytecodeHash, address(this)); + } + + function computeAddress( + bytes32 salt, + bytes32 bytecodeHash, + address deployer + ) internal pure returns (address) { + bytes32 _data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)); + return address(uint160(uint256(_data))); + } + +} \ No newline at end of file diff --git a/contracts/default/proxy/ISing.sol b/contracts/default/proxy/ISing.sol new file mode 100755 index 00000000..f85ad3ca --- /dev/null +++ b/contracts/default/proxy/ISing.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.25; + +/** + * @author SomeJoker + * @title 接口 + */ +interface ISing{ + function singing(address singer) external; +} \ No newline at end of file diff --git a/contracts/default/proxy/Sing.sol b/contracts/default/proxy/Sing.sol new file mode 100755 index 00000000..a4d09036 --- /dev/null +++ b/contracts/default/proxy/Sing.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.25; + +import "./ISing.sol"; +/** + * @author SomeJoker + * @title 实现 + */ +contract Sing is ISing{ + + event SingLog(address singer,uint256 time); + + function singing(address _singer) public { + emit SingLog(_singer, now); + } +} \ No newline at end of file diff --git a/contracts/default/proxy/SingProxy.sol b/contracts/default/proxy/SingProxy.sol new file mode 100755 index 00000000..608c0be3 --- /dev/null +++ b/contracts/default/proxy/SingProxy.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.25; + +import "./ISing.sol"; + +/** + * @author SomeJoker + * @title 代理 + */ +contract SingProxy{ + + event ProxyLog(address singer,string context); + + ISing iSing; + constructor(address _sing) public{ + iSing = ISing(_sing); + } + + function proxySing() public { + emit ProxyLog(msg.sender,"before proxy do someting"); + iSing.singing(msg.sender); + emit ProxyLog(msg.sender,"after proxy do someting"); + } +} \ No newline at end of file diff --git a/docs/base_type/Lib2DArrayForUint256.md b/docs/base_type/Lib2DArrayForUint256.md new file mode 100755 index 00000000..c1f5f67e --- /dev/null +++ b/docs/base_type/Lib2DArrayForUint256.md @@ -0,0 +1,243 @@ +# Lib2DArrayForUint256.sol + +Lib2DArrayForUint256提供了Uint256二维数组的相关操作,包括增加新元素,删除元素,修改值,查找值,合并扩展数组等操作。 + +## 使用方法 + +首先需要通过import引Lib2DArrayForUint256类库,然后通过"."进行方法调用,如下为调用getValue方法的例子: + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array; + + function f() public returns(uint256) { + array = new uint256[][](0); + array = [[1,2],[3,4]]; + return Lib2DArrayForUint256.getValue(array,row,col); + } +} +``` + + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *addValue(uint256[][] storage array,uint256[] value)* | 对一个二维数组添加一个数组元素 +2 | *getValue(uint256[][] storage array, uint256 row, uint256 col) internal returns (uint256)* |查找指定位置的值 +3 | *setValue(uint256[][] storage array, uint256 row, uint256 col, uint256 val) internal returns (uint256[][])* |修改指定位置的值 +4 | *firstIndexOf(uint256[][] storage array, uint256 val) internal returns (bool, uint256, uint256)* | 查找第一个匹配的元素的位置 +5 | *removeByIndex(uint256[][] storage array, uint256 index) internal returns(uint256[][])* | 根据索引删除数组元素 +6 | *extend(uint256[][] storage array1, uint256[][] storage array2) internal returns(uint256[][])* | 合并两个二维数组,将第二个数组合并在第一个数组上 + + +## API详情 + +### ***1. addValue 方法*** + +对一个二维数组增加一个数组元素,若增加的数组为空数组则退出 + +#### 参数 + +- array:二维数组 +- value:一维数组 + +### 返回值 + +- 无 + +#### 实例 + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array; + + function f() public { + array = new uint256[][](0); + uint256[] val = [1,2]; + Lib2DArrayForUint256.addValue(array,val); + } +} +``` + +### ***2. getValue 方法*** + +查找并返回指定位置的值,若位置越界不合法则退出 + +#### 参数 + +- array:二维数组 +- row:值所在行 +- col:值所在列 + +#### 返回值 + +- uint256:查找到的值 + +#### 实例 + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array; + + function f() public returns(uint256) { + array = new uint256[][](0); + uint256[] val = [1,2]; + Lib2DArrayForUint256.addValue(array,val); + return Lib2DArrayForUint256.getValue(array,0,0); + } +} +``` + +### ***3. setValue 方法*** + +修改指定位置的值,并返回修改后的二维数组,若位置越界不合法则退出 + +#### 参数 + +- array:二维数组 +- row:所在行 +- col:所在列 +- val:修改为该值 + +#### 返回值 + +- uint256[][]: 修改后的二维数组 + +#### 实例 + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array; + + function f() public returns(uint256[][]) { + array = new uint256[][](0); + uint256[] val = [1,2]; + Lib2DArrayForUint256.addValue(array,val); + return Lib2DArrayForUint256.setValue(array,0,0,100); + } +} +``` + +### ***4. firstIndexOf 方法*** + +查找第一个匹配元素的位置,若存在则返回(true,row,col),若不存在则返回(false,0,0) + +#### 参数 + +- array:二维数组 +- val:待查找的元素 + +#### 返回值 + +- bool:当查找到元素,则返回true,反之返回false +- uint256:元素所在行 +- uint256:元素所在列 + +#### 实例 + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array; + + function f() public returns(bool,uint256,uint256) { + array = new uint256[][](0); + uint256[] val = [1,2]; + Lib2DArrayForUint256.addValue(array,val); + return Lib2DArrayForUint256.firstIndexOf(array,1); + } +} +``` + +### ***5. removeByIndex 方法*** + +removeByIndex方法用于根据索引删除数组元素。当索引越界时退出。 + +#### 参数 + +- array:二维数组 +- index:待删除的一维数组索引 + +#### 返回值 + +- uint256[][]: 删除指定元素后的数组 + +#### 实例 + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array; + + function f() public returns(uint256[][]) { + array = new uint256[][](0); + uint256[] val = [1,2]; + uint256[] val2 = [3,4,5]; + Lib2DArrayForUint256.addValue(array,val); + return Lib2DArrayForUint256.removeByIndex(array,1); + } +} +``` + +### ***6. extend 方法*** + +合并两个二维数组, + +#### 参数 + +- array1:二维数组 +- array2:二维数组 + +#### 返回值 + +- uint256: 合并后的数组 + +#### 实例 + +``` +pragma solidity >=0.4.25 <0.6.11; + +import "./Lib2DArrayForUint256.sol"; + +contract test { + + uint256[][] private array1; + uint256[][] private array2; + + function f() public returns(uint256[][]) { + + array1 = [[1,2],[3,4]]; + array2 = [[5,6],[7,8]]; + return Lib2DArrayForUint256.extend(array1,array2); + } +} +``` \ No newline at end of file diff --git a/docs/types/LibAddress.md b/docs/base_type/LibAddress.md old mode 100644 new mode 100755 similarity index 100% rename from docs/types/LibAddress.md rename to docs/base_type/LibAddress.md diff --git a/docs/types/LibArrayForUint256Utils.md b/docs/base_type/LibArrayForUint256Utils.md old mode 100644 new mode 100755 similarity index 100% rename from docs/types/LibArrayForUint256Utils.md rename to docs/base_type/LibArrayForUint256Utils.md diff --git a/docs/base_type/LibBitOperationForByte.md b/docs/base_type/LibBitOperationForByte.md new file mode 100755 index 00000000..e8773a3f --- /dev/null +++ b/docs/base_type/LibBitOperationForByte.md @@ -0,0 +1,193 @@ +# LibBitOperationForByte.sol + +LibBitOperationForByte提供solidity内置函数不包括的位操作方法,例如按位非、移位、取前/后n位等方法 + +## 使用方法 + +首先需要通过import引入LibBitOperationForByte类库,调用库的相关方法: + +``` +pragma solidity >=0.4.24 <0.6.11; + +import "./LibBitOperationForByte.sol" + +contract test { + + function getFirstN(bytes1 a, uint8 n) public pure returns (bytes1) { + bytes1 res = LibBitOperationForByte.getFirstN(a, n); + return res; + } +} +``` + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *invert(byte a) internal pure returns (byte)* | 按位非 +2 | *leftShift(byte a, uint n) internal pure returns (byte)* | 向左移动n位 +3 | *rightShift(byte a, uint n) internal pure returns (byte)* | 向右移动n位 +4 | *getFirstN(byte a, uint8 n) internal pure isValidLength(n) returns (byte)* | 取前n位 +5 | *getLastN(byte a, uint8 n) internal pure isValidLength(n) returns (byte)* | 取后n位 +6 | *getBitAtPositionN(byte a, uint8 n) internal pure isValidPosition(n) returns (uint8)* | 获取第n位 +7 | *invertBitAtPositionN(byte a, uint8 n) internal pure isValidPosition(n) returns (byte)* | 将第n位反转 + +## API详情 + +### ***1. invert 方法*** + +按位非 + +#### 参数 + +- byte:操作字节 + +#### 返回值 + +- byte:返回转换结果。 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.invert(a); + //TODO: +} +``` + +### ***2. leftShift 方法*** + +将byte向左移动n位 + +#### 参数 + +- byte:操作字节 + +#### 返回值 + +- byte:返回移位后的结果。 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.leftShift(a, 2); + //TODO: +} +``` + +### ***3. rightShift 方法*** + +将byte向右移动n位 + +#### 参数 + +- byte:操作字节 + +#### 返回值 + +- byte:返回移位后的结果。 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.rightShift(a, 2); + //TODO: +} +``` + +### ***4. getFirstN 方法*** + +获取前n位,如果n大于8,则报错退出 + +#### 参数 + +- byte: 操作字节 +- uint8:获取的位数 + +#### 返回值 + +- byte:返回前n位的结果。 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.getFirstN(a, 2); + //TODO: +} +``` + +### ***5. getLastN 方法*** + +获取后n位,如果n大于8,则报错退出 + +#### 参数 + +- byte: 操作字节 +- uint8:获取的位数 + +#### 返回值 + +- byte:返回后n位的结果。 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.getLastN(a, 2); + //TODO: +} +``` + +### ***6. getBitAtPositionN 方法*** + +获取第n位的值,n大于7,则报错退出 + +#### 参数 + +- byte: 操作字节 +- uint8: 第n位 + +#### 返回值 + +- uint8:第n位的值 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.getBitAtPositionN(a, 2); + //TODO: +} +``` + +### ***7. invertBitAtPositionN 方法*** + +将第n位的值反转,n大于7,则报错退出 + +#### 参数 + +- byte: 操作字节 +- uint8: 第n位 + +#### 返回值 + +- byte:返回转换后的结果 + +#### 实例 + +``` +function f() public view{ + byte a = 0xa1; + byte res = LibBitOperationForByte.invertBitAtPositionN(a, 2); + //TODO: +} +``` \ No newline at end of file diff --git a/docs/base_type/LibBits.md b/docs/base_type/LibBits.md new file mode 100755 index 00000000..0e596ca9 --- /dev/null +++ b/docs/base_type/LibBits.md @@ -0,0 +1,468 @@ +# LibBits.sol + +LibBits 提供了常用的位操作.基于单字节操作 + +## 使用方法 + +首先需要通过import引入LibBits类库, 以下为使用示例 + +``` +pragma solidity >=0.4.24 <0.6.11; + +import "./LibBits.sol"; + +contract TestBits { + + function testAnd() public view returns(bytes1 ){ + bytes1 a = 1; + bytes1 b = 5; + bytes1 result = LibBits.and(a, b);//Expected to be 1 + return result; + } +} +``` + +## 控制台测试 +在控制台中执行,可获得以下的结果。 + +### 部署测试合约 +``` +deploy TestBits +transaction hash: 0xf2c94c9905d70350df1ce324613b4757ddde5162047d1bb679e0e195232a9db9 +contract address: 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 测试所有函数 +按照顺序测试12个函数: + +``` +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testAnd +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x01) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testOr +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x07) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testXor +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x06) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testNegate +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0xfa) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testShiftLeft +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x10) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testShiftLeft +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x10) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testShiftRight +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x01) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testGetLastN +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x04) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 getFirstN +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x20) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testAllOnes +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0xff) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testGetBit +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BOOL) +Return values:(true) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testSetBit +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x13) +--------------------------------------------------------------------------------------------- + +[group:1]> call TestBits 0x02cc48aeab40785f6c3b2dc3b3fe71742e9a18e0 testClearBit +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x01) +--------------------------------------------------------------------------------------------- + +``` + + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *and(bytes1 a, bytes1 b) internal pure returns (bytes1)* | 按位与操作 +2 | *or(bytes1 a, bytes1 b) internal pure returns (bytes1)* | 或操作 +3 | *xor(bytes1 a, bytes1 b) internal pure returns (bytes1)* | 异或操作 +4 | *negate(bytes1 a) internal pure returns (bytes1)* | 按位取非 +5 | *shiftLeft(bytes1 a, uint8 n) internal pure returns (bytes1)* | 左移 +6 | *shiftRight(bytes1 a, uint8 n) internal pure returns (bytes1)* | 右移 +7 | *getFirstN(bytes1 a, uint8 n) internal pure returns (bytes1)* | 获取高N位,保持在高位 +8 | *getLastN(bytes1 a, uint8 n) internal pure returns (bytes1)* | 获取低位数据 +9 | *allOnes() internal pure returns (bytes1)* | 所有位置为1 +10 | *getBit(bytes1 a, uint8 n) internal pure returns (bool)* | 获取指定位的值 +11 | *setBit(bytes1 a, uint8 n) internal pure returns (bytes1)* | 设置指定位的为1 +12 | *clearBit(bytes1 a, uint8 n) internal pure returns (bytes1)* | 清除指定位的值 + +## API详情 + +### ***1. and 方法*** + +按位与操作 + +#### 参数 + +- a: 单字节 +- b: 单字节 + +#### 返回值 + +- bytes1:按位与的值 + +#### 实例 + +``` + function testAnd() public view returns(bytes1 ){ + bytes1 a = 1; // 0x001 + bytes1 b = 5; // 0x101 + bytes1 result = LibBits.and(a, b);//Expected to be 1, 0x001 + return result; + } +``` + +### ***2. or 方法*** + +或运算 + +#### 参数 + +- a: 单字节 +- b: 单字节 + +#### 返回值 + +- bytes:或运算结果 + +#### 实例 + +``` + function testOr() public view returns(bytes1 ){ + bytes1 a = 2; // 0x010 + bytes1 b = 5; // 0x101 + bytes1 result = LibBits.or(a, b);//Expected to be 7, 0x111 + return result; + } +``` + +### ***3. xor 方法*** + +异或运算 + +#### 参数 + +- a: 单字节 +- b: 单字节 + +#### 返回值 + +- 单字节: 异或运算结果 + +#### 实例 + +``` + function testXor() public view returns(bytes1 ){ + bytes1 a = 3; // 0x011 + bytes1 b = 5; // 0x101 + bytes1 result = LibBits.xor(a, b); //Expected to be 6, 0x110 + return result; + } +``` + +### ***4. negate 方法*** + +非运算/NEG + +#### 参数 + +- a: 单字节 + +#### 返回值 +- bytes1: 非运算结果 + +#### 实例 + +``` + function testNegate() public view returns(bytes1){ + bytes1 r = LibBits.negate(5);//Expected to be -6 + return r; + } +``` + +### ***5. shiftLeft 方法*** + +左移 + +#### 参数 + +- a: 单字节 +- n:单字节 + +#### 返回值 + +- bytes1: 将a 左移n位 + +#### 实例 + +``` + function testShiftLeft() public view returns(bytes1){ + bytes1 r = LibBits.shiftLeft(2,3);//Expected to be 16, 0x00000010 -> 0x00010000 + return r; + } +``` + +### ***6. shiftRight 方法*** + +右移 + +#### 参数 + +- a:单字节 +- n:单字节 + +#### 返回值 + +- bytes1: 将a右移n位 + +#### 实例 + +``` + function testShiftRight() public view returns(bytes1){ + bytes1 r = LibBits.shiftRight(15,3);//Expected to be 1, 0x00001111 -> 0x00000001 + return r; + } +``` + +### ***7. getLastN 方法*** + +获取高N位数据,保持在高位 + +#### 参数 + +- a: 单字节 +- n: 单字节 + +#### 返回值 + +- bytes1: 低n位数据 + +#### 实例 + +``` + function testGetLastN() public view returns(bytes1){ + bytes1 r = LibBits.getLastN(60,3);//Expected to be 4 0x00111100 -> 0x00000100 + return r; + } +``` + + +### ***8. getFirstN 方法*** + +获取低N位数据 + +#### 参数 + +- a: 字符串 + +#### 返回值 + +- bytes1: 高位数据 + +#### 实例 + +``` + function getFirstN() public view returns(bytes1){ + byte r = LibBits.getFirstN(60,3);//Expected to be 32, 0x00111100 -> 0x00100000 + return r; + } +``` + + +### ***9. allOnes 方法*** + +单字节所有位值为1 + +#### 参数 + +#### 返回值 + +- bytes1: 0xff + +#### 实例 + +``` + function testAllOnes() public view returns(bytes1){ + byte r = LibBits.allOnes();//Expected to be 255 + return r; + } +``` +### ***10. getBit 方法*** + +获取指定位置的bit值 + +#### 参数 + +- a: 单字节 +- n: 单字节 + +#### 返回值 + +- bytes1: 数据a在位置n的bit值 + +#### 实例 + +``` + function testGetBit() public view returns(bool){ + bool r = LibBits.getBit(3,2);//Expected to be 1 + return r; + } +``` + +### ***11. setBit 方法*** + +设置指定位置的bit值 + +#### 参数 + +- a: 单字节 +- n: 单字节 + +#### 返回值 + +- bytes1: 设置后的值 + +#### 实例 + +``` + function testSetBit() public view returns(bytes1){ + byte r = LibBits.setBit(17,2);//Expected to be 19, 0x00010001 -> 0x00010011 + return r; + } +``` + +### ***12. clearBit 方法*** + +设置指定位置的bit值 + +#### 参数 + +- a: 单字节 +- n: 单字节 + +#### 返回值 + +- bytes1: 清除指定位置后的值 + +#### 实例 + +``` + function testClearBit() public view returns(bytes1){ + byte r = LibBits.clearBit(17,5);//Expected to be 1 + return r; + } +``` \ No newline at end of file diff --git a/docs/types/LibConverter.md b/docs/base_type/LibConverter.md old mode 100644 new mode 100755 similarity index 100% rename from docs/types/LibConverter.md rename to docs/base_type/LibConverter.md diff --git a/docs/base_type/LibSafeMathForFloatUtils.md b/docs/base_type/LibSafeMathForFloatUtils.md new file mode 100755 index 00000000..c27e5da1 --- /dev/null +++ b/docs/base_type/LibSafeMathForFloatUtils.md @@ -0,0 +1,218 @@ +# LibSafeMathForFloatUtils.sol + +Solidity本不支持小数运算(浮点型),LibSafeMathForFloatUtils提供了浮点型的相关计算操作,且保证数据的正确性和安全性,包括加法、减法、乘法、除法等操作。 + +## 使用方法 + +首先需要通过import引LibSafeMathForFloatUtils类库,然后通过"LibSafeMathForFloatUtils."进行方法调用,如下为调用相关方法的例子: + +``` +pragma solidity^0.4.25; +import "./LibSafeMathForFloatUtils.sol"; + +contract testfloat { + // dA代表a的精度,dB代表b的精度,返回值返回运算结果及其精度 + function mathTest(uint256 a, uint8 dA, uint256 b, uint8 dB, uint8 T) public pure returns(uint256, uint8) { + if(T == 0) { + // 加法测试 + return LibSafeMathForFloatUtils.fadd(a, dA, b, dB); + } else if (T == 1) { + // 减法 + return LibSafeMathForFloatUtils.fsub(a, dA, b, dB); + } else if(T == 2) { + // 乘法 + return LibSafeMathForFloatUtils.fmul(a, dA, b, dB); + } else if(T == 3) { + // 除法 + return LibSafeMathForFloatUtils.fdiv(a, dA, b, dB); + } + } +} +``` + +## 控制台测试 +在控制台中执行,可获得以下的结果。 +### 部署测试合约 +``` +[group:1]> deploy testfloat +transaction hash: 0xacfec3a4edc8a7316142362918a51a26c2a6c50c138bee68c6d65394bceec44a +contract address: 0x392324fc2178f8ab4e9c3d70a88935612ccf821c +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 加法测试 +``` +[group:1]> call testfloat 0x392324fc2178f8ab4e9c3d70a88935612ccf821c mathTest 20003 2 50004 1 0 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (UINT, UINT) +Return values:(520043, 2) +--------------------------------------------------------------------------------------------- +``` + +### 减法测试 +``` +[group:1]> call testfloat 0x392324fc2178f8ab4e9c3d70a88935612ccf821c mathTest 500040 2 20003 2 1 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (UINT, UINT) +Return values:(480037, 2) +--------------------------------------------------------------------------------------------- +``` + +### 乘法测试 +``` +[group:1]> call testfloat 0x392324fc2178f8ab4e9c3d70a88935612ccf821c mathTest 68236 2 5431 1 2 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (UINT, UINT) +Return values:(37058971, 2) +--------------------------------------------------------------------------------------------- +``` + +### 除法测试 +``` +[group:1]> call testfloat 0x392324fc2178f8ab4e9c3d70a88935612ccf821c mathTest 68236 2 5431 1 3 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (UINT, UINT) +Return values:(125, 2) +--------------------------------------------------------------------------------------------- +``` + + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *fmul(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals)* | 加法操作 +2 | *fmul(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals)* | 减法操作 +3 | *fmul(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals)* | 乘法操作 +4 | *fmul(uint256 a, uint8 dA, uint256 b, uint8 dB) internal pure returns (uint256 c, uint8 decimals)* | 除法操作 + + +## API详情 + +### ***1. fadd 方法*** + +fadd对两个数进行加法操作,返回相加之后的结果及精度值。 + +#### 参数 + +- a:加数 +- dA:加数a的精度 +- b:加数 +- dB:加数b的精度 + +#### 返回值 + +- uint256:返回相加的结果。 +- uint8:返回结果的精度。 + +#### 实例 + +``` +function f() public view{ + uint256 a = 2560000; + uint256 b = 2000; + (uint256 c, uint8 dC) = LibSafeMathForUint256Utils.fadd(a, 2, b, 3); + //TODO: +} +``` + +### ***2. fsub 方法*** + +fsub对两个数进行减法操作,返回相减之后的结果。 + +#### 参数 + +- a:被减数 +- dA:被减数的精度 +- b:减数 +- dB:减数的精度 + +#### 返回值 + +- uint256:返回相减的结果。 +- uint8:返回结果的精度。 + +#### 实例 + +``` +function f() public view{ + uint256 a = 2560000; + uint256 b = 2000; + (uint256 c, uint8 dC) = LibSafeMathForUint256Utils.fsub(a, 2, b, 3); + //TODO: +} +``` + +### ***3. fmul 方法*** + +fmul方法对两个数进行乘法操作,返回相乘之后的结果。 + +#### 参数 + +- a:被乘数 +- dA:被乘数的精度 +- b:乘数 +- dB:乘数的精度 + +#### 返回值 + +- uint256:返回相乘的结果。 +- uint8:返回结果的精度。 + +#### 实例 + +``` +function f() public view{ + uint256 a = 2560000; + uint256 b = 2000; + (uint256 c, uint8 dC) = LibSafeMathForUint256Utils.fmul(a, 2, b, 3); + //TODO: +} +``` + +### ***4. fdiv 方法*** + +fdiv方法对两个数进行除法操作,返回相除之后的结果。 + +#### 参数 + +- a:被除数 +- dA:被除数的精度 +- b:除数 +- dB:除数的精度 + +#### 返回值 + +- uint256:返回相除的结果。 +- uint8:返回结果的精度。 + +#### 实例 + +``` +function f() public view{ + uint256 a = 2560000; + uint256 b = 2000; + (uint256 c, uint8 dC) = LibSafeMathForUint256Utils.fdiv(a, 2, b, 3); + //TODO: +} +``` diff --git a/docs/types/LibSafeMathForUint256Utils.md b/docs/base_type/LibSafeMathForUint256Utils.md old mode 100644 new mode 100755 similarity index 100% rename from docs/types/LibSafeMathForUint256Utils.md rename to docs/base_type/LibSafeMathForUint256Utils.md diff --git a/docs/types/LibString.md b/docs/base_type/LibString.md old mode 100644 new mode 100755 similarity index 100% rename from docs/types/LibString.md rename to docs/base_type/LibString.md diff --git a/docs/business_template/CarbonFrugalEvidence.md b/docs/business_template/CarbonFrugalEvidence.md old mode 100644 new mode 100755 diff --git a/docs/business_template/Evidence.md b/docs/business_template/Evidence.md old mode 100644 new mode 100755 diff --git a/docs/business_template/MarriageEvidence.md b/docs/business_template/MarriageEvidence.md new file mode 100755 index 00000000..2a017032 --- /dev/null +++ b/docs/business_template/MarriageEvidence.md @@ -0,0 +1,45 @@ +## 功能说明 + +本合约结合角色合约与存证合约打造结婚证书合约实例。也可根据需求开发毕业证书,参会,活动证明等,更多玩法可自由修改。 + +## 接口 + +提供了五个合约:Roles合约,Character合约,Evidence合约,EvidenceFactory合约,MarriageEvidence合约。其中Character合约是对外服务合约,Roles合约是库合约,用于数据和逻辑抽象化。其中Evidence合约是存证基合约,EvidenceFactory合约是存证工厂合约。 + +**Character合约**:主要使用接口。包含: + +- addCharacter(address amount,string _summary): 管理员进行添加角色操作。amount是添加角色的地址,_ _summary添加角色的基本信息 +- getAllCharater():任何人都可以进行查看当前存在的所有角色操作。返回值:address[] + +**EvidenceFactory合约**:主要使用接口。包含: + +- constructor(address[] evidenceSigners) :构造函数。evidenceSigners是签名者地址数组,传入地址数组进行初始化授权 +- verify(address addr):验证addr地址是否为授权签名地址。返回值:bool +- newEvidence(string evi):创建新证书功能。evi是存证信息。返回值:address (证书地址) +- addSignatures(address addr) :进行签名。addr地址者签名。返回值:bool +- getEvidence(address addr) :获取证书信息。addr是证书地址。返回值:存证信息string,授权地址address[],已签名地址address[] + +**MarriageEvidence**:继承Character合约,部署使用EvidenceFactory合约,主要对外接口。包含: + +- deployEvi():部署EvidenceFactory合约,导入夫妻地址 +- newEvi(string _evi):发布结婚存证 +- sign():夫妻签字 +- getEvi():查看证书 + + + +## 使用示例 + +角色的增删改查,整个过程如下: + +合约初始化: + + - 以民政局管理员地址部署MarriageEvidence合约(继承于Character合约) + +合约调用: + + - 管理员调用Character.addCharacter提交添加角色请求,参数传入添加夫妻的地址,夫妻的基本信息(json格式传入) + - 管理员调用MarriageEvidence.deployEvi()提交部署EvidenceFactory合约请求,参数自动以Character.getAllCharater的返回值参入,为夫妻地址在证书中签名授权。 + - 管理员调用MarriageEvidence.newEvi提交创建结婚证书请求 + - 夫妻各自调用MarriageEvidence.sign提交对结婚证书进行签名请求 + - 任何人调用MarriageEvidence.getEvi提交查看结婚证书 \ No newline at end of file diff --git a/docs/business_template/RewardPoint.md b/docs/business_template/RewardPoint.md old mode 100644 new mode 100755 diff --git a/docs/business_template/SimplePoint.md b/docs/business_template/SimplePoint.md new file mode 100755 index 00000000..bd888e75 --- /dev/null +++ b/docs/business_template/SimplePoint.md @@ -0,0 +1,20 @@ +## 功能说明 +本合约为积分合约demo,获取积分和转账积分功能。 + +## 接口 +提供了PointDemo合约,主要是获取积分和转账积分功能 +- mint(address receiver,uint amount):获取积分 +- send(address receiver,uint amount): 转账积分 + + +## 使用示例 +积分合约获取积分和转账积分,整个过程如下: + +合约初始化: + + - 部署PointDemo合约 + +合约调用: + + - 调用PointDemo.mint 获取积分 + - 调用PointDemo.send 转账积分 diff --git a/docs/business_template/Traceability.md b/docs/business_template/Traceability.md old mode 100644 new mode 100755 index 8aeb5f2c..5b3dcb4d --- a/docs/business_template/Traceability.md +++ b/docs/business_template/Traceability.md @@ -9,21 +9,24 @@ 提供了三个合约:TraceabilityFactory合约,Traceability合约,Goods合约。 TraceabilityFactory合约:对外服务的唯一接口。包含: + - createTraceability(bytes32 goodsGroup): 创建溯源商品类,goodsGroup: 为商品类hash码 - createTraceGoods(bytes32 goodsGroup, uint64 goodsId): 创建需要溯源的商品,goodsId:唯一标识商品的Id - changeTraceGoods(bytes32 goodsGroup, uint64 goodsId, int16 goodsStatus, string remark):商品状态改变,goodsStatus:商品流转的每一个环节可以用一个状态进行标识,remark:状态变更的摘要信息 - getStatus(bytes32 goodsGroup, uint64 goodsId): 获取商品的当前状态 - - getTraceInfo(bytes32 goodsGroup, uint64 goodsId) :获取商品的全流程信息,包括每一个环节的状态、时间、操作员、摘要信息 + - getTraceInfo(bytes32 goodsGroup, uint64 goodsId) :获取商品的全流程信息,包括每一个环节的状态、时间、操作员、摘要信息 + - getGoodsGroup(string memory name):计算商品种类的哈希值,name:商品标识或名称 ## 使用示例 合约调用: - - 创建自己的溯源商品类 createTraceability(hash("商品标识")) - - 在商品类下创建商品 createTraceGoods(hash("商品标识"), "100000001") - - 商品状态变更 changeTraceGoods(hash("商品标识"), "100000001", 1, "环节信息") - - 查询商品的当前状态 getStatus(hash("商品标识"), "100000001") - - 查询商品的全流程信息 getTraceInfo(hash("商品标识"), "100000001") + - 获取商品分析哈希值 goodsGroup = getGoodsGroup("商品标识") + - 创建自己的溯源商品类 createTraceability(goodsGroup) + - 在商品类下创建商品 createTraceGoods(goodsGroup, "100000001") + - 商品状态变更 changeTraceGoods(goodsGroup, "100000001", 1, "环节信息") + - 查询商品的当前状态 getStatus(goodsGroup, "100000001") + - 查询商品的全流程信息 getTraceInfo(goodsGroup, "100000001") diff --git a/docs/business_template/bill.md b/docs/business_template/bill.md new file mode 100755 index 00000000..80e30b72 --- /dev/null +++ b/docs/business_template/bill.md @@ -0,0 +1,179 @@ +# 合约说明 + +经验证,本合约能够在fiscobcos上进行运行。 + +## 场景说明 + +本合约用于金融票据上的操作,可以发布票据、对票据进行背书、验证背书、拒绝背书等操作;也可以针对特定条件(当前持票人)查询票据信息等。 + +## BillController 控制合约 + +本合约用于操作票据。比如发布票据、背书签名等。 + +``` +/**发布票据 */ +function issue(string _s) external onlyOwner returns(int256) + +/**批量查询当前持票人的票据 */ +function queryBills(string _holdrCmID) external returns(string[] memory) + +/**根据票据号码查询票据详情 */ +function queryBillByNo(string _infoID) external returns(string) + +/**发起背书请求 */ +function endorse(string _infoID, string _waitEndorseCmID, string _waitEndorseAcct) external onlyOwner returns(bool) + +/**查询待背书票据列表 */ +function queryWaitBills(string _waitEndorseCmID) external returns(string[] memory) + +/**背书签收 */ +function accept(string _infoID, string _holdrCmID, string _holdrAcct) external onlyOwner returns(bool) + +/**拒绝背书 */ +function reject(string _infoID, string _rejectEndorseCmID, string _rejectEndorseAcct) external onlyOwner returns(bool) +``` + +## BillStorage 存储合约 + +本合约用于票据数据存储到Table中。 + +``` +// 插入数据 +function insert(string memory _s) public onlyOwner returns(int) + +// 通过infoID查询数据 +function getDetail(string memory _infoID) public view returns(string memory _json) + +// 通过infoID获取HoldrCmID +function getHoldrCmID(string memory _infoID) public view returns(string memory _holdrCmID) + +// 更新背书人信息 +function updateEndorse(string memory _infoID, string memory _waitEndorseCmID, string memory _waitEndorseAcct) public onlyOwner returns(int256) + +// 更新持票人信息 +function updateEccept(string memory _infoID, string memory _holdrCmID, string memory _holdrAcct) public onlyOwner returns(int256) + +// 更新待背书人信息 +function updateReject(string memory _infoID, string memory _rejectEndorseCmID, string memory _rejectEndorseAcct) public onlyOwner returns(int256) + +// 通过holdrCmID查询数据 +function selectListByHoldrCmID(string memory _holdrCmID) public view returns(string[]) + +// 通过waitEndorseCmID查询数据 +function selectListByWaitEndorseCmID(string memory _waitEndorseCmID) public view returns(string[]) +``` + +## MapStorage 存储合约(KV数据) + +本合约与mapping(string=>string)作用是一样的,用来存储KV格式的数据。考虑合约升级时需要控制版本,才将数据存储到Table中。 + +``` +// 插入数据,已有数据不添加 +function put(string memory _key, string memory _value) public onlyOwner returns(int) + +// 通过key获取value,可以存在多个value +function get(string memory _key) public view returns(string[] memory) +``` + +## 部署合约 + +``` +deploy Bill/BillController +``` + +## 调用合约 + +``` +// 发布票据 +call Bill/BillController 0x9ae09665525be7affa51bac3e3cd0aa7ddefa27e issue "BOC104,4000,12,20110102,20110106,11,11,11,11,11,11,BBB,BID" + +// 根据票据号码查询票据详情 +call Bill/BillController 0x9ae09665525be7affa51bac3e3cd0aa7ddefa27e queryBillByNo "BOC104" + +// 发起背书请求 +call Bill/BillController 0x9ae09665525be7affa51bac3e3cd0aa7ddefa27e endorse "BOC104" "13" "AAA" + +// 批量查询当前持票人的票据 +call Bill/BillController 0x9ae09665525be7affa51bac3e3cd0aa7ddefa27e queryBills "BID" +``` + +## 控制台测试 + +### 部署合约 +``` +[group:1]> deploy BillController +transaction hash: 0x9436796448c65803c06ae15ffbbffeb34804684fea076d28390597449bec15fa +contract address: 0x37949ce7937696dafffeac91411acbbf9ed7e86b +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 函数调用 +``` +[group:1]> call BillController 0x37949ce7937696dafffeac91411acbbf9ed7e86b issue "BOC104,4000,12,20110102,20110106,11,11 +,11,11,11,11,BBB,BID" +transaction hash: 0x355b9aea0e9f7c931d2de941f58930380a1912c662aa9a3929e3ac7ae1b41c3b +--------------------------------------------------------------------------------------------- +transaction status: 0x0 +description: transaction executed successfully +--------------------------------------------------------------------------------------------- +Receipt message: Success +Return message: Success +Return value size:1 +Return types: (INT) +Return values:(1) +--------------------------------------------------------------------------------------------- +Event logs +Event: {"IssueResult":[[1]]} + +[group:1]> call BillController 0x37949ce7937696dafffeac91411acbbf9ed7e86b queryBillByNo "BOC104" +transaction hash: 0xc2b2b1432aafa847df481ebaf36752124fed56c595e4fef42e2817b5059a282b +--------------------------------------------------------------------------------------------- +transaction status: 0x0 +description: transaction executed successfully +--------------------------------------------------------------------------------------------- +Receipt message: Success +Return message: Success +Return value size:1 +Return types: (STRING) +Return values:({'infoID':'BOC104','infoAmt':'4000','infoType':'12','infoIsseDate':'20110102','infoDueDate':'20110106','drwrAcct':'11','drwrCmID':'11','accptrAcct':'11','accptrCmID':'11','pyeeAcct':'11','pyeeCmID':'11','holdrAcct':'BBB','holdrCmID':'BID','waitEndorseAcct':'','waitEndorseCmID':'','rejectEndorseAcct':'','rejectEndorseCmID':'','state':'NewPublish'}) +--------------------------------------------------------------------------------------------- +Event logs +Event: {} + +[group:1]> call BillController 0x37949ce7937696dafffeac91411acbbf9ed7e86b endorse "BOC104" "13" "AAA" +transaction hash: 0xcef2d7c74bc363b5bc7b81bbd15ba34aab5df5614f0ee47a249cfd53211796af +--------------------------------------------------------------------------------------------- +transaction status: 0x0 +description: transaction executed successfully +--------------------------------------------------------------------------------------------- +Receipt message: Success +Return message: Success +Return value size:1 +Return types: (BOOL) +Return values:(true) +--------------------------------------------------------------------------------------------- +Event logs +Event: {"EndorseResult":[[true]]} + +[group:1]> call BillController 0x37949ce7937696dafffeac91411acbbf9ed7e86b queryBills "BID" +transaction hash: 0x809ba2db31f8da04b53532b26430385cfd58276fe4d28c891270cbb7ba4c1ede +--------------------------------------------------------------------------------------------- +transaction status: 0x0 +description: transaction executed successfully +--------------------------------------------------------------------------------------------- +Receipt message: Success +Return message: Success +Return value size:1 +Return types: ([STRING] ) +Return values:([{'infoID':'BOC104','infoAmt':'4000','infoType':'12','infoIsseDate':'20110102','infoDueDate':'20110106','drwrAcct':'11','drwrCmID':'11','accptrAcct':'11','accptrCmID':'11','pyeeAcct':'11','pyeeCmID':'11','holdrAcct':'BBB','holdrCmID':'BID','waitEndorseAcct':'AAA','waitEndorseCmID':'13','rejectEndorseAcct':'','rejectEndorseCmID':'','state':'EndorseWaitSign'}] ) +--------------------------------------------------------------------------------------------- +Event logs +Event: {} +``` + +## 附 开发心得 + +开发过程中,最主要是对整个票据流程的梳理,针对各个方法的开发,其实并不是很难,只是对过程的一种描述。 + +因此,整个开发流程,先确立了先梳理需求,然后针对solidity语言开发出一个可用的版本。 + diff --git a/contracts/business_template/evidence_plus/README.md b/docs/business_template/evidence_plus.md old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/evidence_plus/README.md rename to docs/business_template/evidence_plus.md diff --git a/docs/business_template/redpacket.md b/docs/business_template/redpacket.md old mode 100644 new mode 100755 diff --git a/docs/common_tools/DGHV.md b/docs/common_tools/DGHV.md new file mode 100755 index 00000000..65aca32f --- /dev/null +++ b/docs/common_tools/DGHV.md @@ -0,0 +1,203 @@ +# 基于DGHV的同态加密 +基本概念、学习笔记、参考内容: + +> 概念、个人笔记: +> +> 1. [同态加密的原理详解与go实践](https://blog.csdn.net/weixin_43988498/article/details/118802616) +> 2. [DGHV:整数上的同态加密(1)-算法构建](https://blog.csdn.net/weixin_43988498/article/details/119459857) +> 3. [DGHV:整数上的同态加密(2)-解决噪声与构建全同态蓝图](https://blog.csdn.net/weixin_43988498/article/details/119570507) +> +> 参考: +> +> 1. 论文:[《一种基于智能合约的全同态加密方法》](https://kns.cnki.net/kcms/detail/detail.aspx?dbcode=CJFD&dbname=CJFDLAST2020&filename=AQJS202009005&v=kzaijASy61Kjw7dUtnNnML6O%25mmd2Bv886ZZ4Mq9RnlqNape%25mmd2BABO%25mmd2Bfioot2MYlYfxTEcj) +> 2. [1] M. Dijk, C. Gentry, S. Halevi, and V.Vaikuntanathan. Fully homomorphic encryption over the integers[J]. Applications of Cryptographic Techniques: Springer, Berlin, 2010, 24-43. +> 3. http://blog.sciencenet.cn/blog-411071-617182.html + +> **同态加密等计算量大的算法不适合在合约中计算,合约仅作为测试** + +# 基本设计 + +## 1. 随机数 + +我们所说的随机函数都是伪随机函数即PRF + +随机函数的一般构成是:`随机种子 + 随机数生成算法` + +目前有很多优秀的伪随机算法已经实现,但是在区块链智能合约上的最大困难是**区块链的封闭性** + +可以将区块链看作一个封闭式的信息世界,所以不像一般网络中有丰富的熵增源. + +Solidity通常采用keccak256哈希函数 作为随机数的生成器,该函数有一定的随机数性质,但是随机数生成的过程容易被攻击。 + +传统的随机数生成过程需要本结点的 Nonce值作为随机数种子,恶意节点会大量计算Nonce的值,直到随机事件的结果对自己有利,所以项目采用区块时间戳作为随机种子。 + +使用线性求余法生成随机数,再采用keccak256 Hash函数将区块时间戳与随机数合并取最终的随机数 + +生成公式如下: + +![HUTVJl](http://xwjpics.gumptlu.work/qinniu_uPic/HUTVJl.png) + +## 2. 整数上的全同态加密 + +![iPUQRe](http://xwjpics.gumptlu.work/qinniu_uPic/iPUQRe.png) + +# 功能测试 + +合约实现了输入为单Bit(即m ∈ {0, 1})的**加法同态加密**(使用对称秘钥) + +### step_1 选择参数 + +编译、运行`syn_DGHV.go` + +对于参数η,加法同态始终满足,但是乘法同态满足有要求(因为算法噪音): + +* 经测试η>=9时,乘法同态满足(小于9时不稳定,可见评估结果输出) +* 智能合约中3<=η<=5, 因为η过大会导致参数q过大无法部署合约(solidity最大为int256,没有大数操作) + +```shell +go run syn_DGHV.go 5 # 参数1:η (建议>=9, 合约中<=5) +``` + +运行结果中包含: + +* 生成的秘钥`p` +* 参数`q` + +输出示例(输出包含了多组测试,选择一组参数即可): + +```shell +============================================== +p = 31 +q = 42535295865117307932921825928971026418 +m0 = 0, m1 = 1 +解密结果:n0 = 0, n1 = 1 +加法测试:0 + 1 , true +加法测试:0 + 0 , true +加法测试:1 + 1 , true +加法测试:1 + 0 , true +============================================== +乘法测试:0 * 1 , true +乘法测试:0 * 0 , true +乘法测试:1 * 1 , true +乘法测试:1 * 0 , true +============================================== +``` + +### step_2 部署合约,输入参数 + +#### 以控制台为例 +``` +[group:1]> deploy DGHV_Homomorphic_Encryption +deploy contract failed for cannot encode in encodeMethodFromObject with appropriate interface ABI, cause:Arguments mismatch: arguments size, expected: 3, actual: 0 + +[group:1]> deploy DGHV_Homomorphic_Encryption 5 42535295865117307932921825928971026418 31 +transaction hash: 0xbde9ee1278af7cf59f49fc3dda084852a3d0cf922d40c337b0b72daa063d2afc +contract address: 0x6c0ca924fb69c4bbef81d710c1b2769dc568035b +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 + +[group:1]> call DGHV_Homomorphic_Encryption 0x6c0ca924fb69c4bbef81d710c1b2769dc568035b encrypto 1 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(1318594171818636545920576603798101818965) +--------------------------------------------------------------------------------------------- + +[group:1]> call DGHV_Homomorphic_Encryption 0x6c0ca924fb69c4bbef81d710c1b2769dc568035b encrypto 0 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(1318594171818636545920576603798101818964) +--------------------------------------------------------------------------------------------- + +[group:1]> call DGHV_Homomorphic_Encryption 0x6c0ca924fb69c4bbef81d710c1b2769dc568035b decrypto 131859417181863654592057 +6603798101818965 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(1) +--------------------------------------------------------------------------------------------- + +[group:1]> call DGHV_Homomorphic_Encryption 0x6c0ca924fb69c4bbef81d710c1b2769dc568035b decrypto 131859417181863654592057 +6603798101818964 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(0) +--------------------------------------------------------------------------------------------- + +[group:1]> call DGHV_Homomorphic_Encryption 0x6c0ca924fb69c4bbef81d710c1b2769dc568035b HE_Add 13185941718186365459205766 +03798101818965 1318594171818636545920576603798101818964 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(1) +--------------------------------------------------------------------------------------------- +``` + + +#### 以remix IDE为例 + +输出初始化参数: + +MwFMIc + +### Step_3 测试 + +image-20210812230115286 + +1的密文为:1318594171818636545920576603798101818973 + +KBUSK7 + +0的密文为:1318594171818636545920576603798101818962 + +#### 同态加法 + +1+0 = 1 + +ns3yge + +1+1 = 0 + +Zf6t09 + +0+0 = 0 + +hJzStL + +# 拓展与改进 + +1. 在合约中实现字符串**大数的基本计算**就可以实现合约上的同态乘法(或许有更好的办法) + +2. 虽然输入只支持1bit,但是可以通过组合电路实现高阶的计算: + + * 同态加法 等价于 逻辑异或 + * 同态乘法 等价于 逻辑与 + * 逻辑与与逻辑异或具有完备性,可以实现组合电路任意高阶计算 + + (图片来自论文) + + image-20210812230914554 + +3. 设计电路时注意使用Bootstappable算法减少噪声,不然会时效 + diff --git a/docs/common_tools/DateTimeContract.md b/docs/common_tools/DateTimeContract.md new file mode 100644 index 00000000..f3827d03 --- /dev/null +++ b/docs/common_tools/DateTimeContract.md @@ -0,0 +1,178 @@ +# DateTimeContract.sol -v1.0 + +DateTimeContract.sol 基于block.timestamp 时间戳计算当前的日期,提供年份、月份、日期、小时、分钟、秒的计算函数,基于solidity 0.4.25 到0.6.10之间。 + +## 控制台测试 +在控制台中执行,可获得以下的结果。 + +### 部署测试合约 +``` +[group:1]> deploy DateTimeContract +transaction hash: 0x6b4fde3da4c52df181a3ce69c999a56df7d294ae0429839ad936542f333aedb0 +contract address: 0x8c5295ce0f70772c538a07295069796887bee574 +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 测试将时间戳进行解析 +``` +[group:1]> call DateTimeContract 0x8c5295ce0f70772c538a07295069796887bee574 timestampToDate 1629731615 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:6 +Return types: (UINT, UINT, UINT, UINT, UINT, UINT) +Return values:(2021, 8, 23, 23, 13, 35) +--------------------------------------------------------------------------------------------- +``` + +### 分别测试返回年月日 +``` +[group:1]> call DateTimeContract 0x8c5295ce0f70772c538a07295069796887bee574 getYear 1629731615 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(2021) +--------------------------------------------------------------------------------------------- + +[group:1]> call DateTimeContract 0x8c5295ce0f70772c538a07295069796887bee574 getMonth 1629731615 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(8) +--------------------------------------------------------------------------------------------- + +[group:1]> call DateTimeContract 0x8c5295ce0f70772c538a07295069796887bee574 getDay 1629731615 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(23) +--------------------------------------------------------------------------------------------- + +[group:1]> call DateTimeContract 0x8c5295ce0f70772c538a07295069796887bee574 getMinute 1629731615 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(13) +--------------------------------------------------------------------------------------------- + +[group:1]> call DateTimeContract 0x8c5295ce0f70772c538a07295069796887bee574 getSecond 1629731615 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(35) +--------------------------------------------------------------------------------------------- +``` + + + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *getYear (uint timestamp ) public view returns (uint _year)* |返回年份 +2 | *function getMonth (uint timestamp ) public view returns (uint _month)* |返回月份 +3 | *function getDay (uint timestamp ) public view returns (uint _day)* |返回日期(那一天) +4 | *function getHour (uint timestamp ) public view returns (uint _hour)* |返回小时 +5 | *function getMinute (uint timestamp ) public view returns (uint _minute)* |返回分钟 +6 | *function getSecond (uint timestamp ) public view returns (uint _second)* |返回秒 +7 | *function timestampToDate(uint timestamp) public view returns (uint _year, uint _month,uint _days,uint _hours , uint _minute ,uint _second)* |将参数timestamp通过计算,输出年月日时分秒 + +## API描述 + +### 1.getYear +返回年份。 + ``` + function getYear (uint timestamp ) public view returns (uint _year) + ```` + #### 参数 + - uint timestamp :block.timestamp时间戳 + #### 返回值 + - _year : timestamp对应的年份 + + ### 2.getMonth + 返回月份 + ``` + function getMonth (uint timestamp ) public view returns (uint _month) + ```` + #### 参数 + - uint timestamp :block.timestamp时间戳 + #### 返回值 + - _month : timestamp对应的月份 + + ### 3.getDay + 返回日期(那一天)。 + ``` + function getDay (uint timestamp ) public view returns (uint _day) + ```` + #### 参数 + - uint timestamp :block.timestamp时间戳 + #### 返回值 + - _day : timestamp对应的日期 + + ### 4.getHour + 返回小时。 + ``` + function getHour (uint timestamp ) public view returns (uint _hour) + ```` + #### 参数 + - uint timestamp :block.timestamp时间戳 + #### 返回值 + - _hour : timestamp对应的小时 + + ### 5.getMinute + 返回分钟。 + ``` + function getMinute (uint timestamp ) public view returns (uint _minute) + ```` + #### 参数 + - uint timestamp :block.timestamp时间戳 + #### 返回值 + - _minute : timestamp对应的分钟 + + ### 6.getSecond + 返回秒。 + ``` + function getSecond (uint timestamp ) public view returns (uint _second) + ```` + #### 参数 + - uint timestamp :block.timestamp时间戳 + #### 返回值 + - _second : timestamp对应的秒数 + +### 7.timestampToDate + +将参数timestamp通过计算,输出年月日时分秒 + ``` + function timestampToDate(uint timestamp) private view returns (uint _year, uint _month,uint _days,uint _hours , uint _minute ,uint _second) + ```` + #### 参数 + - uint timestamp : block.timestamp时间戳 + #### 返回值 + - _year : 年份 + - _month: 月份 + - _day: 日期 + - _hour: 小时 + - _minute: 分钟 + - _second: 秒 \ No newline at end of file diff --git a/contracts/business_template/privacy_computation/Fiat-Shamir-ZK/README.md b/docs/common_tools/FiatShamirZK.md old mode 100644 new mode 100755 similarity index 100% rename from contracts/business_template/privacy_computation/Fiat-Shamir-ZK/README.md rename to docs/common_tools/FiatShamirZK.md diff --git a/docs/common_tools/RBAC.md b/docs/common_tools/RBAC.md new file mode 100755 index 00000000..ec5297f9 --- /dev/null +++ b/docs/common_tools/RBAC.md @@ -0,0 +1,46 @@ +# 权限管理 +权限管理有四个合约 +1. Roles library 用于角色管理 +2. RBAC 合约 管理用户和角色的映射关系 +3. Ownable 合约 对合约的所属权进行管理 +4. Example 合约 使用上述三个合约完成的一个小例子 + +## Roles +编号 | API | API描述 +---|---|--- +1 | *function addRole(Role storage role ,address addr) internal* | 添加某个角色里的用户 +2 | *function removeRole(Role storage role,address addr) internal* | 移除某个角色里的用户 +3 | *function hasRole(Role storage role,address addr) internal view returns(bool)* | 检查某个角色下是否有某个用户 +4 | *function checkRole(Role storage role,address addr) public view* | 确保某个用户属于某个角色,否则revert + + +## RBAC +编号 | API | API描述 +---|---|--- +1 | *function addRole(address _operater, string memory _role) internal* | 添加某个角色里的用户 +2 | *function removeRole(address _operater, string memory _role) internal* | 移除某个角色里的用户 +3 | *function hasRole(address _operater, string memory _role) public view returns(bool)* | 检查某个角色下是否有某个用户 +4 | *function checkRole(address _operater, string memory _role) public view* | 确保某个用户属于某个角色,否则revert +5 | *modifier onlyRole(string memory _role)*| 修饰符确保只有某个角色可以操作 + + +## Ownable +编号 | API | API描述 +---|---|--- +1 | *modifier onlyOwner* | 修饰符确保只有owner可以操作 +2 | *function renounceOwnership() public onlyOwner* | 放弃owner权限 +3 | *function transferOwnership(address _newOwner) public onlyOwner* | 将owner权限转给其他地址 + + +## Example +在 Example 实现了加、减、乘、除四个方法,对应了四种权限,只有拥有相应的权限才可以进行相应的操作。 + +编号 | API | API描述 +---|---|--- +1 | *function setRole(address addr,string memory _role) public onlyOwner* | 设置给某个地址设置某个角色 +2 | *function resetRole(address addr,string memory _role) public onlyOwner* | 移除某个地址的某个角色 +3 | *function add(uint a,uint b) public view onlyRole(ADD) returns(uint)* | 加 +4 | *function sub(uint a,uint b) public view onlyRole(SUB) returns(uint)* | 减 +5 | *function mul(uint a,uint b) public view onlyRole(MUL) returns(uint)* | 乘 +6 | *function div(uint a,uint b) public view onlyRole(DIV) returns(uint)* | 除 + diff --git a/docs/Role_operation/Character.md b/docs/common_tools/RoleOperation.md old mode 100644 new mode 100755 similarity index 100% rename from docs/Role_operation/Character.md rename to docs/common_tools/RoleOperation.md diff --git a/docs/common_tools/white_list_manage.md b/docs/common_tools/white_list_manage.md new file mode 100755 index 00000000..8a25422e --- /dev/null +++ b/docs/common_tools/white_list_manage.md @@ -0,0 +1,32 @@ +## 功能说明 +本合约支持白名单管理,包含增删改查相关操作。 + +## 接口 +提供了三个合约:SafeRole 合约,WhitelistAdminRole 合约,WhitelistedRole 合约。其中SafeRole是库合约,WhitelistedRole合约是对外服务合约,用于数据和逻辑抽象化。 +WhitelistedRole合约:对外服务的唯一接口。包含: +- addWhitelistAdmin(address account):添加白名单管理员账户,amount是角色的地址 +- addWhitelisted(address account): 添加白名单账户,amount是角色的地址 +- isWhitelistAdmin(address account): 判断是否是白名单管理员,amount是角色的地址 +- isWhitelisted(address account): 判断账户是否在白名单里,amount是角色的地址 +- removeWhitelisted(address account): 移除白名单管理员账户,amount是角色的地址 +- renounceWhitelisted(): 清空白名单列表 +- renounceWhitelistAdmin(): 清空白名单管理员列表 + + +## 使用示例 +白名单管理的增删改查,整个过程如下: + +合约初始化: + + - 部署WhitelistedRole合约 + +合约调用: + + - 调用WhitelistedRole.addWhitelistAdmin 提交添加白名单管理员 + - 调用WhitelistedRole.addWhitelisted 提交添加用户到白名单列表 + - 调用WhitelistedRole.isWhitelistAdmin 判断是否是白名单管理员 + - 调用WhitelistedRole.isWhitelisted 判断是否在白名单列表 + - 调用WhitelistedRole.removeWhitelisted 移除白名单 + - 调用WhitelistedRole.renounceWhitelisted 清空白名单列表 + - 调用WhitelistedRole.renounceWhitelistAdmin 清空白名单管理员列表 + \ No newline at end of file diff --git a/docs/data_structure/DataTable.md b/docs/data_structure/DataTable.md new file mode 100755 index 00000000..a52886a6 --- /dev/null +++ b/docs/data_structure/DataTable.md @@ -0,0 +1,29 @@ +# DataTable.sol + +DataTable提供了基于bytes32主键的二维表、自定义类型值的可迭代、可查询的映射. + +## 使用方法 + +首先需要通过import引入DataTable合约,然后通过"."进行方法调用,如下为调用例子: + +``` +示例合约 StudentsGradesDemo.sol +``` + + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *function insertItem(bytes32 rowId, bytes32 colId, DataItem item) public* | 新增数据项 +2 | *ffunction getItem(bytes32 rowId, bytes32 colId) public view returns(DataItem)* |获取数据项 +3 | *function getRow(bytes32 rowId) public view returns(DataRow)* |获得数据行 +4 | *function isExists(bytes32 rowId, bytes32 colId) public view returns(bool)* |判断数据项是否存在 +5 | *function isExists(bytes32 rowId) public view returns(bool)* |判断行是否存在 +6 | *function rowCount()public view returns(uint256)* |获取行数 +7 | *function iterate_start() public view returns(Pair)* | 枚举key的游标 +8 | *function can_iterate(Pair iter) public view returns(bool)* | 游标是否可用 +9 | *function iterate_next(Pair iter) public view returns(Pair)* | 下一个游标值 + + + diff --git a/docs/data_structure/LibAddressSet.md b/docs/data_structure/LibAddressSet.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibBytes32Set.md b/docs/data_structure/LibBytes32Set.md new file mode 100755 index 00000000..dd82c7e5 --- /dev/null +++ b/docs/data_structure/LibBytes32Set.md @@ -0,0 +1,347 @@ +# LibBytes32Set.sol + +LibBytes32Set 提供了存储Bytes32类型的Set数据结构,支持包括add, remove, contains, getAll等方法。 + +## 使用方法 + +首先需要通过import引入LibBytes32Set类库,然后通过"."进行方法调用,如下为调用LibBytes32Set.add方法的例子: + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function add() public view returns (bool) { + return bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF); + } +} +``` + +## 控制台测试 + +### 部署测试合约 +``` +[group:1]> deploy Bytes32SetDemo +transaction hash: 0xea2a56d12eef424325d963de9895eaff84023cc79d0d302a2b3393488ba94c35 +contract address: 0x265da37424917fa78740585c7b4fc58fdd59f11e +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 执行测试函数 +``` +[group:1]> call Bytes32SetDemo 0x265da37424917fa78740585c7b4fc58fdd59f11e add +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BOOL) +Return values:(true) +--------------------------------------------------------------------------------------------- + +[group:1]> call Bytes32SetDemo 0x265da37424917fa78740585c7b4fc58fdd59f11e contains +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BOOL) +Return values:(true) +--------------------------------------------------------------------------------------------- + +[group:1]> call Bytes32SetDemo 0x265da37424917fa78740585c7b4fc58fdd59f11e getAll +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: ([BYTES, BYTES, BYTES] ) +Return values:([hex://0x111122223333444455556666777788889999aaaabbbbccccddddeeeeffffccca, hex://0x111122223333444455556666777788889999aaaabbbbccccddddeeeeffffcccb, hex://0x111122223333444455556666777788889999aaaabbbbccccddddeeeeffffcccc] ) +--------------------------------------------------------------------------------------------- + +[group:1]> call Bytes32SetDemo 0x265da37424917fa78740585c7b4fc58fdd59f11e getSize +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(3) +--------------------------------------------------------------------------------------------- + +[group:1]> call Bytes32SetDemo 0x265da37424917fa78740585c7b4fc58fdd59f11e getByIndex 0 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BYTES) +Return values:(hex://0x111122223333444455556666777788889999aaaabbbbccccddddeeeeffffccca) +--------------------------------------------------------------------------------------------- + +[group:1]> call Bytes32SetDemo 0x265da37424917fa78740585c7b4fc58fdd59f11e atPosition +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (BOOL, UINT) +Return values:(true, 2) +--------------------------------------------------------------------------------------------- +``` + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *contains(Bytes32Set storage set, bytes32 val) internal view returns (bool)* | 判断Set里是否包含了元素value。 +2 | *add(Bytes32Set storage set, bytes32 val) internal view returns (bool)* | 往Set里添加元素。 +3 | *remove(Bytes32Set storage set, bytes32 val) internal view returns (bool)* | 删除Set中的元素。 +4 | *getAll(Bytes32Set storage set) internal view returns (bytes32[] memory)* | 返回所有元素。 +5 | *getSize(Bytes32Set storage set) internal view returns (uint256)* | 返回Set中元素数。 +6 | *atPosition(Bytes32Set storage set, bytes32 val) internal view returns (bool, uint256)* | 返回某个元素的位置。 +7 | *getByIndex(Bytes32Set storage set, uint256 index) internal view returns (bytes32)* | 查找某个元素。 + +## API详情 + +### ***1. contains 函数*** + +判断Set里是否包含了元素value + +#### 参数 + +- set: byte32类型Set +- val: 待检查元素 + +#### 返回值 + +-bool: 是否存在, true存在,false 不存在 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function contains() public view returns (bool) { + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF); + return bytesSet.contains(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF); + } +} +``` + +### ***2. add 函数*** + +往Set中添加一个元素 + +#### 参数 + +- set: byte32类型Set +- val: 待加入元素 + +#### 返回值 + +- bool: 是否添加成功 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function add() public view returns (bool) { + return bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCF); + } +} +``` + +### ***3. remove 函数*** + +删除Set中的指定元素 + +#### 参数 + +- set: byte32类型Set +- val: 待删除元素 + +#### 返回值 + +- bool: 是否删除成功 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function remove(bytes32 del) public view returns (bool) { + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC); + return bytesSet.remove(del); + } +} +``` + +### ***4. getAll 函数*** + +获取Set中的所有元素。 + +#### 参数 + +- set: byte32类型Set + +#### 返回值 + +- bytes32[]: 所有元素 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function getAll() public view returns (bytes32[]) { + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC); + return bytesSet.getAll(); + } +} +``` + +### ***5. getSize 函数*** + +返回Set中元素数量 + +#### 参数 + +- set: byte32类型Set + +#### 返回值 +- uint256: 元素数量 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function getSize() public view returns (uint256) { + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC); + return bytesSet.getSize(); + } +} +``` + +### ***6. atPosition 函数*** + +Set中某个元素的位置 + +#### 参数 + +- set: byte32类型Set +- val: 待检测元素 + +#### 返回值 + +- bool: 是否存在该元素 +- uint256: 该元素位置 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function getSize() public view returns (uint256) { + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC); + return bytesSet.atPositon(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC); + } +} +``` + +### ***6. getByIndex 函数*** + +获取Set中的某个元素 + +#### 参数 + +- set: byte32类型Set +- index: 元素的位置 + +#### 返回值 + +- bytes32: 该位置的元素 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibBytes32Set.sol"; + +contract Bytes32SetDemo{ + + using LibBytes32Set for LibBytes32Set.Bytes32Set; + LibBytes32Set.Bytes32Set private bytesSet; + + function getByIndex(uint256 index) public view returns (bytes32) { + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCA); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCB); + bytesSet.add(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC); + return bytesSet.getByIndex(index); + } +} +``` \ No newline at end of file diff --git a/docs/data_structure/LibBytesMap.md b/docs/data_structure/LibBytesMap.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibDeque.md b/docs/data_structure/LibDeque.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibLinkedList.md b/docs/data_structure/LibLinkedList.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibMaxHeapUint256.md b/docs/data_structure/LibMaxHeapUint256.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibMerkleTree.md b/docs/data_structure/LibMerkleTree.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibMinHeapUint256.md b/docs/data_structure/LibMinHeapUint256.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibQueue.md b/docs/data_structure/LibQueue.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibSingleList.md b/docs/data_structure/LibSingleList.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibStack.md b/docs/data_structure/LibStack.md old mode 100644 new mode 100755 diff --git a/docs/data_structure/LibUint256Set.md b/docs/data_structure/LibUint256Set.md new file mode 100755 index 00000000..86598b09 --- /dev/null +++ b/docs/data_structure/LibUint256Set.md @@ -0,0 +1,359 @@ +# LibUint256Set.sol + +LibUint256Set 提供了存储Uint256类型的Set数据结构,支持包括add, remove, contains, getAll等方法。 + +## 使用方法 + +首先需要通过import引入LibUint256Set类库,然后通过"."进行方法调用,如下为调用LibUint256Set.add方法的例子: + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function add() public view returns (bool) { + return uintSet.add(1); + } +} +``` + +## 控制台测试 + +### 部署测试合约 +``` +[group:1]> deploy Uint256SetDemo +transaction hash: 0x4c88711fe9703b23cd01e633770eb57fb5f467d80b4dd802a69e64f68805b471 +contract address: 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 执行测试函数 + +``` +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff add +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BOOL) +Return values:(true) +--------------------------------------------------------------------------------------------- + +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff contains +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (BOOL) +Return values:(true) +--------------------------------------------------------------------------------------------- + +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff getAll +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: ([UINT, UINT, UINT] ) +Return values:([1, 2, 3] ) +--------------------------------------------------------------------------------------------- + +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff remove 2 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (BOOL, [UINT, UINT] ) +Return values:(true, [1, 3] ) +--------------------------------------------------------------------------------------------- + +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff removeAndAtPositon 2 3 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:2 +Return types: (BOOL, UINT) +Return values:(true, 1) +--------------------------------------------------------------------------------------------- + +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff getSize +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(3) +--------------------------------------------------------------------------------------------- + +[group:1]> call Uint256SetDemo 0x67dd71d31bfcd20f3b959c02a23a5c87816194ff getByIndex 2 +--------------------------------------------------------------------------------------------- +Return code: 0 +description: transaction executed successfully +Return message: Success +--------------------------------------------------------------------------------------------- +Return value size:1 +Return types: (UINT) +Return values:(3) +--------------------------------------------------------------------------------------------- +``` + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *contains(Uint256Set storage set, bytes32 val) internal view returns (bool)* | 判断Set里是否包含了元素value。 +2 | *add(Uint256Set storage set, bytes32 val) internal view returns (bool)* | 往Set里添加元素。 +3 | *remove(Uint256Set storage set, bytes32 val) internal view returns (bool)* | 删除Set中的元素。 +4 | *getAll(Uint256Set storage set) internal view returns (uint256[] memory)* | 返回所有元素。 +5 | *getSize(Uint256Set storage set) internal view returns (uint256)* | 返回Set中元素数。 +6 | *atPosition(Uint256Set storage set, bytes32 val) internal view returns (bool, uint256)* | 返回某个元素的位置。 +7 | *getByIndex(Uint256Set storage set, uint256 index) internal view returns (uint256)* | 查找某个元素。 + +## API详情 + +### ***1. contains 函数*** + +判断Set里是否包含了元素value + +#### 参数 + +- set: uint256类型Set +- val: 待检查元素 + +#### 返回值 + +-bool: 是否存在, true存在,false 不存在 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function add() public view returns (bool) { + uintSet.add(1); + return uintSet.contains(1); + } +} +``` + +### ***2. add 函数*** + +往Set中添加一个元素 + +#### 参数 + +- set: uint256类型Set +- val: 待加入元素 + +#### 返回值 + +- bool: 是否添加成功 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function add() public view returns (bool) { + return uintSet.add(1); + } +} +``` + +### ***3. remove 函数*** + +删除Set中的指定元素 + +#### 参数 + +- set: uint256类型Set +- val: 待删除元素 + +#### 返回值 + +- bool: 是否删除成功 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function remove() public view returns (bool) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.remove(3); + } +} +``` + +### ***4. getAll 函数*** + +获取Set中的所有元素。 + +#### 参数 + +- set: uint256类型Set + +#### 返回值 + +- uint256[]: 所有元素 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function remove() public view returns (uint256[]) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.getAll(); + } +} +``` + +### ***5. getSize 函数*** + +返回Set中元素数量 + +#### 参数 + +- set: uint256类型Set + +#### 返回值 +- uint256: 元素数量 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function getSize() public view returns (uint256) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.getSize(); + } +} +``` + +### ***6. atPosition 函数*** + +Set中某个元素的位置 + +#### 参数 + +- set: uint256类型Set +- val: 待检测元素 + +#### 返回值 + +- bool: 是否存在该元素 +- uint256: 该元素位置 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function getSize() public view returns (uint256) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.atPosition(1); + } +} +``` + +### ***6. getByIndex 函数*** + +获取Set中的某个元素 + +#### 参数 + +- set: uint256类型Set +- index: 元素的位置 + +#### 返回值 + +- uint256: 该位置的元素 + +#### 实例 + +``` +pragma solidity ^0.4.25; + +import "./LibUint256Set.sol"; + +contract Uint256SetDemo{ + + using LibUint256Set for LibUint256Set.Uint256Set; + LibUint256Set.Uint256Set private uintSet; + + function getByIndex(uint256 index) public view returns (uint256) { + uintSet.add(1); + uintSet.add(2); + uintSet.add(3); + return uintSet.getByIndex(index); + } +} +``` \ No newline at end of file diff --git a/docs/data_structure/Map.md b/docs/data_structure/Map.md new file mode 100755 index 00000000..79a0f0a6 --- /dev/null +++ b/docs/data_structure/Map.md @@ -0,0 +1,60 @@ +# Map.sol + +Map提供了基于bytes32主键、自定义类型值的可迭代、可查询的映射. + +## 使用方法 + +首先需要通过import引入Map合约,然后通过"."进行方法调用,如下为调用例子: + +``` +pragma solidity >=0.4.24 <0.6.11; + +import "./Map.sol"; + +contract MyData is DataItem{ + string name; + int16 age; + constructor(string n, int16 a){ + name = n; + age = a; + } +} + +contract Test { + + Map _map; + constructor(){ + _map = new Map(); + } + + event Log(uint256 size); + event LogKey(bytes32 key); + function f() public { + string memory name = "张三"; + _map.insert(bytes32("10001"), new MyData(name, 32)); + emit Log(_map.getSize()); + //遍历 + for(Pair item = _map.iterate_start(); _map.can_iterate(item);item = _map.iterate_next(item)){ + emit LogKey(item.getKey()); + MyData data = MyData(item.getValue()); + } + } +} +``` + + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *function insert(bytes32 key, DataItem value)public* | 新增键值对 +2 | *function getValue(bytes32 key)public view returns(DataItem)* |根据key获取value +3 | *function getSize()public view returns(uint256)* |获得当前mapping的容量 +4 | *function isEmpty() public view returns(bool)* |是否为空 +5 | *function isExists(bytes32 key) public view returns(bool)* |判断键值是否存在 +6 | *function iterate_start() public view returns(Pair)* | 枚举key的游标 +7 | *function can_iterate(Pair iter) public view returns(bool)* | 游标是否可用 +8 | *function iterate_next(Pair iter) public view returns(Pair)* | 下一个游标值 + + + diff --git a/docs/data_structure/data_structure.lnk b/docs/data_structure/data_structure.lnk deleted file mode 100644 index 5e53714d..00000000 Binary files a/docs/data_structure/data_structure.lnk and /dev/null differ diff --git a/docs/default/Crypto.md b/docs/default/crypto/Crypto.md old mode 100644 new mode 100755 similarity index 100% rename from docs/default/Crypto.md rename to docs/default/crypto/Crypto.md diff --git a/docs/Crypto/LibCryptoHash.md b/docs/default/crypto/LibCryptoHash.md old mode 100644 new mode 100755 similarity index 100% rename from docs/Crypto/LibCryptoHash.md rename to docs/default/crypto/LibCryptoHash.md diff --git a/docs/Crypto/LibDecode.md b/docs/default/crypto/LibDecode.md old mode 100644 new mode 100755 similarity index 100% rename from docs/Crypto/LibDecode.md rename to docs/default/crypto/LibDecode.md diff --git a/docs/default/internalFunction.md b/docs/default/internalFunction.md new file mode 100755 index 00000000..ed4ac02a --- /dev/null +++ b/docs/default/internalFunction.md @@ -0,0 +1,61 @@ +# solidity 内置函数转换 +提供了一些内置函数的直接访问接口,主要包括block,tx相关 + +## API列表 + +编号 | API | API描述 +---|---|--- +1 | *getBlockhash(uint256 blockNumber) view public returns(bytes32)* | 根据指定的区块号获取hash(仅支持最近256个区块,且不包含当前区块) +2 | *getBlockNumber() view public returns(address)* |获取当前区块的高度 +3 | *getTimestamp() view public returns(uint256)* | 获取当前区块的时间戳 +4 | *isContract(address addr) view public returns(bool)* | 判断一个地址是否是合约地址 +5 | *getCodeByAddress(address addr) view public returns(bytes)* | 根据合约地址获取合约代码 +6 | *computeAddress(bytes32 salt, bytes32 bytecodeHash) view public returns(address)* | 根据字节码计算合约的地址 + +## API 详情 + +### ***1. getBlockhash 函数*** +根据指定的区块号获取hash +#### 参数 +- blockNumber: 区块高度 +#### 返回值 +- 区块的hash + +### ***2. getBlockNumber 函数*** +获取当前区块的高度 +#### 参数 +- 无 +#### 返回值 +- 区块高度 + +### ***3. getTimestamp 函数*** +获取当前区块的时间戳 +#### 参数 +- 无 +#### 返回值 +- 当前区块的时间戳 + + +### ***4. isContract 函数*** +验证一个地址是否是合约地址 +#### 参数 +- address: 待验证的地址 +#### 返回值 +- bool + + +### ***5. getCodeByAddress 函数*** +根据合约地址获取合约代码 +#### 参数 +- address: 合约地址 +#### 返回值 +- bytes: 字节码 + + +### ***6. computeAddress 函数*** +根据字节码计算合约的地址, 对应一些通过creat2方法创建的合约,如果有其字节码和盐,那么可以得到其部署的合约地址 +#### 参数 +- bytes32: salt +- bytes32: bytecodeHash +#### 返回值 +- address: 合约地址 diff --git a/docs/default/proxy/proxy.md b/docs/default/proxy/proxy.md new file mode 100755 index 00000000..a3eb912b --- /dev/null +++ b/docs/default/proxy/proxy.md @@ -0,0 +1,64 @@ +# 代理执行 +代理执行即代理模式的实现,主要分成三个部分 +- 接口合约 +定义了可以被外部调用的方法 +- 实现合约 +方法的具体内容实现 +- 代理合约 +通过接口合约对实现合约的调用,并在调用前后加入一些额外的逻辑 + +下面以一个唱歌方法的代理调用来描述一下执行的流程 +## 接口合约 +定义了一个singing 方法,入参是singer歌手 +```function singing(address singer) external;``` + +## 实现合约 +实现合约实现了接口合约中的singsing方法,以记录一个日志事件来代表方法中所做的内容 +```javascript + function singing(address _singer) public override{ + emit SingLog(_singer, now); + } +``` + +## 代理合约 +代理合约首先在构造方法中传入被代理合约的实例,通过接口合约进行实例化和方法调用。 +在代理合约中可以在具体方法执行前后进行其他的操作,这里也以两个事件代表,并且通过代理合约,对外暴露的方法名以及具体合约方法的入参,都可以起到一定的修饰作用。 +在此例中,外部看到的代理方法名是``` function proxySing() public ```,而且参数也在代理合约内部进行了处理,调用者不再传此参数。 +在某些情况下如果我们在调用一个方法前必须要做某些准备操作,又或者再调用后要做某些善后工作,都可以使用这种代理的模式。 + + +## 测试合约 +在控制台中,可以测试本代理合约。 +### 创建Sing合约的实例。 + +``` +[group:1]> deploy Sing +transaction hash: 0xa956af77a8bccbf3957e8f0f7b13e284684dc096baf2f63e88d99d9df46ee760 +contract address: 0x75adfb58594242bda453f302eb695280cf856c72 +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 部署代理合约 +``` +[group:1]> deploy SingProxy 0x75adfb58594242bda453f302eb695280cf856c72 +transaction hash: 0xad6fb8b6568e3b575d5c4c4e96b0bf096c6fc5524330eaef6ba7f58dc4240436 +contract address: 0x8df5416339b0b55832dabfdf44cecdd81299102c +currentAccount: 0x22fec9d7e121960e7972402789868962238d8037 +``` + +### 调用代理合约 +``` +[group:1]> call SingProxy 0x8df5416339b0b55832dabfdf44cecdd81299102c proxySing +transaction hash: 0x25ecc3d8584c7e8ac8d169848a4e71a8afce7051d3aacda6b39528f58be16771 +--------------------------------------------------------------------------------------------- +transaction status: 0x0 +description: transaction executed successfully +--------------------------------------------------------------------------------------------- +Receipt message: Success +Return message: Success +Return values:[] +--------------------------------------------------------------------------------------------- +Event logs +Event: {"ProxyLog":[["0x22fec9d7e121960e7972402789868962238d8037","before proxy do someting"],["0x22fec9d7e121960e7972402789868962238d8037","after proxy do someting"]]} +``` + diff --git a/webank_blockchain_qrcode.png b/webank_blockchain_qrcode.png old mode 100644 new mode 100755