@activeledger/activeprotocol 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 (49) hide show
  1. package/es/protocol/interfaces/vm.interface.d.ts +9 -5
  2. package/es/protocol/interfaces/vm.interface.d.ts.map +1 -1
  3. package/es/protocol/permissionsChecker.d.ts +5 -3
  4. package/es/protocol/permissionsChecker.d.ts.map +1 -1
  5. package/es/protocol/permissionsChecker.js +149 -120
  6. package/es/protocol/permissionsChecker.js.map +1 -1
  7. package/es/protocol/process.d.ts +10 -9
  8. package/es/protocol/process.d.ts.map +1 -1
  9. package/es/protocol/process.js +281 -214
  10. package/es/protocol/process.js.map +1 -1
  11. package/es/protocol/shared.d.ts +6 -2
  12. package/es/protocol/shared.d.ts.map +1 -1
  13. package/es/protocol/shared.js +41 -29
  14. package/es/protocol/shared.js.map +1 -1
  15. package/es/protocol/streamUpdater.d.ts +1 -6
  16. package/es/protocol/streamUpdater.d.ts.map +1 -1
  17. package/es/protocol/streamUpdater.js +80 -109
  18. package/es/protocol/streamUpdater.js.map +1 -1
  19. package/es/protocol/vm.d.ts +12 -5
  20. package/es/protocol/vm.d.ts.map +1 -1
  21. package/es/protocol/vm.js +212 -138
  22. package/es/protocol/vm.js.map +1 -1
  23. package/es/protocol/vmscript.js +23 -10
  24. package/es/protocol/vmscript.js.map +1 -1
  25. package/lib/protocol/interfaces/vm.interface.d.ts +9 -5
  26. package/lib/protocol/interfaces/vm.interface.d.ts.map +1 -1
  27. package/lib/protocol/permissionsChecker.d.ts +5 -3
  28. package/lib/protocol/permissionsChecker.d.ts.map +1 -1
  29. package/lib/protocol/permissionsChecker.js +149 -120
  30. package/lib/protocol/permissionsChecker.js.map +1 -1
  31. package/lib/protocol/process.d.ts +10 -9
  32. package/lib/protocol/process.d.ts.map +1 -1
  33. package/lib/protocol/process.js +281 -240
  34. package/lib/protocol/process.js.map +1 -1
  35. package/lib/protocol/shared.d.ts +6 -2
  36. package/lib/protocol/shared.d.ts.map +1 -1
  37. package/lib/protocol/shared.js +41 -29
  38. package/lib/protocol/shared.js.map +1 -1
  39. package/lib/protocol/streamUpdater.d.ts +1 -6
  40. package/lib/protocol/streamUpdater.d.ts.map +1 -1
  41. package/lib/protocol/streamUpdater.js +80 -109
  42. package/lib/protocol/streamUpdater.js.map +1 -1
  43. package/lib/protocol/vm.d.ts +12 -5
  44. package/lib/protocol/vm.d.ts.map +1 -1
  45. package/lib/protocol/vm.js +211 -137
  46. package/lib/protocol/vm.js.map +1 -1
  47. package/lib/protocol/vmscript.js +23 -9
  48. package/lib/protocol/vmscript.js.map +1 -1
  49. package/package.json +9 -9
@@ -1,4 +1,4 @@
1
- import * as fs from "fs";
1
+ import { promises as fs } from "fs";
2
2
  import { EventEmitter } from "events";
3
3
  import { VirtualMachine } from "./vm";
4
4
  import { ActiveOptions } from "@activeledger/activeoptions";
@@ -6,9 +6,41 @@ import { ActiveLogger } from "@activeledger/activelogger";
6
6
  import { Shared } from "./shared";
7
7
  import { StreamUpdater } from "./streamUpdater";
8
8
  import { PermissionsChecker } from "./permissionsChecker";
9
- import path from "path";
10
- const BROADCAST_TIMEOUT = 20 * 1000;
9
+ const BROADCAST_TIMEOUT_EARLY = 60 * 1000;
10
+ const BROADCAST_TIMEOUT_VOTE = 60 * 1000;
11
+ const BROADCAST_TIMEOUT_COMMIT = 60 * 1000;
11
12
  export class Process extends EventEmitter {
13
+ entry;
14
+ selfHost;
15
+ reference;
16
+ right;
17
+ db;
18
+ dbe;
19
+ dbev;
20
+ secured;
21
+ static networkNodeLength = 0;
22
+ static generalContractVM;
23
+ isDefault = false;
24
+ inputs;
25
+ outputs;
26
+ nodeResponse;
27
+ contractLocation;
28
+ contractId;
29
+ commiting = false;
30
+ voting = true;
31
+ storeSingleError = false;
32
+ errorOut = {
33
+ code: 0,
34
+ reason: "",
35
+ priority: 0,
36
+ };
37
+ broadcastTimeout;
38
+ currentTrueVotes;
39
+ securityCache;
40
+ shared;
41
+ permissionChecker;
42
+ willEmit;
43
+ willEmitData;
12
44
  constructor(entry, selfHost, reference, right, db, dbe, dbev, secured) {
13
45
  super();
14
46
  this.entry = entry;
@@ -19,18 +51,9 @@ export class Process extends EventEmitter {
19
51
  this.dbe = dbe;
20
52
  this.dbev = dbev;
21
53
  this.secured = secured;
22
- this.isDefault = false;
23
- this.checkRevs = true;
24
- this.commiting = false;
25
- this.voting = true;
26
- this.storeSingleError = false;
27
- this.errorOut = {
28
- code: 0,
29
- reason: "",
30
- priority: 0,
31
- };
32
54
  this.shared = new Shared(this.storeSingleError, this.entry, this.dbe, this);
33
55
  this.nodeResponse = entry.$nodes[reference];
56
+ Process.networkNodeLength = ActiveOptions.get("neighbourhood", []).length;
34
57
  try {
35
58
  if (!Process.generalContractVM) {
36
59
  Process.generalContractVM = new VirtualMachine(this.selfHost, this.secured, this.db, this.dbev);
@@ -40,23 +63,21 @@ export class Process extends EventEmitter {
40
63
  catch (error) {
41
64
  throw new Error(error);
42
65
  }
43
- if (!this.securityCache) {
44
- this.securityCache = ActiveOptions.get("security", null);
45
- }
46
- this.permissionChecker = new PermissionsChecker(this.entry, this.db, this.checkRevs, this.securityCache, this.shared);
66
+ this.securityCache = ActiveOptions.get("security", null);
67
+ this.permissionChecker = new PermissionsChecker(this.entry, this.db, this.securityCache, this.shared);
47
68
  }
48
69
  destroy(umid) {
49
- clearTimeout(this.broadcastTimeout);
50
- if (this.isDefault) {
51
- if (Process.defaultContractsVM)
52
- Process.defaultContractsVM.destroy(umid);
70
+ if (this.entry.$broadcast) {
71
+ clearTimeout(this.broadcastTimeout);
72
+ Process.generalContractVM.destroy(umid);
73
+ delete this.entry;
53
74
  }
54
75
  else {
55
- this.contractRef
56
- ? Process.singleContractVMHolder[this.contractRef].destroy(umid)
57
- : Process.generalContractVM.destroy(umid);
76
+ setTimeout(() => {
77
+ Process.generalContractVM.destroy(umid);
78
+ delete this.entry;
79
+ }, 60000);
58
80
  }
59
- delete this.entry;
60
81
  }
61
82
  sortVersions(a, b) {
62
83
  const padSorting = (v) => {
@@ -69,80 +90,98 @@ export class Process extends EventEmitter {
69
90
  };
70
91
  return padSorting(a).localeCompare(padSorting(b));
71
92
  }
72
- async start(contractVersion) {
73
- ActiveLogger.debug("New TX : " + this.entry.$umid);
74
- const setupDefaultLocation = () => {
93
+ static contractPathCache = {};
94
+ static clearContractPathCache(contractId) {
95
+ if (contractId) {
96
+ for (const key of Object.keys(Process.contractPathCache)) {
97
+ if (key === contractId || Process.contractPathCache[key].includes(contractId)) {
98
+ delete Process.contractPathCache[key];
99
+ }
100
+ }
101
+ }
102
+ else {
103
+ Process.contractPathCache = {};
104
+ }
105
+ }
106
+ async start(contractVersion, contractData) {
107
+ ActiveLogger.debug(`New TX : ${this.entry.$umid}`);
108
+ const setupDefaultLocation = async () => {
75
109
  this.isDefault = true;
76
- this.contractLocation = fs.realpathSync(`${process.cwd()}/default_contracts/${this.entry.$tx.$contract}.js`);
110
+ if (await fs.stat(`${process.cwd()}/default_contracts/_LOCK.${this.entry.$tx.$contract}`).catch(() => false)) {
111
+ throw new Error("Contract Global Lock");
112
+ }
113
+ this.contractLocation = await fs.realpath(`${process.cwd()}/default_contracts/${this.entry.$tx.$contract}.js`);
77
114
  };
78
- const setupLocation = () => {
79
- var _a;
115
+ const setupLocation = async () => {
80
116
  let contract = this.entry.$tx.$contract;
117
+ this.contractId = contract.split("@")[0];
81
118
  try {
82
- let contractId;
83
- let namespacePath;
84
- try {
85
- namespacePath = fs.realpathSync(`${process.cwd()}/contracts/${this.entry.$tx.$namespace}/`);
86
- const trueContractPath = fs.realpathSync(`${namespacePath}/${contract}.js`);
87
- contractId = path.basename(trueContractPath, path.extname(trueContractPath));
88
- if (contractId.indexOf("@") > -1) {
89
- contractId = contractId.split("@")[0];
119
+ if (!Process.contractPathCache[this.entry.$tx.$contract] ||
120
+ (contractVersion && !Process.contractPathCache[this.entry.$tx.$contract].endsWith(`${contractVersion}.js`))) {
121
+ let namespacePath = "";
122
+ try {
123
+ namespacePath = await fs.realpath(`${process.cwd()}/contracts/${this.entry.$tx.$namespace}/`);
124
+ }
125
+ catch {
126
+ throw new Error("Namespace not found");
90
127
  }
91
- }
92
- catch (_b) {
93
- throw new Error("Contract or Namespace not found");
94
- }
95
- this.contractId = contractId;
96
- if (this.entry.$tx.$contract.indexOf("@") === -1) {
97
128
  if (contractVersion) {
98
129
  contract = contractVersion;
99
130
  }
100
131
  else {
101
- try {
102
- contract =
103
- ((_a = fs
104
- .readdirSync(namespacePath)
105
- .filter((fn) => fn.includes(`${this.contractId}@`))
106
- .sort(this.sortVersions)
107
- .pop()) === null || _a === void 0 ? void 0 : _a.replace(".js", "")) || this.contractId;
108
- this.emit("contractLatestVersion", {
109
- contract: this.entry.$tx.$contract,
110
- file: contract,
111
- });
132
+ if (this.entry.$tx.$contract.indexOf("@=") !== -1) {
133
+ contract = this.entry.$tx.$contract.replace("@=", "@");
112
134
  }
113
- catch (_c) {
114
- throw new Error(`${this.contractId}@latest not found`);
135
+ else {
136
+ try {
137
+ contract = ((await fs
138
+ .readdir(namespacePath))
139
+ .filter((fn) => fn.includes(this.entry.$tx.$contract))
140
+ .sort(this.sortVersions)
141
+ .pop() || "notfound.404").replace(".js", "");
142
+ }
143
+ catch {
144
+ throw new Error("Contract not found");
145
+ }
115
146
  }
116
147
  }
148
+ if (!(await fs.stat(`${namespacePath}/${contract}.js`).catch(() => false))) {
149
+ throw new Error("Contract not found");
150
+ }
151
+ if (!contractVersion) {
152
+ this.emit("contractLatestVersion", {
153
+ contract: this.entry.$tx.$contract,
154
+ file: contract,
155
+ refresh: false,
156
+ });
157
+ }
158
+ if (await fs.stat(`${namespacePath}/_LOCK.${this.contractId}`).catch(() => false)) {
159
+ throw new Error("Contract Global Lock");
160
+ }
161
+ if (await fs.stat(`${namespacePath}/_LOCK.${contract}`).catch(() => false)) {
162
+ throw new Error(`Contract Version Lock ${contract.substring(contract.indexOf("@") + 1)}`);
163
+ }
164
+ Process.contractPathCache[this.entry.$tx.$contract] = await fs.realpath(`${namespacePath}/${contract}.js`);
117
165
  }
118
- if (fs.existsSync(`${namespacePath}/_LOCK.${this.contractId}`)) {
119
- throw new Error("Contract Global Lock");
120
- }
121
- if (fs.existsSync(`${namespacePath}/_LOCK.${contract}`)) {
122
- throw new Error(`Contract Version Lock ${contract.substring(contract.indexOf("@") + 1)}`);
123
- }
124
- this.contractLocation = fs.realpathSync(`${namespacePath}/${contract}.js`);
166
+ this.contractLocation =
167
+ Process.contractPathCache[this.entry.$tx.$contract];
125
168
  }
126
169
  catch (e) {
127
170
  throw e;
128
171
  }
129
172
  };
130
173
  try {
131
- this.entry.$tx.$namespace === "default"
174
+ await (this.entry.$tx.$namespace === "default"
132
175
  ? setupDefaultLocation()
133
- : setupLocation();
176
+ : setupLocation());
134
177
  }
135
178
  catch (error) {
136
- this.entry.$nodes[this.reference].error = `Init Contract Error - ${error.message}`;
179
+ this.entry.$nodes[this.reference].error = `Init Contract Error - ${error.message || error}`;
137
180
  this.emit("commited", { instant: true });
138
181
  return;
139
182
  }
140
- const virtualMachine = this.isDefault
141
- ? Process.defaultContractsVM
142
- : this.contractRef
143
- ? Process.singleContractVMHolder[this.contractRef]
144
- : Process.generalContractVM;
145
- if (fs.existsSync(this.contractLocation)) {
183
+ const virtualMachine = Process.generalContractVM;
184
+ if (await fs.stat(this.contractLocation).catch(() => false)) {
146
185
  this.inputs = Object.keys(this.entry.$tx.$i || {});
147
186
  if (this.inputs.length) {
148
187
  this.labelOrKey();
@@ -152,7 +191,6 @@ export class Process extends EventEmitter {
152
191
  this.labelOrKey(true);
153
192
  }
154
193
  if (!this.entry.$revs) {
155
- this.checkRevs = false;
156
194
  this.entry.$revs = {
157
195
  $i: {},
158
196
  $o: {},
@@ -162,28 +200,24 @@ export class Process extends EventEmitter {
162
200
  try {
163
201
  const inputStreams = await this.permissionChecker.process(this.inputs);
164
202
  const outputStreams = await this.permissionChecker.process(this.outputs, false);
165
- let contractData = undefined;
166
- if (!this.isDefault) {
167
- try {
168
- const contractDataStreams = await this.permissionChecker.process([`${this.contractId}:data`], false);
169
- if (contractDataStreams.length > 0) {
170
- contractData = contractDataStreams[0]
171
- .state;
172
- }
173
- }
174
- catch (e) {
175
- if (e.code === 1200) {
176
- throw e;
177
- }
178
- }
179
- }
180
- this.process(inputStreams, outputStreams, contractData);
203
+ this.process(inputStreams, outputStreams, await this.getContractDate(contractData));
181
204
  }
182
205
  catch (error) {
183
- this.postVote(virtualMachine, {
184
- code: error.code,
185
- reason: error.reason || error.message,
186
- });
206
+ const reason = error.reason || error.message || error;
207
+ if (this.entry.$unanimous &&
208
+ !this.entry.$broadcast &&
209
+ !this.entry.$spiRetry &&
210
+ (reason.indexOf("Position Incorrect") !== -1 ||
211
+ reason === "Stream(s) not found")) {
212
+ this.entry.$nodes[this.reference].error = reason;
213
+ this.emitFailed({ status: error.code || 1200, error: reason, entry: this.entry }, true);
214
+ }
215
+ else {
216
+ this.postVote(virtualMachine, {
217
+ code: error.code,
218
+ reason,
219
+ });
220
+ }
187
221
  }
188
222
  }
189
223
  else {
@@ -211,15 +245,29 @@ export class Process extends EventEmitter {
211
245
  }
212
246
  }
213
247
  }
248
+ else {
249
+ return this.shared.raiseLedgerError(1260, new Error("Self signed - Must have inputs"));
250
+ }
214
251
  try {
215
252
  const outputStreams = await this.permissionChecker.process(this.outputs, false);
216
- this.process([], outputStreams, undefined);
253
+ this.process([], outputStreams, await this.getContractDate(contractData));
217
254
  }
218
255
  catch (error) {
219
- this.postVote(virtualMachine, {
220
- code: error.code,
221
- reason: error.reason || error.message,
222
- });
256
+ const reason = error.reason || error.message || error;
257
+ if (this.entry.$unanimous &&
258
+ !this.entry.$broadcast &&
259
+ !this.entry.$spiRetry &&
260
+ (reason === "Stream(s) not found" ||
261
+ reason.indexOf("Position Incorrect") !== -1)) {
262
+ this.entry.$nodes[this.reference].error = reason;
263
+ this.emitFailed({ status: error.code || 1200, error: reason, entry: this.entry }, true);
264
+ }
265
+ else {
266
+ this.postVote(virtualMachine, {
267
+ code: error.code,
268
+ reason,
269
+ });
270
+ }
223
271
  }
224
272
  }
225
273
  }
@@ -234,10 +282,13 @@ export class Process extends EventEmitter {
234
282
  if (this.isCommiting()) {
235
283
  return;
236
284
  }
285
+ if (node[this.reference]) {
286
+ delete node[this.reference];
287
+ }
237
288
  this.entry.$nodes = Object.assign(this.entry.$nodes, node);
238
289
  if (this.willEmit) {
239
290
  const nodes = Object.keys(this.entry.$nodes);
240
- if (!this.hasOutstandingVotes(nodes.length) && !this.canCommit()) {
291
+ if (!(this.hasOutstandingVotes()) && !this.canCommit()) {
241
292
  this.emitFailed(this.willEmitData);
242
293
  }
243
294
  else {
@@ -251,42 +302,62 @@ export class Process extends EventEmitter {
251
302
  }
252
303
  else {
253
304
  if (!this.isCommiting() && !this.voting) {
254
- this.nodeResponse = this.entry.$nodes[this.reference];
255
- this.isDefault
256
- ? this.commit(Process.defaultContractsVM)
257
- : this.contractRef
258
- ? this.commit(Process.singleContractVMHolder[this.contractRef])
259
- : this.commit(Process.generalContractVM);
305
+ this.commit(Process.generalContractVM);
260
306
  }
261
307
  }
262
308
  }
263
309
  isCommiting() {
264
310
  return this.commiting;
265
311
  }
266
- processDefaultContracts(payload, contractName) {
267
- if (!Process.defaultContractsVM) {
268
- try {
269
- Process.defaultContractsVM = new VirtualMachine(this.selfHost, this.secured, this.db, this.dbev);
270
- Process.defaultContractsVM.initialiseVirtualMachine(["fs", "path", "os", "crypto"], ["typescript"]);
312
+ async getContractDate(contractData) {
313
+ if (!contractData && !this.isDefault) {
314
+ if (await this.db.exists(`${this.contractId}:data`)) {
315
+ try {
316
+ const contractDataStreams = await this.permissionChecker.process([`${this.contractId}:data`], false, 5);
317
+ if (contractDataStreams.length > 0) {
318
+ contractData = contractDataStreams[0]
319
+ .state;
320
+ }
321
+ }
322
+ catch (e) {
323
+ if (e.code === 1200) {
324
+ this.emit("contractData", {
325
+ contract: this.contractId,
326
+ data: {},
327
+ });
328
+ throw e;
329
+ }
330
+ }
271
331
  }
272
- catch (error) {
273
- throw new Error(error);
332
+ else {
333
+ contractData = { _id: "", data: {} };
274
334
  }
335
+ this.emit("contractData", {
336
+ contract: this.contractId,
337
+ data: contractData,
338
+ });
275
339
  }
276
- this.handleVM(Process.defaultContractsVM, payload, contractName);
277
- }
278
- processUnsafeContracts(payload, namespace, contractName, extraBuiltins, extraExternals, extraMocks) {
279
- this.contractRef = namespace;
280
- if (!Process.singleContractVMHolder[this.contractRef]) {
281
- try {
282
- Process.singleContractVMHolder[this.contractRef] = new VirtualMachine(this.selfHost, this.secured, this.db, this.dbev);
283
- Process.singleContractVMHolder[this.contractRef].initialiseVirtualMachine(extraBuiltins, extraExternals, extraMocks);
284
- }
285
- catch (error) {
286
- throw new Error(error);
340
+ else {
341
+ if (contractData && this.contractId) {
342
+ const rev = `0-context:${contractData._rev}`;
343
+ if (this.entry.$revs.$o[`${this.contractId}:data`]) {
344
+ if (this.entry.$revs.$o[`${this.contractId}:data`] !== rev) {
345
+ this.emit("contractData", {
346
+ contract: this.contractId,
347
+ data: {},
348
+ });
349
+ throw {
350
+ code: 1200,
351
+ reason: "Output Stream Position Incorrect",
352
+ };
353
+ }
354
+ }
355
+ else {
356
+ this.entry.$revs.$o[`${this.contractId}:data`] = rev;
357
+ }
287
358
  }
288
359
  }
289
- this.handleVM(Process.singleContractVMHolder[this.contractRef], payload, contractName);
360
+ return contractData;
290
361
  }
291
362
  async handleVM(virtualMachine, payload, contractName) {
292
363
  const handleVoteError = async (error) => {
@@ -294,7 +365,7 @@ export class Process extends EventEmitter {
294
365
  ActiveLogger.debug(this.nodeResponse.error, `Handle Vote Error ${payload.umid}`);
295
366
  ActiveLogger.debug(`Calling Contract Return Data - ${payload.umid}`);
296
367
  this.nodeResponse.return = virtualMachine.getReturnContractData(this.entry.$umid);
297
- this.postVote(virtualMachine);
368
+ this.postVote(virtualMachine, this.nodeResponse.error);
298
369
  };
299
370
  let continueProcessing = true;
300
371
  try {
@@ -319,7 +390,12 @@ export class Process extends EventEmitter {
319
390
  try {
320
391
  if (continueProcessing)
321
392
  ActiveLogger.debug(`Calling Contract Vote - ${payload.umid}`);
322
- await virtualMachine.vote(this.entry.$nodes, payload.umid);
393
+ const vote = await virtualMachine.vote(this.entry.$nodes, payload.umid);
394
+ if (typeof vote !== "boolean" && vote.leader) {
395
+ this.nodeResponse.vote = this.nodeResponse.leader = true;
396
+ this.commit(virtualMachine);
397
+ return;
398
+ }
323
399
  }
324
400
  catch (error) {
325
401
  handleVoteError(error);
@@ -327,6 +403,7 @@ export class Process extends EventEmitter {
327
403
  }
328
404
  if (continueProcessing) {
329
405
  this.nodeResponse.vote = true;
406
+ this.nodeResponse.early = false;
330
407
  ActiveLogger.debug(`Calling Contract INC - ${payload.umid}`);
331
408
  this.nodeResponse.incomms = virtualMachine.getInternodeCommsFromVM(payload.umid);
332
409
  ActiveLogger.debug(`Calling Contract Return Data - ${payload.umid}`);
@@ -342,6 +419,7 @@ export class Process extends EventEmitter {
342
419
  }
343
420
  catch (error) {
344
421
  this.nodeResponse.error = "Read Error - " + JSON.stringify(error);
422
+ this.nodeResponse.early = false;
345
423
  }
346
424
  this.nodeResponse.commit = true;
347
425
  this.emit("commited");
@@ -349,8 +427,10 @@ export class Process extends EventEmitter {
349
427
  }
350
428
  async process(inputs, outputs = [], contractData = undefined) {
351
429
  try {
352
- if (this.entry.$broadcast) {
353
- this.emit("broadcast", true);
430
+ if (this.entry.$broadcast && !this.entry.$wait) {
431
+ if (this.entry.$origin === this.reference) {
432
+ this.emit("broadcast", true);
433
+ }
354
434
  }
355
435
  const readonly = await this.getReadOnlyStreams();
356
436
  const contractName = this.contractLocation.substring(this.contractLocation.lastIndexOf("/") + 1);
@@ -374,46 +454,10 @@ export class Process extends EventEmitter {
374
454
  inputs,
375
455
  outputs,
376
456
  readonly,
377
- key: Math.floor(Math.random() * 100),
378
- contractData,
457
+ key: 0,
458
+ contractData: contractData ? contractData : { _id: "", data: {} },
379
459
  };
380
- if (!this.securityCache) {
381
- this.securityCache = ActiveOptions.get("security", null);
382
- }
383
- if (payload.transaction.$namespace === "default") {
384
- this.processDefaultContracts(payload, contractName);
385
- }
386
- else {
387
- if (this.securityCache &&
388
- this.securityCache.namespace &&
389
- this.securityCache.namespace[payload.transaction.$namespace]) {
390
- const builtin = [];
391
- const external = [];
392
- const mocks = [];
393
- const namespaceExtras = this.securityCache.namespace[payload.transaction.$namespace];
394
- if (namespaceExtras) {
395
- if (namespaceExtras.std) {
396
- namespaceExtras.std.forEach((item) => {
397
- builtin.push(item);
398
- });
399
- }
400
- if (namespaceExtras.external) {
401
- namespaceExtras.external.forEach((item) => {
402
- external.push(item);
403
- });
404
- }
405
- if (namespaceExtras.mock) {
406
- namespaceExtras.mock.forEach((item) => {
407
- mocks.push(item);
408
- });
409
- }
410
- }
411
- this.processUnsafeContracts(payload, payload.transaction.$namespace, contractName, builtin, external, mocks);
412
- }
413
- else {
414
- this.handleVM(Process.generalContractVM, payload, contractName);
415
- }
416
- }
460
+ this.handleVM(Process.generalContractVM, payload, contractName);
417
461
  }
418
462
  catch (error) {
419
463
  this.shared.raiseLedgerError(1210, new Error("Read Only Stream Error"));
@@ -422,6 +466,8 @@ export class Process extends EventEmitter {
422
466
  }
423
467
  postVote(virtualMachine, error = false) {
424
468
  this.voting = false;
469
+ this.nodeResponse.early = false;
470
+ delete this.nodeResponse.early;
425
471
  if (!this.entry) {
426
472
  ActiveLogger.debug(`postVote entry is missing?`);
427
473
  return;
@@ -432,25 +478,32 @@ export class Process extends EventEmitter {
432
478
  }
433
479
  if (this.entry.$broadcast) {
434
480
  if (error) {
435
- this.entry.$nodes[this.reference].error = error.reason;
481
+ this.entry.$nodes[this.reference].error = error.reason
482
+ ? error.reason
483
+ : error;
484
+ if (error.code === 950) {
485
+ this.shared.raiseLedgerError(error.code, error.reason);
486
+ }
436
487
  }
437
- this.emit("broadcast");
438
- if (this.canCommit()) {
439
- this.commit(virtualMachine);
488
+ if (!this.nodeResponse.leader) {
489
+ this.emit("broadcast");
440
490
  }
491
+ this.commit(virtualMachine);
441
492
  }
442
493
  else {
443
494
  if (this.right.reference != this.entry.$origin) {
444
- ActiveLogger.debug("Attempting commit with too early commit callback (to send right");
495
+ ActiveLogger.debug("Attempting commit with too early commit callback (to send right)");
445
496
  this.commit(virtualMachine, async () => {
446
497
  try {
447
498
  const response = await this.initRightKnock();
448
499
  if (!this.nodeResponse.commit) {
449
- this.entry.$territoriality = response.data.$territoriality;
450
- this.entry.$nodes = response.data.$nodes;
500
+ const data = response.data;
501
+ this.entry.$territoriality =
502
+ data.$territoriality ?? this.entry.$territoriality;
503
+ this.entry.$nodes = data.$nodes ?? this.entry.$nodes;
451
504
  this.nodeResponse = this.entry.$nodes[this.reference];
452
505
  if (error) {
453
- this.shared.raiseLedgerError(error.code, error.reason, true, 10);
506
+ this.shared.raiseLedgerError(error.code || 1000, error.reason || error, true, 10);
454
507
  }
455
508
  ActiveLogger.debug("Sending Commit without callback");
456
509
  this.commit(virtualMachine);
@@ -467,15 +520,16 @@ export class Process extends EventEmitter {
467
520
  else {
468
521
  ActiveLogger.debug("Origin is next (Sending Back)");
469
522
  error
470
- ? this.shared.raiseLedgerError(error.code, error.reason)
523
+ ? this.shared.raiseLedgerError(error.code || 1000, error.reason || error)
471
524
  : this.commit(virtualMachine);
472
525
  }
473
526
  }
474
527
  }
475
- emitFailed(data) {
476
- if (this.willEmit) {
528
+ emitFailed(data, noWait) {
529
+ this.commiting = false;
530
+ if (this.willEmit || noWait) {
477
531
  clearTimeout(this.willEmit);
478
- this.emit("failed", this.willEmitData);
532
+ this.emit("failed", this.willEmitData || data);
479
533
  }
480
534
  else {
481
535
  if (this.entry &&
@@ -491,14 +545,23 @@ export class Process extends EventEmitter {
491
545
  }
492
546
  }
493
547
  }
494
- hasOutstandingVotes(nodes) {
495
- const neighbours = ActiveOptions.get("neighbourhood", []).length;
496
- return !!(neighbours - (nodes || Object.keys(this.entry.$nodes).length));
548
+ hasOutstandingVotes() {
549
+ return !!(Process.networkNodeLength - this.countOutstandingVotes());
550
+ }
551
+ countOutstandingVotes() {
552
+ const nodes = Object.keys(this.entry.$nodes);
553
+ let votedNodes = 0;
554
+ for (let i = nodes.length; i--;) {
555
+ if (!this.entry.$nodes[nodes[i]].early) {
556
+ votedNodes++;
557
+ }
558
+ }
559
+ return votedNodes;
497
560
  }
498
561
  async initRightKnock(retries = 0) {
499
562
  try {
500
563
  ActiveLogger.debug(`Sending -> ${this.right.reference} - ${this.entry.$umid}`);
501
- return await this.right.knock("init", this.entry);
564
+ return await this.right.knock("init-legacy", this.entry);
502
565
  }
503
566
  catch (e) {
504
567
  if (retries <= 2) {
@@ -516,22 +579,27 @@ export class Process extends EventEmitter {
516
579
  }
517
580
  canCommit() {
518
581
  let networkNodes = Object.keys(this.entry.$nodes);
519
- this.currentVotes = 0;
520
- for (let i = networkNodes.length; i--;) {
521
- if (this.entry.$nodes[networkNodes[i]].vote)
522
- this.currentVotes++;
523
- }
524
- const percent = this.entry.$unanimous
525
- ? 100
526
- : ActiveOptions.get("consensus", {}).reached;
527
- return ((this.currentVotes /
528
- ActiveOptions.get("neighbourhood", []).length) *
529
- 100 >=
530
- percent || false);
582
+ this.currentTrueVotes = 0;
583
+ if (networkNodes) {
584
+ for (let i = networkNodes.length; i--;) {
585
+ if (!this.entry.$nodes[networkNodes[i]].early &&
586
+ this.entry.$nodes[networkNodes[i]].vote)
587
+ this.currentTrueVotes++;
588
+ }
589
+ const percent = this.entry.$unanimous
590
+ ? 100
591
+ : ActiveOptions.get("consensus", {}).reached;
592
+ const reached = (this.currentTrueVotes / Process.networkNodeLength) * 100 >= percent;
593
+ return reached;
594
+ }
595
+ else {
596
+ return false;
597
+ }
531
598
  }
532
599
  async commit(virtualMachine, earlyCommit) {
533
600
  if (!this.nodeResponse.commit && !this.isCommiting()) {
534
- if (this.canCommit() && this.nodeResponse.vote) {
601
+ if (this.nodeResponse.vote &&
602
+ (this.nodeResponse.leader || this.canCommit())) {
535
603
  this.commiting = true;
536
604
  clearTimeout(this.broadcastTimeout);
537
605
  try {
@@ -542,15 +610,8 @@ export class Process extends EventEmitter {
542
610
  this.nodeResponse.incomms = virtualMachine.getInternodeCommsFromVM(this.entry.$umid);
543
611
  ActiveLogger.debug(`Calling Contract Return Data X2 - ${this.entry.$umid}`);
544
612
  this.nodeResponse.return = virtualMachine.getReturnContractData(this.entry.$umid);
545
- this.entry = this.shared.clearAllComms(virtualMachine, this.nodeResponse.incomms);
546
- let throws = virtualMachine.getThrowsFromVM(this.entry.$umid);
547
- if (throws && throws.length) {
548
- this.emit("throw", { locations: throws });
549
- }
550
613
  const streamUpdater = new StreamUpdater(this.entry, virtualMachine, this.reference, this.nodeResponse, this.db, this.dbev, this, this.shared, this.contractId);
551
- earlyCommit
552
- ? streamUpdater.updateStreams(earlyCommit)
553
- : streamUpdater.updateStreams();
614
+ await streamUpdater.updateStreams(earlyCommit);
554
615
  }
555
616
  catch (error) {
556
617
  if (earlyCommit)
@@ -575,7 +636,7 @@ export class Process extends EventEmitter {
575
636
  if (reconciled) {
576
637
  ActiveLogger.info("Self Reconcile Successful");
577
638
  const streamUpdater = new StreamUpdater(this.entry, virtualMachine, this.reference, this.nodeResponse, this.db, this.dbev, this, this.shared, this.contractId);
578
- streamUpdater.updateStreams();
639
+ await streamUpdater.updateStreams();
579
640
  }
580
641
  else {
581
642
  if (this.errorOut.code === 1505) {
@@ -607,9 +668,8 @@ export class Process extends EventEmitter {
607
668
  this.shared.raiseLedgerError(1510, new Error("Failed Network Voting Round - Non Broadcast"));
608
669
  }
609
670
  else {
610
- const neighbours = ActiveOptions.get("neighbourhood", []).length;
611
671
  const consensusNeeded = ActiveOptions.get("consensus", {}).reached;
612
- const outstandingVoters = neighbours - Object.keys(this.entry.$nodes).length;
672
+ const outstandingVoters = Process.networkNodeLength - this.countOutstandingVotes();
613
673
  if (!outstandingVoters) {
614
674
  clearTimeout(this.broadcastTimeout);
615
675
  if (this.nodeResponse.error) {
@@ -626,12 +686,17 @@ export class Process extends EventEmitter {
626
686
  }
627
687
  else {
628
688
  clearTimeout(this.broadcastTimeout);
629
- if (((this.currentVotes + outstandingVoters) / neighbours) * 100 >=
689
+ if (((this.currentTrueVotes + outstandingVoters) / Process.networkNodeLength) *
690
+ 100 >=
630
691
  consensusNeeded) {
631
692
  this.broadcastTimeout = setTimeout(() => {
632
- ActiveLogger.debug("VM Commit Failure, NETWORK Timeout");
633
- return this.shared.raiseLedgerError(1510, new Error("Failed Network Voting Timeout - Voters Timed Out"));
634
- }, BROADCAST_TIMEOUT);
693
+ if (!this.isCommiting()) {
694
+ ActiveLogger.debug("VM Commit Failure, NETWORK Timeout");
695
+ return this.shared.raiseLedgerError(1510, new Error("Failed Network Voting Timeout - Voters Timed Out"));
696
+ }
697
+ }, this.isCommiting()
698
+ ? BROADCAST_TIMEOUT_COMMIT
699
+ : this.currentTrueVotes === 0 ? BROADCAST_TIMEOUT_EARLY : BROADCAST_TIMEOUT_VOTE);
635
700
  }
636
701
  else {
637
702
  if (this.nodeResponse.error) {
@@ -699,9 +764,11 @@ export class Process extends EventEmitter {
699
764
  let streamId = txIO[streams[i]].$stream || streams[i];
700
765
  map[streamId] = streams[i];
701
766
  streams[i] = streamId;
767
+ if (!outputs && txIO[map[streamId]].$sigOnly) {
768
+ this.shared.sigOnly[streams[i]] = true;
769
+ }
702
770
  }
703
771
  }
704
772
  }
705
773
  }
706
- Process.singleContractVMHolder = {};
707
774
  //# sourceMappingURL=process.js.map