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