@peerbit/rpc 1.0.2
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/LICENSE +202 -0
- package/README.md +65 -0
- package/lib/esm/controller.d.ts +62 -0
- package/lib/esm/controller.js +266 -0
- package/lib/esm/controller.js.map +1 -0
- package/lib/esm/encoding.d.ts +19 -0
- package/lib/esm/encoding.js +59 -0
- package/lib/esm/encoding.js.map +1 -0
- package/lib/esm/index.d.ts +4 -0
- package/lib/esm/index.js +5 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/io.d.ts +22 -0
- package/lib/esm/io.js +3 -0
- package/lib/esm/io.js.map +1 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/utils.d.ts +6 -0
- package/lib/esm/utils.js +57 -0
- package/lib/esm/utils.js.map +1 -0
- package/package.json +45 -0
- package/src/controller.ts +413 -0
- package/src/encoding.ts +41 -0
- package/src/index.ts +4 -0
- package/src/io.ts +28 -0
- package/src/utils.ts +73 -0
package/src/index.ts
ADDED
package/src/io.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
X25519PublicKey,
|
|
3
|
+
Ed25519PublicKey,
|
|
4
|
+
PublicSignKey,
|
|
5
|
+
X25519Keypair,
|
|
6
|
+
} from "@peerbit/crypto";
|
|
7
|
+
import { logger as loggerFn } from "@peerbit/logger";
|
|
8
|
+
|
|
9
|
+
export const logger = loggerFn({ module: "rpc" });
|
|
10
|
+
export type RPCOptions<R> = {
|
|
11
|
+
amount?: number;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
isTrusted?: (publicKey: PublicSignKey) => Promise<boolean>;
|
|
14
|
+
strict?: boolean;
|
|
15
|
+
onResponse?: (response: R, from?: PublicSignKey) => void;
|
|
16
|
+
stopper?: (stopper: () => void) => void;
|
|
17
|
+
} & PublishOptions;
|
|
18
|
+
|
|
19
|
+
export type PublishOptions = {
|
|
20
|
+
encryption?: {
|
|
21
|
+
key: X25519Keypair;
|
|
22
|
+
responders?: (X25519PublicKey | Ed25519PublicKey)[];
|
|
23
|
+
};
|
|
24
|
+
to?: PublicSignKey[] | string[];
|
|
25
|
+
strict?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type RPCResponse<R> = { response: R; from?: PublicSignKey };
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { RPC } from "./controller";
|
|
2
|
+
import { RPCOptions, RPCResponse } from "./io";
|
|
3
|
+
export class MissingResponsesError extends Error {
|
|
4
|
+
constructor(message: string) {
|
|
5
|
+
super(message);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export const queryAll = <Q, R>(
|
|
9
|
+
rpc: RPC<Q, R>,
|
|
10
|
+
groups: string[][],
|
|
11
|
+
request: Q,
|
|
12
|
+
responseHandler: (response: RPCResponse<R>[]) => Promise<void> | void,
|
|
13
|
+
options?: RPCOptions<R> | undefined
|
|
14
|
+
) => {
|
|
15
|
+
// In each shard/group only query a subset
|
|
16
|
+
groups = [...groups].filter(
|
|
17
|
+
(x) => !x.find((y) => y === rpc.node.identity.publicKey.hashcode())
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
let rng = Math.round(Math.random() * groups.length);
|
|
21
|
+
const startRng = rng;
|
|
22
|
+
const fn = async () => {
|
|
23
|
+
let missingReponses = false;
|
|
24
|
+
while (groups.length > 0) {
|
|
25
|
+
const peersToQuery: string[] = new Array(groups.length);
|
|
26
|
+
let counter = 0;
|
|
27
|
+
const peerToGroupIndex = new Map<string, number>();
|
|
28
|
+
for (let i = 0; i < groups.length; i++) {
|
|
29
|
+
const group = groups[i];
|
|
30
|
+
peersToQuery[counter] = group[rng % group.length];
|
|
31
|
+
peerToGroupIndex.set(peersToQuery[counter], i);
|
|
32
|
+
counter++;
|
|
33
|
+
}
|
|
34
|
+
if (peersToQuery.length > 0) {
|
|
35
|
+
const results = await rpc.request(request, {
|
|
36
|
+
...options,
|
|
37
|
+
to: peersToQuery,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
for (const result of results) {
|
|
41
|
+
if (!result.from) {
|
|
42
|
+
throw new Error("Unexpected, missing from");
|
|
43
|
+
}
|
|
44
|
+
peerToGroupIndex.delete(result.from.hashcode());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await responseHandler(results);
|
|
48
|
+
|
|
49
|
+
const indicesLeft = new Set([...peerToGroupIndex.values()]);
|
|
50
|
+
|
|
51
|
+
rng += 1;
|
|
52
|
+
groups = groups.filter((v, ix) => {
|
|
53
|
+
if (indicesLeft.has(ix)) {
|
|
54
|
+
const peerIndex = rng % v.length;
|
|
55
|
+
if (rng === startRng || peerIndex === startRng % v.length) {
|
|
56
|
+
// TODO Last condition needed?
|
|
57
|
+
missingReponses = true;
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (missingReponses) {
|
|
67
|
+
throw new MissingResponsesError(
|
|
68
|
+
"Did not recieve responses from all shards"
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return fn();
|
|
73
|
+
};
|