@hardkas/testing 0.7.3-alpha → 0.7.5-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adversarial-fixtures.js +1 -1
- package/dist/{chunk-IRVMANZV.js → chunk-J7YJZ3SC.js} +3 -1
- package/dist/{chunk-HH4OIGEG.js → chunk-QO3ONDVW.js} +20 -4
- package/dist/{chunk-SIJI3FRM.js → chunk-WJNTOLTB.js} +14 -3
- package/dist/index.js +925 -255
- package/dist/reproducibility.js +1 -1
- package/dist/setup.js +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AdversarialFixtures
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QO3ONDVW.js";
|
|
4
4
|
import {
|
|
5
5
|
generateReproducibilityReport
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WJNTOLTB.js";
|
|
7
7
|
import {
|
|
8
8
|
clearMassRecords,
|
|
9
9
|
createTestHarness,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./chunk-DDZQ5CH4.js";
|
|
14
14
|
import {
|
|
15
15
|
hardKasMatchers
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-J7YJZ3SC.js";
|
|
17
17
|
import {
|
|
18
18
|
__require
|
|
19
19
|
} from "./chunk-3RG5ZIWI.js";
|
|
@@ -29,7 +29,9 @@ function createFixture(def) {
|
|
|
29
29
|
for (const tx of def.setup) {
|
|
30
30
|
const result = harness.send(tx);
|
|
31
31
|
if (!result.ok) {
|
|
32
|
-
throw new Error(
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Fixture "${def.name}" failed during setup: ${tx.from} -> ${tx.to} (${tx.amountSompi} sompi). Error: ${result.receipt?.errors?.join(", ") || "Unknown error"}`
|
|
34
|
+
);
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -96,10 +98,18 @@ var TortureInvariantError = class extends Error {
|
|
|
96
98
|
// src/torture/buckets.ts
|
|
97
99
|
import fs from "fs";
|
|
98
100
|
import path from "path";
|
|
99
|
-
import {
|
|
101
|
+
import {
|
|
102
|
+
calculateContentHash,
|
|
103
|
+
ARTIFACT_VERSION,
|
|
104
|
+
CURRENT_HASH_VERSION
|
|
105
|
+
} from "@hardkas/artifacts";
|
|
100
106
|
import { HardkasStore, SqliteQueryBackend } from "@hardkas/query-store";
|
|
101
107
|
function createSandbox(ctx) {
|
|
102
|
-
const sandboxDir = path.join(
|
|
108
|
+
const sandboxDir = path.join(
|
|
109
|
+
ctx.workspaceDir,
|
|
110
|
+
".tmp",
|
|
111
|
+
`torture-sandbox-${ctx.caseId}-${ctx.caseSeed}`
|
|
112
|
+
);
|
|
103
113
|
const hardkasDir = path.join(sandboxDir, ".hardkas");
|
|
104
114
|
const artifactsDir = path.join(hardkasDir, "artifacts");
|
|
105
115
|
const dbPath = path.join(hardkasDir, "store.db");
|
|
@@ -125,7 +135,7 @@ registerTortureBucket({
|
|
|
125
135
|
for (let i = 0; i < artifactCount; i++) {
|
|
126
136
|
const payload = {
|
|
127
137
|
schema: "hardkas.txPlan",
|
|
128
|
-
hardkasVersion: "0.7.
|
|
138
|
+
hardkasVersion: "0.7.5-alpha",
|
|
129
139
|
version: ARTIFACT_VERSION,
|
|
130
140
|
networkId: "simnet",
|
|
131
141
|
mode: "simulated",
|
|
@@ -166,7 +176,9 @@ registerTortureBucket({
|
|
|
166
176
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
167
177
|
const indexedBefore = await backend.findArtifacts();
|
|
168
178
|
if (indexedBefore.length !== artifactCount) {
|
|
169
|
-
throw new Error(
|
|
179
|
+
throw new Error(
|
|
180
|
+
`Expected ${artifactCount} artifacts to be indexed, got ${indexedBefore.length}`
|
|
181
|
+
);
|
|
170
182
|
}
|
|
171
183
|
store.disconnect();
|
|
172
184
|
if (fs.existsSync(dbPath)) {
|
|
@@ -186,12 +198,16 @@ registerTortureBucket({
|
|
|
186
198
|
const indexedAfter = await newBackend.findArtifacts();
|
|
187
199
|
newStore.disconnect();
|
|
188
200
|
if (indexedAfter.length !== artifactCount) {
|
|
189
|
-
throw new Error(
|
|
201
|
+
throw new Error(
|
|
202
|
+
`State authority failure. Rebuilt database has ${indexedAfter.length} artifacts, expected ${artifactCount}`
|
|
203
|
+
);
|
|
190
204
|
}
|
|
191
205
|
for (const artId of generatedIds) {
|
|
192
206
|
const found = indexedAfter.find((a) => a.artifactId === artId);
|
|
193
207
|
if (!found) {
|
|
194
|
-
throw new Error(
|
|
208
|
+
throw new Error(
|
|
209
|
+
`State authority failure. Missing reconstructed artifact: ${artId}`
|
|
210
|
+
);
|
|
195
211
|
}
|
|
196
212
|
}
|
|
197
213
|
return {
|
|
@@ -213,7 +229,7 @@ registerTortureBucket({
|
|
|
213
229
|
try {
|
|
214
230
|
const payload = {
|
|
215
231
|
schema: "hardkas.txPlan",
|
|
216
|
-
hardkasVersion: "0.7.
|
|
232
|
+
hardkasVersion: "0.7.5-alpha",
|
|
217
233
|
version: ARTIFACT_VERSION,
|
|
218
234
|
networkId: "simnet",
|
|
219
235
|
mode: "simulated",
|
|
@@ -268,7 +284,9 @@ registerTortureBucket({
|
|
|
268
284
|
}
|
|
269
285
|
store.disconnect();
|
|
270
286
|
if (!threwCorrectly) {
|
|
271
|
-
throw new Error(
|
|
287
|
+
throw new Error(
|
|
288
|
+
"Invariant violated: corrupted artifact synchronized successfully without error under strict mode"
|
|
289
|
+
);
|
|
272
290
|
}
|
|
273
291
|
return {
|
|
274
292
|
flow: "Verify tampered artifact integrity",
|
|
@@ -291,7 +309,7 @@ registerTortureBucket({
|
|
|
291
309
|
const orderA = prngA.shuffle(["alice", "bob", "carol", "dave"]);
|
|
292
310
|
const payloadA = {
|
|
293
311
|
schema: "hardkas.txPlan",
|
|
294
|
-
version: "0.7.
|
|
312
|
+
version: "0.7.5-alpha",
|
|
295
313
|
networkId: "simnet",
|
|
296
314
|
mode: "simulated",
|
|
297
315
|
amountSompi: amountSompiA,
|
|
@@ -305,7 +323,7 @@ registerTortureBucket({
|
|
|
305
323
|
const orderB = prngB.shuffle(["alice", "bob", "carol", "dave"]);
|
|
306
324
|
const payloadB = {
|
|
307
325
|
schema: "hardkas.txPlan",
|
|
308
|
-
version: "0.7.
|
|
326
|
+
version: "0.7.5-alpha",
|
|
309
327
|
networkId: "simnet",
|
|
310
328
|
mode: "simulated",
|
|
311
329
|
amountSompi: amountSompiB,
|
|
@@ -314,7 +332,9 @@ registerTortureBucket({
|
|
|
314
332
|
};
|
|
315
333
|
const hashB = calculateContentHash(payloadB);
|
|
316
334
|
if (hashA !== hashB) {
|
|
317
|
-
throw new Error(
|
|
335
|
+
throw new Error(
|
|
336
|
+
`Divergence detected under same seed ${ctx.caseSeed}. Hash A: ${hashA}, Hash B: ${hashB}`
|
|
337
|
+
);
|
|
318
338
|
}
|
|
319
339
|
if (JSON.stringify(payloadA) !== JSON.stringify(payloadB)) {
|
|
320
340
|
throw new Error("Semantic payloads differ despite identical seed execution");
|
|
@@ -335,7 +355,7 @@ registerTortureBucket({
|
|
|
335
355
|
try {
|
|
336
356
|
const payloadV1 = {
|
|
337
357
|
schema: "hardkas.txPlan",
|
|
338
|
-
hardkasVersion: "0.7.
|
|
358
|
+
hardkasVersion: "0.7.5-alpha",
|
|
339
359
|
version: ARTIFACT_VERSION,
|
|
340
360
|
networkId: "simnet",
|
|
341
361
|
mode: "simulated",
|
|
@@ -402,7 +422,9 @@ registerTortureBucket({
|
|
|
402
422
|
throw new Error("Artifact deleted unexpectedly after update sync");
|
|
403
423
|
}
|
|
404
424
|
if (artAfter.contentHash !== hashV2 || artAfter.payload.state !== "progressed") {
|
|
405
|
-
throw new Error(
|
|
425
|
+
throw new Error(
|
|
426
|
+
`Staleness invariant failure. Expected hash ${hashV2} and state 'progressed', got hash ${artAfter.contentHash} and state '${artAfter.payload.state}'`
|
|
427
|
+
);
|
|
406
428
|
}
|
|
407
429
|
return {
|
|
408
430
|
flow: "Verify incremental update detection",
|
|
@@ -434,7 +456,7 @@ registerTortureBucket({
|
|
|
434
456
|
}
|
|
435
457
|
const planArtifact = {
|
|
436
458
|
schema: "hardkas.txPlan",
|
|
437
|
-
hardkasVersion: "0.7.
|
|
459
|
+
hardkasVersion: "0.7.5-alpha",
|
|
438
460
|
version: ARTIFACT_VERSION,
|
|
439
461
|
networkId: "simnet",
|
|
440
462
|
mode: "simulated",
|
|
@@ -491,7 +513,7 @@ registerTortureBucket({
|
|
|
491
513
|
}
|
|
492
514
|
const receiptArtifact = {
|
|
493
515
|
schema: "hardkas.txReceipt",
|
|
494
|
-
hardkasVersion: "0.7.
|
|
516
|
+
hardkasVersion: "0.7.5-alpha",
|
|
495
517
|
version: ARTIFACT_VERSION,
|
|
496
518
|
networkId: "simnet",
|
|
497
519
|
mode: "simulated",
|
|
@@ -524,10 +546,14 @@ registerTortureBucket({
|
|
|
524
546
|
const finalReceipt = await newBackend.getArtifact(receiptId);
|
|
525
547
|
newStore.disconnect();
|
|
526
548
|
if (!finalReceipt) {
|
|
527
|
-
throw new Error(
|
|
549
|
+
throw new Error(
|
|
550
|
+
"Failed to index final transaction receipt after resuming workflow"
|
|
551
|
+
);
|
|
528
552
|
}
|
|
529
553
|
if (finalReceipt.payload.lineage.parentArtifactId !== planId) {
|
|
530
|
-
throw new Error(
|
|
554
|
+
throw new Error(
|
|
555
|
+
"Lineage continuity violated: resumed receipt parentId does not match pre-crash planId"
|
|
556
|
+
);
|
|
531
557
|
}
|
|
532
558
|
return {
|
|
533
559
|
flow: "Recover from intermediate workflow crash and complete pipeline",
|
|
@@ -554,7 +580,7 @@ registerTortureBucket({
|
|
|
554
580
|
const planId = `plan-mock-${ctx.caseId}-${ctx.caseSeed}`;
|
|
555
581
|
const payload = {
|
|
556
582
|
schema: "hardkas.txPlan",
|
|
557
|
-
hardkasVersion: "0.7.
|
|
583
|
+
hardkasVersion: "0.7.5-alpha",
|
|
558
584
|
version: ARTIFACT_VERSION,
|
|
559
585
|
networkId: "simnet",
|
|
560
586
|
mode: "simulated",
|
|
@@ -566,8 +592,15 @@ registerTortureBucket({
|
|
|
566
592
|
amountSompi: "1000",
|
|
567
593
|
estimatedFeeSompi: "100",
|
|
568
594
|
estimatedMass: "10",
|
|
569
|
-
inputs: [
|
|
570
|
-
|
|
595
|
+
inputs: [
|
|
596
|
+
{ outpoint: { transactionId: "a".repeat(64), index: 0 }, amountSompi: "2000" }
|
|
597
|
+
],
|
|
598
|
+
outputs: [
|
|
599
|
+
{
|
|
600
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
601
|
+
amountSompi: "1000"
|
|
602
|
+
}
|
|
603
|
+
]
|
|
571
604
|
};
|
|
572
605
|
const validHash = calculateContentHash(payload);
|
|
573
606
|
const artifactId = `plan-${validHash.slice(0, 16)}`;
|
|
@@ -579,7 +612,11 @@ registerTortureBucket({
|
|
|
579
612
|
let checkIgnored = false;
|
|
580
613
|
switch (subCase) {
|
|
581
614
|
case 1:
|
|
582
|
-
fs.writeFileSync(
|
|
615
|
+
fs.writeFileSync(
|
|
616
|
+
badFile,
|
|
617
|
+
`{"schema": "hardkas.txPlan", "planId": "${planId}"`,
|
|
618
|
+
"utf-8"
|
|
619
|
+
);
|
|
583
620
|
shouldSyncThrow = true;
|
|
584
621
|
break;
|
|
585
622
|
case 2:
|
|
@@ -593,13 +630,29 @@ registerTortureBucket({
|
|
|
593
630
|
break;
|
|
594
631
|
}
|
|
595
632
|
case 4: {
|
|
596
|
-
const hashMismatchArt = {
|
|
633
|
+
const hashMismatchArt = {
|
|
634
|
+
...validArtifact,
|
|
635
|
+
amountSompi: "9999",
|
|
636
|
+
artifactId: "plan-mismatch"
|
|
637
|
+
};
|
|
597
638
|
fs.writeFileSync(badFile, JSON.stringify(hashMismatchArt, null, 2));
|
|
598
639
|
shouldSyncThrow = true;
|
|
599
640
|
break;
|
|
600
641
|
}
|
|
601
642
|
case 5:
|
|
602
|
-
fs.writeFileSync(
|
|
643
|
+
fs.writeFileSync(
|
|
644
|
+
badFile,
|
|
645
|
+
JSON.stringify(
|
|
646
|
+
{
|
|
647
|
+
schema: "hardkas.txPlan",
|
|
648
|
+
version: ARTIFACT_VERSION,
|
|
649
|
+
contentHash: validHash,
|
|
650
|
+
artifactId: "plan-meta-only"
|
|
651
|
+
},
|
|
652
|
+
null,
|
|
653
|
+
2
|
|
654
|
+
)
|
|
655
|
+
);
|
|
603
656
|
shouldSyncThrow = true;
|
|
604
657
|
break;
|
|
605
658
|
case 6:
|
|
@@ -616,7 +669,7 @@ registerTortureBucket({
|
|
|
616
669
|
case 8: {
|
|
617
670
|
const orphanReceipt = {
|
|
618
671
|
schema: "hardkas.txReceipt",
|
|
619
|
-
hardkasVersion: "0.7.
|
|
672
|
+
hardkasVersion: "0.7.5-alpha",
|
|
620
673
|
version: ARTIFACT_VERSION,
|
|
621
674
|
networkId: "simnet",
|
|
622
675
|
mode: "simulated",
|
|
@@ -637,7 +690,14 @@ registerTortureBucket({
|
|
|
637
690
|
};
|
|
638
691
|
const receiptHash = calculateContentHash(orphanReceipt);
|
|
639
692
|
const receiptId = `receipt-${receiptHash.slice(0, 16)}`;
|
|
640
|
-
fs.writeFileSync(
|
|
693
|
+
fs.writeFileSync(
|
|
694
|
+
path.join(artifactsDir, `${receiptId}.json`),
|
|
695
|
+
JSON.stringify(
|
|
696
|
+
{ ...orphanReceipt, artifactId: receiptId, contentHash: receiptHash },
|
|
697
|
+
null,
|
|
698
|
+
2
|
|
699
|
+
)
|
|
700
|
+
);
|
|
641
701
|
break;
|
|
642
702
|
}
|
|
643
703
|
case 9:
|
|
@@ -672,7 +732,9 @@ registerTortureBucket({
|
|
|
672
732
|
}
|
|
673
733
|
const records = await backend.findArtifacts();
|
|
674
734
|
if (checkIgnored) {
|
|
675
|
-
const badFound = records.some(
|
|
735
|
+
const badFound = records.some(
|
|
736
|
+
(r) => r.artifactId.includes(`bad-artifact-${subCase}`) || r.artifactId.includes(`.tmp-`)
|
|
737
|
+
);
|
|
676
738
|
if (badFound) {
|
|
677
739
|
throw new TortureInvariantError(
|
|
678
740
|
`Temp or ignored file was indexed into the query-store under case ${subCase}`,
|
|
@@ -683,7 +745,9 @@ registerTortureBucket({
|
|
|
683
745
|
}
|
|
684
746
|
if (subCase === 8 || subCase === 9) {
|
|
685
747
|
const edges = await backend.getLineageEdges();
|
|
686
|
-
const hasBadEdge = edges.some(
|
|
748
|
+
const hasBadEdge = edges.some(
|
|
749
|
+
(e) => e.parentArtifactId === "non-existent-parent-id"
|
|
750
|
+
);
|
|
687
751
|
if (hasBadEdge) {
|
|
688
752
|
throw new TortureInvariantError(
|
|
689
753
|
"Orphan child created a valid lineage edge to a missing parent",
|
|
@@ -729,7 +793,7 @@ registerTortureBucket({
|
|
|
729
793
|
const pId = `plan-race-${i}-${ctx.caseSeed}`;
|
|
730
794
|
const payload = {
|
|
731
795
|
schema: "hardkas.txPlan",
|
|
732
|
-
hardkasVersion: "0.7.
|
|
796
|
+
hardkasVersion: "0.7.5-alpha",
|
|
733
797
|
version: ARTIFACT_VERSION,
|
|
734
798
|
networkId: "simnet",
|
|
735
799
|
mode: "simulated",
|
|
@@ -741,20 +805,34 @@ registerTortureBucket({
|
|
|
741
805
|
amountSompi: "5000",
|
|
742
806
|
estimatedFeeSompi: "100",
|
|
743
807
|
estimatedMass: "10",
|
|
744
|
-
inputs: [
|
|
808
|
+
inputs: [
|
|
809
|
+
{
|
|
810
|
+
outpoint: { transactionId: "c".repeat(64), index: i },
|
|
811
|
+
amountSompi: "10000"
|
|
812
|
+
}
|
|
813
|
+
],
|
|
745
814
|
outputs: [{ address: `kaspa:sim_to_${i}`, amountSompi: "5000" }]
|
|
746
815
|
};
|
|
747
816
|
const hash = calculateContentHash(payload);
|
|
748
817
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
749
818
|
generatedIds.push(artId);
|
|
750
|
-
promises.push(
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
819
|
+
promises.push(
|
|
820
|
+
(async () => {
|
|
821
|
+
const file = path.join(artifactsDir, `${artId}.json`);
|
|
822
|
+
fs.writeFileSync(
|
|
823
|
+
file,
|
|
824
|
+
JSON.stringify(
|
|
825
|
+
{ ...payload, artifactId: artId, contentHash: hash },
|
|
826
|
+
null,
|
|
827
|
+
2
|
|
828
|
+
)
|
|
829
|
+
);
|
|
830
|
+
try {
|
|
831
|
+
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
832
|
+
} catch (err) {
|
|
833
|
+
}
|
|
834
|
+
})()
|
|
835
|
+
);
|
|
758
836
|
}
|
|
759
837
|
await Promise.all(promises);
|
|
760
838
|
const syncRes = await backend.sync({ strict: true, cwd: sandboxDir });
|
|
@@ -800,7 +878,7 @@ registerTortureBucket({
|
|
|
800
878
|
const planId = `plan-stale-${ctx.caseSeed}`;
|
|
801
879
|
const payload = {
|
|
802
880
|
schema: "hardkas.txPlan",
|
|
803
|
-
hardkasVersion: "0.7.
|
|
881
|
+
hardkasVersion: "0.7.5-alpha",
|
|
804
882
|
version: ARTIFACT_VERSION,
|
|
805
883
|
networkId: "simnet",
|
|
806
884
|
mode: "simulated",
|
|
@@ -812,20 +890,37 @@ registerTortureBucket({
|
|
|
812
890
|
amountSompi: "1000",
|
|
813
891
|
estimatedFeeSompi: "100",
|
|
814
892
|
estimatedMass: "10",
|
|
815
|
-
inputs: [
|
|
816
|
-
|
|
893
|
+
inputs: [
|
|
894
|
+
{ outpoint: { transactionId: "d".repeat(64), index: 0 }, amountSompi: "2000" }
|
|
895
|
+
],
|
|
896
|
+
outputs: [
|
|
897
|
+
{
|
|
898
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
899
|
+
amountSompi: "1000"
|
|
900
|
+
}
|
|
901
|
+
]
|
|
817
902
|
};
|
|
818
903
|
const hash = calculateContentHash(payload);
|
|
819
904
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
820
905
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
821
|
-
fs.writeFileSync(
|
|
906
|
+
fs.writeFileSync(
|
|
907
|
+
file,
|
|
908
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
909
|
+
);
|
|
822
910
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
823
911
|
const statusBefore = await backend.doctor();
|
|
824
912
|
if (!statusBefore.ok) {
|
|
825
913
|
throw new Error("Doctor check failed on initial fresh index");
|
|
826
914
|
}
|
|
827
915
|
const mutatedPayload = { ...payload, amountSompi: "9999" };
|
|
828
|
-
fs.writeFileSync(
|
|
916
|
+
fs.writeFileSync(
|
|
917
|
+
file,
|
|
918
|
+
JSON.stringify(
|
|
919
|
+
{ ...mutatedPayload, artifactId: artId, contentHash: hash },
|
|
920
|
+
null,
|
|
921
|
+
2
|
|
922
|
+
)
|
|
923
|
+
);
|
|
829
924
|
const futureTime = Date.now() + 5e4;
|
|
830
925
|
fs.utimesSync(file, new Date(futureTime), new Date(futureTime));
|
|
831
926
|
const statusAfter = await backend.doctor();
|
|
@@ -895,7 +990,9 @@ registerTortureBucket({
|
|
|
895
990
|
if (pat.name === "readdirSync()" && line.includes(".sort(")) continue;
|
|
896
991
|
const isCoreDeterministic = relPath.includes("packages/artifacts/src/") || relPath.includes("packages/query-store/src/") || relPath.includes("packages/sdk/src/replay.ts") || relPath.includes("packages/sdk/src/workflow.ts") || relPath.includes("packages/localnet/src/");
|
|
897
992
|
if (isCoreDeterministic) {
|
|
898
|
-
findings.push(
|
|
993
|
+
findings.push(
|
|
994
|
+
`${relPath}:${lineNum} - Found core determinism violation: ${pat.name}`
|
|
995
|
+
);
|
|
899
996
|
}
|
|
900
997
|
}
|
|
901
998
|
}
|
|
@@ -936,7 +1033,7 @@ registerTortureBucket({
|
|
|
936
1033
|
for (let i = 0; i < 10; i++) {
|
|
937
1034
|
const payload = {
|
|
938
1035
|
schema: "hardkas.txPlan",
|
|
939
|
-
hardkasVersion: "0.7.
|
|
1036
|
+
hardkasVersion: "0.7.5-alpha",
|
|
940
1037
|
version: ARTIFACT_VERSION,
|
|
941
1038
|
networkId: "simnet",
|
|
942
1039
|
mode: "simulated",
|
|
@@ -948,14 +1045,27 @@ registerTortureBucket({
|
|
|
948
1045
|
amountSompi: (1000n * BigInt(i + 1)).toString(),
|
|
949
1046
|
estimatedFeeSompi: "100",
|
|
950
1047
|
estimatedMass: "10",
|
|
951
|
-
inputs: [
|
|
952
|
-
|
|
1048
|
+
inputs: [
|
|
1049
|
+
{
|
|
1050
|
+
outpoint: { transactionId: "e".repeat(64), index: i },
|
|
1051
|
+
amountSompi: "20000"
|
|
1052
|
+
}
|
|
1053
|
+
],
|
|
1054
|
+
outputs: [
|
|
1055
|
+
{
|
|
1056
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
1057
|
+
amountSompi: "1000"
|
|
1058
|
+
}
|
|
1059
|
+
]
|
|
953
1060
|
};
|
|
954
1061
|
const hash = calculateContentHash(payload);
|
|
955
1062
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
956
1063
|
generatedIds.push(artId);
|
|
957
1064
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
958
|
-
fs.writeFileSync(
|
|
1065
|
+
fs.writeFileSync(
|
|
1066
|
+
file,
|
|
1067
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
1068
|
+
);
|
|
959
1069
|
const evEnvelope = {
|
|
960
1070
|
schema: "hardkas.event",
|
|
961
1071
|
eventId: `ev-storm-${i}`,
|
|
@@ -1010,7 +1120,7 @@ registerTortureBucket({
|
|
|
1010
1120
|
const traverseArtId = "../../traversal-escape";
|
|
1011
1121
|
const payload = {
|
|
1012
1122
|
schema: "hardkas.txPlan",
|
|
1013
|
-
hardkasVersion: "0.7.
|
|
1123
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1014
1124
|
version: ARTIFACT_VERSION,
|
|
1015
1125
|
networkId: "simnet",
|
|
1016
1126
|
mode: "simulated",
|
|
@@ -1022,12 +1132,31 @@ registerTortureBucket({
|
|
|
1022
1132
|
amountSompi: "1000",
|
|
1023
1133
|
estimatedFeeSompi: "100",
|
|
1024
1134
|
estimatedMass: "10",
|
|
1025
|
-
inputs: [
|
|
1026
|
-
|
|
1135
|
+
inputs: [
|
|
1136
|
+
{ outpoint: { transactionId: "g".repeat(64), index: 0 }, amountSompi: "2000" }
|
|
1137
|
+
],
|
|
1138
|
+
outputs: [
|
|
1139
|
+
{
|
|
1140
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
1141
|
+
amountSompi: "1000"
|
|
1142
|
+
}
|
|
1143
|
+
]
|
|
1027
1144
|
};
|
|
1028
1145
|
const hash = calculateContentHash(payload);
|
|
1029
|
-
const traverseFile = path.join(
|
|
1030
|
-
|
|
1146
|
+
const traverseFile = path.join(
|
|
1147
|
+
artifactsDir,
|
|
1148
|
+
"..",
|
|
1149
|
+
"..",
|
|
1150
|
+
`traversal-${ctx.caseSeed}.json`
|
|
1151
|
+
);
|
|
1152
|
+
fs.writeFileSync(
|
|
1153
|
+
traverseFile,
|
|
1154
|
+
JSON.stringify(
|
|
1155
|
+
{ ...payload, artifactId: traverseArtId, contentHash: hash },
|
|
1156
|
+
null,
|
|
1157
|
+
2
|
|
1158
|
+
)
|
|
1159
|
+
);
|
|
1031
1160
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
1032
1161
|
const records = await backend.findArtifacts();
|
|
1033
1162
|
const escaped = records.some((r) => r.artifactId.includes("traversal"));
|
|
@@ -1041,7 +1170,10 @@ registerTortureBucket({
|
|
|
1041
1170
|
}
|
|
1042
1171
|
const validId = `plan-move-${ctx.caseSeed}`;
|
|
1043
1172
|
const validFile = path.join(artifactsDir, `${validId}.json`);
|
|
1044
|
-
fs.writeFileSync(
|
|
1173
|
+
fs.writeFileSync(
|
|
1174
|
+
validFile,
|
|
1175
|
+
JSON.stringify({ ...payload, artifactId: validId, contentHash: hash }, null, 2)
|
|
1176
|
+
);
|
|
1045
1177
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
1046
1178
|
store.disconnect();
|
|
1047
1179
|
const newSandboxDir = `${sandboxDir}-moved`;
|
|
@@ -1053,7 +1185,10 @@ registerTortureBucket({
|
|
|
1053
1185
|
const newStore = new HardkasStore({ dbPath: newDbPath });
|
|
1054
1186
|
newStore.connect({ autoMigrate: true });
|
|
1055
1187
|
const newBackend = new SqliteQueryBackend(newStore);
|
|
1056
|
-
const rebuildResult = await newBackend.rebuild({
|
|
1188
|
+
const rebuildResult = await newBackend.rebuild({
|
|
1189
|
+
strict: true,
|
|
1190
|
+
cwd: newSandboxDir
|
|
1191
|
+
});
|
|
1057
1192
|
if (!rebuildResult.ok) {
|
|
1058
1193
|
throw new Error("Failed to rebuild after moving workspace folder");
|
|
1059
1194
|
}
|
|
@@ -1203,7 +1338,11 @@ registerTortureBucket({
|
|
|
1203
1338
|
const originalCwd = process.cwd();
|
|
1204
1339
|
try {
|
|
1205
1340
|
const { createTestHarness: createTestHarness2 } = await import("./index.js");
|
|
1206
|
-
fs.writeFileSync(
|
|
1341
|
+
fs.writeFileSync(
|
|
1342
|
+
path.join(sandboxDir, "hardkas.config.ts"),
|
|
1343
|
+
"export default {};",
|
|
1344
|
+
"utf-8"
|
|
1345
|
+
);
|
|
1207
1346
|
const harness = createTestHarness2({ accounts: 3, initialBalance: 100000000000n });
|
|
1208
1347
|
const names = harness.accountNames();
|
|
1209
1348
|
const tx = harness.send({
|
|
@@ -1219,9 +1358,20 @@ registerTortureBucket({
|
|
|
1219
1358
|
...tx.plan,
|
|
1220
1359
|
artifactId: planId
|
|
1221
1360
|
};
|
|
1222
|
-
conformingPlan.contentHash = calculateContentHash(
|
|
1223
|
-
|
|
1224
|
-
|
|
1361
|
+
conformingPlan.contentHash = calculateContentHash(
|
|
1362
|
+
conformingPlan,
|
|
1363
|
+
CURRENT_HASH_VERSION
|
|
1364
|
+
);
|
|
1365
|
+
fs.writeFileSync(
|
|
1366
|
+
path.join(artifactsDir, `${planId}.json`),
|
|
1367
|
+
JSON.stringify(conformingPlan, null, 2),
|
|
1368
|
+
"utf-8"
|
|
1369
|
+
);
|
|
1370
|
+
fs.writeFileSync(
|
|
1371
|
+
path.join(sandboxDir, "tx-plan.json"),
|
|
1372
|
+
JSON.stringify(conformingPlan, null, 2),
|
|
1373
|
+
"utf-8"
|
|
1374
|
+
);
|
|
1225
1375
|
const receiptId = `receipt-${tx.receipt.txId.slice(0, 16)}`;
|
|
1226
1376
|
const conformingReceipt = {
|
|
1227
1377
|
...tx.receipt,
|
|
@@ -1233,9 +1383,20 @@ registerTortureBucket({
|
|
|
1233
1383
|
rootArtifactId: planId
|
|
1234
1384
|
}
|
|
1235
1385
|
};
|
|
1236
|
-
conformingReceipt.contentHash = calculateContentHash(
|
|
1237
|
-
|
|
1238
|
-
|
|
1386
|
+
conformingReceipt.contentHash = calculateContentHash(
|
|
1387
|
+
conformingReceipt,
|
|
1388
|
+
CURRENT_HASH_VERSION
|
|
1389
|
+
);
|
|
1390
|
+
fs.writeFileSync(
|
|
1391
|
+
path.join(artifactsDir, `${receiptId}.json`),
|
|
1392
|
+
JSON.stringify(conformingReceipt, null, 2),
|
|
1393
|
+
"utf-8"
|
|
1394
|
+
);
|
|
1395
|
+
fs.writeFileSync(
|
|
1396
|
+
path.join(sandboxDir, "tx-receipt.json"),
|
|
1397
|
+
JSON.stringify(conformingReceipt, null, 2),
|
|
1398
|
+
"utf-8"
|
|
1399
|
+
);
|
|
1239
1400
|
const store = new HardkasStore({ dbPath });
|
|
1240
1401
|
store.connect({ autoMigrate: true });
|
|
1241
1402
|
const backend = new SqliteQueryBackend(store);
|
|
@@ -1256,13 +1417,18 @@ registerTortureBucket({
|
|
|
1256
1417
|
}
|
|
1257
1418
|
fs.renameSync(sandboxDir, newSandboxDir);
|
|
1258
1419
|
if (fs.existsSync(sandboxDir)) {
|
|
1259
|
-
throw new Error(
|
|
1420
|
+
throw new Error(
|
|
1421
|
+
"Failed to completely relocate workspace directory during environment reconstruction"
|
|
1422
|
+
);
|
|
1260
1423
|
}
|
|
1261
1424
|
const newDbPath = path.join(newSandboxDir, ".hardkas", "store.db");
|
|
1262
1425
|
const newStore = new HardkasStore({ dbPath: newDbPath });
|
|
1263
1426
|
newStore.connect({ autoMigrate: true });
|
|
1264
1427
|
const newBackend = new SqliteQueryBackend(newStore);
|
|
1265
|
-
const rebuildResult = await newBackend.rebuild({
|
|
1428
|
+
const rebuildResult = await newBackend.rebuild({
|
|
1429
|
+
strict: true,
|
|
1430
|
+
cwd: newSandboxDir
|
|
1431
|
+
});
|
|
1266
1432
|
if (!rebuildResult.ok) {
|
|
1267
1433
|
throw new Error("Rebuild failed under reconstructed workspace environment");
|
|
1268
1434
|
}
|
|
@@ -1284,7 +1450,11 @@ registerTortureBucket({
|
|
|
1284
1450
|
}
|
|
1285
1451
|
const { Hardkas } = await import("@hardkas/sdk");
|
|
1286
1452
|
const localnetStatePath = path.join(newSandboxDir, ".hardkas", "localnet.json");
|
|
1287
|
-
fs.writeFileSync(
|
|
1453
|
+
fs.writeFileSync(
|
|
1454
|
+
localnetStatePath,
|
|
1455
|
+
JSON.stringify(harness.state, null, 2),
|
|
1456
|
+
"utf-8"
|
|
1457
|
+
);
|
|
1288
1458
|
process.chdir(newSandboxDir);
|
|
1289
1459
|
const sdk = await Hardkas.open({
|
|
1290
1460
|
cwd: newSandboxDir,
|
|
@@ -1338,7 +1508,7 @@ registerTortureBucket({
|
|
|
1338
1508
|
const idx = generatedIds.length;
|
|
1339
1509
|
const payload = {
|
|
1340
1510
|
schema: "hardkas.txPlan",
|
|
1341
|
-
hardkasVersion: "0.7.
|
|
1511
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1342
1512
|
version: ARTIFACT_VERSION,
|
|
1343
1513
|
networkId: "simnet",
|
|
1344
1514
|
mode: "simulated",
|
|
@@ -1350,8 +1520,18 @@ registerTortureBucket({
|
|
|
1350
1520
|
amountSompi: (1000n * BigInt(ctx.prng.nextInt(1, 100) * 10 + idx)).toString(),
|
|
1351
1521
|
estimatedFeeSompi: "100",
|
|
1352
1522
|
estimatedMass: "10",
|
|
1353
|
-
inputs: [
|
|
1354
|
-
|
|
1523
|
+
inputs: [
|
|
1524
|
+
{
|
|
1525
|
+
outpoint: { transactionId: "s".repeat(64), index: idx },
|
|
1526
|
+
amountSompi: "20000"
|
|
1527
|
+
}
|
|
1528
|
+
],
|
|
1529
|
+
outputs: [
|
|
1530
|
+
{
|
|
1531
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
1532
|
+
amountSompi: "1000"
|
|
1533
|
+
}
|
|
1534
|
+
]
|
|
1355
1535
|
};
|
|
1356
1536
|
if (parentId) {
|
|
1357
1537
|
payload.lineage = {
|
|
@@ -1376,7 +1556,9 @@ registerTortureBucket({
|
|
|
1376
1556
|
const syncResult = await backend.sync({ strict: true, cwd: sandboxDir });
|
|
1377
1557
|
const syncDurationMs = Date.now() - syncStart;
|
|
1378
1558
|
if (!syncResult.ok) {
|
|
1379
|
-
throw new Error(
|
|
1559
|
+
throw new Error(
|
|
1560
|
+
`Full sync failed on ${generatedIds.length} artifacts: ${syncResult.errors.join(", ")}`
|
|
1561
|
+
);
|
|
1380
1562
|
}
|
|
1381
1563
|
const allArtifacts = await backend.findArtifacts();
|
|
1382
1564
|
if (allArtifacts.length !== generatedIds.length) {
|
|
@@ -1470,38 +1652,52 @@ registerTortureBucket({
|
|
|
1470
1652
|
const allGeneratedIds = [];
|
|
1471
1653
|
const workerPromises = [];
|
|
1472
1654
|
for (let w = 0; w < workerCount; w++) {
|
|
1473
|
-
workerPromises.push(
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1655
|
+
workerPromises.push(
|
|
1656
|
+
(async () => {
|
|
1657
|
+
const workerIds = [];
|
|
1658
|
+
const workerPrng = new LcgPrng(ctx.caseSeed + w * 1e3);
|
|
1659
|
+
for (let i = 0; i < artifactsPerWorker; i++) {
|
|
1660
|
+
const payload = {
|
|
1661
|
+
schema: "hardkas.txPlan",
|
|
1662
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1663
|
+
version: ARTIFACT_VERSION,
|
|
1664
|
+
networkId: "simnet",
|
|
1665
|
+
mode: "simulated",
|
|
1666
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1667
|
+
// hardkas-determinism-allow: mock timestamp
|
|
1668
|
+
planId: `plan-mp-w${w}-${i}-${ctx.caseSeed}`,
|
|
1669
|
+
from: { address: `kaspa:sim_worker_${w}` },
|
|
1670
|
+
to: { address: `kaspa:sim_target_${w}` },
|
|
1671
|
+
amountSompi: (1000n * BigInt(workerPrng.nextInt(1, 100))).toString(),
|
|
1672
|
+
estimatedFeeSompi: "100",
|
|
1673
|
+
estimatedMass: "10",
|
|
1674
|
+
inputs: [
|
|
1675
|
+
{
|
|
1676
|
+
outpoint: { transactionId: "m".repeat(64), index: w * 100 + i },
|
|
1677
|
+
amountSompi: "20000"
|
|
1678
|
+
}
|
|
1679
|
+
],
|
|
1680
|
+
outputs: [{ address: `kaspa:sim_target_${w}`, amountSompi: "1000" }]
|
|
1681
|
+
};
|
|
1682
|
+
const hash = calculateContentHash(payload);
|
|
1683
|
+
const artId = `plan-${hash.slice(0, 16)}`;
|
|
1684
|
+
workerIds.push(artId);
|
|
1685
|
+
const file = path.join(artifactsDir, `${artId}.json`);
|
|
1686
|
+
fs.writeFileSync(
|
|
1687
|
+
file,
|
|
1688
|
+
JSON.stringify(
|
|
1689
|
+
{ ...payload, artifactId: artId, contentHash: hash },
|
|
1690
|
+
null,
|
|
1691
|
+
2
|
|
1692
|
+
)
|
|
1693
|
+
);
|
|
1694
|
+
if (workerPrng.nextInt(0, 3) === 0) {
|
|
1695
|
+
await new Promise((r) => setTimeout(r, workerPrng.nextInt(1, 10)));
|
|
1696
|
+
}
|
|
1501
1697
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1698
|
+
return workerIds;
|
|
1699
|
+
})()
|
|
1700
|
+
);
|
|
1505
1701
|
}
|
|
1506
1702
|
const workerResults = await Promise.all(workerPromises);
|
|
1507
1703
|
for (const ids2 of workerResults) {
|
|
@@ -1575,7 +1771,12 @@ registerTortureBucket({
|
|
|
1575
1771
|
const { sandboxDir, artifactsDir, dbPath } = createSandbox(ctx);
|
|
1576
1772
|
const subCase = ctx.prng.nextInt(1, 5);
|
|
1577
1773
|
try {
|
|
1578
|
-
const {
|
|
1774
|
+
const {
|
|
1775
|
+
acquireLock,
|
|
1776
|
+
clearLock,
|
|
1777
|
+
listLocks,
|
|
1778
|
+
isProcessAlive: checkAlive
|
|
1779
|
+
} = await import("@hardkas/core");
|
|
1579
1780
|
const lockDir = path.join(sandboxDir, ".hardkas", "locks");
|
|
1580
1781
|
fs.mkdirSync(lockDir, { recursive: true });
|
|
1581
1782
|
switch (subCase) {
|
|
@@ -1714,22 +1915,18 @@ registerTortureBucket({
|
|
|
1714
1915
|
const { withLocks } = await import("@hardkas/core");
|
|
1715
1916
|
let locksAcquired = false;
|
|
1716
1917
|
try {
|
|
1717
|
-
await withLocks(
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
"LOCK_FILES_MISSING",
|
|
1728
|
-
"critical"
|
|
1729
|
-
);
|
|
1730
|
-
}
|
|
1918
|
+
await withLocks(sandboxDir, ["artifacts", "query-store"], async () => {
|
|
1919
|
+
locksAcquired = true;
|
|
1920
|
+
const artLock = path.join(lockDir, "artifacts.lock");
|
|
1921
|
+
const qsLock = path.join(lockDir, "query-store.lock");
|
|
1922
|
+
if (!fs.existsSync(artLock) || !fs.existsSync(qsLock)) {
|
|
1923
|
+
throw new TortureInvariantError(
|
|
1924
|
+
"Lock files not created on disk while held",
|
|
1925
|
+
"LOCK_FILES_MISSING",
|
|
1926
|
+
"critical"
|
|
1927
|
+
);
|
|
1731
1928
|
}
|
|
1732
|
-
);
|
|
1929
|
+
});
|
|
1733
1930
|
} catch (err) {
|
|
1734
1931
|
if (err instanceof TortureInvariantError) throw err;
|
|
1735
1932
|
}
|
|
@@ -1752,7 +1949,7 @@ registerTortureBucket({
|
|
|
1752
1949
|
const backend = new SqliteQueryBackend(store);
|
|
1753
1950
|
const payload = {
|
|
1754
1951
|
schema: "hardkas.txPlan",
|
|
1755
|
-
hardkasVersion: "0.7.
|
|
1952
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1756
1953
|
version: ARTIFACT_VERSION,
|
|
1757
1954
|
networkId: "simnet",
|
|
1758
1955
|
mode: "simulated",
|
|
@@ -1764,13 +1961,23 @@ registerTortureBucket({
|
|
|
1764
1961
|
amountSompi: "1000",
|
|
1765
1962
|
estimatedFeeSompi: "100",
|
|
1766
1963
|
estimatedMass: "10",
|
|
1767
|
-
inputs: [
|
|
1768
|
-
|
|
1964
|
+
inputs: [
|
|
1965
|
+
{ outpoint: { transactionId: "l".repeat(64), index: 0 }, amountSompi: "2000" }
|
|
1966
|
+
],
|
|
1967
|
+
outputs: [
|
|
1968
|
+
{
|
|
1969
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
1970
|
+
amountSompi: "1000"
|
|
1971
|
+
}
|
|
1972
|
+
]
|
|
1769
1973
|
};
|
|
1770
1974
|
const hash = calculateContentHash(payload);
|
|
1771
1975
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
1772
1976
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
1773
|
-
fs.writeFileSync(
|
|
1977
|
+
fs.writeFileSync(
|
|
1978
|
+
file,
|
|
1979
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
1980
|
+
);
|
|
1774
1981
|
const syncResult = await backend.sync({ strict: true, cwd: sandboxDir });
|
|
1775
1982
|
store.disconnect();
|
|
1776
1983
|
if (!syncResult.ok) {
|
|
@@ -1805,7 +2012,7 @@ registerTortureBucket({
|
|
|
1805
2012
|
case 1: {
|
|
1806
2013
|
const payload1 = {
|
|
1807
2014
|
schema: "hardkas.txPlan",
|
|
1808
|
-
hardkasVersion: "0.7.
|
|
2015
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1809
2016
|
version: ARTIFACT_VERSION,
|
|
1810
2017
|
networkId: "simnet",
|
|
1811
2018
|
mode: "simulated",
|
|
@@ -1817,18 +2024,36 @@ registerTortureBucket({
|
|
|
1817
2024
|
amountSompi: "1000",
|
|
1818
2025
|
estimatedFeeSompi: "100",
|
|
1819
2026
|
estimatedMass: "10",
|
|
1820
|
-
inputs: [
|
|
1821
|
-
|
|
2027
|
+
inputs: [
|
|
2028
|
+
{
|
|
2029
|
+
outpoint: { transactionId: "w".repeat(64), index: 0 },
|
|
2030
|
+
amountSompi: "2000"
|
|
2031
|
+
}
|
|
2032
|
+
],
|
|
2033
|
+
outputs: [
|
|
2034
|
+
{
|
|
2035
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2036
|
+
amountSompi: "1000"
|
|
2037
|
+
}
|
|
2038
|
+
]
|
|
1822
2039
|
};
|
|
1823
2040
|
const hash1 = calculateContentHash(payload1);
|
|
1824
|
-
const art1 = {
|
|
2041
|
+
const art1 = {
|
|
2042
|
+
...payload1,
|
|
2043
|
+
artifactId: `Plan-Upper-${hash1.slice(0, 8)}`,
|
|
2044
|
+
contentHash: hash1
|
|
2045
|
+
};
|
|
1825
2046
|
const payload2 = {
|
|
1826
2047
|
...payload1,
|
|
1827
2048
|
planId: `plan-case-lower-${ctx.caseSeed}`,
|
|
1828
2049
|
amountSompi: "2000"
|
|
1829
2050
|
};
|
|
1830
2051
|
const hash2 = calculateContentHash(payload2);
|
|
1831
|
-
const art2 = {
|
|
2052
|
+
const art2 = {
|
|
2053
|
+
...payload2,
|
|
2054
|
+
artifactId: `plan-lower-${hash2.slice(0, 8)}`,
|
|
2055
|
+
contentHash: hash2
|
|
2056
|
+
};
|
|
1832
2057
|
const file1 = path.join(artifactsDir, `CaseTest.json`);
|
|
1833
2058
|
const file2 = path.join(artifactsDir, `casetest.json`);
|
|
1834
2059
|
fs.writeFileSync(file1, JSON.stringify(art1, null, 2));
|
|
@@ -1870,7 +2095,7 @@ registerTortureBucket({
|
|
|
1870
2095
|
}
|
|
1871
2096
|
const safePayload = {
|
|
1872
2097
|
schema: "hardkas.txPlan",
|
|
1873
|
-
hardkasVersion: "0.7.
|
|
2098
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1874
2099
|
version: ARTIFACT_VERSION,
|
|
1875
2100
|
networkId: "simnet",
|
|
1876
2101
|
mode: "simulated",
|
|
@@ -1882,12 +2107,29 @@ registerTortureBucket({
|
|
|
1882
2107
|
amountSompi: "3000",
|
|
1883
2108
|
estimatedFeeSompi: "100",
|
|
1884
2109
|
estimatedMass: "10",
|
|
1885
|
-
inputs: [
|
|
1886
|
-
|
|
2110
|
+
inputs: [
|
|
2111
|
+
{
|
|
2112
|
+
outpoint: { transactionId: "r".repeat(64), index: 0 },
|
|
2113
|
+
amountSompi: "4000"
|
|
2114
|
+
}
|
|
2115
|
+
],
|
|
2116
|
+
outputs: [
|
|
2117
|
+
{
|
|
2118
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2119
|
+
amountSompi: "3000"
|
|
2120
|
+
}
|
|
2121
|
+
]
|
|
1887
2122
|
};
|
|
1888
2123
|
const safeHash = calculateContentHash(safePayload);
|
|
1889
|
-
const safeArt = {
|
|
1890
|
-
|
|
2124
|
+
const safeArt = {
|
|
2125
|
+
...safePayload,
|
|
2126
|
+
artifactId: `plan-${safeHash.slice(0, 16)}`,
|
|
2127
|
+
contentHash: safeHash
|
|
2128
|
+
};
|
|
2129
|
+
fs.writeFileSync(
|
|
2130
|
+
path.join(artifactsDir, `${safeArt.artifactId}.json`),
|
|
2131
|
+
JSON.stringify(safeArt, null, 2)
|
|
2132
|
+
);
|
|
1891
2133
|
const syncResult = await backend.sync({ strict: true, cwd: sandboxDir });
|
|
1892
2134
|
if (!syncResult.ok) {
|
|
1893
2135
|
throw new TortureInvariantError(
|
|
@@ -1901,7 +2143,7 @@ registerTortureBucket({
|
|
|
1901
2143
|
case 3: {
|
|
1902
2144
|
const payload = {
|
|
1903
2145
|
schema: "hardkas.txPlan",
|
|
1904
|
-
hardkasVersion: "0.7.
|
|
2146
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1905
2147
|
version: ARTIFACT_VERSION,
|
|
1906
2148
|
networkId: "simnet",
|
|
1907
2149
|
mode: "simulated",
|
|
@@ -1913,8 +2155,18 @@ registerTortureBucket({
|
|
|
1913
2155
|
amountSompi: "5000",
|
|
1914
2156
|
estimatedFeeSompi: "100",
|
|
1915
2157
|
estimatedMass: "10",
|
|
1916
|
-
inputs: [
|
|
1917
|
-
|
|
2158
|
+
inputs: [
|
|
2159
|
+
{
|
|
2160
|
+
outpoint: { transactionId: "b".repeat(64), index: 0 },
|
|
2161
|
+
amountSompi: "6000"
|
|
2162
|
+
}
|
|
2163
|
+
],
|
|
2164
|
+
outputs: [
|
|
2165
|
+
{
|
|
2166
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2167
|
+
amountSompi: "5000"
|
|
2168
|
+
}
|
|
2169
|
+
]
|
|
1918
2170
|
};
|
|
1919
2171
|
const hash = calculateContentHash(payload);
|
|
1920
2172
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
@@ -1956,7 +2208,7 @@ registerTortureBucket({
|
|
|
1956
2208
|
}
|
|
1957
2209
|
const payload = {
|
|
1958
2210
|
schema: "hardkas.txPlan",
|
|
1959
|
-
hardkasVersion: "0.7.
|
|
2211
|
+
hardkasVersion: "0.7.5-alpha",
|
|
1960
2212
|
version: ARTIFACT_VERSION,
|
|
1961
2213
|
networkId: "simnet",
|
|
1962
2214
|
mode: "simulated",
|
|
@@ -1968,13 +2220,26 @@ registerTortureBucket({
|
|
|
1968
2220
|
amountSompi: "7000",
|
|
1969
2221
|
estimatedFeeSompi: "100",
|
|
1970
2222
|
estimatedMass: "10",
|
|
1971
|
-
inputs: [
|
|
1972
|
-
|
|
2223
|
+
inputs: [
|
|
2224
|
+
{
|
|
2225
|
+
outpoint: { transactionId: "p".repeat(64), index: 0 },
|
|
2226
|
+
amountSompi: "8000"
|
|
2227
|
+
}
|
|
2228
|
+
],
|
|
2229
|
+
outputs: [
|
|
2230
|
+
{
|
|
2231
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2232
|
+
amountSompi: "7000"
|
|
2233
|
+
}
|
|
2234
|
+
]
|
|
1973
2235
|
};
|
|
1974
2236
|
const hash = calculateContentHash(payload);
|
|
1975
2237
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
1976
2238
|
const safeArt = { ...payload, artifactId: artId, contentHash: hash };
|
|
1977
|
-
fs.writeFileSync(
|
|
2239
|
+
fs.writeFileSync(
|
|
2240
|
+
path.join(artifactsDir, `${artId}.json`),
|
|
2241
|
+
JSON.stringify(safeArt, null, 2)
|
|
2242
|
+
);
|
|
1978
2243
|
const syncResult = await backend.sync({ strict: false, cwd: sandboxDir });
|
|
1979
2244
|
const artifacts = await backend.findArtifacts();
|
|
1980
2245
|
if (artifacts.length === 0) {
|
|
@@ -1989,7 +2254,10 @@ registerTortureBucket({
|
|
|
1989
2254
|
const newStore = new HardkasStore({ dbPath });
|
|
1990
2255
|
newStore.connect({ autoMigrate: true });
|
|
1991
2256
|
const newBackend = new SqliteQueryBackend(newStore);
|
|
1992
|
-
const rebuildResult = await newBackend.rebuild({
|
|
2257
|
+
const rebuildResult = await newBackend.rebuild({
|
|
2258
|
+
strict: false,
|
|
2259
|
+
cwd: sandboxDir
|
|
2260
|
+
});
|
|
1993
2261
|
const rebuiltArtifacts = await newBackend.findArtifacts();
|
|
1994
2262
|
if (rebuiltArtifacts.length !== artifacts.length) {
|
|
1995
2263
|
throw new TortureInvariantError(
|
|
@@ -2004,7 +2272,7 @@ registerTortureBucket({
|
|
|
2004
2272
|
case 5: {
|
|
2005
2273
|
const payloadWithCRLF = {
|
|
2006
2274
|
schema: "hardkas.txPlan",
|
|
2007
|
-
hardkasVersion: "0.7.
|
|
2275
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2008
2276
|
version: ARTIFACT_VERSION,
|
|
2009
2277
|
networkId: "simnet",
|
|
2010
2278
|
mode: "simulated",
|
|
@@ -2016,12 +2284,28 @@ registerTortureBucket({
|
|
|
2016
2284
|
amountSompi: "9000",
|
|
2017
2285
|
estimatedFeeSompi: "100",
|
|
2018
2286
|
estimatedMass: "10",
|
|
2019
|
-
inputs: [
|
|
2020
|
-
|
|
2287
|
+
inputs: [
|
|
2288
|
+
{
|
|
2289
|
+
outpoint: { transactionId: "c".repeat(64), index: 0 },
|
|
2290
|
+
amountSompi: "10000"
|
|
2291
|
+
}
|
|
2292
|
+
],
|
|
2293
|
+
outputs: [
|
|
2294
|
+
{
|
|
2295
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2296
|
+
amountSompi: "9000"
|
|
2297
|
+
}
|
|
2298
|
+
]
|
|
2021
2299
|
};
|
|
2022
2300
|
const hashLF = calculateContentHash(payloadWithCRLF, CURRENT_HASH_VERSION);
|
|
2023
|
-
const payloadCRLFInjected = {
|
|
2024
|
-
|
|
2301
|
+
const payloadCRLFInjected = {
|
|
2302
|
+
...payloadWithCRLF,
|
|
2303
|
+
planId: `plan-crlf-test-${ctx.caseSeed}`.replace(/\n/g, "\r\n")
|
|
2304
|
+
};
|
|
2305
|
+
const hashCRLF = calculateContentHash(
|
|
2306
|
+
payloadCRLFInjected,
|
|
2307
|
+
CURRENT_HASH_VERSION
|
|
2308
|
+
);
|
|
2025
2309
|
if (hashLF !== hashCRLF) {
|
|
2026
2310
|
throw new TortureInvariantError(
|
|
2027
2311
|
`CRLF normalization failed: LF hash ${hashLF.slice(0, 16)} !== CRLF hash ${hashCRLF.slice(0, 16)}`,
|
|
@@ -2039,7 +2323,7 @@ registerTortureBucket({
|
|
|
2039
2323
|
case 6: {
|
|
2040
2324
|
const payload = {
|
|
2041
2325
|
schema: "hardkas.txPlan",
|
|
2042
|
-
hardkasVersion: "0.7.
|
|
2326
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2043
2327
|
version: ARTIFACT_VERSION,
|
|
2044
2328
|
networkId: "simnet",
|
|
2045
2329
|
mode: "simulated",
|
|
@@ -2051,20 +2335,38 @@ registerTortureBucket({
|
|
|
2051
2335
|
amountSompi: "11000",
|
|
2052
2336
|
estimatedFeeSompi: "100",
|
|
2053
2337
|
estimatedMass: "10",
|
|
2054
|
-
inputs: [
|
|
2055
|
-
|
|
2338
|
+
inputs: [
|
|
2339
|
+
{
|
|
2340
|
+
outpoint: { transactionId: "k".repeat(64), index: 0 },
|
|
2341
|
+
amountSompi: "12000"
|
|
2342
|
+
}
|
|
2343
|
+
],
|
|
2344
|
+
outputs: [
|
|
2345
|
+
{
|
|
2346
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2347
|
+
amountSompi: "11000"
|
|
2348
|
+
}
|
|
2349
|
+
]
|
|
2056
2350
|
};
|
|
2057
2351
|
const hash = calculateContentHash(payload);
|
|
2058
2352
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2059
2353
|
const art = { ...payload, artifactId: artId, contentHash: hash };
|
|
2060
2354
|
const filePath = path.join(artifactsDir, `${artId}.json`);
|
|
2061
2355
|
fs.writeFileSync(filePath, JSON.stringify(art, null, 2));
|
|
2062
|
-
const payload2 = {
|
|
2356
|
+
const payload2 = {
|
|
2357
|
+
...payload,
|
|
2358
|
+
planId: `plan-unlocked-${ctx.caseSeed}`,
|
|
2359
|
+
amountSompi: "99000"
|
|
2360
|
+
};
|
|
2063
2361
|
const hash2 = calculateContentHash(payload2);
|
|
2064
2362
|
const artId2 = `plan-${hash2.slice(0, 16)}`;
|
|
2065
2363
|
fs.writeFileSync(
|
|
2066
2364
|
path.join(artifactsDir, `${artId2}.json`),
|
|
2067
|
-
JSON.stringify(
|
|
2365
|
+
JSON.stringify(
|
|
2366
|
+
{ ...payload2, artifactId: artId2, contentHash: hash2 },
|
|
2367
|
+
null,
|
|
2368
|
+
2
|
|
2369
|
+
)
|
|
2068
2370
|
);
|
|
2069
2371
|
const syncResult = await backend.sync({ strict: false, cwd: sandboxDir });
|
|
2070
2372
|
const artifacts = await backend.findArtifacts();
|
|
@@ -2105,7 +2407,7 @@ registerTortureBucket({
|
|
|
2105
2407
|
const nfdString = "e\u0301";
|
|
2106
2408
|
const payload1 = {
|
|
2107
2409
|
schema: "hardkas.txPlan",
|
|
2108
|
-
hardkasVersion: "0.7.
|
|
2410
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2109
2411
|
version: ARTIFACT_VERSION,
|
|
2110
2412
|
networkId: "simnet",
|
|
2111
2413
|
mode: "simulated",
|
|
@@ -2117,10 +2419,23 @@ registerTortureBucket({
|
|
|
2117
2419
|
amountSompi: "1000",
|
|
2118
2420
|
estimatedFeeSompi: "100",
|
|
2119
2421
|
estimatedMass: "10",
|
|
2120
|
-
inputs: [
|
|
2121
|
-
|
|
2422
|
+
inputs: [
|
|
2423
|
+
{
|
|
2424
|
+
outpoint: { transactionId: "u".repeat(64), index: 0 },
|
|
2425
|
+
amountSompi: "2000"
|
|
2426
|
+
}
|
|
2427
|
+
],
|
|
2428
|
+
outputs: [
|
|
2429
|
+
{
|
|
2430
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2431
|
+
amountSompi: "1000"
|
|
2432
|
+
}
|
|
2433
|
+
]
|
|
2434
|
+
};
|
|
2435
|
+
const payload2 = {
|
|
2436
|
+
...payload1,
|
|
2437
|
+
planId: `plan-nfc-${nfdString}-${ctx.caseSeed}`
|
|
2122
2438
|
};
|
|
2123
|
-
const payload2 = { ...payload1, planId: `plan-nfc-${nfdString}-${ctx.caseSeed}` };
|
|
2124
2439
|
const hash1 = calculateContentHash(payload1, CURRENT_HASH_VERSION);
|
|
2125
2440
|
const hash2 = calculateContentHash(payload2, CURRENT_HASH_VERSION);
|
|
2126
2441
|
if (hash1 !== hash2) {
|
|
@@ -2132,7 +2447,10 @@ registerTortureBucket({
|
|
|
2132
2447
|
}
|
|
2133
2448
|
const artId = `plan-${hash1.slice(0, 16)}`;
|
|
2134
2449
|
const art = { ...payload1, artifactId: artId, contentHash: hash1 };
|
|
2135
|
-
fs.writeFileSync(
|
|
2450
|
+
fs.writeFileSync(
|
|
2451
|
+
path.join(artifactsDir, `${artId}.json`),
|
|
2452
|
+
JSON.stringify(art, null, 2)
|
|
2453
|
+
);
|
|
2136
2454
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2137
2455
|
break;
|
|
2138
2456
|
}
|
|
@@ -2141,7 +2459,7 @@ registerTortureBucket({
|
|
|
2141
2459
|
const emoji = ctx.prng.pick(emojiStrings);
|
|
2142
2460
|
const payload = {
|
|
2143
2461
|
schema: "hardkas.txPlan",
|
|
2144
|
-
hardkasVersion: "0.7.
|
|
2462
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2145
2463
|
version: ARTIFACT_VERSION,
|
|
2146
2464
|
networkId: "simnet",
|
|
2147
2465
|
mode: "simulated",
|
|
@@ -2153,13 +2471,26 @@ registerTortureBucket({
|
|
|
2153
2471
|
amountSompi: "2000",
|
|
2154
2472
|
estimatedFeeSompi: "100",
|
|
2155
2473
|
estimatedMass: "10",
|
|
2156
|
-
inputs: [
|
|
2157
|
-
|
|
2474
|
+
inputs: [
|
|
2475
|
+
{
|
|
2476
|
+
outpoint: { transactionId: "e".repeat(64), index: 0 },
|
|
2477
|
+
amountSompi: "3000"
|
|
2478
|
+
}
|
|
2479
|
+
],
|
|
2480
|
+
outputs: [
|
|
2481
|
+
{
|
|
2482
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2483
|
+
amountSompi: "2000"
|
|
2484
|
+
}
|
|
2485
|
+
]
|
|
2158
2486
|
};
|
|
2159
2487
|
const hash = calculateContentHash(payload);
|
|
2160
2488
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2161
2489
|
const art = { ...payload, artifactId: artId, contentHash: hash };
|
|
2162
|
-
fs.writeFileSync(
|
|
2490
|
+
fs.writeFileSync(
|
|
2491
|
+
path.join(artifactsDir, `${artId}.json`),
|
|
2492
|
+
JSON.stringify(art, null, 2)
|
|
2493
|
+
);
|
|
2163
2494
|
const syncResult = await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2164
2495
|
if (!syncResult.ok) {
|
|
2165
2496
|
throw new TortureInvariantError(
|
|
@@ -2195,7 +2526,7 @@ registerTortureBucket({
|
|
|
2195
2526
|
const invisible = ctx.prng.pick(invisibleChars);
|
|
2196
2527
|
const payload = {
|
|
2197
2528
|
schema: "hardkas.txPlan",
|
|
2198
|
-
hardkasVersion: "0.7.
|
|
2529
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2199
2530
|
version: ARTIFACT_VERSION,
|
|
2200
2531
|
networkId: "simnet",
|
|
2201
2532
|
mode: "simulated",
|
|
@@ -2207,15 +2538,31 @@ registerTortureBucket({
|
|
|
2207
2538
|
amountSompi: "4000",
|
|
2208
2539
|
estimatedFeeSompi: "100",
|
|
2209
2540
|
estimatedMass: "10",
|
|
2210
|
-
inputs: [
|
|
2211
|
-
|
|
2541
|
+
inputs: [
|
|
2542
|
+
{
|
|
2543
|
+
outpoint: { transactionId: "z".repeat(64), index: 0 },
|
|
2544
|
+
amountSompi: "5000"
|
|
2545
|
+
}
|
|
2546
|
+
],
|
|
2547
|
+
outputs: [
|
|
2548
|
+
{
|
|
2549
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2550
|
+
amountSompi: "4000"
|
|
2551
|
+
}
|
|
2552
|
+
]
|
|
2212
2553
|
};
|
|
2213
2554
|
const hash = calculateContentHash(payload);
|
|
2214
|
-
const payloadWithout = {
|
|
2555
|
+
const payloadWithout = {
|
|
2556
|
+
...payload,
|
|
2557
|
+
planId: `plan-invisiblechar-${ctx.caseSeed}`
|
|
2558
|
+
};
|
|
2215
2559
|
const hashWithout = calculateContentHash(payloadWithout);
|
|
2216
2560
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2217
2561
|
const art = { ...payload, artifactId: artId, contentHash: hash };
|
|
2218
|
-
fs.writeFileSync(
|
|
2562
|
+
fs.writeFileSync(
|
|
2563
|
+
path.join(artifactsDir, `${artId}.json`),
|
|
2564
|
+
JSON.stringify(art, null, 2)
|
|
2565
|
+
);
|
|
2219
2566
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2220
2567
|
const artifacts = await backend.findArtifacts();
|
|
2221
2568
|
const found = artifacts.find((a) => a.artifactId === artId);
|
|
@@ -2233,7 +2580,7 @@ registerTortureBucket({
|
|
|
2233
2580
|
const cyrillicAddr = "kaspa:sim_address_with_\u0430";
|
|
2234
2581
|
const payloadLatin = {
|
|
2235
2582
|
schema: "hardkas.txPlan",
|
|
2236
|
-
hardkasVersion: "0.7.
|
|
2583
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2237
2584
|
version: ARTIFACT_VERSION,
|
|
2238
2585
|
networkId: "simnet",
|
|
2239
2586
|
mode: "simulated",
|
|
@@ -2245,10 +2592,24 @@ registerTortureBucket({
|
|
|
2245
2592
|
amountSompi: "6000",
|
|
2246
2593
|
estimatedFeeSompi: "100",
|
|
2247
2594
|
estimatedMass: "10",
|
|
2248
|
-
inputs: [
|
|
2249
|
-
|
|
2595
|
+
inputs: [
|
|
2596
|
+
{
|
|
2597
|
+
outpoint: { transactionId: "h".repeat(64), index: 0 },
|
|
2598
|
+
amountSompi: "7000"
|
|
2599
|
+
}
|
|
2600
|
+
],
|
|
2601
|
+
outputs: [
|
|
2602
|
+
{
|
|
2603
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2604
|
+
amountSompi: "6000"
|
|
2605
|
+
}
|
|
2606
|
+
]
|
|
2607
|
+
};
|
|
2608
|
+
const payloadCyrillic = {
|
|
2609
|
+
...payloadLatin,
|
|
2610
|
+
planId: `plan-homoglyph-cyrillic-${ctx.caseSeed}`,
|
|
2611
|
+
from: { address: cyrillicAddr }
|
|
2250
2612
|
};
|
|
2251
|
-
const payloadCyrillic = { ...payloadLatin, planId: `plan-homoglyph-cyrillic-${ctx.caseSeed}`, from: { address: cyrillicAddr } };
|
|
2252
2613
|
const hashLatin = calculateContentHash(payloadLatin);
|
|
2253
2614
|
const hashCyrillic = calculateContentHash(payloadCyrillic);
|
|
2254
2615
|
if (hashLatin === hashCyrillic) {
|
|
@@ -2258,10 +2619,24 @@ registerTortureBucket({
|
|
|
2258
2619
|
"catastrophic"
|
|
2259
2620
|
);
|
|
2260
2621
|
}
|
|
2261
|
-
const art1 = {
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2622
|
+
const art1 = {
|
|
2623
|
+
...payloadLatin,
|
|
2624
|
+
artifactId: `plan-${hashLatin.slice(0, 16)}`,
|
|
2625
|
+
contentHash: hashLatin
|
|
2626
|
+
};
|
|
2627
|
+
const art2 = {
|
|
2628
|
+
...payloadCyrillic,
|
|
2629
|
+
artifactId: `plan-${hashCyrillic.slice(0, 16)}`,
|
|
2630
|
+
contentHash: hashCyrillic
|
|
2631
|
+
};
|
|
2632
|
+
fs.writeFileSync(
|
|
2633
|
+
path.join(artifactsDir, `${art1.artifactId}.json`),
|
|
2634
|
+
JSON.stringify(art1, null, 2)
|
|
2635
|
+
);
|
|
2636
|
+
fs.writeFileSync(
|
|
2637
|
+
path.join(artifactsDir, `${art2.artifactId}.json`),
|
|
2638
|
+
JSON.stringify(art2, null, 2)
|
|
2639
|
+
);
|
|
2265
2640
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2266
2641
|
const artifacts = await backend.findArtifacts();
|
|
2267
2642
|
if (artifacts.length < 2) {
|
|
@@ -2277,7 +2652,7 @@ registerTortureBucket({
|
|
|
2277
2652
|
const mixedString = "caf\xE9 re\u0301sume\u0301";
|
|
2278
2653
|
const payload = {
|
|
2279
2654
|
schema: "hardkas.txPlan",
|
|
2280
|
-
hardkasVersion: "0.7.
|
|
2655
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2281
2656
|
version: ARTIFACT_VERSION,
|
|
2282
2657
|
networkId: "simnet",
|
|
2283
2658
|
mode: "simulated",
|
|
@@ -2289,10 +2664,23 @@ registerTortureBucket({
|
|
|
2289
2664
|
amountSompi: "8000",
|
|
2290
2665
|
estimatedFeeSompi: "100",
|
|
2291
2666
|
estimatedMass: "10",
|
|
2292
|
-
inputs: [
|
|
2293
|
-
|
|
2667
|
+
inputs: [
|
|
2668
|
+
{
|
|
2669
|
+
outpoint: { transactionId: "n".repeat(64), index: 0 },
|
|
2670
|
+
amountSompi: "9000"
|
|
2671
|
+
}
|
|
2672
|
+
],
|
|
2673
|
+
outputs: [
|
|
2674
|
+
{
|
|
2675
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2676
|
+
amountSompi: "8000"
|
|
2677
|
+
}
|
|
2678
|
+
]
|
|
2679
|
+
};
|
|
2680
|
+
const allNFC = {
|
|
2681
|
+
...payload,
|
|
2682
|
+
planId: `plan-mixed-${mixedString.normalize("NFC")}-${ctx.caseSeed}`
|
|
2294
2683
|
};
|
|
2295
|
-
const allNFC = { ...payload, planId: `plan-mixed-${mixedString.normalize("NFC")}-${ctx.caseSeed}` };
|
|
2296
2684
|
const hash = calculateContentHash(payload, CURRENT_HASH_VERSION);
|
|
2297
2685
|
const hashNFC = calculateContentHash(allNFC, CURRENT_HASH_VERSION);
|
|
2298
2686
|
if (hash !== hashNFC) {
|
|
@@ -2304,7 +2692,10 @@ registerTortureBucket({
|
|
|
2304
2692
|
}
|
|
2305
2693
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2306
2694
|
const art = { ...payload, artifactId: artId, contentHash: hash };
|
|
2307
|
-
fs.writeFileSync(
|
|
2695
|
+
fs.writeFileSync(
|
|
2696
|
+
path.join(artifactsDir, `${artId}.json`),
|
|
2697
|
+
JSON.stringify(art, null, 2)
|
|
2698
|
+
);
|
|
2308
2699
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2309
2700
|
break;
|
|
2310
2701
|
}
|
|
@@ -2330,7 +2721,7 @@ registerTortureBucket({
|
|
|
2330
2721
|
let writeArtifact2 = function(suffix, amount) {
|
|
2331
2722
|
const payload = {
|
|
2332
2723
|
schema: "hardkas.txPlan",
|
|
2333
|
-
hardkasVersion: "0.7.
|
|
2724
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2334
2725
|
version: ARTIFACT_VERSION,
|
|
2335
2726
|
networkId: "simnet",
|
|
2336
2727
|
mode: "simulated",
|
|
@@ -2342,13 +2733,29 @@ registerTortureBucket({
|
|
|
2342
2733
|
amountSompi: amount,
|
|
2343
2734
|
estimatedFeeSompi: "100",
|
|
2344
2735
|
estimatedMass: "10",
|
|
2345
|
-
inputs: [
|
|
2346
|
-
|
|
2736
|
+
inputs: [
|
|
2737
|
+
{
|
|
2738
|
+
outpoint: {
|
|
2739
|
+
transactionId: "t".repeat(64),
|
|
2740
|
+
index: parseInt(suffix.replace(/\D/g, "") || "0")
|
|
2741
|
+
},
|
|
2742
|
+
amountSompi: "20000"
|
|
2743
|
+
}
|
|
2744
|
+
],
|
|
2745
|
+
outputs: [
|
|
2746
|
+
{
|
|
2747
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2748
|
+
amountSompi: amount
|
|
2749
|
+
}
|
|
2750
|
+
]
|
|
2347
2751
|
};
|
|
2348
2752
|
const hash = calculateContentHash(payload);
|
|
2349
2753
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2350
2754
|
const filePath = path.join(artifactsDir, `${artId}.json`);
|
|
2351
|
-
fs.writeFileSync(
|
|
2755
|
+
fs.writeFileSync(
|
|
2756
|
+
filePath,
|
|
2757
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
2758
|
+
);
|
|
2352
2759
|
return filePath;
|
|
2353
2760
|
};
|
|
2354
2761
|
var writeArtifact = writeArtifact2;
|
|
@@ -2361,7 +2768,11 @@ registerTortureBucket({
|
|
|
2361
2768
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2362
2769
|
const pastTime = new Date(Date.now() - 365 * 24 * 60 * 60 * 1e3);
|
|
2363
2770
|
fs.utimesSync(filePath, pastTime, pastTime);
|
|
2364
|
-
const newPayload = {
|
|
2771
|
+
const newPayload = {
|
|
2772
|
+
schema: "hardkas.txPlan",
|
|
2773
|
+
changed: true,
|
|
2774
|
+
planId: "modified"
|
|
2775
|
+
};
|
|
2365
2776
|
fs.writeFileSync(filePath, JSON.stringify(newPayload));
|
|
2366
2777
|
fs.utimesSync(filePath, pastTime, pastTime);
|
|
2367
2778
|
store.disconnect();
|
|
@@ -2434,7 +2845,7 @@ registerTortureBucket({
|
|
|
2434
2845
|
fs.utimesSync(filePath, oldTime, oldTime);
|
|
2435
2846
|
const newPayload = {
|
|
2436
2847
|
schema: "hardkas.txPlan",
|
|
2437
|
-
hardkasVersion: "0.7.
|
|
2848
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2438
2849
|
version: ARTIFACT_VERSION,
|
|
2439
2850
|
networkId: "simnet",
|
|
2440
2851
|
mode: "simulated",
|
|
@@ -2446,11 +2857,32 @@ registerTortureBucket({
|
|
|
2446
2857
|
amountSompi: "99999",
|
|
2447
2858
|
estimatedFeeSompi: "100",
|
|
2448
2859
|
estimatedMass: "10",
|
|
2449
|
-
inputs: [
|
|
2450
|
-
|
|
2860
|
+
inputs: [
|
|
2861
|
+
{
|
|
2862
|
+
outpoint: { transactionId: "f".repeat(64), index: 99 },
|
|
2863
|
+
amountSompi: "100000"
|
|
2864
|
+
}
|
|
2865
|
+
],
|
|
2866
|
+
outputs: [
|
|
2867
|
+
{
|
|
2868
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2869
|
+
amountSompi: "99999"
|
|
2870
|
+
}
|
|
2871
|
+
]
|
|
2451
2872
|
};
|
|
2452
2873
|
const newHash = calculateContentHash(newPayload);
|
|
2453
|
-
fs.writeFileSync(
|
|
2874
|
+
fs.writeFileSync(
|
|
2875
|
+
filePath,
|
|
2876
|
+
JSON.stringify(
|
|
2877
|
+
{
|
|
2878
|
+
...newPayload,
|
|
2879
|
+
artifactId: `plan-${newHash.slice(0, 16)}`,
|
|
2880
|
+
contentHash: newHash
|
|
2881
|
+
},
|
|
2882
|
+
null,
|
|
2883
|
+
2
|
|
2884
|
+
)
|
|
2885
|
+
);
|
|
2454
2886
|
fs.utimesSync(filePath, oldTime, oldTime);
|
|
2455
2887
|
store.disconnect();
|
|
2456
2888
|
if (fs.existsSync(dbPath)) fs.unlinkSync(dbPath);
|
|
@@ -2488,7 +2920,7 @@ registerTortureBucket({
|
|
|
2488
2920
|
for (let i = 0; i < artifactCount; i++) {
|
|
2489
2921
|
const payload = {
|
|
2490
2922
|
schema: "hardkas.txPlan",
|
|
2491
|
-
hardkasVersion: "0.7.
|
|
2923
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2492
2924
|
version: ARTIFACT_VERSION,
|
|
2493
2925
|
networkId: "simnet",
|
|
2494
2926
|
mode: "simulated",
|
|
@@ -2500,8 +2932,18 @@ registerTortureBucket({
|
|
|
2500
2932
|
amountSompi: `${(i + 1) * 1e3}`,
|
|
2501
2933
|
estimatedFeeSompi: "100",
|
|
2502
2934
|
estimatedMass: "10",
|
|
2503
|
-
inputs: [
|
|
2504
|
-
|
|
2935
|
+
inputs: [
|
|
2936
|
+
{
|
|
2937
|
+
outpoint: { transactionId: "o".repeat(64), index: i },
|
|
2938
|
+
amountSompi: "20000"
|
|
2939
|
+
}
|
|
2940
|
+
],
|
|
2941
|
+
outputs: [
|
|
2942
|
+
{
|
|
2943
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
2944
|
+
amountSompi: `${(i + 1) * 1e3}`
|
|
2945
|
+
}
|
|
2946
|
+
]
|
|
2505
2947
|
};
|
|
2506
2948
|
const hash = calculateContentHash(payload);
|
|
2507
2949
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
@@ -2577,7 +3019,7 @@ registerTortureBucket({
|
|
|
2577
3019
|
for (let i = 0; i < extraCount; i++) {
|
|
2578
3020
|
const payload = {
|
|
2579
3021
|
schema: "hardkas.txPlan",
|
|
2580
|
-
hardkasVersion: "0.7.
|
|
3022
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2581
3023
|
version: ARTIFACT_VERSION,
|
|
2582
3024
|
networkId: "simnet",
|
|
2583
3025
|
mode: "simulated",
|
|
@@ -2589,14 +3031,28 @@ registerTortureBucket({
|
|
|
2589
3031
|
amountSompi: `${(i + 100) * 1e3}`,
|
|
2590
3032
|
estimatedFeeSompi: "100",
|
|
2591
3033
|
estimatedMass: "10",
|
|
2592
|
-
inputs: [
|
|
2593
|
-
|
|
3034
|
+
inputs: [
|
|
3035
|
+
{
|
|
3036
|
+
outpoint: { transactionId: "x".repeat(64), index: i + 100 },
|
|
3037
|
+
amountSompi: "200000"
|
|
3038
|
+
}
|
|
3039
|
+
],
|
|
3040
|
+
outputs: [
|
|
3041
|
+
{
|
|
3042
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3043
|
+
amountSompi: `${(i + 100) * 1e3}`
|
|
3044
|
+
}
|
|
3045
|
+
]
|
|
2594
3046
|
};
|
|
2595
3047
|
const hash = calculateContentHash(payload);
|
|
2596
3048
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2597
3049
|
fs.writeFileSync(
|
|
2598
3050
|
path.join(artifactsDir, `${artId}.json`),
|
|
2599
|
-
JSON.stringify(
|
|
3051
|
+
JSON.stringify(
|
|
3052
|
+
{ ...payload, artifactId: artId, contentHash: hash },
|
|
3053
|
+
null,
|
|
3054
|
+
2
|
|
3055
|
+
)
|
|
2600
3056
|
);
|
|
2601
3057
|
}
|
|
2602
3058
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
@@ -2633,7 +3089,7 @@ registerTortureBucket({
|
|
|
2633
3089
|
for (let i = 0; i < 5; i++) {
|
|
2634
3090
|
const payload = {
|
|
2635
3091
|
schema: "hardkas.txPlan",
|
|
2636
|
-
hardkasVersion: "0.7.
|
|
3092
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2637
3093
|
version: ARTIFACT_VERSION,
|
|
2638
3094
|
networkId: "simnet",
|
|
2639
3095
|
mode: "simulated",
|
|
@@ -2645,8 +3101,18 @@ registerTortureBucket({
|
|
|
2645
3101
|
amountSompi: `${(i + 1) * 1e3}`,
|
|
2646
3102
|
estimatedFeeSompi: "100",
|
|
2647
3103
|
estimatedMass: "10",
|
|
2648
|
-
inputs: [
|
|
2649
|
-
|
|
3104
|
+
inputs: [
|
|
3105
|
+
{
|
|
3106
|
+
outpoint: { transactionId: "H".repeat(64), index: i },
|
|
3107
|
+
amountSompi: "20000"
|
|
3108
|
+
}
|
|
3109
|
+
],
|
|
3110
|
+
outputs: [
|
|
3111
|
+
{
|
|
3112
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3113
|
+
amountSompi: `${(i + 1) * 1e3}`
|
|
3114
|
+
}
|
|
3115
|
+
]
|
|
2650
3116
|
};
|
|
2651
3117
|
const hash = calculateContentHash(payload);
|
|
2652
3118
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
@@ -2708,7 +3174,11 @@ registerTortureBucket({
|
|
|
2708
3174
|
}
|
|
2709
3175
|
case 4: {
|
|
2710
3176
|
const eventsPath = path.join(hardkasDir, "events.jsonl");
|
|
2711
|
-
fs.writeFileSync(
|
|
3177
|
+
fs.writeFileSync(
|
|
3178
|
+
eventsPath,
|
|
3179
|
+
"{{GARBAGE}}\n{also invalid}\nNOT JSON AT ALL\n",
|
|
3180
|
+
"utf-8"
|
|
3181
|
+
);
|
|
2712
3182
|
store.disconnect();
|
|
2713
3183
|
if (fs.existsSync(dbPath)) fs.unlinkSync(dbPath);
|
|
2714
3184
|
const newStore = new HardkasStore({ dbPath });
|
|
@@ -2729,7 +3199,7 @@ registerTortureBucket({
|
|
|
2729
3199
|
case 5: {
|
|
2730
3200
|
const phantomPayload = {
|
|
2731
3201
|
schema: "hardkas.txPlan",
|
|
2732
|
-
hardkasVersion: "0.7.
|
|
3202
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2733
3203
|
version: ARTIFACT_VERSION,
|
|
2734
3204
|
networkId: "simnet",
|
|
2735
3205
|
mode: "simulated",
|
|
@@ -2744,8 +3214,18 @@ registerTortureBucket({
|
|
|
2744
3214
|
amountSompi: "666",
|
|
2745
3215
|
estimatedFeeSompi: "100",
|
|
2746
3216
|
estimatedMass: "10",
|
|
2747
|
-
inputs: [
|
|
2748
|
-
|
|
3217
|
+
inputs: [
|
|
3218
|
+
{
|
|
3219
|
+
outpoint: { transactionId: "P".repeat(64), index: 0 },
|
|
3220
|
+
amountSompi: "1000"
|
|
3221
|
+
}
|
|
3222
|
+
],
|
|
3223
|
+
outputs: [
|
|
3224
|
+
{
|
|
3225
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3226
|
+
amountSompi: "666"
|
|
3227
|
+
}
|
|
3228
|
+
]
|
|
2749
3229
|
};
|
|
2750
3230
|
fs.writeFileSync(
|
|
2751
3231
|
path.join(artifactsDir, "phantom-fake-id-12345.json"),
|
|
@@ -2788,7 +3268,7 @@ registerTortureBucket({
|
|
|
2788
3268
|
let writePlan2 = function(id, amount) {
|
|
2789
3269
|
const payload = {
|
|
2790
3270
|
schema: "hardkas.txPlan",
|
|
2791
|
-
hardkasVersion: "0.7.
|
|
3271
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2792
3272
|
version: ARTIFACT_VERSION,
|
|
2793
3273
|
networkId: "simnet",
|
|
2794
3274
|
mode: "simulated",
|
|
@@ -2800,13 +3280,26 @@ registerTortureBucket({
|
|
|
2800
3280
|
amountSompi: amount,
|
|
2801
3281
|
estimatedFeeSompi: "100",
|
|
2802
3282
|
estimatedMass: "10",
|
|
2803
|
-
inputs: [
|
|
2804
|
-
|
|
3283
|
+
inputs: [
|
|
3284
|
+
{
|
|
3285
|
+
outpoint: { transactionId: "a".repeat(64), index: 0 },
|
|
3286
|
+
amountSompi: "10000"
|
|
3287
|
+
}
|
|
3288
|
+
],
|
|
3289
|
+
outputs: [
|
|
3290
|
+
{
|
|
3291
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3292
|
+
amountSompi: amount
|
|
3293
|
+
}
|
|
3294
|
+
]
|
|
2805
3295
|
};
|
|
2806
3296
|
const hash = calculateContentHash(payload);
|
|
2807
3297
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2808
3298
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
2809
|
-
fs.writeFileSync(
|
|
3299
|
+
fs.writeFileSync(
|
|
3300
|
+
file,
|
|
3301
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
3302
|
+
);
|
|
2810
3303
|
return { artId, file, payload };
|
|
2811
3304
|
};
|
|
2812
3305
|
var writePlan = writePlan2;
|
|
@@ -2817,7 +3310,10 @@ registerTortureBucket({
|
|
|
2817
3310
|
case 1: {
|
|
2818
3311
|
const files = [];
|
|
2819
3312
|
for (let i = 0; i < 5; i++) {
|
|
2820
|
-
const { file } = writePlan2(
|
|
3313
|
+
const { file } = writePlan2(
|
|
3314
|
+
`plan-av-${i}-${ctx.caseSeed}`,
|
|
3315
|
+
`${(i + 1) * 1e3}`
|
|
3316
|
+
);
|
|
2821
3317
|
files.push(file);
|
|
2822
3318
|
}
|
|
2823
3319
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
@@ -2867,9 +3363,17 @@ registerTortureBucket({
|
|
|
2867
3363
|
break;
|
|
2868
3364
|
}
|
|
2869
3365
|
case 3: {
|
|
2870
|
-
const { artId, file, payload } = writePlan2(
|
|
3366
|
+
const { artId, file, payload } = writePlan2(
|
|
3367
|
+
`plan-corrupt-${ctx.caseSeed}`,
|
|
3368
|
+
"9000"
|
|
3369
|
+
);
|
|
2871
3370
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
2872
|
-
const corrupted = {
|
|
3371
|
+
const corrupted = {
|
|
3372
|
+
...payload,
|
|
3373
|
+
artifactId: artId,
|
|
3374
|
+
contentHash: "12345fakehash",
|
|
3375
|
+
amountSompi: "99999"
|
|
3376
|
+
};
|
|
2873
3377
|
fs.writeFileSync(file, JSON.stringify(corrupted, null, 2));
|
|
2874
3378
|
const report = await backend.doctor();
|
|
2875
3379
|
if (report.ok) {
|
|
@@ -2934,12 +3438,16 @@ registerTortureBucket({
|
|
|
2934
3438
|
async run(ctx) {
|
|
2935
3439
|
const { sandboxDir, hardkasDir, artifactsDir, dbPath } = createSandbox(ctx);
|
|
2936
3440
|
const subCase = ctx.prng.nextInt(1, 5);
|
|
2937
|
-
const outsideDir = path.join(
|
|
3441
|
+
const outsideDir = path.join(
|
|
3442
|
+
ctx.workspaceDir,
|
|
3443
|
+
".tmp",
|
|
3444
|
+
`torture-outside-${ctx.caseId}-${ctx.caseSeed}`
|
|
3445
|
+
);
|
|
2938
3446
|
fs.mkdirSync(outsideDir, { recursive: true });
|
|
2939
3447
|
const outsideFile = path.join(outsideDir, "outside-artifact.json");
|
|
2940
3448
|
const outsidePayload = {
|
|
2941
3449
|
schema: "hardkas.txPlan",
|
|
2942
|
-
hardkasVersion: "0.7.
|
|
3450
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2943
3451
|
version: ARTIFACT_VERSION,
|
|
2944
3452
|
networkId: "simnet",
|
|
2945
3453
|
mode: "simulated",
|
|
@@ -2951,16 +3459,34 @@ registerTortureBucket({
|
|
|
2951
3459
|
amountSompi: "500000",
|
|
2952
3460
|
estimatedFeeSompi: "100",
|
|
2953
3461
|
estimatedMass: "10",
|
|
2954
|
-
inputs: [
|
|
2955
|
-
|
|
3462
|
+
inputs: [
|
|
3463
|
+
{ outpoint: { transactionId: "o".repeat(64), index: 0 }, amountSompi: "600000" }
|
|
3464
|
+
],
|
|
3465
|
+
outputs: [
|
|
3466
|
+
{
|
|
3467
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3468
|
+
amountSompi: "500000"
|
|
3469
|
+
}
|
|
3470
|
+
]
|
|
2956
3471
|
};
|
|
2957
3472
|
const outsideHash = calculateContentHash(outsidePayload);
|
|
2958
|
-
fs.writeFileSync(
|
|
3473
|
+
fs.writeFileSync(
|
|
3474
|
+
outsideFile,
|
|
3475
|
+
JSON.stringify(
|
|
3476
|
+
{
|
|
3477
|
+
...outsidePayload,
|
|
3478
|
+
artifactId: `plan-${outsideHash.slice(0, 16)}`,
|
|
3479
|
+
contentHash: outsideHash
|
|
3480
|
+
},
|
|
3481
|
+
null,
|
|
3482
|
+
2
|
|
3483
|
+
)
|
|
3484
|
+
);
|
|
2959
3485
|
try {
|
|
2960
3486
|
let writePlan2 = function(id, amount) {
|
|
2961
3487
|
const payload = {
|
|
2962
3488
|
schema: "hardkas.txPlan",
|
|
2963
|
-
hardkasVersion: "0.7.
|
|
3489
|
+
hardkasVersion: "0.7.5-alpha",
|
|
2964
3490
|
version: ARTIFACT_VERSION,
|
|
2965
3491
|
networkId: "simnet",
|
|
2966
3492
|
mode: "simulated",
|
|
@@ -2972,13 +3498,26 @@ registerTortureBucket({
|
|
|
2972
3498
|
amountSompi: amount,
|
|
2973
3499
|
estimatedFeeSompi: "100",
|
|
2974
3500
|
estimatedMass: "10",
|
|
2975
|
-
inputs: [
|
|
2976
|
-
|
|
3501
|
+
inputs: [
|
|
3502
|
+
{
|
|
3503
|
+
outpoint: { transactionId: "s".repeat(64), index: 0 },
|
|
3504
|
+
amountSompi: "10000"
|
|
3505
|
+
}
|
|
3506
|
+
],
|
|
3507
|
+
outputs: [
|
|
3508
|
+
{
|
|
3509
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3510
|
+
amountSompi: amount
|
|
3511
|
+
}
|
|
3512
|
+
]
|
|
2977
3513
|
};
|
|
2978
3514
|
const hash = calculateContentHash(payload);
|
|
2979
3515
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
2980
3516
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
2981
|
-
fs.writeFileSync(
|
|
3517
|
+
fs.writeFileSync(
|
|
3518
|
+
file,
|
|
3519
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
3520
|
+
);
|
|
2982
3521
|
return { artId, file };
|
|
2983
3522
|
};
|
|
2984
3523
|
var writePlan = writePlan2;
|
|
@@ -3016,7 +3555,9 @@ registerTortureBucket({
|
|
|
3016
3555
|
fs.symlinkSync(outsideFile, linkPath);
|
|
3017
3556
|
await backend.sync({ strict: false, cwd: sandboxDir });
|
|
3018
3557
|
const artifacts = await backend.findArtifacts();
|
|
3019
|
-
const foundOutside = artifacts.find(
|
|
3558
|
+
const foundOutside = artifacts.find(
|
|
3559
|
+
(a) => a.payload.planId === `plan-outside-${ctx.caseSeed}`
|
|
3560
|
+
);
|
|
3020
3561
|
if (foundOutside) {
|
|
3021
3562
|
throw new TortureInvariantError(
|
|
3022
3563
|
"Indexed artifact from a symlink pointing outside the workspace boundary",
|
|
@@ -3054,7 +3595,7 @@ registerTortureBucket({
|
|
|
3054
3595
|
}
|
|
3055
3596
|
const payload = {
|
|
3056
3597
|
schema: "hardkas.txPlan",
|
|
3057
|
-
hardkasVersion: "0.7.
|
|
3598
|
+
hardkasVersion: "0.7.5-alpha",
|
|
3058
3599
|
version: ARTIFACT_VERSION,
|
|
3059
3600
|
networkId: "simnet",
|
|
3060
3601
|
mode: "simulated",
|
|
@@ -3066,13 +3607,31 @@ registerTortureBucket({
|
|
|
3066
3607
|
amountSompi: "3000",
|
|
3067
3608
|
estimatedFeeSompi: "100",
|
|
3068
3609
|
estimatedMass: "10",
|
|
3069
|
-
inputs: [
|
|
3070
|
-
|
|
3610
|
+
inputs: [
|
|
3611
|
+
{
|
|
3612
|
+
outpoint: { transactionId: "d".repeat(64), index: 0 },
|
|
3613
|
+
amountSompi: "5000"
|
|
3614
|
+
}
|
|
3615
|
+
],
|
|
3616
|
+
outputs: [
|
|
3617
|
+
{
|
|
3618
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3619
|
+
amountSompi: "3000"
|
|
3620
|
+
}
|
|
3621
|
+
]
|
|
3071
3622
|
};
|
|
3072
3623
|
const hash = calculateContentHash(payload);
|
|
3073
3624
|
fs.writeFileSync(
|
|
3074
3625
|
path.join(currentDir, `plan-deep-${hash.slice(0, 8)}.json`),
|
|
3075
|
-
JSON.stringify(
|
|
3626
|
+
JSON.stringify(
|
|
3627
|
+
{
|
|
3628
|
+
...payload,
|
|
3629
|
+
artifactId: `plan-${hash.slice(0, 16)}`,
|
|
3630
|
+
contentHash: hash
|
|
3631
|
+
},
|
|
3632
|
+
null,
|
|
3633
|
+
2
|
|
3634
|
+
)
|
|
3076
3635
|
);
|
|
3077
3636
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
3078
3637
|
}
|
|
@@ -3102,7 +3661,9 @@ registerTortureBucket({
|
|
|
3102
3661
|
fs.symlinkSync(outsideDir, linkPath, "junction");
|
|
3103
3662
|
await backend.sync({ strict: false, cwd: sandboxDir });
|
|
3104
3663
|
const artifacts = await backend.findArtifacts();
|
|
3105
|
-
const foundOutside = artifacts.find(
|
|
3664
|
+
const foundOutside = artifacts.find(
|
|
3665
|
+
(a) => a.payload.planId === `plan-outside-${ctx.caseSeed}`
|
|
3666
|
+
);
|
|
3106
3667
|
if (foundOutside) {
|
|
3107
3668
|
throw new TortureInvariantError(
|
|
3108
3669
|
"Indexed artifact from outside the workspace via a directory junction point",
|
|
@@ -3151,7 +3712,7 @@ registerTortureBucket({
|
|
|
3151
3712
|
let writePlan2 = function(id, amount) {
|
|
3152
3713
|
const payload = {
|
|
3153
3714
|
schema: "hardkas.txPlan",
|
|
3154
|
-
hardkasVersion: "0.7.
|
|
3715
|
+
hardkasVersion: "0.7.5-alpha",
|
|
3155
3716
|
version: ARTIFACT_VERSION,
|
|
3156
3717
|
networkId: "simnet",
|
|
3157
3718
|
mode: "simulated",
|
|
@@ -3163,13 +3724,26 @@ registerTortureBucket({
|
|
|
3163
3724
|
amountSompi: amount,
|
|
3164
3725
|
estimatedFeeSompi: "100",
|
|
3165
3726
|
estimatedMass: "10",
|
|
3166
|
-
inputs: [
|
|
3167
|
-
|
|
3727
|
+
inputs: [
|
|
3728
|
+
{
|
|
3729
|
+
outpoint: { transactionId: "d".repeat(64), index: 0 },
|
|
3730
|
+
amountSompi: "10000"
|
|
3731
|
+
}
|
|
3732
|
+
],
|
|
3733
|
+
outputs: [
|
|
3734
|
+
{
|
|
3735
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3736
|
+
amountSompi: amount
|
|
3737
|
+
}
|
|
3738
|
+
]
|
|
3168
3739
|
};
|
|
3169
3740
|
const hash = calculateContentHash(payload);
|
|
3170
3741
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
3171
3742
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
3172
|
-
fs.writeFileSync(
|
|
3743
|
+
fs.writeFileSync(
|
|
3744
|
+
file,
|
|
3745
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
3746
|
+
);
|
|
3173
3747
|
return { artId, file, payload };
|
|
3174
3748
|
};
|
|
3175
3749
|
var writePlan = writePlan2;
|
|
@@ -3270,7 +3844,7 @@ registerTortureBucket({
|
|
|
3270
3844
|
let writePlan2 = function(id, amount) {
|
|
3271
3845
|
const payload = {
|
|
3272
3846
|
schema: "hardkas.txPlan",
|
|
3273
|
-
hardkasVersion: "0.7.
|
|
3847
|
+
hardkasVersion: "0.7.5-alpha",
|
|
3274
3848
|
version: ARTIFACT_VERSION,
|
|
3275
3849
|
networkId: "simnet",
|
|
3276
3850
|
mode: "simulated",
|
|
@@ -3282,13 +3856,26 @@ registerTortureBucket({
|
|
|
3282
3856
|
amountSompi: amount,
|
|
3283
3857
|
estimatedFeeSompi: "100",
|
|
3284
3858
|
estimatedMass: "10",
|
|
3285
|
-
inputs: [
|
|
3286
|
-
|
|
3859
|
+
inputs: [
|
|
3860
|
+
{
|
|
3861
|
+
outpoint: { transactionId: "c".repeat(64), index: 0 },
|
|
3862
|
+
amountSompi: "10000"
|
|
3863
|
+
}
|
|
3864
|
+
],
|
|
3865
|
+
outputs: [
|
|
3866
|
+
{
|
|
3867
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
3868
|
+
amountSompi: amount
|
|
3869
|
+
}
|
|
3870
|
+
]
|
|
3287
3871
|
};
|
|
3288
3872
|
const hash = calculateContentHash(payload);
|
|
3289
3873
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
3290
3874
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
3291
|
-
fs.writeFileSync(
|
|
3875
|
+
fs.writeFileSync(
|
|
3876
|
+
file,
|
|
3877
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
3878
|
+
);
|
|
3292
3879
|
return { artId, file, payload };
|
|
3293
3880
|
};
|
|
3294
3881
|
var writePlan = writePlan2;
|
|
@@ -3342,7 +3929,10 @@ registerTortureBucket({
|
|
|
3342
3929
|
const newStore = new HardkasStore({ dbPath });
|
|
3343
3930
|
newStore.connect({ autoMigrate: true });
|
|
3344
3931
|
const newBackend = new SqliteQueryBackend(newStore);
|
|
3345
|
-
const rebuildResult = await newBackend.rebuild({
|
|
3932
|
+
const rebuildResult = await newBackend.rebuild({
|
|
3933
|
+
strict: true,
|
|
3934
|
+
cwd: sandboxDir
|
|
3935
|
+
});
|
|
3346
3936
|
if (!rebuildResult.ok) {
|
|
3347
3937
|
throw new TortureInvariantError(
|
|
3348
3938
|
"Rebuild failed after database file deletion",
|
|
@@ -3413,7 +4003,7 @@ registerTortureBucket({
|
|
|
3413
4003
|
let writePlan2 = function(id, amount) {
|
|
3414
4004
|
const payload = {
|
|
3415
4005
|
schema: "hardkas.txPlan",
|
|
3416
|
-
hardkasVersion: "0.7.
|
|
4006
|
+
hardkasVersion: "0.7.5-alpha",
|
|
3417
4007
|
version: ARTIFACT_VERSION,
|
|
3418
4008
|
networkId: "simnet",
|
|
3419
4009
|
mode: "simulated",
|
|
@@ -3425,13 +4015,26 @@ registerTortureBucket({
|
|
|
3425
4015
|
amountSompi: amount,
|
|
3426
4016
|
estimatedFeeSompi: "100",
|
|
3427
4017
|
estimatedMass: "10",
|
|
3428
|
-
inputs: [
|
|
3429
|
-
|
|
4018
|
+
inputs: [
|
|
4019
|
+
{
|
|
4020
|
+
outpoint: { transactionId: "n".repeat(64), index: 0 },
|
|
4021
|
+
amountSompi: "10000"
|
|
4022
|
+
}
|
|
4023
|
+
],
|
|
4024
|
+
outputs: [
|
|
4025
|
+
{
|
|
4026
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
4027
|
+
amountSompi: amount
|
|
4028
|
+
}
|
|
4029
|
+
]
|
|
3430
4030
|
};
|
|
3431
4031
|
const hash = calculateContentHash(payload);
|
|
3432
4032
|
const artId = `plan-${hash.slice(0, 16)}`;
|
|
3433
4033
|
const file = path.join(artifactsDir, `${artId}.json`);
|
|
3434
|
-
fs.writeFileSync(
|
|
4034
|
+
fs.writeFileSync(
|
|
4035
|
+
file,
|
|
4036
|
+
JSON.stringify({ ...payload, artifactId: artId, contentHash: hash }, null, 2)
|
|
4037
|
+
);
|
|
3435
4038
|
return { artId, file, payload };
|
|
3436
4039
|
};
|
|
3437
4040
|
var writePlan = writePlan2;
|
|
@@ -3445,7 +4048,7 @@ registerTortureBucket({
|
|
|
3445
4048
|
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
3446
4049
|
const payload = {
|
|
3447
4050
|
schema: "hardkas.txPlan",
|
|
3448
|
-
hardkasVersion: "0.7.
|
|
4051
|
+
hardkasVersion: "0.7.5-alpha",
|
|
3449
4052
|
version: ARTIFACT_VERSION,
|
|
3450
4053
|
networkId: "simnet",
|
|
3451
4054
|
mode: "simulated",
|
|
@@ -3457,11 +4060,28 @@ registerTortureBucket({
|
|
|
3457
4060
|
amountSompi: "99000",
|
|
3458
4061
|
estimatedFeeSompi: "100",
|
|
3459
4062
|
estimatedMass: "10",
|
|
3460
|
-
inputs: [
|
|
3461
|
-
|
|
4063
|
+
inputs: [
|
|
4064
|
+
{
|
|
4065
|
+
outpoint: { transactionId: "n".repeat(64), index: 0 },
|
|
4066
|
+
amountSompi: "100000"
|
|
4067
|
+
}
|
|
4068
|
+
],
|
|
4069
|
+
outputs: [
|
|
4070
|
+
{
|
|
4071
|
+
address: "kaspa:sim_qq0d6h0prjm5mpdld5pncst3adu0yam6xch9fkr6eg",
|
|
4072
|
+
amountSompi: "99000"
|
|
4073
|
+
}
|
|
4074
|
+
]
|
|
3462
4075
|
};
|
|
3463
4076
|
const hash = calculateContentHash(payload);
|
|
3464
|
-
fs.writeFileSync(
|
|
4077
|
+
fs.writeFileSync(
|
|
4078
|
+
file,
|
|
4079
|
+
JSON.stringify(
|
|
4080
|
+
{ ...payload, artifactId: `plan-${hash.slice(0, 16)}`, contentHash: hash },
|
|
4081
|
+
null,
|
|
4082
|
+
2
|
|
4083
|
+
)
|
|
4084
|
+
);
|
|
3465
4085
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
3466
4086
|
const artifacts = await backend.findArtifacts();
|
|
3467
4087
|
const found = artifacts.find((a) => a.payload.amountSompi === "99000");
|
|
@@ -3477,7 +4097,10 @@ registerTortureBucket({
|
|
|
3477
4097
|
case 2: {
|
|
3478
4098
|
const plans = [];
|
|
3479
4099
|
for (let i = 0; i < 10; i++) {
|
|
3480
|
-
const { artId } = writePlan2(
|
|
4100
|
+
const { artId } = writePlan2(
|
|
4101
|
+
`plan-ooo-${i}-${ctx.caseSeed}`,
|
|
4102
|
+
`${(i + 1) * 1e3}`
|
|
4103
|
+
);
|
|
3481
4104
|
plans.push(artId);
|
|
3482
4105
|
}
|
|
3483
4106
|
await backend.sync({ strict: true, cwd: sandboxDir });
|
|
@@ -3504,7 +4127,10 @@ registerTortureBucket({
|
|
|
3504
4127
|
case 3: {
|
|
3505
4128
|
const files = [];
|
|
3506
4129
|
for (let i = 0; i < 10; i++) {
|
|
3507
|
-
const { file } = writePlan2(
|
|
4130
|
+
const { file } = writePlan2(
|
|
4131
|
+
`plan-partial-${i}-${ctx.caseSeed}`,
|
|
4132
|
+
`${(i + 1) * 1e3}`
|
|
4133
|
+
);
|
|
3508
4134
|
files.push(file);
|
|
3509
4135
|
}
|
|
3510
4136
|
await backend.syncPaths(files.slice(0, 5), { strict: true, cwd: sandboxDir });
|
|
@@ -3584,14 +4210,26 @@ registerTortureBucket({
|
|
|
3584
4210
|
const cliPath = fileURLToPath(new URL("../../cli/dist/index.js", import.meta.url));
|
|
3585
4211
|
fs2.writeFileSync(path2.join(runDir, "package.json"), "{}");
|
|
3586
4212
|
try {
|
|
3587
|
-
execSync(`node "${cliPath}" dev init`, {
|
|
4213
|
+
execSync(`node "${cliPath}" dev init`, {
|
|
4214
|
+
cwd: runDir,
|
|
4215
|
+
stdio: "pipe",
|
|
4216
|
+
encoding: "utf-8"
|
|
4217
|
+
});
|
|
3588
4218
|
} catch (e) {
|
|
3589
|
-
throw new TortureInvariantError(
|
|
4219
|
+
throw new TortureInvariantError(
|
|
4220
|
+
`hardkas dev init failed: ${e.message}
|
|
3590
4221
|
${e.stdout}
|
|
3591
|
-
${e.stderr}`,
|
|
4222
|
+
${e.stderr}`,
|
|
4223
|
+
"INIT_FAILED",
|
|
4224
|
+
"critical"
|
|
4225
|
+
);
|
|
3592
4226
|
}
|
|
3593
4227
|
if (!fs2.existsSync(path2.join(runDir, "hardkas.config.ts"))) {
|
|
3594
|
-
throw new TortureInvariantError(
|
|
4228
|
+
throw new TortureInvariantError(
|
|
4229
|
+
"hardkas.config.ts was not generated",
|
|
4230
|
+
"MISSING_CONFIG",
|
|
4231
|
+
"critical"
|
|
4232
|
+
);
|
|
3595
4233
|
}
|
|
3596
4234
|
const minimalConfig = `export default {
|
|
3597
4235
|
defaultNetwork: "simulated",
|
|
@@ -3607,12 +4245,23 @@ ${e.stderr}`, "INIT_FAILED", "critical");
|
|
|
3607
4245
|
const artifactsDir = path2.join(runDir, ".hardkas", "artifacts");
|
|
3608
4246
|
fs2.mkdirSync(artifactsDir, { recursive: true });
|
|
3609
4247
|
const eventsPath = path2.join(artifactsDir, "events.jsonl");
|
|
3610
|
-
const mockArtifact = {
|
|
4248
|
+
const mockArtifact = {
|
|
4249
|
+
schema: "hardkas.artifact.v1",
|
|
4250
|
+
type: "transfer",
|
|
4251
|
+
amount: 100,
|
|
4252
|
+
timestamp: Date.now()
|
|
4253
|
+
};
|
|
3611
4254
|
fs2.appendFileSync(eventsPath, JSON.stringify(mockArtifact) + "\n");
|
|
3612
4255
|
try {
|
|
3613
|
-
const doctorOutput = execSync(`node "${cliPath}" dev doctor --json`, {
|
|
4256
|
+
const doctorOutput = execSync(`node "${cliPath}" dev doctor --json`, {
|
|
4257
|
+
cwd: runDir,
|
|
4258
|
+
stdio: "pipe",
|
|
4259
|
+
encoding: "utf-8"
|
|
4260
|
+
});
|
|
3614
4261
|
const doctorResult = JSON.parse(doctorOutput);
|
|
3615
|
-
const workspaceCheck = doctorResult.checks?.find(
|
|
4262
|
+
const workspaceCheck = doctorResult.checks?.find(
|
|
4263
|
+
(c) => c.name === "Workspace Validity"
|
|
4264
|
+
);
|
|
3616
4265
|
if (workspaceCheck?.status === "error") {
|
|
3617
4266
|
throw new TortureInvariantError(
|
|
3618
4267
|
`dev doctor: workspace invalid \u2014 ${workspaceCheck.message}`,
|
|
@@ -3625,7 +4274,9 @@ ${e.stderr}`, "INIT_FAILED", "critical");
|
|
|
3625
4274
|
const stdout = e.stdout || "";
|
|
3626
4275
|
try {
|
|
3627
4276
|
const doctorResult = JSON.parse(stdout);
|
|
3628
|
-
const workspaceCheck = doctorResult.checks?.find(
|
|
4277
|
+
const workspaceCheck = doctorResult.checks?.find(
|
|
4278
|
+
(c) => c.name === "Workspace Validity"
|
|
4279
|
+
);
|
|
3629
4280
|
if (workspaceCheck?.status === "error") {
|
|
3630
4281
|
throw new TortureInvariantError(
|
|
3631
4282
|
`dev doctor: workspace invalid \u2014 ${workspaceCheck.message}`,
|
|
@@ -3665,25 +4316,44 @@ registerTortureBucket({
|
|
|
3665
4316
|
fs3.rmSync(runDir, { recursive: true, force: true });
|
|
3666
4317
|
fs3.mkdirSync(runDir, { recursive: true });
|
|
3667
4318
|
const eventsPath = path3.join(runDir, "events.jsonl");
|
|
3668
|
-
const largePayload = {
|
|
4319
|
+
const largePayload = {
|
|
4320
|
+
schema: "hardkas.artifact.v1",
|
|
4321
|
+
type: "large",
|
|
4322
|
+
data: "x".repeat(7e4)
|
|
4323
|
+
};
|
|
3669
4324
|
fs3.writeFileSync(eventsPath, JSON.stringify(largePayload) + "\n");
|
|
3670
4325
|
const validSize = fs3.statSync(eventsPath).size;
|
|
3671
|
-
fs3.appendFileSync(
|
|
4326
|
+
fs3.appendFileSync(
|
|
4327
|
+
eventsPath,
|
|
4328
|
+
'{"schema":"hardkas.artifact.v1","type":"corrupted","d'
|
|
4329
|
+
);
|
|
3672
4330
|
const newArtifact = { schema: "hardkas.artifact.v1", type: "recovery-test" };
|
|
3673
4331
|
AppendCoordinator.appendAtomic(eventsPath, JSON.stringify(newArtifact), runDir);
|
|
3674
4332
|
const content = fs3.readFileSync(eventsPath, "utf-8");
|
|
3675
4333
|
const lines = content.split("\n").filter((l) => l.trim().length > 0);
|
|
3676
4334
|
if (lines.length !== 2) {
|
|
3677
|
-
throw new TortureInvariantError(
|
|
4335
|
+
throw new TortureInvariantError(
|
|
4336
|
+
`Expected exactly 2 lines after recovery, got ${lines.length}`,
|
|
4337
|
+
"CORRUPTION_RECOVERY_FAILED",
|
|
4338
|
+
"catastrophic"
|
|
4339
|
+
);
|
|
3678
4340
|
}
|
|
3679
4341
|
try {
|
|
3680
4342
|
JSON.parse(lines[0]);
|
|
3681
4343
|
JSON.parse(lines[1]);
|
|
3682
4344
|
} catch (e) {
|
|
3683
|
-
throw new TortureInvariantError(
|
|
4345
|
+
throw new TortureInvariantError(
|
|
4346
|
+
"Recovered JSON lines are invalid",
|
|
4347
|
+
"CORRUPTION_RECOVERY_JSON_PARSE",
|
|
4348
|
+
"catastrophic"
|
|
4349
|
+
);
|
|
3684
4350
|
}
|
|
3685
4351
|
if (lines[0].length < 7e4) {
|
|
3686
|
-
throw new TortureInvariantError(
|
|
4352
|
+
throw new TortureInvariantError(
|
|
4353
|
+
"Large JSONL line was incorrectly truncated",
|
|
4354
|
+
"LARGE_LINE_TRUNCATED",
|
|
4355
|
+
"catastrophic"
|
|
4356
|
+
);
|
|
3687
4357
|
}
|
|
3688
4358
|
fs3.rmSync(runDir, { recursive: true, force: true });
|
|
3689
4359
|
return {
|