@omnitronix/bonnys-fortune-game-engine 1.2.6 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -0
- package/dist/bonnys-fortune-v1.game-engine.js +2 -2
- package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
- package/dist/config/reel-strips-config/reels-BASE.csv +0 -0
- package/dist/config/reel-strips-config/reels-BONUS.csv +0 -0
- package/dist/index.js.map +1 -1
- package/dist/logic/handlers/base-game.handler.js +1 -19
- package/dist/logic/handlers/base-game.handler.js.map +1 -1
- package/dist/logic/handlers/collect-feature-bonus.handler.js +2 -2
- package/dist/logic/handlers/collect-feature-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/free-spins-bonus.handler.js +2 -4
- package/dist/logic/handlers/free-spins-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js +2 -4
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js +2 -4
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js.map +1 -1
- package/dist/rng/rng-client.factory.js +3 -46
- package/dist/rng/rng-client.factory.js.map +1 -1
- package/package.json +1 -1
- package/dist/__tests__/rng-gli19-compliance.test.js +0 -222
- package/dist/__tests__/rng-gli19-compliance.test.js.map +0 -1
- package/dist/__tests__/rng-seed-security.test.js +0 -263
- package/dist/__tests__/rng-seed-security.test.js.map +0 -1
- package/dist/__tests__/rng-seed-type.test.js +0 -282
- package/dist/__tests__/rng-seed-type.test.js.map +0 -1
- package/dist/__tests__/rng-stress-boundary.test.js +0 -386
- package/dist/__tests__/rng-stress-boundary.test.js.map +0 -1
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* RNG Seed Security Tests - Bonny's Fortune
|
|
4
|
-
* Comprehensive Attack Vector Coverage for GLI-19 Compliance
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const bonnys_fortune_v1_game_engine_1 = require("../bonnys-fortune-v1.game-engine");
|
|
8
|
-
const bonnys_fortune_types_1 = require("../logic/bonnys-fortune.types");
|
|
9
|
-
describe('RNG Seed Security - Attack Vector Tests', () => {
|
|
10
|
-
let engine;
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
engine = new bonnys_fortune_v1_game_engine_1.BonnysFortuneV1GameEngine();
|
|
13
|
-
});
|
|
14
|
-
async function initSession() {
|
|
15
|
-
return engine.processCommand(null, null, {
|
|
16
|
-
id: 'init-security',
|
|
17
|
-
type: 'INIT_SESSION_STATE',
|
|
18
|
-
payload: { betAmountThresholds: [1, 2, 5, 10], defaultBetAmount: 1 },
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
async function executeSpin(publicState, privateState) {
|
|
22
|
-
return engine.processCommand(publicState, privateState, {
|
|
23
|
-
id: `spin-${Math.random().toString(36).slice(2)}`,
|
|
24
|
-
type: 'SPIN',
|
|
25
|
-
payload: { sessionId: 'test', betAmount: 1, gameCode: 'bonnys-fortune', gameVersion: '1.0.0', lines: 10, creditsPerLine: 1 },
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
async function executeBonusRound(publicState, privateState) {
|
|
29
|
-
const pendingBonus = privateState.pendingBonuses?.[0];
|
|
30
|
-
if (!pendingBonus) {
|
|
31
|
-
throw new Error('No pending bonus found');
|
|
32
|
-
}
|
|
33
|
-
return engine.processCommand(publicState, privateState, {
|
|
34
|
-
id: `bonus-${Math.random().toString(36).slice(2)}`,
|
|
35
|
-
type: 'START_BONUS_ROUND',
|
|
36
|
-
payload: {
|
|
37
|
-
sessionId: 'test',
|
|
38
|
-
betAmount: pendingBonus.betAmount || 1,
|
|
39
|
-
bonusId: pendingBonus.bonusId,
|
|
40
|
-
bonusType: pendingBonus.bonusType,
|
|
41
|
-
gameCode: 'bonnys-fortune',
|
|
42
|
-
gameVersion: '1.0.0',
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
async function executeSpinWithBonusHandling(publicState, privateState) {
|
|
47
|
-
const results = [];
|
|
48
|
-
let pub = publicState;
|
|
49
|
-
let priv = privateState;
|
|
50
|
-
const spin = await executeSpin(pub, priv);
|
|
51
|
-
results.push(spin);
|
|
52
|
-
pub = spin.publicState;
|
|
53
|
-
priv = spin.privateState;
|
|
54
|
-
// Handle bonus rounds - any non-BASE_GAME_SPIN with pending bonuses
|
|
55
|
-
while (priv.nextSpinType !== bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN && priv.pendingBonuses?.length > 0) {
|
|
56
|
-
const bonus = await executeBonusRound(pub, priv);
|
|
57
|
-
results.push(bonus);
|
|
58
|
-
pub = bonus.publicState;
|
|
59
|
-
priv = bonus.privateState;
|
|
60
|
-
}
|
|
61
|
-
return { results, publicState: pub, privateState: priv };
|
|
62
|
-
}
|
|
63
|
-
function canonicalizeForHash(outcome) {
|
|
64
|
-
const entries = Object.entries(outcome)
|
|
65
|
-
.map(([actionId, record]) => ({
|
|
66
|
-
actionId,
|
|
67
|
-
result: Number(record.result),
|
|
68
|
-
seed: String(record.seed),
|
|
69
|
-
min: Number(record.min),
|
|
70
|
-
max: Number(record.max),
|
|
71
|
-
}))
|
|
72
|
-
.sort((a, b) => a.actionId.localeCompare(b.actionId));
|
|
73
|
-
return JSON.stringify(entries);
|
|
74
|
-
}
|
|
75
|
-
// ============================================================
|
|
76
|
-
// MALFORMED SEED INJECTION
|
|
77
|
-
// ============================================================
|
|
78
|
-
describe('Malformed Seed Injection', () => {
|
|
79
|
-
it('should handle whitespace-padded seeds differently', () => {
|
|
80
|
-
const outcome1 = { test: { result: 5, seed: 123, min: 0, max: 10 } };
|
|
81
|
-
const outcome2 = { test: { result: 5, seed: ' 123', min: 0, max: 10 } };
|
|
82
|
-
expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
|
|
83
|
-
});
|
|
84
|
-
it('should escape special JSON characters in actionIds', () => {
|
|
85
|
-
const outcome = { 'action\n"test': { result: 5, seed: 123, min: 0, max: 10 } };
|
|
86
|
-
const canonical = canonicalizeForHash(outcome);
|
|
87
|
-
expect(() => JSON.parse(canonical)).not.toThrow();
|
|
88
|
-
});
|
|
89
|
-
it('should handle zero-width unicode characters', () => {
|
|
90
|
-
const outcome = { test: { result: 5, seed: '123\u200B456', min: 0, max: 10 } };
|
|
91
|
-
const canonical = canonicalizeForHash(outcome);
|
|
92
|
-
expect(canonical.length).toBeGreaterThan(0);
|
|
93
|
-
});
|
|
94
|
-
it('should not interpret hex strings as numbers', () => {
|
|
95
|
-
const outcome = { test: { result: 5, seed: '0xFF', min: 0, max: 10 } };
|
|
96
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"0xFF"');
|
|
97
|
-
});
|
|
98
|
-
it('should not interpret octal strings as numbers', () => {
|
|
99
|
-
const outcome = { test: { result: 5, seed: '0777', min: 0, max: 10 } };
|
|
100
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"0777"');
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
// ============================================================
|
|
104
|
-
// TYPE CONFUSION
|
|
105
|
-
// ============================================================
|
|
106
|
-
describe('Type Confusion', () => {
|
|
107
|
-
it('should handle array seeds', () => {
|
|
108
|
-
const outcome = { test: { result: 5, seed: [123], min: 0, max: 10 } };
|
|
109
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"123"');
|
|
110
|
-
});
|
|
111
|
-
it('should handle null seeds', () => {
|
|
112
|
-
const outcome = { test: { result: 5, seed: null, min: 0, max: 10 } };
|
|
113
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"null"');
|
|
114
|
-
});
|
|
115
|
-
it('should handle undefined seeds', () => {
|
|
116
|
-
const outcome = { test: { result: 5, seed: undefined, min: 0, max: 10 } };
|
|
117
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"undefined"');
|
|
118
|
-
});
|
|
119
|
-
it('should handle boolean seeds', () => {
|
|
120
|
-
const outcome = { test: { result: 5, seed: true, min: 0, max: 10 } };
|
|
121
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"true"');
|
|
122
|
-
});
|
|
123
|
-
it('should handle BigInt seeds', () => {
|
|
124
|
-
const outcome = { test: { result: 5, seed: BigInt(123), min: 0, max: 10 } };
|
|
125
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"123"');
|
|
126
|
-
});
|
|
127
|
-
it('should handle Symbol seeds', () => {
|
|
128
|
-
const symbol = Symbol('test');
|
|
129
|
-
expect(String(symbol)).toBe('Symbol(test)');
|
|
130
|
-
});
|
|
131
|
-
it('should handle object with custom toString', () => {
|
|
132
|
-
const malicious = { toString: () => '123', valueOf: () => 456 };
|
|
133
|
-
const outcome = { test: { result: 5, seed: malicious, min: 0, max: 10 } };
|
|
134
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"123"');
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
// ============================================================
|
|
138
|
-
// INTEGER BOUNDARIES
|
|
139
|
-
// ============================================================
|
|
140
|
-
describe('Integer Boundaries', () => {
|
|
141
|
-
it('should handle MAX_SAFE_INTEGER', () => {
|
|
142
|
-
const outcome = { test: { result: 5, seed: Number.MAX_SAFE_INTEGER, min: 0, max: 10 } };
|
|
143
|
-
expect(canonicalizeForHash(outcome)).toContain(`"seed":"${Number.MAX_SAFE_INTEGER}"`);
|
|
144
|
-
});
|
|
145
|
-
it('should handle MIN_SAFE_INTEGER', () => {
|
|
146
|
-
const outcome = { test: { result: 5, seed: Number.MIN_SAFE_INTEGER, min: -100, max: 100 } };
|
|
147
|
-
expect(canonicalizeForHash(outcome)).toContain(`"seed":"${Number.MIN_SAFE_INTEGER}"`);
|
|
148
|
-
});
|
|
149
|
-
it('should handle zero seed', () => {
|
|
150
|
-
const outcome = { test: { result: 5, seed: 0, min: 0, max: 10 } };
|
|
151
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"0"');
|
|
152
|
-
});
|
|
153
|
-
it('should handle negative seeds', () => {
|
|
154
|
-
const outcome = { test: { result: 5, seed: -12345, min: -100, max: 100 } };
|
|
155
|
-
expect(canonicalizeForHash(outcome)).toContain('"seed":"-12345"');
|
|
156
|
-
});
|
|
157
|
-
it('should handle NaN in result', () => {
|
|
158
|
-
const outcome = { test: { result: NaN, seed: 123, min: 0, max: 10 } };
|
|
159
|
-
expect(canonicalizeForHash(outcome)).toContain('"result":null');
|
|
160
|
-
});
|
|
161
|
-
it('should handle Infinity', () => {
|
|
162
|
-
const outcome = { test: { result: Infinity, seed: 123, min: 0, max: 10 } };
|
|
163
|
-
expect(canonicalizeForHash(outcome)).toContain('"result":null');
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
// ============================================================
|
|
167
|
-
// HASH COLLISION PREVENTION
|
|
168
|
-
// ============================================================
|
|
169
|
-
describe('Hash Collision Prevention', () => {
|
|
170
|
-
it('should produce different hashes for adjacent seeds', () => {
|
|
171
|
-
const outcome1 = { action: { result: 5, seed: 123, min: 0, max: 10 } };
|
|
172
|
-
const outcome2 = { action: { result: 5, seed: 124, min: 0, max: 10 } };
|
|
173
|
-
expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
|
|
174
|
-
});
|
|
175
|
-
it('should produce different hashes for different actionIds', () => {
|
|
176
|
-
const outcome1 = { action_a: { result: 5, seed: 123, min: 0, max: 10 } };
|
|
177
|
-
const outcome2 = { action_b: { result: 5, seed: 123, min: 0, max: 10 } };
|
|
178
|
-
expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
|
|
179
|
-
});
|
|
180
|
-
it('should produce same hash for number and string seeds after canonicalization', () => {
|
|
181
|
-
const outcome1 = { action: { result: 5, seed: 123, min: 0, max: 10 } };
|
|
182
|
-
const outcome2 = { action: { result: 5, seed: '123', min: 0, max: 10 } };
|
|
183
|
-
expect(canonicalizeForHash(outcome1)).toBe(canonicalizeForHash(outcome2));
|
|
184
|
-
});
|
|
185
|
-
it('should resist JSON injection in actionId', () => {
|
|
186
|
-
const outcome1 = { 'a","seed":"999': { result: 5, seed: 123, min: 0, max: 10 } };
|
|
187
|
-
const outcome2 = { 'a': { result: 5, seed: 999, min: 0, max: 10 } };
|
|
188
|
-
expect(canonicalizeForHash(outcome1)).not.toBe(canonicalizeForHash(outcome2));
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
// ============================================================
|
|
192
|
-
// PROTOTYPE POLLUTION
|
|
193
|
-
// ============================================================
|
|
194
|
-
describe('Prototype Pollution Prevention', () => {
|
|
195
|
-
it('should handle constructor as actionId', () => {
|
|
196
|
-
const outcome = { 'constructor': { result: 5, seed: 123, min: 0, max: 10 } };
|
|
197
|
-
const canonical = canonicalizeForHash(outcome);
|
|
198
|
-
expect(() => JSON.parse(canonical)).not.toThrow();
|
|
199
|
-
});
|
|
200
|
-
it('should handle toString as actionId', () => {
|
|
201
|
-
const outcome = { 'toString': { result: 5, seed: 123, min: 0, max: 10 } };
|
|
202
|
-
expect(() => canonicalizeForHash(outcome)).not.toThrow();
|
|
203
|
-
});
|
|
204
|
-
it('should not pollute prototype', () => {
|
|
205
|
-
const outcome = { 'normal': { result: 6, seed: 456, min: 0, max: 10 } };
|
|
206
|
-
canonicalizeForHash(outcome);
|
|
207
|
-
expect({}.__proto__.result).toBeUndefined();
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
// ============================================================
|
|
211
|
-
// ENGINE RNG VALIDATION
|
|
212
|
-
// ============================================================
|
|
213
|
-
describe('Engine RNG Validation', () => {
|
|
214
|
-
it('should return numeric seeds from engine', async () => {
|
|
215
|
-
const init = await initSession();
|
|
216
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
217
|
-
expect(spin.success).toBe(true);
|
|
218
|
-
if (spin.rngOutcome) {
|
|
219
|
-
for (const [, record] of Object.entries(spin.rngOutcome)) {
|
|
220
|
-
expect(typeof record.seed).toBe('number');
|
|
221
|
-
expect(Number.isSafeInteger(record.seed)).toBe(true);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
it('should have valid result within range', async () => {
|
|
226
|
-
const init = await initSession();
|
|
227
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
228
|
-
if (spin.rngOutcome) {
|
|
229
|
-
for (const [, record] of Object.entries(spin.rngOutcome)) {
|
|
230
|
-
expect(record.result).toBeGreaterThanOrEqual(record.min);
|
|
231
|
-
expect(record.result).toBeLessThanOrEqual(record.max);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
it('should have unique actionIds', async () => {
|
|
236
|
-
const init = await initSession();
|
|
237
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
238
|
-
if (spin.rngOutcome) {
|
|
239
|
-
const actionIds = Object.keys(spin.rngOutcome);
|
|
240
|
-
expect(actionIds.length).toBe(new Set(actionIds).size);
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
it('should maintain type consistency across 50 spins', async () => {
|
|
244
|
-
const init = await initSession();
|
|
245
|
-
let pub = init.publicState;
|
|
246
|
-
let priv = init.privateState;
|
|
247
|
-
for (let i = 0; i < 50; i++) {
|
|
248
|
-
const { results, publicState, privateState } = await executeSpinWithBonusHandling(pub, priv);
|
|
249
|
-
// Verify RNG structure for all results (spin + any bonus rounds)
|
|
250
|
-
for (const result of results) {
|
|
251
|
-
if (result.rngOutcome) {
|
|
252
|
-
for (const [, record] of Object.entries(result.rngOutcome)) {
|
|
253
|
-
expect(typeof record.seed).toBe('number');
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
pub = publicState;
|
|
258
|
-
priv = privateState;
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
//# sourceMappingURL=rng-seed-security.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rng-seed-security.test.js","sourceRoot":"","sources":["../../src/__tests__/rng-seed-security.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* RNG Seed Type Tests - GLI-19 Compliance Verification
|
|
4
|
-
*
|
|
5
|
-
* These tests verify that the RNG seed type fix is working correctly:
|
|
6
|
-
* 1. Seeds are returned as numbers (internal format)
|
|
7
|
-
* 2. Seeds can be safely converted to strings (wire format)
|
|
8
|
-
* 3. Hash canonicalization produces deterministic results
|
|
9
|
-
* 4. Edge cases are handled correctly
|
|
10
|
-
*
|
|
11
|
-
* GLI-19 Sections:
|
|
12
|
-
* - 3.4: Tamper-evident audit trails
|
|
13
|
-
* - 3.4.2: Tamper detection
|
|
14
|
-
* - 4.2.1: Deterministic replay
|
|
15
|
-
*/
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
const bonnys_fortune_v1_game_engine_1 = require("../bonnys-fortune-v1.game-engine");
|
|
18
|
-
describe('RNG Seed Type - GLI-19 Compliance', () => {
|
|
19
|
-
let engine;
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
engine = new bonnys_fortune_v1_game_engine_1.BonnysFortuneV1GameEngine();
|
|
22
|
-
});
|
|
23
|
-
// Helper to initialize session
|
|
24
|
-
async function initSession(betAmount = 1.0) {
|
|
25
|
-
const command = {
|
|
26
|
-
id: 'init',
|
|
27
|
-
type: 'INIT_SESSION_STATE',
|
|
28
|
-
payload: {
|
|
29
|
-
betAmount,
|
|
30
|
-
currency: 'EUR',
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
return engine.processCommand(null, null, command);
|
|
34
|
-
}
|
|
35
|
-
// Helper to execute spin
|
|
36
|
-
async function executeSpin(publicState, privateState) {
|
|
37
|
-
const spinCommand = {
|
|
38
|
-
id: `spin-${Date.now()}`,
|
|
39
|
-
type: 'SPIN',
|
|
40
|
-
payload: {
|
|
41
|
-
sessionId: 'test-session',
|
|
42
|
-
betAmount: 1.0,
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
return engine.processCommand(publicState, privateState, spinCommand);
|
|
46
|
-
}
|
|
47
|
-
describe('Seed Type Verification', () => {
|
|
48
|
-
it('should return rngOutcome with numeric seeds', async () => {
|
|
49
|
-
const init = await initSession();
|
|
50
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
51
|
-
expect(spin.success).toBe(true);
|
|
52
|
-
expect(spin.rngOutcome).toBeDefined();
|
|
53
|
-
// Verify all seeds are numbers
|
|
54
|
-
for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
|
|
55
|
-
expect(typeof record.seed).toBe('number');
|
|
56
|
-
expect(Number.isInteger(record.seed)).toBe(true);
|
|
57
|
-
expect(Number.isSafeInteger(record.seed)).toBe(true);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
it('should have seeds within safe integer range', async () => {
|
|
61
|
-
const init = await initSession();
|
|
62
|
-
// Run multiple spins to get variety of seeds
|
|
63
|
-
let currentPublic = init.publicState;
|
|
64
|
-
let currentPrivate = init.privateState;
|
|
65
|
-
for (let i = 0; i < 10; i++) {
|
|
66
|
-
const spin = await executeSpin(currentPublic, currentPrivate);
|
|
67
|
-
if (spin.rngOutcome) {
|
|
68
|
-
for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
|
|
69
|
-
expect(record.seed).toBeLessThanOrEqual(Number.MAX_SAFE_INTEGER);
|
|
70
|
-
expect(record.seed).toBeGreaterThanOrEqual(Number.MIN_SAFE_INTEGER);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
currentPublic = spin.publicState;
|
|
74
|
-
currentPrivate = spin.privateState;
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
it('should have consistent rngOutcome structure', async () => {
|
|
78
|
-
const init = await initSession();
|
|
79
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
80
|
-
expect(spin.rngOutcome).toBeDefined();
|
|
81
|
-
for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
|
|
82
|
-
// Verify structure
|
|
83
|
-
expect(typeof actionId).toBe('string');
|
|
84
|
-
expect(actionId.length).toBeGreaterThan(0);
|
|
85
|
-
// Verify record fields
|
|
86
|
-
expect(typeof record.result).toBe('number');
|
|
87
|
-
expect(typeof record.seed).toBe('number');
|
|
88
|
-
expect(typeof record.min).toBe('number');
|
|
89
|
-
expect(typeof record.max).toBe('number');
|
|
90
|
-
// Verify result is within range
|
|
91
|
-
expect(record.result).toBeGreaterThanOrEqual(record.min);
|
|
92
|
-
expect(record.result).toBeLessThanOrEqual(record.max);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
describe('Wire Format Conversion', () => {
|
|
97
|
-
it('seeds should be safely convertible to strings', async () => {
|
|
98
|
-
const init = await initSession();
|
|
99
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
100
|
-
for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
|
|
101
|
-
const seedAsString = String(record.seed);
|
|
102
|
-
const backToNumber = Number(seedAsString);
|
|
103
|
-
// Round-trip conversion must be lossless
|
|
104
|
-
expect(backToNumber).toBe(record.seed);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
it('string conversion should not lose precision', async () => {
|
|
108
|
-
// Run 50 independent sessions to test various seed values
|
|
109
|
-
// Each session gets fresh state to avoid bonus state complications
|
|
110
|
-
for (let i = 0; i < 50; i++) {
|
|
111
|
-
const init = await initSession();
|
|
112
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
113
|
-
if (spin.rngOutcome) {
|
|
114
|
-
for (const [, record] of Object.entries(spin.rngOutcome)) {
|
|
115
|
-
const original = record.seed;
|
|
116
|
-
const asString = String(original);
|
|
117
|
-
const restored = Number(asString);
|
|
118
|
-
expect(restored).toBe(original);
|
|
119
|
-
expect(asString).not.toContain('e'); // No scientific notation
|
|
120
|
-
expect(asString).not.toContain('.'); // Must be integer
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
describe('Hash Canonicalization Verification', () => {
|
|
127
|
-
/**
|
|
128
|
-
* Simulates the canonicalization that RGS uses for hashing.
|
|
129
|
-
* This must produce identical output for number vs string seeds.
|
|
130
|
-
*/
|
|
131
|
-
function canonicalizeForHash(outcome) {
|
|
132
|
-
const entries = Object.entries(outcome)
|
|
133
|
-
.map(([actionId, record]) => ({
|
|
134
|
-
actionId,
|
|
135
|
-
result: Number(record.result),
|
|
136
|
-
seed: String(record.seed),
|
|
137
|
-
min: Number(record.min),
|
|
138
|
-
max: Number(record.max),
|
|
139
|
-
}))
|
|
140
|
-
.sort((a, b) => a.actionId.localeCompare(b.actionId));
|
|
141
|
-
return JSON.stringify(entries);
|
|
142
|
-
}
|
|
143
|
-
it('should produce same canonical form for number and string seeds', async () => {
|
|
144
|
-
const init = await initSession();
|
|
145
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
146
|
-
// Get canonical with number seeds (as returned by engine)
|
|
147
|
-
const canonicalNumber = canonicalizeForHash(spin.rngOutcome);
|
|
148
|
-
// Convert seeds to strings (simulating wire format)
|
|
149
|
-
const withStringSeeds = {};
|
|
150
|
-
for (const [actionId, record] of Object.entries(spin.rngOutcome)) {
|
|
151
|
-
withStringSeeds[actionId] = {
|
|
152
|
-
...record,
|
|
153
|
-
seed: String(record.seed),
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
const canonicalString = canonicalizeForHash(withStringSeeds);
|
|
157
|
-
// CRITICAL: Both must produce identical canonical form
|
|
158
|
-
expect(canonicalNumber).toBe(canonicalString);
|
|
159
|
-
});
|
|
160
|
-
it('should produce deterministic canonical form across multiple calls', async () => {
|
|
161
|
-
const init = await initSession();
|
|
162
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
163
|
-
const canonical1 = canonicalizeForHash(spin.rngOutcome);
|
|
164
|
-
const canonical2 = canonicalizeForHash(spin.rngOutcome);
|
|
165
|
-
const canonical3 = canonicalizeForHash(spin.rngOutcome);
|
|
166
|
-
expect(canonical1).toBe(canonical2);
|
|
167
|
-
expect(canonical2).toBe(canonical3);
|
|
168
|
-
});
|
|
169
|
-
it('should sort entries alphabetically by actionId', async () => {
|
|
170
|
-
// Create outcome with known actionIds in reverse order
|
|
171
|
-
const outcome = {
|
|
172
|
-
z_action: { result: 1, seed: 100, min: 0, max: 10 },
|
|
173
|
-
a_action: { result: 2, seed: 200, min: 0, max: 10 },
|
|
174
|
-
m_action: { result: 3, seed: 300, min: 0, max: 10 },
|
|
175
|
-
};
|
|
176
|
-
const canonical = canonicalizeForHash(outcome);
|
|
177
|
-
const parsed = JSON.parse(canonical);
|
|
178
|
-
expect(parsed[0].actionId).toBe('a_action');
|
|
179
|
-
expect(parsed[1].actionId).toBe('m_action');
|
|
180
|
-
expect(parsed[2].actionId).toBe('z_action');
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
describe('Bonus Round RNG Tracking', () => {
|
|
184
|
-
it('should track RNG outcomes during bonus trigger', async () => {
|
|
185
|
-
const init = await initSession();
|
|
186
|
-
// Trigger a bonus via debug command
|
|
187
|
-
const triggerResult = await engine.processCommand(init.publicState, init.privateState, {
|
|
188
|
-
id: 'debug-trigger',
|
|
189
|
-
type: 'DEBUG_TRIGGER_BONUS',
|
|
190
|
-
payload: {
|
|
191
|
-
bonusType: 'bonusGame1', // Treasure Hunt
|
|
192
|
-
betAmount: 1.0,
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
expect(triggerResult.success).toBe(true);
|
|
196
|
-
// Debug trigger may or may not have rngOutcome depending on implementation
|
|
197
|
-
});
|
|
198
|
-
it('should maintain seed type consistency across bonus spins', async () => {
|
|
199
|
-
const init = await initSession();
|
|
200
|
-
// Trigger free spins bonus
|
|
201
|
-
const trigger = await engine.processCommand(init.publicState, init.privateState, {
|
|
202
|
-
id: 'debug-trigger',
|
|
203
|
-
type: 'DEBUG_TRIGGER_BONUS',
|
|
204
|
-
payload: {
|
|
205
|
-
bonusType: 'bonusGame2', // Free Spins
|
|
206
|
-
betAmount: 1.0,
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
if (trigger.rngOutcome) {
|
|
210
|
-
for (const [, record] of Object.entries(trigger.rngOutcome)) {
|
|
211
|
-
expect(typeof record.seed).toBe('number');
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
describe('Edge Cases', () => {
|
|
217
|
-
it('should handle zero seed correctly', () => {
|
|
218
|
-
const outcome = {
|
|
219
|
-
test_action: { result: 5, seed: 0, min: 0, max: 10 },
|
|
220
|
-
};
|
|
221
|
-
const canonical = JSON.stringify(Object.entries(outcome)
|
|
222
|
-
.map(([actionId, record]) => ({
|
|
223
|
-
actionId,
|
|
224
|
-
result: record.result,
|
|
225
|
-
seed: String(record.seed),
|
|
226
|
-
min: record.min,
|
|
227
|
-
max: record.max,
|
|
228
|
-
}))
|
|
229
|
-
.sort((a, b) => a.actionId.localeCompare(b.actionId)));
|
|
230
|
-
expect(canonical).toContain('"seed":"0"');
|
|
231
|
-
});
|
|
232
|
-
it('should handle negative seed correctly', () => {
|
|
233
|
-
const outcome = {
|
|
234
|
-
test_action: { result: 5, seed: -12345, min: -100, max: 100 },
|
|
235
|
-
};
|
|
236
|
-
const canonical = JSON.stringify(Object.entries(outcome)
|
|
237
|
-
.map(([actionId, record]) => ({
|
|
238
|
-
actionId,
|
|
239
|
-
result: record.result,
|
|
240
|
-
seed: String(record.seed),
|
|
241
|
-
min: record.min,
|
|
242
|
-
max: record.max,
|
|
243
|
-
})));
|
|
244
|
-
expect(canonical).toContain('"seed":"-12345"');
|
|
245
|
-
});
|
|
246
|
-
it('should handle MAX_SAFE_INTEGER seed correctly', () => {
|
|
247
|
-
const maxSafe = Number.MAX_SAFE_INTEGER;
|
|
248
|
-
const outcome = {
|
|
249
|
-
test_action: { result: 5, seed: maxSafe, min: 0, max: 100 },
|
|
250
|
-
};
|
|
251
|
-
const seedString = String(maxSafe);
|
|
252
|
-
const backToNumber = Number(seedString);
|
|
253
|
-
expect(backToNumber).toBe(maxSafe);
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
describe('Multiple Spins Consistency', () => {
|
|
257
|
-
it('should maintain type consistency across 100 spins', async () => {
|
|
258
|
-
const allSeeds = [];
|
|
259
|
-
// Run 100 independent sessions to avoid bonus state complications
|
|
260
|
-
// Each session gets fresh state
|
|
261
|
-
for (let i = 0; i < 100; i++) {
|
|
262
|
-
const init = await initSession();
|
|
263
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
264
|
-
if (spin.rngOutcome) {
|
|
265
|
-
for (const [, record] of Object.entries(spin.rngOutcome)) {
|
|
266
|
-
expect(typeof record.seed).toBe('number');
|
|
267
|
-
allSeeds.push(record.seed);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
// Verify all seeds are safe integers
|
|
272
|
-
expect(allSeeds.every(s => Number.isSafeInteger(s))).toBe(true);
|
|
273
|
-
// Log statistics for analysis document
|
|
274
|
-
console.log(`\n=== RNG Seed Statistics (100 spins) - Bonny's Fortune ===`);
|
|
275
|
-
console.log(`Total seeds collected: ${allSeeds.length}`);
|
|
276
|
-
console.log(`Min seed: ${Math.min(...allSeeds)}`);
|
|
277
|
-
console.log(`Max seed: ${Math.max(...allSeeds)}`);
|
|
278
|
-
console.log(`All safe integers: ${allSeeds.every(s => Number.isSafeInteger(s))}`);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
});
|
|
282
|
-
//# sourceMappingURL=rng-seed-type.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rng-seed-type.test.js","sourceRoot":"","sources":["../../src/__tests__/rng-seed-type.test.ts"],"names":[],"mappings":"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"}
|