Skip to content

Commit f773677

Browse files
committed
added local computation of random beacon
1 parent 2465572 commit f773677

File tree

8 files changed

+166
-10
lines changed

8 files changed

+166
-10
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Beacon } from './model/Beacon';
2+
import { RNGImpl } from 'crypto/random';
3+
4+
const STEPS = 66;
5+
6+
async function main() {
7+
8+
console.log('creating random beacon...');
9+
10+
let beacon = new Beacon(new RNGImpl().randomHexString(128), STEPS);
11+
12+
//let res = await Beacon.computeVdfAsync(STEPS, new RNGImpl().randomHexString(128));
13+
14+
beacon.startCompute();
15+
16+
}
17+
18+
main();

examples/randomness-beacon/model/Beacon.ts

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1+
import '@hyper-hyper-space/node-env';
2+
13
import { Hashing, HashedObject, MutableObject, MutationOp } from 'data/model';
24

35
import { BeaconValueOp } from './BeaconValueOp';
46

7+
import { Worker, parentPort } from 'worker_threads';
8+
import { Logger, LogLevel } from 'util/logging';
9+
10+
const createVdf = require('@subspace/vdf').default;
11+
(global as any).document = { }; // yikes!
12+
513
class Beacon extends MutableObject {
614

15+
static log = new Logger(Beacon.name, LogLevel.DEBUG)
16+
17+
718
static className = 'hhs/v0/examples/Beacon';
819
static opClasses = [BeaconValueOp.className];
920

@@ -12,6 +23,28 @@ class Beacon extends MutableObject {
1223
_lastOp?: BeaconValueOp;
1324
_values: string[];
1425

26+
_computation?: Worker;
27+
_autoCompute: boolean;
28+
29+
static computeVdf(): void {
30+
31+
parentPort?.on('message', async (q: {challenge: string, steps: number}) => {
32+
33+
const vdfInstance = await createVdf();
34+
const result = vdfInstance.generate(q.steps, Buffer.from(q.challenge, 'hex'), 2048, true);
35+
36+
parentPort?.postMessage(
37+
{
38+
challenge: q.challenge,
39+
steps: q.steps,
40+
result: Buffer.from(result).toString('hex')
41+
}
42+
);
43+
});
44+
45+
46+
}
47+
1548
constructor(seed?: string, steps?: number) {
1649
super(Beacon.opClasses);
1750

@@ -21,22 +54,89 @@ class Beacon extends MutableObject {
2154
}
2255

2356
this._values = [];
57+
this._autoCompute = false;
58+
}
59+
60+
startCompute() {
61+
this._autoCompute = true;
62+
this.race();
63+
}
64+
65+
stopCompute() {
66+
this._autoCompute = false;
67+
this.stopCompute();
68+
}
69+
70+
race() {
71+
if (this._computation === undefined) {
72+
73+
Beacon.log.debug(() => 'Racing for challenge (' + this.steps + ' steps): "' + this.currentChallenge() + '".');
74+
75+
this._computation = new Worker('./dist-examples/examples/randomness-beacon/model/worker.js');
76+
77+
this._computation.postMessage({steps: this.steps, challenge: this.currentChallenge()});
78+
79+
this._computation.on('message', async (msg: {challenge: string, result: string}) => {
80+
81+
Beacon.log.debug(() => 'Solved challenge "' + msg.challenge + '" with: "' + msg.result + '".');
82+
83+
this.stopRace();
84+
85+
if (msg.challenge === this.currentChallenge()) {
86+
let op = new BeaconValueOp(this, this.currentSeq(), msg.result);
87+
88+
if (this._lastOp !== undefined) {
89+
op.setPrevOps(new Set([this._lastOp.createReference()]).values());
90+
}
91+
92+
await this.applyNewOp(op);
93+
if (this._autoCompute) {
94+
this.race();
95+
}
96+
}
97+
});
98+
}
99+
}
100+
101+
stopRace() {
102+
if (this._computation !== undefined) {
103+
this._computation.terminate();
104+
this._computation = undefined;
105+
}
106+
}
107+
108+
private currentChallenge(): string {
109+
if (this._lastOp === undefined) {
110+
return this.getId() as string;
111+
} else {
112+
return Hashing.toHex(this._lastOp.hash());
113+
}
114+
}
115+
116+
private currentSeq() {
117+
if (this._lastOp === undefined) {
118+
return 0;
119+
} else {
120+
return (this._lastOp.seq as number) + 1;
121+
}
24122
}
25123

26124

27125
async mutate(op: MutationOp, isNew: boolean): Promise<void> {
28126

127+
isNew;
128+
29129
if (op instanceof BeaconValueOp) {
30130

31-
if (!isNew && this._lastOp !== undefined &&
131+
if (this._lastOp === undefined ||
32132
!this._lastOp.equals(op)) {
33133

34134
if (op.prevOps?.size() === 0) {
135+
35136
if (this._lastOp !== undefined) {
36137
throw new Error('Initial BeaconValueOp received, but there are already other ops in this beacon.');
37138
}
38139

39-
40140
} else {
41141
if (this._lastOp === undefined) {
42142
throw new Error('Non-initial BeaconValueOp received, but there are no values in this beacon.');
@@ -48,7 +148,14 @@ class Beacon extends MutableObject {
48148
}
49149

50150
this._lastOp = op;
151+
51152
this._values.push(Hashing.toHex(op.hash()));
153+
154+
this.stopRace();
155+
156+
if (this._autoCompute) {
157+
this.race();
158+
}
52159

53160
}
54161

@@ -58,7 +165,7 @@ class Beacon extends MutableObject {
58165
}
59166

60167
getClassName(): string {
61-
throw new Error('Method not implemented.');
168+
return Beacon.className;
62169
}
63170

64171
init(): void {

examples/randomness-beacon/model/BeaconValueOp.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class BeaconValueOp extends MutationOp {
9494

9595
const steps = (this.getTarget() as Beacon).steps as number;
9696

97+
98+
//TODO: make sure there is no upper/lowercase ambiguity in the vdfResult!
99+
97100
if (!BeaconValueOp.vdfVerifier.verify(steps, challenge, this.vdfResult, 2048, true)) {
98101
return false;
99102
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { Beacon } from './Beacon';
2+
3+
Beacon.computeVdf();

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
"scripts": {
1515
"build": "npx microbundle-crl --tsconfig tsconfig.build.json && npx tsc --project tsconfig.build.json --declaration --outDir ./decl",
1616
"build-test": "npx microbundle-crl --tsconfig tsconfig.json --output dist-test",
17-
"build-chat": "npx tsc --module CommonJs --project tsconfig.json --outDir ./dist-chat",
18-
"chat": "NODE_PATH=\"dist-chat/src:dist-chat/examples/chat\" node ./dist-chat/examples/chat/index.js",
19-
"winchat": "./scripts/chat.bat",
20-
"clean": "rm -rf ./decl/* ./dist/* ./dist-test/* ./dist-chat/*",
21-
"winclean": "if exist decl (rmdir decl /s /q) && mkdir decl && if exist dist (rmdir dist /s /q) && mkdir dist && if exist dist-test (rmdir dist-test /s /q) && mkdir dist-test && if exist dist-chat (rmdir dist-chat /s /q) && mkdir dist-chat",
17+
"build-examples": "npx tsc --module CommonJs --project tsconfig.json --outDir ./dist-examples",
18+
"example-chat": "NODE_PATH=\"dist-examples/src:dist-examples/examples/chat\" node ./dist-examples/examples/chat/index.js",
19+
"example-chat-win": "./scripts/chat.bat",
20+
"example-beacon": "NODE_PATH=\"dist-examples/src:dist-examples/examples/chat\" node ./dist-examples/examples/randomness-beacon/index.js",
21+
"example-beacon-win": "./scripts/beacon.bat",
22+
"clean": "rm -rf ./decl/* ./dist/* ./dist-test/* ./dist-examples/*",
23+
"winclean": "if exist decl (rmdir decl /s /q) && mkdir decl && if exist dist (rmdir dist /s /q) && mkdir dist && if exist dist-test (rmdir dist-test /s /q) && mkdir dist-test && if exist dist-examples (rmdir dist-examples /s /q) && mkdir dist-examples",
2224
"test": "npx jest"
2325
},
2426
"devDependencies": {

scripts/beacon.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@ECHO OFF
2+
setx NODE_PATH "dist-examples/src;dist-examples/examples/randomness-beacon" > $null
3+
@ECHO ON
4+
node ./dist-examples/examples/randomness-beacon/index.js

scripts/chat.bat

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
@ECHO OFF
2-
setx NODE_PATH "dist-chat/src;dist-chat/examples/chat" > $null
2+
setx NODE_PATH "dist-examples/src;dist-examples/examples/chat" > $null
33
@ECHO ON
4-
node ./dist-chat/examples/chat/index.js
4+
5+
echo ${NODE_PATH}
6+
7+
node ./dist-examples/examples/chat/index.js

src/crypto/ciphers/JSEncryptRSA.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,33 @@ import { SHA, SHAImpl } from '../hashing';
44

55
// dummy objects for JSEncrypt
66

7+
let fixNavigator = false;
8+
79
if ((global as any).navigator === undefined) {
810
(global as any).navigator = {appName: 'nodejs'};
11+
fixNavigator = true;
912
}
1013

14+
let fixWindow = false;
15+
1116
if ((global as any).window === undefined) {
1217
(global as any).window = {};
18+
fixWindow = true;
1319
}
1420

1521

1622
const JSEncrypt = require('jsencrypt').JSEncrypt;
1723

24+
25+
if (fixNavigator) {
26+
(global as any).navigator = undefined;
27+
}
28+
29+
if (fixWindow) {
30+
(global as any).window = undefined;
31+
}
32+
33+
1834
class JSEncryptRSA implements RSA {
1935

2036
static PKCS8 = 'pkcs8';

0 commit comments

Comments
 (0)