-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmulti-roulette.ts
141 lines (121 loc) · 3.98 KB
/
multi-roulette.ts
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
import {
bytesToHex,
concatBytes,
randomBytes,
utf8ToBytes,
} from "@noble/hashes/utils";
import { sha256 } from "@noble/hashes/sha256";
import { bls12_381 as bls } from "@noble/curves/bls12-381";
import * as vx from "./vx";
import { CommitmentContext, computeMultiRouletteResult } from "vx-verifier";
import { assert } from "tsafe";
import { MultiRoulette_Outcome } from "vx-verifier/dist/generated/message-contexts/multi-roulette";
import { Currency } from "vx-verifier/dist/generated/currency";
const clientSeed = "chicken"; // Note: this is treated as ascii, should be found via a seeding event
async function main() {
console.log("Running vx multi-roulette demo...");
// First lets generate a hash chain
const hashChainLength = 11;
let iterator = randomBytes(32); // very secret!
const hashChain: Uint8Array[] = [];
for (let i = 0; i < hashChainLength; i++) {
hashChain.push(iterator);
iterator = sha256(iterator);
}
// We won't reverse the hash chain, as we'll iterate by poping off the last element
const commitment = hashChain.pop();
assert(commitment !== undefined);
console.log(
"Our hash chain has been established. The terminating hash is: ",
bytesToHex(commitment)
);
console.log(`COMMITMENT := 0x${bytesToHex(commitment)}\n\n`);
const url = `https://actuallyfair.com/apps/demo/vx/summary/${bytesToHex(
commitment
)}`;
console.log("You should see all related API requests @ ", url, "\n\n");
const commitmentContext: CommitmentContext = { sha256Chain: {} };
const VX_PUBKEY = await vx.make_commitment(commitment, commitmentContext);
console.log(
`Hey Player! We're ready to go with the following values:
COMMITMENT := ${bytesToHex(commitment)}
VX_PUBKEY := ${bytesToHex(VX_PUBKEY)}
Please see: https://actuallyfair.com/apps/demo/vx/summary/${bytesToHex(
commitment
)}
`
);
let gameId = 0;
let hash = commitment;
assert(hash !== undefined);
while (hashChain.length >= 1) {
gameId++;
// Now let's get the next hash for our game
const h = hashChain.pop();
assert(h !== undefined); // Hack to make TS happy
hash = h;
const red: MultiRoulette_Outcome = {
probability: 0.495,
multiplier: 2,
bets: [
// all the red players go here...
{ uname: "RedMaster", amount: { value: 23, currency: Currency.BTC } },
{ uname: "BloodBath", amount: { value: 13, currency: Currency.BTC } },
],
name: "red",
};
const green: MultiRoulette_Outcome = {
probability: 0.495,
multiplier: 2,
bets: [
// all the players betting blue should be here
{ uname: "BlueDevil", amount: { value: 1, currency: Currency.TBTC } },
],
name: "green",
};
const bonus: MultiRoulette_Outcome = {
probability: 0.01,
multiplier: 99,
bets: [
// all the players betting bonus should be here
{
uname: "BonusHunter",
amount: { value: 14, currency: Currency.ETH },
},
],
name: "bonus",
};
const wager = {
multiRoulette: {
outcomes: [red, green, bonus],
},
};
const message = concatBytes(hash, utf8ToBytes(clientSeed));
const vxSignature = await vx.make_message(
commitment,
message,
gameId,
0,
wager
);
const verified = bls.verify(vxSignature, message, VX_PUBKEY);
if (!verified) {
throw new Error("huh?! vx gave us something that didn't verify");
}
// Now let's compute the result of the game
const res = computeMultiRouletteResult(vxSignature, wager.multiRoulette);
let outcomeName;
if (res == 0) {
outcomeName = "red";
} else if (res == 1) {
outcomeName = "green";
} else if (res == 2) {
outcomeName = "bonus";
} else {
throw new Error("unknown roulette outcome?!");
}
console.log(`Game id ${gameId} = ${outcomeName}`);
}
// There's really no point revealing, but after all done we can... (Todo:...)
}
main();