Skip to content

Commit b1d081b

Browse files
JqLiu123longJJ2016yekai1003itherunderKesling515
authored
DevSecretBallot (#86)
* longjj2016 (#78) 1.修改之前问题,改为以下方法 10进制ascii转字符串 16进制ascii转字符串 2.文档描述更新 * 添加剪刀石头布的合约玩法 (#79) * add solidity file * add tutorial * add basic solidity tutorials * add assets * divergence * add divergence game * 增加func_call_contract.sol 及doc (#80) * Base64编解码库 (#81) * Counter: SimpleCounter; MultiSigCounter (#82) * 32 医疗卫生合约通用模版 (#84) * #32 医疗卫生合约模版 * 完善#32 医疗合约模版 * Solidity开发教程进阶版 (#85) * add solidity file * add tutorial * add basic solidity tutorials * add assets * divergence * add divergence game * advance solidity tutorial init * solidity tutorial advance Co-authored-by: longJJ2016 <1017303686@qq.com> Co-authored-by: 高野 <yekai1003@163.com> Co-authored-by: itherunder <61953384+itherunder@users.noreply.github.com> Co-authored-by: Kesling <43846775+Kesling515@users.noreply.github.com> Co-authored-by: kimroniny <1301862177@qq.com> Co-authored-by: Ferwoo <wufeiphil@163.com>
1 parent a2a47fa commit b1d081b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2849
-81
lines changed

contracts/base_type/LibAscii.sol

Lines changed: 55 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,70 +6,76 @@ pragma solidity ^0.4.25;
66
library LibAscii{
77

88
/**
9-
* 字符串转ascii字符串
9+
* 单个10进制ascii字符串转字符串
10+
* 例:"55" 得出 "U"
11+
* "109" 得出 "m"
12+
**/
13+
function decAscii2str(string data) internal pure returns (string){
14+
uint _data = decStrToUint(data);
15+
require(_data < 128, "data must be 0 ~ 127");
16+
bytes memory result = new bytes(1);
17+
result[0] = byte(_data);
18+
return string(result);
19+
}
20+
21+
/**
22+
* 单个16进制ascii字符串转字符串
1023
*
1124
* @ param data 原字符串(大小写均可)
12-
* @ param radix 原字符串进制 仅支持10,16进制
1325
*
14-
* 例:"55,16" 得出 "U" 16进制
15-
* "55,10" 得出 "7" 10进制
26+
* 例:"55" 得出 "U"
27+
* "6D" 得出 "Z"
1628
**/
17-
function str2ascii(string data, uint radix) internal pure returns (string){
18-
require(radix == 10 || radix == 16, "radix must only 10 or 16");
19-
20-
bytes memory _data = bytes(data);
21-
22-
require(_data.length % 2 == 0, "data length must be even");
23-
24-
uint[] memory temp = new uint[](_data.length);
25-
26-
for(uint i = 0; i < _data.length; i++) {
27-
uint _d = uint(_data[i]);
28-
29-
require(check(_d,radix), "data can only contain 0-9,a-f,A-F");//校验字符内容
30-
31-
if (_d > 96) {//a-f 97-102
32-
temp[i] = _d - 97 + 10;
33-
} else if (_d > 64) {//A-F 65-70
34-
temp[i] = _d - 65 + 10;
35-
} else {//0-9 48-57
36-
temp[i] = _d - 48;
37-
}
38-
}
39-
40-
bytes memory result = new bytes(temp.length / 2);
41-
for(uint _i = 0; _i < temp.length; _i += 2) {
42-
result[_i / 2] = byte(temp[_i] * radix + temp[_i + 1]);
43-
}
44-
45-
return string(result);
29+
function hexAscii2str(string data) internal pure returns(string){
30+
uint _data = hexStrToUint(data);
31+
require(_data < 128, "data must be 0x00 ~ 0x7F");
32+
return decAscii2str(uint2str(_data));
4633
}
4734

4835
/**
49-
* ascii字符串转10进制字符串
36+
* 字符串转ascii字符串
5037
* 例:"aa" 得出9797 10进制
5138
**/
52-
function ascii2str(string ascii) internal pure returns(string){
53-
bytes memory temp = bytes(ascii);
54-
string memory resultStr = "";
39+
function str2ascii(string data) internal pure returns(string){
40+
bytes memory temp = bytes(data);
41+
bytes memory resultStr = "";
5542
for(uint i = 0; i<temp.length; i++){
5643
uint _t = uint(temp[i]);
57-
resultStr = concat(resultStr,uint2str(_t));
44+
resultStr=abi.encodePacked(resultStr,uint2str(_t));
5845
}
59-
return resultStr;
46+
return string(resultStr);
6047
}
6148

6249
//-----------HELPER METHOD--------------//
63-
64-
//校验字符内容
65-
function check(uint _d, uint radix) internal pure returns(bool){
66-
if( radix == 10){//10进制 只有数字,范围48~57
67-
return _d > 47 && _d<58;
68-
}else if( radix == 16){ //16进制 除数字外,字母范围 A~F:64~70、a~f:97~102
69-
return (_d>47 && _d<58) || (_d>64 && _d<71) || (_d>96 && _d<103);
70-
}else{
71-
return false;
50+
51+
//10字符串转int
52+
function decStrToUint(string data) internal pure returns (uint){
53+
bytes memory temp = bytes(data);
54+
uint result=0;
55+
for(uint i = temp.length; i>0; i--){
56+
uint _t = uint(temp[i-1]);//ascii码的十进制
57+
result+=(_t-48)*(10**(temp.length-i));
7258
}
59+
return result;
60+
}
61+
62+
//字符串转int
63+
function hexStrToUint(string data) internal pure returns (uint){
64+
bytes memory temp = bytes(data);
65+
uint result=0;
66+
for(uint i = temp.length; i>0; i--){
67+
uint _t = uint(temp[i-1]);//ascii码的十进制
68+
uint _t1=0;
69+
if (_t > 96) {//a-f 97-102
70+
_t1 = _t - 97 + 10;
71+
} else if (_t > 64) {//A-F 65-70
72+
_t1 = _t - 65 + 10;
73+
} else {//0-9 48-57
74+
_t1 = _t - 48;
75+
}
76+
result+=_t1*(16**(temp.length-i));
77+
}
78+
return result;
7379
}
7480

7581
//数字转字符串
@@ -89,15 +95,4 @@ library LibAscii{
8995
}
9096
return string(result);
9197
}
92-
93-
//字符串拼接
94-
function concat(string _a, string _b) internal pure returns (string){
95-
bytes memory _ba = bytes(_a);
96-
bytes memory _bb = bytes(_b);
97-
bytes memory result = new bytes(_ba.length + _bb.length);
98-
uint k = 0;
99-
for (uint i = 0; i < _ba.length; i++) result[k++] = _ba[i];
100-
for (i = 0; i < _bb.length; i++) result[k++] = _bb[i];
101-
return string(result);
102-
}
103-
}
98+
}

contracts/base_type/LibAsciiDemo.sol

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@ import "./LibAscii.sol";
44

55
contract LibAsciiDemo{
66

7-
function str2ascii() public view returns(string,string){
8-
string memory result= LibAscii.str2ascii("55",10);
7+
function ascii2str() public pure returns(string,string,string,string){
8+
//10进制ascii转字符串
9+
string memory result= LibAscii.decAscii2str("55");
910
//result:"7"
10-
string memory result1= LibAscii.str2ascii("55",16);
11-
//result1:"U"
12-
return (result,result1);
11+
string memory result1= LibAscii.decAscii2str("109");
12+
//result:"m"
13+
14+
//16进制ascii转字符串
15+
string memory result2= LibAscii.hexAscii2str("37");
16+
//result1:"7"
17+
string memory result3= LibAscii.hexAscii2str("6D");
18+
//result1:"m"
19+
20+
return (result,result1,result2,result3);
1321
}
1422

15-
function ascii2str() public view returns(string){
16-
string memory result=LibAscii.ascii2str("Aa");
17-
//result:"6597"
23+
function str2ascii() public pure returns(string){
24+
string memory result=LibAscii.str2ascii("Zz");
25+
//result:"90122"
1826
return result;
1927
}
2028
}
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity^0.6.10;
3+
import "./LibGameCompare.sol";
4+
import "./IDivergence.sol";
5+
6+
// 玩家信息
7+
struct Player {
8+
address addr;
9+
string name;
10+
uint8 opt; // 出手选项 0 - 剪刀,1 - 石头,2 - 布
11+
bytes32 hash;
12+
uint256 round; // 出手轮次
13+
uint8 status; // 状态:0 - 未出手;1 - 已经出手;2 - 已提交证明
14+
}
15+
16+
17+
// 合约实现
18+
contract Divergence is IDivergence {
19+
20+
// 控制玩家数量=2
21+
uint8 userCount;
22+
// 记录玩家信息
23+
Player[2] playerlist;
24+
// 游戏是否结束
25+
bool isFinished; // 默认值 false
26+
// 记录胜利玩家
27+
uint8 winnerIndex;
28+
// 出手内容定义
29+
string[3] gameOpts = ["scissors", "rock", "paper"];
30+
31+
// 出手event
32+
event Punch(address indexed addr, bytes32 hash);
33+
// 提出证明
34+
event Proof(address indexed addr, uint8 opt, string salt);
35+
// 胜出通知
36+
event WinnerBorn(address indexed winner, string name, uint8 opt, uint256 round);
37+
38+
// 注册
39+
function register(string memory _name) override external {
40+
require(userCount < 2, "two player already go");
41+
playerlist[userCount].addr = msg.sender;
42+
playerlist[userCount].name = _name;
43+
userCount ++;
44+
if(userCount == 2) {
45+
require(playerlist[0].addr != playerlist[1].addr, "You can not play this game with yourself");
46+
}
47+
}
48+
// 出手 先出手不用关心对方出什么,后出手的需要判断对方是什么,决定游戏是否结束
49+
function punch(bytes32 _hash) override external {
50+
// 1. 玩家身份
51+
require(isPlayer(msg.sender), "only register player can do");
52+
// 2. 游戏没有结束
53+
require(!isFinished, "game already finished");
54+
// 3. 两个玩家具备了再开始
55+
require(userCount == 2, "please wait a rival");
56+
57+
(uint8 host, uint8 rival) = getIndex(msg.sender);
58+
59+
Player storage player = playerlist[host];
60+
// 判断对方是否出手
61+
require(player.round <= playerlist[rival].round, "please wait");
62+
// 4. 玩家尚未出手
63+
require(player.status == 0, "player already throw a punch");
64+
player.hash = _hash;
65+
player.round ++;
66+
player.status = 1;
67+
68+
emit Punch(msg.sender, _hash);
69+
70+
}
71+
// 证明
72+
function proofing(string memory _salt, uint8 _opt) override external {
73+
// 1. 游戏没有结束
74+
require(!isFinished, "game already finished");
75+
bytes32 hash = keccak256(abi.encode(_salt, _opt));
76+
// 区分玩家1 和 玩家2
77+
(uint8 host, uint8 rival) = getIndex(msg.sender);
78+
Player storage player = playerlist[host];
79+
require(player.round == playerlist[rival].round, "It may not safe to commit proof");
80+
require(player.status == 1, "user can not commit proof at current status");
81+
player.status = 2;
82+
if(_opt > 2 || hash != player.hash) {
83+
// 直接判负
84+
isFinished = true;
85+
winnerIndex = rival;
86+
// 触发事件
87+
emit WinnerBorn(playerlist[winnerIndex].addr, playerlist[winnerIndex].name, playerlist[winnerIndex].opt, playerlist[winnerIndex].round);
88+
return;
89+
}
90+
emit Proof(msg.sender, _opt, _salt);
91+
player.opt = _opt;
92+
if(player.status == 2 && playerlist[rival].status == 2) {
93+
// 处理胜负逻辑
94+
uint8 win = LibGameCompare.max(player.opt, playerlist[rival].opt);
95+
if(win == 1) {
96+
isFinished = true;
97+
winnerIndex = host;
98+
} else if(win == 2) {
99+
isFinished = true;
100+
winnerIndex = rival;
101+
} else {
102+
playerlist[rival].status = 0;
103+
player.status = 0;
104+
}
105+
if(isFinished) {
106+
// 触发事件
107+
emit WinnerBorn(playerlist[winnerIndex].addr, playerlist[winnerIndex].name, playerlist[winnerIndex].opt, playerlist[winnerIndex].round);
108+
}
109+
110+
}
111+
112+
}
113+
// 查看获胜
114+
// 返回值: 1. 昵称 2. 玩家1出手 3. 玩家2出手 4. 轮次
115+
function winner() override external view returns (string memory, string memory, string memory, uint256) {
116+
if(!isFinished) {
117+
return ("none", "none", "none", 88888);
118+
}
119+
120+
uint8 rival = 0; // 表示输的一方下标
121+
if(winnerIndex == 0) rival = 1;
122+
123+
return (
124+
playerlist[winnerIndex].name,
125+
gameOpts[playerlist[winnerIndex].opt],
126+
gameOpts[playerlist[rival].opt],
127+
playerlist[winnerIndex].round
128+
);
129+
}
130+
131+
// 判断是否是注册玩家
132+
function isPlayer(address _addr) public view returns (bool) {
133+
if(_addr == playerlist[0].addr || _addr == playerlist[1].addr) return true;
134+
return false;
135+
}
136+
//yekai 123 2 0xe4c1209281b0ee06c09e03055af06926da954ba2697a9798e20ae11ed9bb531e
137+
//fuhongxue 123 1 0x5610d70754a691266ad97a972c2306bd75073fa9756a5cfeada56b6ab4aefd0e
138+
function helper(string memory _salt, uint8 _opt) public view returns (bytes32) {
139+
return keccak256(abi.encode(_salt, _opt));
140+
}
141+
142+
// 区分本人和对手的序号
143+
function getIndex(address _addr) internal view returns (uint8, uint8) {
144+
// 区分玩家1 和 玩家2
145+
uint8 host; // 代表本人
146+
uint8 rival; // 代表对方
147+
if(playerlist[0].addr == _addr) {
148+
host = 0;
149+
rival = 1;
150+
} else {
151+
host = 1;
152+
rival = 0;
153+
}
154+
155+
return (host, rival);
156+
}
157+
158+
// 重新开始游戏
159+
function reset() external {
160+
require(isFinished, "game is running");
161+
isFinished = false;
162+
playerlist[0].status = 0;
163+
playerlist[0].round = 0;
164+
playerlist[1].status = 0;
165+
playerlist[1].round = 0;
166+
}
167+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity^0.6.10;
3+
4+
// 定义接口
5+
interface IDivergence {
6+
// 注册
7+
function register(string memory _name) external;
8+
// 出手
9+
function punch(bytes32 _hash) external;
10+
// 证明
11+
function proofing(string memory _salt, uint8 _opt) external;
12+
// 查看获胜
13+
// 返回值: 1. 昵称 2. 玩家1出手 3. 玩家2出手 4. 轮次
14+
function winner() external view returns (string memory, string memory, string memory, uint256);
15+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
3+
// 定义library 计算获胜方
4+
library LibGameCompare {
5+
// 玩家1 & 玩家2
6+
// 返回值: 0 - 相等 ; 1 - 大于 ; 2 - 小于
7+
function max(uint8 a, uint8 b) internal pure returns (uint8) {
8+
require(a <= 2);
9+
require(b <= 2);
10+
if(a == b) {
11+
return 0;
12+
} else if(a > b) {
13+
// 1 ,0 ; 2,1; 2, 0
14+
return a - b;
15+
16+
} else {
17+
if(b - a == 2) return 1;
18+
if(b - a == 1) return 2;
19+
}
20+
21+
return 0;
22+
}
23+
}

0 commit comments

Comments
 (0)