-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.rsh v0.2
166 lines (131 loc) · 4.05 KB
/
index.rsh v0.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
This version sends two cards to each player and calculates
the total, assuming 1 for ace. It deals a single hand.
Game logic implemented - still testing.
*/
'reach 0.1';
const [gameOutcome, PLAYER_WINS, DEALER_WINS, DRAW, PLAYER_BUST] = makeEnum(4);
// here is the game logic
// start small and build up
const winner = (playerHand, dealerHand) => {
if(playerHand > 21){
return PLAYER_BUST;
} else {
if(dealerHand > 21){
return PLAYER_WINS;
} else {
if(dealerHand == playerHand){
return DRAW;
} else {
if(playerHand > dealerHand){
return PLAYER_WINS;
} else {
return DEALER_WINS;
}
}
}
}
};
// assertions
assert(winner(20, 20) == DRAW);
assert(winner(22, 16) == PLAYER_BUST);
assert(winner(18, 20) == DEALER_WINS);
// test all possibilites
forall(UInt, playerHand =>
forall(UInt, dealerHand =>
assert(gameOutcome(winner(playerHand, dealerHand)))));
// shared Player method signatures
const Player = {
...hasRandom,
getCard: Fun([], UInt),
seeOutcome: Fun([UInt], Null),
informTimeout: Fun([], Null),
seeActual: Fun([UInt], Null),
//bust: Fun([], Null),
};
export const main = Reach.App(() => {
const Shark = Participant('Shark', {
...Player,
wager: UInt,
deadline: UInt,
});
const Dealer = Participant('Dealer', {
...Player,
acceptWager: Fun([UInt], Null),
});
init();
const informTimeout = () => {
each([Shark, Dealer], () => {
interact.informTimeout();
});
};
Shark.only(() => {
const wager = declassify(interact.wager);
const deadline = declassify(interact.deadline);
});
Shark.publish(wager, deadline)
.pay(wager);
commit();
Dealer.only(() => {
interact.acceptWager(wager);
});
Dealer.pay(wager)
.timeout(relativeTime(deadline), () => closeTo(Shark, informTimeout));
var outcome = DRAW;
invariant(balance() == 2 * wager && gameOutcome(outcome));
while (outcome == DRAW){
commit();
Shark.only(() => {
// create private card value
const _sharkCardA = interact.getCard();
const _sharkCardB = interact.getCard();
// create salt and commit values for first card
const [_commitA, _saltA] = makeCommitment(interact, _sharkCardA);
const commitA = declassify(_commitA); // publish hashed commit value
// create salt and commit values for the second card
const [_commitB, _saltB] = makeCommitment(interact, _sharkCardB);
const commitB = declassify(_commitB);
});
Shark.publish(commitA, commitB)
.timeout(relativeTime(deadline), () => closeTo(Dealer, informTimeout));
commit();
unknowable(Dealer, Shark(_sharkCardA, _saltA, _sharkCardB, _saltB));
Dealer.only(() => {
const _dealerCardA = interact.getCard();
const _dealerCardB = interact.getCard();
const cardA = declassify(_dealerCardA);
const cardB = declassify(_dealerCardB);
});
Dealer.publish(cardA, cardB)
.timeout(relativeTime(deadline), () => closeTo(Shark, informTimeout));
commit();
Shark.only(() => {
const [saltA, sharkCardA] = declassify([_saltA, _sharkCardA]);
const [saltB, sharkCardB] = declassify([_saltB, _sharkCardB]);
});
// publish these values to the blockchain
Shark.publish(saltA, sharkCardA, saltB, sharkCardB)
.timeout(relativeTime(deadline), () => closeTo(Dealer, informTimeout));
checkCommitment(commitA, saltA, sharkCardA);
checkCommitment(commitB, saltB, sharkCardB);
const playerTotal = sharkCardA + sharkCardB;
const dealerTotal = cardA + cardB;
// display total
Shark.only(() => {
interact.seeActual(playerTotal);
});
// display total
Dealer.only(() => {
interact.seeActual(dealerTotal);
});
outcome = winner(playerTotal, dealerTotal);
continue;
};
assert( outcome == PLAYER_BUST || outcome == DEALER_WINS || outcome == PLAYER_WINS);
transfer(2 * wager).to(outcome == PLAYER_WINS ? Shark : Dealer);
commit();
each([Shark, Dealer], () => {
interact.seeOutcome(outcome);
});
exit();
});