@activeledger/activenetwork 2.15.7 → 4.3.3

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.
Files changed (79) hide show
  1. package/es/network/cpus.d.ts +1 -0
  2. package/es/network/cpus.d.ts.map +1 -1
  3. package/es/network/cpus.js +26 -15
  4. package/es/network/cpus.js.map +1 -1
  5. package/es/network/endpoints.d.ts +7 -3
  6. package/es/network/endpoints.d.ts.map +1 -1
  7. package/es/network/endpoints.js +685 -172
  8. package/es/network/endpoints.js.map +1 -1
  9. package/es/network/home.d.ts.map +1 -1
  10. package/es/network/home.js +41 -19
  11. package/es/network/home.js.map +1 -1
  12. package/es/network/host.d.ts +15 -7
  13. package/es/network/host.d.ts.map +1 -1
  14. package/es/network/host.js +631 -240
  15. package/es/network/host.js.map +1 -1
  16. package/es/network/locker.d.ts +10 -5
  17. package/es/network/locker.d.ts.map +1 -1
  18. package/es/network/locker.js +50 -17
  19. package/es/network/locker.js.map +1 -1
  20. package/es/network/maintain.d.ts.map +1 -1
  21. package/es/network/maintain.js +42 -42
  22. package/es/network/maintain.js.map +1 -1
  23. package/es/network/neighbour.d.ts +8 -4
  24. package/es/network/neighbour.d.ts.map +1 -1
  25. package/es/network/neighbour.js +82 -18
  26. package/es/network/neighbour.js.map +1 -1
  27. package/es/network/neighbourhood.d.ts +1 -1
  28. package/es/network/neighbourhood.d.ts.map +1 -1
  29. package/es/network/neighbourhood.js +39 -42
  30. package/es/network/neighbourhood.js.map +1 -1
  31. package/es/network/p2pClient.d.ts +20 -0
  32. package/es/network/p2pClient.d.ts.map +1 -0
  33. package/es/network/p2pClient.js +84 -0
  34. package/es/network/p2pClient.js.map +1 -0
  35. package/es/network/process.js +99 -65
  36. package/es/network/process.js.map +1 -1
  37. package/es/network/utils.d.ts.map +1 -1
  38. package/es/network/utils.js +17 -21
  39. package/es/network/utils.js.map +1 -1
  40. package/lib/network/cpus.d.ts +1 -0
  41. package/lib/network/cpus.d.ts.map +1 -1
  42. package/lib/network/cpus.js +26 -15
  43. package/lib/network/cpus.js.map +1 -1
  44. package/lib/network/endpoints.d.ts +7 -3
  45. package/lib/network/endpoints.d.ts.map +1 -1
  46. package/lib/network/endpoints.js +684 -171
  47. package/lib/network/endpoints.js.map +1 -1
  48. package/lib/network/home.d.ts.map +1 -1
  49. package/lib/network/home.js +41 -19
  50. package/lib/network/home.js.map +1 -1
  51. package/lib/network/host.d.ts +15 -7
  52. package/lib/network/host.d.ts.map +1 -1
  53. package/lib/network/host.js +630 -239
  54. package/lib/network/host.js.map +1 -1
  55. package/lib/network/locker.d.ts +10 -5
  56. package/lib/network/locker.d.ts.map +1 -1
  57. package/lib/network/locker.js +50 -17
  58. package/lib/network/locker.js.map +1 -1
  59. package/lib/network/maintain.d.ts.map +1 -1
  60. package/lib/network/maintain.js +42 -42
  61. package/lib/network/maintain.js.map +1 -1
  62. package/lib/network/neighbour.d.ts +8 -4
  63. package/lib/network/neighbour.d.ts.map +1 -1
  64. package/lib/network/neighbour.js +82 -18
  65. package/lib/network/neighbour.js.map +1 -1
  66. package/lib/network/neighbourhood.d.ts +1 -1
  67. package/lib/network/neighbourhood.d.ts.map +1 -1
  68. package/lib/network/neighbourhood.js +39 -42
  69. package/lib/network/neighbourhood.js.map +1 -1
  70. package/lib/network/p2pClient.d.ts +20 -0
  71. package/lib/network/p2pClient.d.ts.map +1 -0
  72. package/lib/network/p2pClient.js +88 -0
  73. package/lib/network/p2pClient.js.map +1 -0
  74. package/lib/network/process.js +98 -64
  75. package/lib/network/process.js.map +1 -1
  76. package/lib/network/utils.d.ts.map +1 -1
  77. package/lib/network/utils.js +17 -21
  78. package/lib/network/utils.js.map +1 -1
  79. package/package.json +10 -8
@@ -2,132 +2,402 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Endpoints = void 0;
4
4
  const activeoptions_1 = require("@activeledger/activeoptions");
5
+ const activeutilities_1 = require("@activeledger/activeutilities");
5
6
  const activelogger_1 = require("@activeledger/activelogger");
6
7
  const activedefinitions_1 = require("@activeledger/activedefinitions");
7
8
  const activecrypto_1 = require("@activeledger/activecrypto");
8
9
  const home_1 = require("./home");
9
- const neighbourhood_1 = require("./neighbourhood");
10
10
  const maintain_1 = require("./maintain");
11
+ const locker_1 = require("./locker");
12
+ const MAX_COUNTERS = 10;
11
13
  class Endpoints {
12
- static ExternalInitalise(host, body, ip) {
13
- return new Promise((resolve, reject) => {
14
- if (body && activedefinitions_1.ActiveDefinitions.LedgerTypeChecks.isEntry(body)) {
15
- let tx = body;
16
- tx.$datetime = new Date();
17
- if (tx.$tx.$expire && new Date(tx.$tx.$expire) <= tx.$datetime) {
18
- return resolve(this.successfulFailure(`Transaction Expired : ${tx.$tx.$expire}`));
19
- }
20
- if (!tx.$sigs) {
21
- return resolve(this.successfulFailure(`$sigs not found`));
22
- }
23
- tx.$origin = host.reference;
24
- tx.$umid = activecrypto_1.ActiveCrypto.Hash.getHash(JSON.stringify(tx));
25
- tx.$remoteAddr = ip;
26
- if (tx.$multi) {
27
- return resolve({
28
- statusCode: 400,
29
- content: "Multiple Transaction Not Implemented",
30
- });
31
- }
32
- if (host.neighbourhood.count() < 4) {
33
- tx.$broadcast = false;
34
- }
35
- else if (!tx.$territoriality && !tx.$broadcast) {
36
- tx.$broadcast = true;
37
- }
38
- Endpoints.DirectInternalInitalise(host, tx)
39
- .then((response) => {
40
- if (response.status == "200" && !response.data.error) {
41
- let tx = response.data;
42
- let summary = {
43
- total: 0,
44
- vote: 0,
45
- commit: 0,
46
- };
47
- let responses = [];
48
- let nodes = Object.keys(tx.$nodes);
49
- for (let i = nodes.length; i--;) {
50
- summary.total++;
51
- if (tx.$nodes[nodes[i]].vote)
52
- summary.vote++;
53
- if (tx.$nodes[nodes[i]].commit)
54
- summary.commit++;
55
- if (tx.$nodes[nodes[i]].error) {
56
- if (summary.errors) {
57
- summary.errors.push(tx.$nodes[nodes[i]].error);
58
- }
59
- else {
60
- summary.errors = [tx.$nodes[nodes[i]].error];
61
- }
62
- }
63
- if (tx.$nodes[nodes[i]].return) {
64
- responses.push(tx.$nodes[nodes[i]].return);
65
- }
66
- if (!tx.$streams && tx.$nodes[nodes[i]].streams) {
67
- tx.$streams = tx.$nodes[nodes[i]].streams;
68
- }
14
+ static rebaseThrottle = 0;
15
+ static ExternalInitalise(host, body, ip, db) {
16
+ return new Promise(async (resolve, reject) => {
17
+ const process = (body) => {
18
+ return new Promise(async (resolve, reject) => {
19
+ if (body && activedefinitions_1.ActiveDefinitions.LedgerTypeChecks.isEntry(body)) {
20
+ let tx = body;
21
+ const now = new Date();
22
+ if (tx.$datetime) {
23
+ this.successfulFailure(`$datetime cannot be preset`);
69
24
  }
70
- if (tx.$broadcast && summary.vote) {
71
- const percent = tx.$unanimous
72
- ? 100
73
- : activeoptions_1.ActiveOptions.get("consensus", {}).reached;
74
- if ((summary.vote / summary.total) * 100 >= percent || false) {
75
- summary.commit = summary.vote;
25
+ if (tx.$tx.$expire) {
26
+ if (new Date(tx.$tx.$expire) <= now) {
27
+ return resolve(this.successfulFailure(`Transaction Expired : ${tx.$tx.$expire}`));
28
+ }
29
+ else {
30
+ tx.$umid = activecrypto_1.ActiveCrypto.Hash.getHash(JSON.stringify(tx));
31
+ if (await db.exists(`${tx.$umid}:umid`)) {
32
+ return resolve(this.successfulFailure(`Transaction Exists : ${tx.$umid}`));
33
+ }
34
+ tx.$datetime = now;
76
35
  }
77
36
  }
78
- let output = {
79
- $umid: tx.$umid,
80
- $summary: summary,
81
- $streams: tx.$streams,
82
- };
83
- if (responses.length) {
84
- output.$responses = responses;
37
+ else {
38
+ tx.$datetime = now;
39
+ tx.$umid = activecrypto_1.ActiveCrypto.Hash.getHash(JSON.stringify(tx));
85
40
  }
86
- if (activeoptions_1.ActiveOptions.get("debug", false)) {
87
- output.$debug = tx;
41
+ if (!tx.$sigs) {
42
+ return resolve(this.successfulFailure(`$sigs not found`));
88
43
  }
89
- return resolve({
90
- statusCode: 200,
91
- content: output,
92
- });
93
- }
94
- else {
95
- if (response.rebroadcasted) {
96
- return resolve({
97
- statusCode: 200,
98
- content: response.data,
99
- });
44
+ tx.$origin = host.reference;
45
+ tx.$remoteAddr = ip;
46
+ if (!tx.$territoriality && !tx.$broadcast) {
47
+ tx.$broadcast = true;
100
48
  }
101
- else {
102
- return resolve({
103
- statusCode: response.status,
104
- content: response.data,
49
+ activelogger_1.ActiveLogger.debug("Client Sent TX : " + tx.$umid);
50
+ const resendable = (initTx, counter = 0) => {
51
+ Endpoints.DirectInternalInitalise(host, initTx)
52
+ .then(async (response) => {
53
+ if (response.status == "200" && !response.data?.error) {
54
+ let tx = response.data;
55
+ if (!tx) {
56
+ delete initTx.$nodes;
57
+ delete initTx.$revs;
58
+ delete initTx.$streams;
59
+ activelogger_1.ActiveLogger.warn(initTx.$tx, `SPI NOTX (Empty Response) Resending ${counter}`);
60
+ setTimeout(() => {
61
+ if (!response.dontRelease) {
62
+ host.release(initTx.$umid);
63
+ }
64
+ resendable(initTx, ++counter);
65
+ }, 50);
66
+ return;
67
+ }
68
+ let summary = {
69
+ total: 0,
70
+ vote: 0,
71
+ commit: 0,
72
+ };
73
+ let responses = [];
74
+ if (tx?.$nodes) {
75
+ let nodes = Object.keys(tx.$nodes);
76
+ for (let i = nodes.length; i--;) {
77
+ summary.total++;
78
+ if (tx.$nodes[nodes[i]].vote)
79
+ summary.vote++;
80
+ if (tx.$nodes[nodes[i]].commit)
81
+ summary.commit++;
82
+ if (tx.$nodes[nodes[i]]?.error) {
83
+ if (summary.errors) {
84
+ summary.errors.push(tx.$nodes[nodes[i]].error);
85
+ }
86
+ else {
87
+ summary.errors = [
88
+ tx.$nodes[nodes[i]].error,
89
+ ];
90
+ }
91
+ }
92
+ if (tx.$nodes[nodes[i]].return) {
93
+ responses.push(tx.$nodes[nodes[i]].return);
94
+ }
95
+ if (!tx.$streams && tx.$nodes[nodes[i]].streams) {
96
+ tx.$streams = tx.$nodes[nodes[i]].streams;
97
+ }
98
+ }
99
+ if (!summary.commit &&
100
+ summary.total > 1 &&
101
+ summary.errors &&
102
+ counter <= MAX_COUNTERS) {
103
+ activelogger_1.ActiveLogger.warn(summary, `SPI Checking - Origin Node, Is it wrong? umid: ${tx.$umid}`);
104
+ if (Endpoints.shouldTriggerSpiLookup(summary.errors, tx.$nodes[home_1.Home.reference].error)) {
105
+ activelogger_1.ActiveLogger.warn(`SPI Checked - Origin Node, Wrong. Starting lookup umid: ${tx.$umid}`);
106
+ setTimeout(async () => {
107
+ let rewroteSomething = false;
108
+ const streams = [
109
+ ...new Set([
110
+ ...this.labelOrKey(tx.$tx.$i),
111
+ ...this.labelOrKey(tx.$tx.$o),
112
+ ]),
113
+ ];
114
+ if (streams.length) {
115
+ const rewrote = activeoptions_1.ActiveCacheManager.fetch("rewrote", 1500);
116
+ for (let i = streams.length; i--;) {
117
+ streams.push(`${streams[i]}:stream`);
118
+ }
119
+ streams.push(`${tx.$tx.$contract.substring(0, 64)}:data`);
120
+ if (streams.length) {
121
+ const networkStreams = await host.neighbourhood.knockAll("stream", {
122
+ $streams: streams,
123
+ });
124
+ const consensusReached = Math.ceil((activeoptions_1.ActiveOptions.get("consensus", {})
125
+ .reached /
126
+ 100) *
127
+ host.neighbourhood.count() -
128
+ 1);
129
+ if (networkStreams.length >= consensusReached) {
130
+ const consensus = {};
131
+ for (let i = networkStreams.length; i--;) {
132
+ const nodeStreams = networkStreams[i];
133
+ if (nodeStreams?.length) {
134
+ for (let ii = nodeStreams.length; ii--;) {
135
+ const streamDoc = nodeStreams[ii];
136
+ if (streamDoc && streamDoc._id && streamDoc._rev) {
137
+ if (!consensus[streamDoc._id]) {
138
+ consensus[streamDoc._id] = {};
139
+ }
140
+ if (consensus[streamDoc._id][streamDoc._rev]) {
141
+ consensus[streamDoc._id][streamDoc._rev].votes++;
142
+ }
143
+ else {
144
+ consensus[streamDoc._id][streamDoc._rev] = {
145
+ votes: 1,
146
+ doc: streamDoc,
147
+ };
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ const docs = Object.keys(consensus);
154
+ for (let g = docs.length; g--;) {
155
+ const doc = consensus[docs[g]];
156
+ if (rewrote.has(docs[g])) {
157
+ continue;
158
+ }
159
+ let max = 0;
160
+ let winner = "";
161
+ for (let x in doc) {
162
+ if (doc[x].votes >= consensusReached) {
163
+ activelogger_1.ActiveLogger.warn(`SPI ${doc[x].votes} >= ${consensusReached} for ${docs[g]}@${x}`);
164
+ if (doc[x].votes > max) {
165
+ max = doc[x].votes;
166
+ winner = x;
167
+ }
168
+ else if (doc[x].votes === max) {
169
+ const [xPos] = x.split("-");
170
+ const [wPos] = winner.split("-");
171
+ if (+xPos > +wPos) {
172
+ activelogger_1.ActiveLogger.warn(`SPI matching max (${max}) but has higher position`);
173
+ winner = x;
174
+ }
175
+ }
176
+ }
177
+ }
178
+ if (winner && !rewrote.has(docs[g])) {
179
+ const winningDoc = doc[winner].doc;
180
+ rewrote.set(winningDoc._id, winningDoc._rev);
181
+ const dblCheck = await host.dbConnection.get(winningDoc._id);
182
+ if (dblCheck._rev !== winningDoc._rev) {
183
+ activelogger_1.ActiveLogger.error(`SPI REWRITING #1 ${winningDoc._id} @ ${winningDoc._rev} NOT ${dblCheck._rev} : ${tx.$umid} CACHE : ${rewrote.get(winningDoc._id)}`);
184
+ await host.dbConnection.bulkDocs([winningDoc], {
185
+ new_edits: true,
186
+ force_rev: winningDoc._rev,
187
+ });
188
+ rewroteSomething = true;
189
+ }
190
+ }
191
+ else {
192
+ if (!rewrote.has(docs[g])) {
193
+ activelogger_1.ActiveLogger.warn(`SPI NOWINNER #1 - ${docs[g]}`);
194
+ }
195
+ }
196
+ }
197
+ if (rewroteSomething) {
198
+ delete initTx.$nodes;
199
+ delete initTx.$revs;
200
+ delete initTx.$streams;
201
+ if (!response.dontRelease) {
202
+ host.release(initTx.$umid);
203
+ }
204
+ initTx.$umid = activecrypto_1.ActiveCrypto.Hash.getHash(JSON.stringify(initTx) + counter);
205
+ activelogger_1.ActiveLogger.warn(initTx, `SPI (Rewrite) Resending #1 ${counter}`);
206
+ setTimeout(() => {
207
+ resendable(initTx, ++counter);
208
+ }, 50);
209
+ return;
210
+ }
211
+ else {
212
+ if (!response.dontRelease) {
213
+ host.release(tx.$umid);
214
+ }
215
+ const output = {
216
+ $umid: tx.$umid,
217
+ $summary: summary,
218
+ $streams: tx.$streams,
219
+ };
220
+ if (responses.length) {
221
+ output.$responses = responses;
222
+ }
223
+ if (activeoptions_1.ActiveOptions.get("debugToClient", false)) {
224
+ output.$debug = tx;
225
+ }
226
+ activelogger_1.ActiveLogger.warn(output, `SPI Failed to find an issue returning to client`);
227
+ return resolve({
228
+ statusCode: 200,
229
+ content: output,
230
+ });
231
+ }
232
+ }
233
+ else {
234
+ activelogger_1.ActiveLogger.warn(`SPI Skipped not enough returned for consensus yet (${networkStreams.length}/${consensusReached})`);
235
+ return resolve({
236
+ statusCode: 200,
237
+ content: output,
238
+ });
239
+ }
240
+ }
241
+ }
242
+ }, 100);
243
+ return;
244
+ }
245
+ else {
246
+ if (summary.errors?.some((e) => e.indexOf("Busy Locks") !== -1 ||
247
+ e.indexOf("IBL01") !== -1) &&
248
+ !initTx.$nolock) {
249
+ delete initTx.$nodes;
250
+ delete initTx.$revs;
251
+ delete initTx.$streams;
252
+ if (!response.dontRelease) {
253
+ host.release(initTx.$umid);
254
+ }
255
+ initTx.$umid = activecrypto_1.ActiveCrypto.Hash.getHash(JSON.stringify(initTx) + counter);
256
+ activelogger_1.ActiveLogger.warn(initTx.$tx, `SPI Resending #2 ${counter} in 5s`);
257
+ setTimeout(() => {
258
+ resendable(initTx, ++counter);
259
+ }, 50);
260
+ return;
261
+ }
262
+ }
263
+ }
264
+ }
265
+ if (!response.dontRelease) {
266
+ host.release(tx.$umid);
267
+ }
268
+ const output = {
269
+ $umid: tx.$umid,
270
+ $summary: summary,
271
+ $streams: tx.$streams,
272
+ };
273
+ if (responses.length) {
274
+ output.$responses = responses;
275
+ }
276
+ if (activeoptions_1.ActiveOptions.get("debugToClient", false)) {
277
+ output.$debug = tx;
278
+ }
279
+ return resolve({
280
+ statusCode: 200,
281
+ content: output,
282
+ });
283
+ }
284
+ else {
285
+ if (response.rebroadcasted) {
286
+ return resolve({
287
+ statusCode: 200,
288
+ content: response.data,
289
+ });
290
+ }
291
+ else {
292
+ return resolve({
293
+ statusCode: response.status,
294
+ content: response.data,
295
+ });
296
+ }
297
+ }
298
+ })
299
+ .catch((error) => {
300
+ host.release(initTx.$umid);
301
+ if (error?.status == 100 && error.error) {
302
+ if (counter <= MAX_COUNTERS &&
303
+ error.error === "Busy Locks" &&
304
+ !initTx.$nolock) {
305
+ delete initTx.$nodes;
306
+ delete initTx.$revs;
307
+ delete initTx.$streams;
308
+ initTx.$umid = activecrypto_1.ActiveCrypto.Hash.getHash(JSON.stringify(initTx) + counter);
309
+ activelogger_1.ActiveLogger.warn(initTx.$tx, `SPI Resending #3 ${counter}`);
310
+ setTimeout(() => {
311
+ resendable(initTx, ++counter);
312
+ }, 250);
313
+ return;
314
+ }
315
+ else {
316
+ return resolve(this.successfulFailure(error.error || error, 0));
317
+ }
318
+ }
319
+ else {
320
+ activelogger_1.ActiveLogger.error(error, "Sent 500 Response (1000)");
321
+ return reject({
322
+ statusCode: 500,
323
+ content: error instanceof Error
324
+ ? { error: error.message }
325
+ : error,
326
+ });
327
+ }
105
328
  });
106
- }
107
- }
108
- })
109
- .catch((error) => {
110
- if ((error === null || error === void 0 ? void 0 : error.status) == "100" && error.error) {
111
- return resolve(this.successfulFailure(error.error || error));
329
+ };
330
+ resendable(tx);
112
331
  }
113
332
  else {
114
- activelogger_1.ActiveLogger.error(error, "Sent 500 Response (1000)");
333
+ activelogger_1.ActiveLogger.error("Sent 500 Response (1200)");
115
334
  return reject({
116
335
  statusCode: 500,
117
- content: error,
336
+ content: "Invalid Transaction",
118
337
  });
119
338
  }
120
339
  });
340
+ };
341
+ if (body.$multi) {
342
+ const results = [];
343
+ if (body.$seq) {
344
+ for (let i = body.$multi.length; i--;) {
345
+ results.push(await process(body.$multi[i]));
346
+ }
347
+ const response = [];
348
+ for (let i = results.length; i--;) {
349
+ response.push(results[i].content);
350
+ }
351
+ resolve({
352
+ statusCode: 200,
353
+ content: response,
354
+ });
355
+ }
356
+ else {
357
+ for (let i = body.$multi.length; i--;) {
358
+ results.push(process(body.$multi[i]));
359
+ }
360
+ const results2 = (await Promise.all(results));
361
+ const response = [];
362
+ for (let i = results2.length; i--;) {
363
+ response.push(results2[i].content);
364
+ }
365
+ resolve({
366
+ statusCode: 200,
367
+ content: response,
368
+ });
369
+ }
121
370
  }
122
371
  else {
123
- activelogger_1.ActiveLogger.error("Sent 500 Response (1200)");
124
- return reject({
125
- statusCode: 500,
126
- content: "Invalid Transaction",
127
- });
372
+ process(body).then(resolve).catch(reject);
128
373
  }
129
374
  });
130
375
  }
376
+ static shouldTriggerSpiLookup(errors, selfError) {
377
+ const spiErrorCount = errors?.filter((e) => e.indexOf("Stream Position Incorrect") !== -1)
378
+ .length || 0;
379
+ return ((spiErrorCount > 0 &&
380
+ spiErrorCount >= Math.floor((errors?.length || 0) / 3)) ||
381
+ (selfError !== undefined &&
382
+ selfError.indexOf("Stream Position Incorrect") !== -1));
383
+ }
384
+ static labelOrKey(txIO) {
385
+ const keys = Object.keys(txIO || {});
386
+ const out = [];
387
+ for (let i = keys.length; i--;) {
388
+ const addr = this.filterPrefix(txIO[keys[i]].$stream || keys[i]);
389
+ if (addr.length === 64) {
390
+ out.push(addr);
391
+ }
392
+ }
393
+ return out;
394
+ }
395
+ static filterPrefix(streamId) {
396
+ if (streamId.length > 64) {
397
+ streamId = streamId.slice(-64);
398
+ }
399
+ return streamId;
400
+ }
131
401
  static ExternalEncrypt(host, body, encHeader, db) {
132
402
  return new Promise((resolve, reject) => {
133
403
  if (encHeader) {
@@ -161,27 +431,247 @@ class Endpoints {
161
431
  }
162
432
  });
163
433
  }
164
- static InternalInitalise(host, body) {
434
+ static InternalInitalise(host, body, remoteAddr, retried = false, isP2P = false) {
165
435
  return new Promise((resolve, reject) => {
166
- if (host.getStatus() != neighbourhood_1.NeighbourStatus.Stable) {
167
- activelogger_1.ActiveLogger.error("Sent 500 Response (1500)");
168
- return resolve({
169
- statusCode: 500,
170
- content: "Network Not Stable",
171
- });
172
- }
173
436
  let tx = body;
437
+ if (!retried) {
438
+ tx.$spiRetry = false;
439
+ }
174
440
  host
175
- .pending(tx, true)
176
- .then((ledger) => {
177
- return resolve({
178
- statusCode: ledger.status,
179
- content: ledger.data,
180
- });
441
+ .pending(tx, remoteAddr, true, retried, isP2P)
442
+ .then(async (ledger) => {
443
+ let canRetry = false;
444
+ let resolved = false;
445
+ if (!tx.$unanimous || retried) {
446
+ resolved = true;
447
+ resolve({
448
+ statusCode: ledger.status,
449
+ content: ledger.data,
450
+ });
451
+ }
452
+ const rewrote = activeoptions_1.ActiveCacheManager.fetch("rewrote", 500);
453
+ if (ledger?.data?.$nodes && !rewrote.has(tx.$umid)) {
454
+ if (ledger?.data?.$nodes[home_1.Home.reference] &&
455
+ ledger.data.$nodes[home_1.Home.reference].error) {
456
+ const spiError = ledger.data.$nodes[home_1.Home.reference].error.indexOf("Position Incorrect") !== -1;
457
+ const spi404Error = ledger.data.$nodes[home_1.Home.reference].error.indexOf("Stream(s) not found") !== -1;
458
+ if (spiError || spi404Error) {
459
+ rewrote.set(tx.$umid, 1);
460
+ activelogger_1.ActiveLogger.warn(tx.$umid, "SPI NON Origin - Position Incorrect or 404");
461
+ let check = false;
462
+ let posCount = 0;
463
+ let myPos = false;
464
+ if (spiError) {
465
+ const nodes = Object.keys(ledger.data.$nodes);
466
+ for (let i = nodes.length; i--;) {
467
+ if (ledger.data.$nodes[nodes[i]].commit) {
468
+ check = true;
469
+ break;
470
+ }
471
+ if (ledger.data.$nodes[nodes[i]].error?.indexOf("Stream Position Incorrect") !== -1) {
472
+ posCount++;
473
+ if (nodes[i] === home_1.Home.reference) {
474
+ myPos = true;
475
+ }
476
+ }
477
+ }
478
+ }
479
+ else {
480
+ check = spi404Error;
481
+ }
482
+ if (check || (posCount >= 1 && myPos)) {
483
+ activelogger_1.ActiveLogger.warn(tx.$umid, "SPI NON Origin - Must Check");
484
+ const streams = [
485
+ ...new Set([
486
+ ...this.labelOrKey(ledger.data.$tx.$i),
487
+ ...this.labelOrKey(ledger.data.$tx.$o),
488
+ ]),
489
+ ];
490
+ if (streams.length) {
491
+ for (let i = streams.length; i--;) {
492
+ streams.push(`${streams[i]}:stream`);
493
+ }
494
+ streams.push(`${ledger.data.$tx.$contract.substring(0, 64)}:data`);
495
+ if (streams.length) {
496
+ const tmp = async () => {
497
+ const networkStreams = await host.neighbourhood.knockAll("stream", {
498
+ $streams: streams,
499
+ });
500
+ const consensusReached = Math.ceil((activeoptions_1.ActiveOptions.get("consensus", {}).reached /
501
+ 100) *
502
+ host.neighbourhood.count() -
503
+ 1);
504
+ if (networkStreams.length < consensusReached) {
505
+ activelogger_1.ActiveLogger.warn(`SPI Skipped not enough returned for consensus yet (${networkStreams.length}/${consensusReached})`);
506
+ return;
507
+ }
508
+ const consensus = {};
509
+ for (let i = networkStreams.length; i--;) {
510
+ const nodeStreams = networkStreams[i];
511
+ if (nodeStreams?.length) {
512
+ for (let ii = nodeStreams.length; ii--;) {
513
+ const streamDoc = nodeStreams[ii];
514
+ if (streamDoc && streamDoc._id && streamDoc._rev) {
515
+ if (!consensus[streamDoc._id]) {
516
+ consensus[streamDoc._id] = {};
517
+ }
518
+ if (consensus[streamDoc._id][streamDoc._rev]) {
519
+ consensus[streamDoc._id][streamDoc._rev].votes++;
520
+ }
521
+ else {
522
+ consensus[streamDoc._id][streamDoc._rev] = {
523
+ votes: 1,
524
+ doc: streamDoc,
525
+ };
526
+ }
527
+ }
528
+ }
529
+ }
530
+ }
531
+ const docs = Object.keys(consensus);
532
+ for (let g = docs.length; g--;) {
533
+ const doc = consensus[docs[g]];
534
+ if (rewrote.has(docs[g])) {
535
+ continue;
536
+ }
537
+ let max = 0;
538
+ let winner = "";
539
+ for (let x in doc) {
540
+ if (doc[x].votes >= consensusReached) {
541
+ activelogger_1.ActiveLogger.warn(`SPI ${doc[x].votes} >= ${consensusReached} for ${docs[g]}@${x}`);
542
+ if (doc[x].votes > max) {
543
+ max = doc[x].votes;
544
+ winner = x;
545
+ }
546
+ else if (doc[x].votes === max) {
547
+ const [xPos] = x.split("-");
548
+ const [wPos] = winner.split("-");
549
+ if (+xPos > +wPos) {
550
+ activelogger_1.ActiveLogger.warn(`SPI matching max (${max}) but has higher position`);
551
+ winner = x;
552
+ }
553
+ }
554
+ }
555
+ }
556
+ if (winner && !rewrote.has(docs[g])) {
557
+ const winningDoc = doc[winner].doc;
558
+ rewrote.set(tx.$umid, true);
559
+ rewrote.set(winningDoc._id, winningDoc._rev);
560
+ const dblCheck = await host.dbConnection.get(winningDoc._id);
561
+ if (dblCheck._rev !== winningDoc._rev) {
562
+ activelogger_1.ActiveLogger.error(`SPI REWRITING #2 ${winningDoc._id} @ ${winningDoc._rev} NOT ${dblCheck._rev} : ${tx.$umid} CACHE : ${rewrote.get(winningDoc._id)}`);
563
+ if (!dblCheck._rev) {
564
+ try {
565
+ await host.dbConnection.put(winningDoc);
566
+ activelogger_1.ActiveLogger.warn(`SPI 404 - Create Base for ${winningDoc._id}`);
567
+ }
568
+ catch {
569
+ activelogger_1.ActiveLogger.error(`SPI 404 - Failed to create ${winningDoc._id}`);
570
+ }
571
+ }
572
+ await host.dbConnection.bulkDocs([winningDoc], {
573
+ new_edits: true,
574
+ force_rev: winningDoc._rev,
575
+ });
576
+ canRetry = true;
577
+ }
578
+ }
579
+ else {
580
+ if (!rewrote.has(docs[g])) {
581
+ activelogger_1.ActiveLogger.warn(`SPI NOWINNER #2 - ${docs[g]}`);
582
+ }
583
+ }
584
+ }
585
+ if (rewrote.has(tx.$umid)) {
586
+ activelogger_1.ActiveLogger.warn(tx.$umid, `SPI Adding 950 Checker`);
587
+ await host.dbErrorConnection.post({
588
+ _id: `${tx.$umid}:${Date.now()}`,
589
+ code: 950,
590
+ processed: false,
591
+ umid: tx.$umid,
592
+ transaction: {
593
+ $broadcast: true,
594
+ $tx: {},
595
+ $revs: {},
596
+ },
597
+ reason: 'Vote Failure - "SPI#2 UMID not found',
598
+ });
599
+ }
600
+ if (!ledger.dontRelease) {
601
+ host.release(tx.$umid);
602
+ }
603
+ };
604
+ if (resolved) {
605
+ setTimeout(async () => {
606
+ activelogger_1.ActiveLogger.warn(`SPI WAITING - ${tx.$umid}`);
607
+ tmp();
608
+ }, 500);
609
+ }
610
+ else {
611
+ activelogger_1.ActiveLogger.warn(`SPI NOW - ${tx.$umid}`);
612
+ await tmp();
613
+ if (canRetry && tx.$unanimous) {
614
+ activelogger_1.ActiveLogger.warn(tx.$umid, `SPI RETRY as it was unanimous and written`);
615
+ tx.$spiRetry = true;
616
+ this.InternalInitalise(host, tx, remoteAddr, true)
617
+ .then(resolve)
618
+ .catch(reject);
619
+ }
620
+ else {
621
+ activelogger_1.ActiveLogger.warn(tx.$umid, `SPI Delay resolved`);
622
+ return resolve({
623
+ statusCode: ledger.status,
624
+ content: ledger.data,
625
+ });
626
+ }
627
+ }
628
+ }
629
+ else {
630
+ if (!ledger.dontRelease) {
631
+ host.release(tx.$umid);
632
+ }
633
+ }
634
+ }
635
+ else {
636
+ if (!ledger.dontRelease) {
637
+ host.release(tx.$umid);
638
+ }
639
+ }
640
+ }
641
+ else {
642
+ if (!ledger.dontRelease) {
643
+ host.release(tx.$umid);
644
+ }
645
+ }
646
+ }
647
+ else {
648
+ if (!ledger.dontRelease) {
649
+ host.release(tx.$umid);
650
+ }
651
+ }
652
+ }
653
+ else {
654
+ if (!ledger.dontRelease) {
655
+ host.release(tx.$umid);
656
+ }
657
+ if (!resolved) {
658
+ resolve({
659
+ statusCode: ledger.status,
660
+ content: ledger.data,
661
+ });
662
+ }
663
+ }
664
+ }
665
+ else {
666
+ if (!ledger.dontRelease) {
667
+ host.release(tx.$umid);
668
+ }
669
+ }
181
670
  })
182
671
  .catch((error) => {
183
672
  activelogger_1.ActiveLogger.error(tx, "Transaction error");
184
673
  activelogger_1.ActiveLogger.error(error, "Sent 500 Response (1600)");
674
+ host.release(tx.$umid);
185
675
  return reject({
186
676
  statusCode: 500,
187
677
  content: error,
@@ -191,11 +681,6 @@ class Endpoints {
191
681
  }
192
682
  static DirectInternalInitalise(host, tx) {
193
683
  return new Promise((resolve, reject) => {
194
- if (host.getStatus() != neighbourhood_1.NeighbourStatus.Stable)
195
- return reject({
196
- status: 100,
197
- error: "Network Not Stable",
198
- });
199
684
  if (tx.$territoriality) {
200
685
  if (tx.$broadcast) {
201
686
  return reject({
@@ -205,11 +690,11 @@ class Endpoints {
205
690
  }
206
691
  let sending = host.terriMap(tx.$territoriality);
207
692
  if (sending) {
208
- activelogger_1.ActiveLogger.info("Rebroadcasting to : " + sending);
209
693
  if (sending !== host.reference) {
694
+ activelogger_1.ActiveLogger.info("Rebroadcasting to : " + sending);
210
695
  let rebroadcast = host.neighbourhood.get(sending);
211
696
  rebroadcast
212
- .knock("", tx, true)
697
+ .knock("", tx, true, 0, false)
213
698
  .then((ledger) => {
214
699
  ledger.rebroadcasted = true;
215
700
  resolve(ledger);
@@ -225,9 +710,14 @@ class Endpoints {
225
710
  }
226
711
  }
227
712
  host
228
- .pending(tx)
713
+ .pending(tx, home_1.Home.host)
229
714
  .then((ledger) => resolve(ledger))
230
- .catch((error) => reject(error));
715
+ .catch((error) => {
716
+ activelogger_1.ActiveLogger.fatal(tx, "last tx sent in");
717
+ activelogger_1.ActiveLogger.fatal(error, "error that is bubbling");
718
+ host.release(tx.$umid);
719
+ reject(error);
720
+ });
231
721
  });
232
722
  }
233
723
  static status(host, requester) {
@@ -283,42 +773,54 @@ class Endpoints {
283
773
  static streams(db, body) {
284
774
  return new Promise((resolve, reject) => {
285
775
  if (body.$streams) {
286
- let i = body.$streams.length;
287
- let fetchStream = [];
288
- while (i--) {
776
+ const fetchStream = [];
777
+ for (let i = body.$streams.length; i--;) {
289
778
  if (body.$streams[i].indexOf(":volatile") !== -1) {
290
779
  return reject({
291
780
  statusCode: 403,
292
781
  content: "Request not allowed",
293
782
  });
294
783
  }
295
- fetchStream.push(db.get(body.$streams[i]).catch((error) => {
296
- return { _error: error };
297
- }));
298
- }
299
- Promise.all(fetchStream)
300
- .then((docs) => {
301
- let i = docs.length;
302
- let streams = [];
303
- while (i--) {
304
- if (docs[i]._id) {
305
- streams.push({
306
- _id: docs[i]._id,
307
- _rev: docs[i]._rev,
308
- });
784
+ const holdValue = body.$streams[i].replace(":stream", "");
785
+ if (locker_1.Locker.hold(holdValue, "SPI")) {
786
+ setTimeout(() => {
787
+ locker_1.Locker.release(holdValue, "SPI");
788
+ }, 1000);
789
+ fetchStream.push(db.get(body.$streams[i]));
790
+ }
791
+ else {
792
+ if (locker_1.Locker.is(holdValue, "SPI")) {
793
+ fetchStream.push(db.get(body.$streams[i]));
309
794
  }
310
795
  }
311
- return resolve({
312
- statusCode: 200,
313
- content: streams,
796
+ }
797
+ if (fetchStream.length) {
798
+ Promise.all(fetchStream)
799
+ .then((docs) => {
800
+ const streams = [];
801
+ for (let i = docs.length; i--;) {
802
+ if (docs[i]._id) {
803
+ streams.push(docs[i]);
804
+ }
805
+ }
806
+ return resolve({
807
+ statusCode: 200,
808
+ content: streams,
809
+ });
810
+ })
811
+ .catch(() => {
812
+ return resolve({
813
+ statusCode: 200,
814
+ content: [],
815
+ });
314
816
  });
315
- })
316
- .catch(() => {
817
+ }
818
+ else {
317
819
  return resolve({
318
820
  statusCode: 200,
319
821
  content: [],
320
822
  });
321
- });
823
+ }
322
824
  }
323
825
  else {
324
826
  if (body.$stream && body.$rev) {
@@ -374,7 +876,7 @@ class Endpoints {
374
876
  });
375
877
  })
376
878
  .catch(() => {
377
- reject({});
879
+ reject({ error: 3 });
378
880
  });
379
881
  });
380
882
  }
@@ -388,7 +890,7 @@ class Endpoints {
388
890
  });
389
891
  })
390
892
  .catch(() => {
391
- reject({});
893
+ reject({ error: 2 });
392
894
  });
393
895
  });
394
896
  }
@@ -399,13 +901,14 @@ class Endpoints {
399
901
  return !(row.id.indexOf(":volatile") !== -1);
400
902
  }
401
903
  static postConvertor(host, body, encryptHeader) {
402
- return new Promise((resolve, reject) => {
904
+ return new Promise(async (resolve, reject) => {
905
+ let data;
403
906
  if (encryptHeader) {
404
907
  activelogger_1.ActiveLogger.info("Encrypted Transaction Inbound");
405
908
  try {
406
- resolve(JSON.parse(Buffer.from(host.decrypt(body), "base64").toString()));
909
+ data = Buffer.from(host.decrypt(body), "base64");
407
910
  }
408
- catch (_a) {
911
+ catch {
409
912
  activelogger_1.ActiveLogger.error("Sent 500 Response (1700)");
410
913
  return reject({
411
914
  statusCode: 500,
@@ -414,20 +917,23 @@ class Endpoints {
414
917
  }
415
918
  }
416
919
  else {
417
- const bodyObject = this.makeSureNotBuffer(JSON.parse(body));
418
- if (bodyObject.$neighbour && bodyObject.$packet) {
419
- activelogger_1.ActiveLogger.debug("Converting Signed for Post");
420
- if (bodyObject.$neighbour.reference != host.reference) {
421
- if (bodyObject.$enc ||
920
+ data = typeof body === "string" ? Buffer.from(body) : body;
921
+ }
922
+ try {
923
+ const bodyObject = await activeutilities_1.ActiveClone.deserialize(data);
924
+ if (bodyObject && bodyObject.$neighbour && bodyObject.$packet) {
925
+ const bodyObj = bodyObject;
926
+ if (bodyObj.$neighbour.reference != host.reference) {
927
+ if (bodyObj.$enc ||
422
928
  activeoptions_1.ActiveOptions.get("security", {}).encryptedConsensus) {
423
- bodyObject.$packet = JSON.parse(Buffer.from(host.decrypt(bodyObject.$packet), "base64").toString());
929
+ bodyObj.$packet = await activeutilities_1.ActiveClone.deserialize(Buffer.from(host.decrypt(bodyObj.$packet), "base64"));
424
930
  }
425
931
  }
426
- if (bodyObject.$neighbour.signature ||
932
+ if (bodyObj.$neighbour.signature ||
427
933
  activeoptions_1.ActiveOptions.get("security", {}).signedConsensus) {
428
934
  if (!host.neighbourhood
429
- .get(bodyObject.$neighbour.reference)
430
- .verifySignature(bodyObject.$neighbour.signature, bodyObject.$packet)) {
935
+ .get(bodyObj.$neighbour.reference)
936
+ .verifySignature(bodyObj.$neighbour.signature, bodyObj.$packet)) {
431
937
  activelogger_1.ActiveLogger.error("Sent 500 Response (1800)");
432
938
  return reject({
433
939
  statusCode: 500,
@@ -436,26 +942,33 @@ class Endpoints {
436
942
  }
437
943
  }
438
944
  return resolve({
439
- from: bodyObject.$neighbour.reference,
440
- body: bodyObject.$packet,
945
+ from: bodyObj.$neighbour.reference,
946
+ body: bodyObj.$packet,
441
947
  });
442
948
  }
443
949
  else {
444
950
  resolve({ body: bodyObject });
445
951
  }
446
952
  }
953
+ catch (e) {
954
+ activelogger_1.ActiveLogger.error(e, "Deserialization Error");
955
+ return reject({
956
+ statusCode: 500,
957
+ content: "Deserialization Error",
958
+ });
959
+ }
447
960
  });
448
961
  }
449
- static makeSureNotBuffer(obj) {
450
- var _a;
451
- if (obj.type === "Buffer" && ((_a = obj.data) === null || _a === void 0 ? void 0 : _a.length)) {
452
- const tmp = JSON.parse(Buffer.from(obj.data).toString());
453
- activelogger_1.ActiveLogger.error(tmp, "Buffer Found");
454
- return tmp;
962
+ static async makeSureNotBuffer(obj) {
963
+ if (obj.type === "Buffer" && obj.data?.length) {
964
+ if (obj.data[0] == 0x1f && obj.data[1] == 0x8b) {
965
+ return JSON.parse((await activeoptions_1.ActiveGZip.ungzip(Buffer.from(obj.data))).toString());
966
+ }
967
+ return JSON.parse(Buffer.from(obj.data).toString());
455
968
  }
456
969
  return obj;
457
970
  }
458
- static successfulFailure(error) {
971
+ static successfulFailure(error, counter = 0) {
459
972
  return {
460
973
  statusCode: 200,
461
974
  content: {
@@ -465,6 +978,7 @@ class Endpoints {
465
978
  vote: 0,
466
979
  commit: 0,
467
980
  errors: [error],
981
+ counter,
468
982
  },
469
983
  $streams: {
470
984
  new: [],
@@ -475,5 +989,4 @@ class Endpoints {
475
989
  }
476
990
  }
477
991
  exports.Endpoints = Endpoints;
478
- Endpoints.rebaseThrottle = 0;
479
992
  //# sourceMappingURL=endpoints.js.map