@peerbit/stream-interface 1.0.1
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 +3 -0
- package/lib/esm/index.d.ts +11 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/messages.d.ts +133 -0
- package/lib/esm/messages.js +678 -0
- package/lib/esm/messages.js.map +1 -0
- package/lib/esm/package.json +3 -0
- package/package.json +58 -0
- package/src/index.ts +14 -0
- package/src/messages.ts +758 -0
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var DataMessage_1, Hello_1, Goodbye_1, PingPong_1, Ping_1, Pong_1;
|
|
11
|
+
import { variant, vec, field, serialize, deserialize, fixedArray, option, } from "@dao-xyz/borsh";
|
|
12
|
+
import { equals } from "uint8arrays";
|
|
13
|
+
import { PublicSignKey, SignatureWithKey, verify, randomBytes, sha256Base64, sha256, } from "@peerbit/crypto";
|
|
14
|
+
/**
|
|
15
|
+
* The default msgID implementation
|
|
16
|
+
* Child class can override this.
|
|
17
|
+
*/
|
|
18
|
+
export const getMsgId = async (msg) => {
|
|
19
|
+
// first bytes is discriminator,
|
|
20
|
+
// next 32 bytes should be an id
|
|
21
|
+
//return Buffer.from(msg.slice(0, 33)).toString('base64');
|
|
22
|
+
return sha256Base64(msg.subarray(0, 33)); // base64EncArr(msg, 0, ID_LENGTH + 1);
|
|
23
|
+
};
|
|
24
|
+
let concatBytes;
|
|
25
|
+
if (globalThis.Buffer) {
|
|
26
|
+
concatBytes = globalThis.Buffer.concat;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
concatBytes = (arrays, length) => {
|
|
30
|
+
if (length == null) {
|
|
31
|
+
let length = 0;
|
|
32
|
+
for (const element of arrays) {
|
|
33
|
+
length += element.length;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const output = new Uint8Array(length);
|
|
37
|
+
let offset = 0;
|
|
38
|
+
for (const arr of arrays) {
|
|
39
|
+
output.set(arr, offset);
|
|
40
|
+
offset += arr.length;
|
|
41
|
+
}
|
|
42
|
+
return output;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export const ID_LENGTH = 32;
|
|
46
|
+
const WEEK_MS = 7 * 24 * 60 * 60 + 1000;
|
|
47
|
+
export let MessageHeader = class MessageHeader {
|
|
48
|
+
_id;
|
|
49
|
+
_timestamp;
|
|
50
|
+
_expires;
|
|
51
|
+
constructor(properties) {
|
|
52
|
+
this._id = properties?.id || randomBytes(ID_LENGTH);
|
|
53
|
+
this._expires = properties?.expires || BigInt(+new Date() + WEEK_MS);
|
|
54
|
+
this._timestamp = BigInt(+new Date());
|
|
55
|
+
}
|
|
56
|
+
get id() {
|
|
57
|
+
return this._id;
|
|
58
|
+
}
|
|
59
|
+
get expires() {
|
|
60
|
+
return this._expires;
|
|
61
|
+
}
|
|
62
|
+
get timetamp() {
|
|
63
|
+
return this._timestamp;
|
|
64
|
+
}
|
|
65
|
+
equals(other) {
|
|
66
|
+
return this._expires === other.expires && equals(this._id, other.id);
|
|
67
|
+
}
|
|
68
|
+
verify() {
|
|
69
|
+
return this.expires >= +new Date();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
__decorate([
|
|
73
|
+
field({ type: fixedArray("u8", ID_LENGTH) }),
|
|
74
|
+
__metadata("design:type", Uint8Array)
|
|
75
|
+
], MessageHeader.prototype, "_id", void 0);
|
|
76
|
+
__decorate([
|
|
77
|
+
field({ type: "u64" }),
|
|
78
|
+
__metadata("design:type", BigInt)
|
|
79
|
+
], MessageHeader.prototype, "_timestamp", void 0);
|
|
80
|
+
__decorate([
|
|
81
|
+
field({ type: "u64" }),
|
|
82
|
+
__metadata("design:type", BigInt)
|
|
83
|
+
], MessageHeader.prototype, "_expires", void 0);
|
|
84
|
+
MessageHeader = __decorate([
|
|
85
|
+
variant(0),
|
|
86
|
+
__metadata("design:paramtypes", [Object])
|
|
87
|
+
], MessageHeader);
|
|
88
|
+
class PublicKeys {
|
|
89
|
+
keys;
|
|
90
|
+
constructor(keys) {
|
|
91
|
+
this.keys = keys;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
__decorate([
|
|
95
|
+
field({ type: vec(PublicSignKey) }),
|
|
96
|
+
__metadata("design:type", Array)
|
|
97
|
+
], PublicKeys.prototype, "keys", void 0);
|
|
98
|
+
const SIGNATURES_SIZE_ENCODING = "u8"; // with 7 steps you know everyone in the world?, so u8 *should* suffice
|
|
99
|
+
export let Signatures = class Signatures {
|
|
100
|
+
signatures;
|
|
101
|
+
constructor(signatures = []) {
|
|
102
|
+
this.signatures = signatures;
|
|
103
|
+
}
|
|
104
|
+
equals(other) {
|
|
105
|
+
return (this.signatures.length === other.signatures.length &&
|
|
106
|
+
this.signatures.every((value, i) => other.signatures[i].equals(value)));
|
|
107
|
+
}
|
|
108
|
+
get publicKeys() {
|
|
109
|
+
return this.signatures.map((x) => x.publicKey);
|
|
110
|
+
}
|
|
111
|
+
hashPublicKeys() {
|
|
112
|
+
return sha256Base64(serialize(new PublicKeys(this.publicKeys)));
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
__decorate([
|
|
116
|
+
field({ type: vec(SignatureWithKey, SIGNATURES_SIZE_ENCODING) }),
|
|
117
|
+
__metadata("design:type", Array)
|
|
118
|
+
], Signatures.prototype, "signatures", void 0);
|
|
119
|
+
Signatures = __decorate([
|
|
120
|
+
variant(0),
|
|
121
|
+
__metadata("design:paramtypes", [Array])
|
|
122
|
+
], Signatures);
|
|
123
|
+
const keyMap = new Map();
|
|
124
|
+
const verifyMultiSig = async (message, expectSignatures) => {
|
|
125
|
+
const signatures = message.signatures.signatures;
|
|
126
|
+
if (signatures.length === 0) {
|
|
127
|
+
return !expectSignatures;
|
|
128
|
+
}
|
|
129
|
+
await message.createPrefix();
|
|
130
|
+
const dataGenerator = getMultiSigDataToSignHistory(message, 0);
|
|
131
|
+
let done = false;
|
|
132
|
+
for (const signature of signatures) {
|
|
133
|
+
if (done) {
|
|
134
|
+
throw new Error("Unexpected, the amount of signatures does not match the amount of data verify");
|
|
135
|
+
}
|
|
136
|
+
const data = dataGenerator.next();
|
|
137
|
+
done = data.done;
|
|
138
|
+
if (!(await verify(signature, data.value))) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
144
|
+
const emptySignatures = serialize(new Signatures());
|
|
145
|
+
function* getMultiSigDataToSignHistory(message, from = 0) {
|
|
146
|
+
if (from === 0) {
|
|
147
|
+
yield concatBytes([message.prefix, emptySignatures], message.prefix.length + emptySignatures.length);
|
|
148
|
+
}
|
|
149
|
+
for (let i = Math.max(from - 1, 0); i < message.signatures.signatures.length; i++) {
|
|
150
|
+
const bytes = message.getSuffix(i); // TODO make more performant
|
|
151
|
+
const concat = [message.prefix];
|
|
152
|
+
let len = message.prefix.length;
|
|
153
|
+
if (bytes instanceof Uint8Array) {
|
|
154
|
+
concat.push(bytes);
|
|
155
|
+
len += bytes.byteLength;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
for (const arr of bytes) {
|
|
159
|
+
concat.push(arr);
|
|
160
|
+
len += arr.byteLength;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
yield concatBytes(concat, len);
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
export class Message {
|
|
168
|
+
static deserialize(bytes) {
|
|
169
|
+
if (bytes.get(0) === DATA_VARIANT) {
|
|
170
|
+
// Data
|
|
171
|
+
return DataMessage.deserialize(bytes);
|
|
172
|
+
}
|
|
173
|
+
else if (bytes.get(0) === HELLO_VARIANT) {
|
|
174
|
+
// heartbeat
|
|
175
|
+
return Hello.deserialize(bytes);
|
|
176
|
+
}
|
|
177
|
+
else if (bytes.get(0) === GOODBYE_VARIANT) {
|
|
178
|
+
// heartbeat
|
|
179
|
+
return Goodbye.deserialize(bytes);
|
|
180
|
+
}
|
|
181
|
+
else if (bytes.get(0) === PING_VARIANT) {
|
|
182
|
+
return PingPong.deserialize(bytes);
|
|
183
|
+
}
|
|
184
|
+
throw new Error("Unsupported");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// I pack data with this message
|
|
188
|
+
const DATA_VARIANT = 0;
|
|
189
|
+
export let DataMessage = DataMessage_1 = class DataMessage extends Message {
|
|
190
|
+
_header;
|
|
191
|
+
_to; // not signed! TODO should we sign this?
|
|
192
|
+
_signatures;
|
|
193
|
+
_data;
|
|
194
|
+
constructor(properties) {
|
|
195
|
+
super();
|
|
196
|
+
this._data = properties.data;
|
|
197
|
+
this._header = properties.header || new MessageHeader();
|
|
198
|
+
this._to = properties.to || [];
|
|
199
|
+
this._signatures = properties.signatures || new Signatures();
|
|
200
|
+
}
|
|
201
|
+
get id() {
|
|
202
|
+
return this._header.id;
|
|
203
|
+
}
|
|
204
|
+
get signatures() {
|
|
205
|
+
return this._signatures;
|
|
206
|
+
}
|
|
207
|
+
get header() {
|
|
208
|
+
return this._header;
|
|
209
|
+
}
|
|
210
|
+
get to() {
|
|
211
|
+
return this._to;
|
|
212
|
+
}
|
|
213
|
+
set to(to) {
|
|
214
|
+
this._serialized = undefined;
|
|
215
|
+
this._to = to;
|
|
216
|
+
}
|
|
217
|
+
get sender() {
|
|
218
|
+
return this.signatures.signatures[0].publicKey;
|
|
219
|
+
}
|
|
220
|
+
get data() {
|
|
221
|
+
return this._data;
|
|
222
|
+
}
|
|
223
|
+
_serialized;
|
|
224
|
+
get serialized() {
|
|
225
|
+
return this.serialized;
|
|
226
|
+
}
|
|
227
|
+
_prefix;
|
|
228
|
+
get prefix() {
|
|
229
|
+
if (!this._prefix) {
|
|
230
|
+
throw new Error("Prefix not created");
|
|
231
|
+
}
|
|
232
|
+
return this._prefix;
|
|
233
|
+
}
|
|
234
|
+
async createPrefix() {
|
|
235
|
+
if (this._prefix) {
|
|
236
|
+
return this._prefix;
|
|
237
|
+
}
|
|
238
|
+
const headerSer = serialize(this._header);
|
|
239
|
+
const hashBytes = await sha256(this.data);
|
|
240
|
+
this._prefix = concatBytes([new Uint8Array([DATA_VARIANT]), headerSer, hashBytes], 1 + headerSer.length + hashBytes.length);
|
|
241
|
+
return this._prefix;
|
|
242
|
+
}
|
|
243
|
+
getSuffix(iteration) {
|
|
244
|
+
return serialize(new Signatures(this.signatures.signatures.slice(0, iteration + 1)));
|
|
245
|
+
}
|
|
246
|
+
async sign(sign) {
|
|
247
|
+
this._serialized = undefined; // because we will change this object, so the serialized version will not be applicable anymore
|
|
248
|
+
await this.createPrefix();
|
|
249
|
+
this.signatures.signatures.push(await sign(getMultiSigDataToSignHistory(this, this.signatures.signatures.length).next().value));
|
|
250
|
+
return this;
|
|
251
|
+
}
|
|
252
|
+
async verify(expectSignatures) {
|
|
253
|
+
return this._header.verify() && verifyMultiSig(this, expectSignatures);
|
|
254
|
+
}
|
|
255
|
+
/** Manually ser/der for performance gains */
|
|
256
|
+
serialize() {
|
|
257
|
+
if (this._serialized) {
|
|
258
|
+
return this._serialized;
|
|
259
|
+
}
|
|
260
|
+
return serialize(this);
|
|
261
|
+
}
|
|
262
|
+
static deserialize(bytes) {
|
|
263
|
+
if (bytes.get(0) !== 0) {
|
|
264
|
+
throw new Error("Unsupported");
|
|
265
|
+
}
|
|
266
|
+
const arr = bytes.subarray();
|
|
267
|
+
const ret = deserialize(arr, DataMessage_1);
|
|
268
|
+
ret._serialized = arr;
|
|
269
|
+
return ret;
|
|
270
|
+
}
|
|
271
|
+
equals(other) {
|
|
272
|
+
if (other instanceof DataMessage_1) {
|
|
273
|
+
const a = equals(this.data, other.data) &&
|
|
274
|
+
equals(this.id, other.id) &&
|
|
275
|
+
this.to.length === other.to.length;
|
|
276
|
+
if (!a) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
for (let i = 0; i < this.to.length; i++) {
|
|
280
|
+
if (this.to[i] !== other.to[i]) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return this.signatures.equals(other.signatures);
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
__decorate([
|
|
290
|
+
field({ type: MessageHeader }),
|
|
291
|
+
__metadata("design:type", MessageHeader)
|
|
292
|
+
], DataMessage.prototype, "_header", void 0);
|
|
293
|
+
__decorate([
|
|
294
|
+
field({ type: vec("string") }),
|
|
295
|
+
__metadata("design:type", Array)
|
|
296
|
+
], DataMessage.prototype, "_to", void 0);
|
|
297
|
+
__decorate([
|
|
298
|
+
field({ type: Signatures }),
|
|
299
|
+
__metadata("design:type", Signatures)
|
|
300
|
+
], DataMessage.prototype, "_signatures", void 0);
|
|
301
|
+
__decorate([
|
|
302
|
+
field({ type: Uint8Array }),
|
|
303
|
+
__metadata("design:type", Uint8Array)
|
|
304
|
+
], DataMessage.prototype, "_data", void 0);
|
|
305
|
+
DataMessage = DataMessage_1 = __decorate([
|
|
306
|
+
variant(DATA_VARIANT),
|
|
307
|
+
__metadata("design:paramtypes", [Object])
|
|
308
|
+
], DataMessage);
|
|
309
|
+
export let NetworkInfo = class NetworkInfo {
|
|
310
|
+
pingLatencies;
|
|
311
|
+
constructor(pingLatencies) {
|
|
312
|
+
this.pingLatencies = pingLatencies;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
__decorate([
|
|
316
|
+
field({ type: vec("u32", SIGNATURES_SIZE_ENCODING) }),
|
|
317
|
+
__metadata("design:type", Array)
|
|
318
|
+
], NetworkInfo.prototype, "pingLatencies", void 0);
|
|
319
|
+
NetworkInfo = __decorate([
|
|
320
|
+
variant(0),
|
|
321
|
+
__metadata("design:paramtypes", [Array])
|
|
322
|
+
], NetworkInfo);
|
|
323
|
+
// I send this too all my peers
|
|
324
|
+
const HELLO_VARIANT = 1;
|
|
325
|
+
export let Hello = Hello_1 = class Hello extends Message {
|
|
326
|
+
header;
|
|
327
|
+
multiaddrs;
|
|
328
|
+
data;
|
|
329
|
+
networkInfo;
|
|
330
|
+
signatures;
|
|
331
|
+
constructor(options) {
|
|
332
|
+
super();
|
|
333
|
+
this.header = new MessageHeader();
|
|
334
|
+
this.data = options?.data;
|
|
335
|
+
this.multiaddrs =
|
|
336
|
+
options?.multiaddrs?.filter((x) => !x.includes("/p2p-circuit/")) || []; // don't forward relay addresess (TODO ?)
|
|
337
|
+
this.signatures = new Signatures();
|
|
338
|
+
this.networkInfo = new NetworkInfo([]);
|
|
339
|
+
}
|
|
340
|
+
get sender() {
|
|
341
|
+
return this.signatures.signatures[0].publicKey;
|
|
342
|
+
}
|
|
343
|
+
serialize() {
|
|
344
|
+
return serialize(this);
|
|
345
|
+
}
|
|
346
|
+
static deserialize(bytes) {
|
|
347
|
+
const result = deserialize(bytes.subarray(), Hello_1);
|
|
348
|
+
if (result.signatures.signatures.length === 0) {
|
|
349
|
+
throw new Error("Missing sender on Hello");
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
_prefix;
|
|
354
|
+
get prefix() {
|
|
355
|
+
if (!this._prefix) {
|
|
356
|
+
throw new Error("Prefix not created");
|
|
357
|
+
}
|
|
358
|
+
return this._prefix;
|
|
359
|
+
}
|
|
360
|
+
async createPrefix() {
|
|
361
|
+
if (this._prefix) {
|
|
362
|
+
return this._prefix;
|
|
363
|
+
}
|
|
364
|
+
const headerSer = serialize(this.header);
|
|
365
|
+
const hashBytes = this.data ? await sha256(this.data) : new Uint8Array();
|
|
366
|
+
this._prefix = concatBytes([new Uint8Array([HELLO_VARIANT]), headerSer, hashBytes], 1 + headerSer.length + hashBytes.length);
|
|
367
|
+
return this._prefix;
|
|
368
|
+
}
|
|
369
|
+
getSuffix(iteration) {
|
|
370
|
+
return [
|
|
371
|
+
serialize(new NetworkInfo(this.networkInfo.pingLatencies.slice(0, iteration + 1))),
|
|
372
|
+
serialize(new Signatures(this.signatures.signatures.slice(0, iteration + 1))),
|
|
373
|
+
];
|
|
374
|
+
}
|
|
375
|
+
async sign(sign) {
|
|
376
|
+
await this.createPrefix();
|
|
377
|
+
const toSign = getMultiSigDataToSignHistory(this, this.signatures.signatures.length).next().value;
|
|
378
|
+
this.signatures.signatures.push(await sign(toSign));
|
|
379
|
+
return this;
|
|
380
|
+
}
|
|
381
|
+
async verify(expectSignatures) {
|
|
382
|
+
return (this.header.verify() &&
|
|
383
|
+
this.networkInfo.pingLatencies.length ===
|
|
384
|
+
this.signatures.signatures.length - 1 &&
|
|
385
|
+
verifyMultiSig(this, expectSignatures));
|
|
386
|
+
}
|
|
387
|
+
equals(other) {
|
|
388
|
+
if (other instanceof Hello_1) {
|
|
389
|
+
const dataEquals = (!!this.data && !!other.data && equals(this.data, other.data)) ||
|
|
390
|
+
!this.data === !other.data;
|
|
391
|
+
if (!dataEquals) {
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
return (this.header.equals(other.header) &&
|
|
395
|
+
this.signatures.equals(other.signatures));
|
|
396
|
+
}
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
__decorate([
|
|
401
|
+
field({ type: MessageHeader }),
|
|
402
|
+
__metadata("design:type", MessageHeader)
|
|
403
|
+
], Hello.prototype, "header", void 0);
|
|
404
|
+
__decorate([
|
|
405
|
+
field({ type: vec("string") }),
|
|
406
|
+
__metadata("design:type", Array)
|
|
407
|
+
], Hello.prototype, "multiaddrs", void 0);
|
|
408
|
+
__decorate([
|
|
409
|
+
field({ type: option(Uint8Array) }),
|
|
410
|
+
__metadata("design:type", Uint8Array)
|
|
411
|
+
], Hello.prototype, "data", void 0);
|
|
412
|
+
__decorate([
|
|
413
|
+
field({ type: NetworkInfo }),
|
|
414
|
+
__metadata("design:type", NetworkInfo)
|
|
415
|
+
], Hello.prototype, "networkInfo", void 0);
|
|
416
|
+
__decorate([
|
|
417
|
+
field({ type: Signatures }),
|
|
418
|
+
__metadata("design:type", Signatures)
|
|
419
|
+
], Hello.prototype, "signatures", void 0);
|
|
420
|
+
Hello = Hello_1 = __decorate([
|
|
421
|
+
variant(HELLO_VARIANT),
|
|
422
|
+
__metadata("design:paramtypes", [Object])
|
|
423
|
+
], Hello);
|
|
424
|
+
// Me or some my peer disconnected
|
|
425
|
+
const GOODBYE_VARIANT = 2;
|
|
426
|
+
export let Goodbye = Goodbye_1 = class Goodbye extends Message {
|
|
427
|
+
header;
|
|
428
|
+
early; // is early goodbye, I send this to my peers so when I disconnect, they can relay the message for me
|
|
429
|
+
data; // not signed
|
|
430
|
+
signatures;
|
|
431
|
+
constructor(properties) {
|
|
432
|
+
// disconnected: PeerId | string,
|
|
433
|
+
super();
|
|
434
|
+
this.header = properties?.header || new MessageHeader();
|
|
435
|
+
this.data = properties?.data;
|
|
436
|
+
this.early = properties?.early;
|
|
437
|
+
this.signatures = new Signatures();
|
|
438
|
+
}
|
|
439
|
+
get sender() {
|
|
440
|
+
return this.signatures.signatures[0].publicKey;
|
|
441
|
+
}
|
|
442
|
+
serialize() {
|
|
443
|
+
return serialize(this);
|
|
444
|
+
}
|
|
445
|
+
static deserialize(bytes) {
|
|
446
|
+
const result = deserialize(bytes.subarray(), Goodbye_1);
|
|
447
|
+
if (result.signatures.signatures.length === 0) {
|
|
448
|
+
throw new Error("Missing sender on Goodbye");
|
|
449
|
+
}
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
_prefix;
|
|
453
|
+
get prefix() {
|
|
454
|
+
if (!this._prefix) {
|
|
455
|
+
throw new Error("Prefix not created");
|
|
456
|
+
}
|
|
457
|
+
return this._prefix;
|
|
458
|
+
}
|
|
459
|
+
async createPrefix() {
|
|
460
|
+
if (this._prefix) {
|
|
461
|
+
return this._prefix;
|
|
462
|
+
}
|
|
463
|
+
const headerSer = serialize(this.header);
|
|
464
|
+
const hashBytes = this.data ? await sha256(this.data) : new Uint8Array();
|
|
465
|
+
this._prefix = concatBytes([new Uint8Array([GOODBYE_VARIANT]), headerSer, hashBytes], 1 + headerSer.length + 1 + hashBytes.length);
|
|
466
|
+
return this._prefix;
|
|
467
|
+
}
|
|
468
|
+
getSuffix(iteration) {
|
|
469
|
+
return serialize(new Signatures(this.signatures.signatures.slice(0, iteration + 1)));
|
|
470
|
+
}
|
|
471
|
+
async sign(sign) {
|
|
472
|
+
await this.createPrefix();
|
|
473
|
+
this.signatures.signatures.push(await sign(getMultiSigDataToSignHistory(this, this.signatures.signatures.length).next().value));
|
|
474
|
+
return this;
|
|
475
|
+
}
|
|
476
|
+
async verify(expectSignatures) {
|
|
477
|
+
return this.header.verify() && verifyMultiSig(this, expectSignatures);
|
|
478
|
+
}
|
|
479
|
+
equals(other) {
|
|
480
|
+
if (other instanceof Goodbye_1) {
|
|
481
|
+
if (this.early !== other.early) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
const dataEquals = (!!this.data && !!other.data && equals(this.data, other.data)) ||
|
|
485
|
+
!this.data === !other.data;
|
|
486
|
+
if (!dataEquals) {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
return (this.header.equals(other.header) &&
|
|
490
|
+
this.signatures.equals(other.signatures));
|
|
491
|
+
}
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
__decorate([
|
|
496
|
+
field({ type: MessageHeader }),
|
|
497
|
+
__metadata("design:type", MessageHeader)
|
|
498
|
+
], Goodbye.prototype, "header", void 0);
|
|
499
|
+
__decorate([
|
|
500
|
+
field({ type: "bool" }),
|
|
501
|
+
__metadata("design:type", Boolean)
|
|
502
|
+
], Goodbye.prototype, "early", void 0);
|
|
503
|
+
__decorate([
|
|
504
|
+
field({ type: option(Uint8Array) }),
|
|
505
|
+
__metadata("design:type", Uint8Array)
|
|
506
|
+
], Goodbye.prototype, "data", void 0);
|
|
507
|
+
__decorate([
|
|
508
|
+
field({ type: Signatures }),
|
|
509
|
+
__metadata("design:type", Signatures)
|
|
510
|
+
], Goodbye.prototype, "signatures", void 0);
|
|
511
|
+
Goodbye = Goodbye_1 = __decorate([
|
|
512
|
+
variant(GOODBYE_VARIANT),
|
|
513
|
+
__metadata("design:paramtypes", [Object])
|
|
514
|
+
], Goodbye);
|
|
515
|
+
const PING_VARIANT = 3;
|
|
516
|
+
export let PingPong = PingPong_1 = class PingPong extends Message {
|
|
517
|
+
static deserialize(bytes) {
|
|
518
|
+
return deserialize(bytes.subarray(), PingPong_1);
|
|
519
|
+
}
|
|
520
|
+
serialize() {
|
|
521
|
+
return serialize(this);
|
|
522
|
+
}
|
|
523
|
+
verify(_expectSignatures) {
|
|
524
|
+
return Promise.resolve(true);
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
PingPong = PingPong_1 = __decorate([
|
|
528
|
+
variant(PING_VARIANT)
|
|
529
|
+
], PingPong);
|
|
530
|
+
export let Ping = Ping_1 = class Ping extends PingPong {
|
|
531
|
+
pingBytes;
|
|
532
|
+
constructor() {
|
|
533
|
+
super();
|
|
534
|
+
this.pingBytes = randomBytes(32);
|
|
535
|
+
}
|
|
536
|
+
equals(other) {
|
|
537
|
+
if (other instanceof Ping_1) {
|
|
538
|
+
return equals(this.pingBytes, other.pingBytes);
|
|
539
|
+
}
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
__decorate([
|
|
544
|
+
field({ type: fixedArray("u8", 32) }),
|
|
545
|
+
__metadata("design:type", Uint8Array)
|
|
546
|
+
], Ping.prototype, "pingBytes", void 0);
|
|
547
|
+
Ping = Ping_1 = __decorate([
|
|
548
|
+
variant(0),
|
|
549
|
+
__metadata("design:paramtypes", [])
|
|
550
|
+
], Ping);
|
|
551
|
+
export let Pong = Pong_1 = class Pong extends PingPong {
|
|
552
|
+
pingBytes;
|
|
553
|
+
constructor(pingBytes) {
|
|
554
|
+
super();
|
|
555
|
+
this.pingBytes = pingBytes;
|
|
556
|
+
}
|
|
557
|
+
equals(other) {
|
|
558
|
+
if (other instanceof Pong_1) {
|
|
559
|
+
return equals(this.pingBytes, other.pingBytes);
|
|
560
|
+
}
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
__decorate([
|
|
565
|
+
field({ type: fixedArray("u8", 32) }),
|
|
566
|
+
__metadata("design:type", Uint8Array)
|
|
567
|
+
], Pong.prototype, "pingBytes", void 0);
|
|
568
|
+
Pong = Pong_1 = __decorate([
|
|
569
|
+
variant(1),
|
|
570
|
+
__metadata("design:paramtypes", [Uint8Array])
|
|
571
|
+
], Pong);
|
|
572
|
+
export let Connections = class Connections {
|
|
573
|
+
connections;
|
|
574
|
+
constructor(connections) {
|
|
575
|
+
this.connections = connections;
|
|
576
|
+
}
|
|
577
|
+
equals(other) {
|
|
578
|
+
if (this.connections.length !== other.connections.length) {
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
for (let i = 0; i < this.connections.length; i++) {
|
|
582
|
+
if (this.connections[i].length !== other.connections[i].length) {
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
const a1 = this.connections[i][0];
|
|
586
|
+
const a2 = this.connections[i][1];
|
|
587
|
+
const b1 = other.connections[i][0];
|
|
588
|
+
const b2 = other.connections[i][1];
|
|
589
|
+
if (a1 === b1 && a2 === b2) {
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
if (a1 === b2 && a2 === b1) {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
return true;
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
__decorate([
|
|
601
|
+
field({ type: vec(fixedArray("string", 2)) }),
|
|
602
|
+
__metadata("design:type", Array)
|
|
603
|
+
], Connections.prototype, "connections", void 0);
|
|
604
|
+
Connections = __decorate([
|
|
605
|
+
variant(0),
|
|
606
|
+
__metadata("design:paramtypes", [Array])
|
|
607
|
+
], Connections);
|
|
608
|
+
// Share connections
|
|
609
|
+
/* const NETWORK_INFO_VARIANT = 3;
|
|
610
|
+
@variant(NETWORK_INFO_VARIANT)
|
|
611
|
+
export class NetworkInfo extends Message {
|
|
612
|
+
|
|
613
|
+
@field({ type: MessageHeader })
|
|
614
|
+
header: MessageHeader;
|
|
615
|
+
|
|
616
|
+
@field({ type: Connections })
|
|
617
|
+
connections: Connections;
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
@field({ type: Signatures })
|
|
621
|
+
signatures: Signatures
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
constructor(connections: [string, string][]) {
|
|
625
|
+
super();
|
|
626
|
+
this.header = new MessageHeader();
|
|
627
|
+
this.connections = new Connections(connections);
|
|
628
|
+
this.signatures = new Signatures()
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
getDataToSign(): Uint8Array {
|
|
632
|
+
return this.serialize()
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
_prefix: Uint8Array | undefined
|
|
636
|
+
get prefix(): Uint8Array {
|
|
637
|
+
if (this._prefix)
|
|
638
|
+
return this._prefix
|
|
639
|
+
const header = serialize(this.header);
|
|
640
|
+
const connections = serialize(this.connections);
|
|
641
|
+
this._prefix = concatBytes([new Uint8Array([NETWORK_INFO_VARIANT]), header, connections], 1 + header.length + connections.length);
|
|
642
|
+
return this._prefix;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
sign(sign: (bytes: Uint8Array) => SignatureWithKey) {
|
|
646
|
+
this.signatures.signatures.push(sign(getMultiSigDataToSignHistory(this, this.signatures.signatures.length).next().value!));
|
|
647
|
+
return this;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
verify(): boolean {
|
|
651
|
+
return this.header.verify() && verifyMultiSig(this)
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
serialize() {
|
|
656
|
+
return serialize(this)
|
|
657
|
+
}
|
|
658
|
+
static deserialize(bytes: Uint8ArrayList): NetworkInfo {
|
|
659
|
+
return deserialize(bytes.subarray(), NetworkInfo)
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
equals(other: Message) {
|
|
663
|
+
if (other instanceof NetworkInfo) {
|
|
664
|
+
if (!equals(this.header.id, other.header.id) || !this.header.equals(other.header)) { // TODO fix uneccessary copy
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
if (!this.connections.equals(other.connections)) {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
return this.signatures.equals(other.signatures)
|
|
672
|
+
}
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
*/
|
|
678
|
+
//# sourceMappingURL=messages.js.map
|