@blockcast/fec-worker 0.3.0 → 0.4.0-main.248efb07e294

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.
@@ -10,20 +10,6 @@ function toOwnedArrayBuffer(view) {
10
10
  // src/block-order.ts
11
11
  var SPAN = 4294967296;
12
12
  var HALF = 2147483648;
13
- function blockStart(sbn, k) {
14
- return sbn * k % SPAN;
15
- }
16
- function precedingDistance(a, b, k) {
17
- const distance = (blockStart(b, k) - blockStart(a, k) + SPAN) % SPAN;
18
- return distance !== 0 && distance < HALF ? distance : null;
19
- }
20
- function blockPrecedes(a, b, k) {
21
- return precedingDistance(a, b, k) !== null;
22
- }
23
- function blocksBehind(a, b, k) {
24
- const distance = precedingDistance(a, b, k);
25
- return distance === null ? 0 : Math.ceil(distance / k);
26
- }
27
13
  function serialDistance(from, to) {
28
14
  return (to - from + SPAN) % SPAN;
29
15
  }
@@ -47,8 +33,6 @@ function isoBlocksBehind(a, b, kMax) {
47
33
  // src/fec-worker.ts
48
34
  var wasmDecoder = null;
49
35
  var config = null;
50
- var altaEnabled = false;
51
- var altaVerifier = null;
52
36
  var snapshotTimer = null;
53
37
  var blockUpdatesSubscribed = false;
54
38
  var blocks = /* @__PURE__ */ new Map();
@@ -62,19 +46,12 @@ var SSBG1_LENGTH_FIELD_BYTES = 2;
62
46
  var MAX_INTERLEAVE_DEPTH = 255;
63
47
  var MAX_SYMBOL_SIZE = 65528;
64
48
  var MAX_RAPTORQ_SOURCE_SYMBOLS_PER_BLOCK = 56403;
49
+ var MAX_REED_SOLOMON_SOURCE_SYMBOLS_PER_BLOCK = 254;
65
50
  var sourceSymbols = 0;
66
51
  var repairSymbols = 0;
67
52
  var blocksComplete = 0;
68
53
  var blocksRecovered = 0;
69
54
  var blocksFailed = 0;
70
- var altaVerified = 0;
71
- var altaFailed = 0;
72
- var altaFailedDetails = [];
73
- var altaPending = 0;
74
- var altaPendingEvictedCap = 0;
75
- var altaPendingEvictedTtl = 0;
76
- var altaError = 0;
77
- var altaInitFailed = false;
78
55
  var relayBlocksVerified = 0;
79
56
  var relayBlocksFailed = 0;
80
57
  var liveSbn = 0;
@@ -85,9 +62,6 @@ var sourceDroppedTerminal = 0;
85
62
  var sourceDroppedDuplicate = 0;
86
63
  var sourceUnplacedRetired = 0;
87
64
  var recoveryTimes = [];
88
- var pendingVerify = /* @__PURE__ */ new Map();
89
- var pendingVerifyCap = 0;
90
- var pendingVerifyTtlMs = 0;
91
65
  function emit(event, transfer) {
92
66
  self.postMessage(event, transfer ?? []);
93
67
  }
@@ -106,17 +80,13 @@ function clearBlockTracking() {
106
80
  acceptedSourceEsis.clear();
107
81
  acceptedRepairEsis.clear();
108
82
  unplacedSources.clear();
109
- pendingVerify.clear();
110
83
  recoveryTimes.length = 0;
111
84
  liveSbn = 0;
112
85
  liveSbnKnown = false;
113
86
  }
114
87
  function isRetiredSbn(sbn) {
115
88
  if (config === null || !liveSbnKnown) return false;
116
- return config.blockProfile === "iso-ssbg1-v1" ? isoBlocksBehind(sbn, liveSbn, config.k) > config.interleaveDepth : blocksBehind(sbn, liveSbn, config.k) > config.interleaveDepth;
117
- }
118
- function isIsoProfile() {
119
- return config?.blockProfile === "iso-ssbg1-v1";
89
+ return isoBlocksBehind(sbn, liveSbn, config.k) > config.interleaveDepth;
120
90
  }
121
91
  function isoKnownLength(block) {
122
92
  return block.ssbLength ?? 1;
@@ -128,7 +98,7 @@ function findIsoBlock(ssId) {
128
98
  return void 0;
129
99
  }
130
100
  function isRetiredBlock(key, block) {
131
- return isIsoProfile() ? isRetiredSbn((key + isoKnownLength(block) - 1) % SS_ID_SPAN) : isRetiredSbn(key);
101
+ return isRetiredSbn((key + isoKnownLength(block) - 1) % SS_ID_SPAN);
132
102
  }
133
103
  function trimBlockRetention() {
134
104
  for (const [sbn, block] of blocks) {
@@ -139,10 +109,7 @@ function trimBlockRetention() {
139
109
  }
140
110
  function advanceMediaHorizon(sbn) {
141
111
  if (!config) return;
142
- if (liveSbnKnown) {
143
- const ahead = config.blockProfile === "iso-ssbg1-v1" ? serialPrecedes(liveSbn, sbn) : blockPrecedes(liveSbn, sbn, config.k);
144
- if (!ahead) return;
145
- }
112
+ if (liveSbnKnown && !serialPrecedes(liveSbn, sbn)) return;
146
113
  liveSbn = sbn;
147
114
  liveSbnKnown = true;
148
115
  trimBlockRetention();
@@ -155,8 +122,7 @@ function markBlockTerminal(block, state) {
155
122
  }
156
123
  function synchronizeDecoderHorizon() {
157
124
  if (!wasmDecoder || !liveSbnKnown) return;
158
- const iso = isIsoProfile();
159
- const expired = iso ? wasmDecoder.cleanup_by_ss_start(liveSbn) : wasmDecoder.cleanup_by_sbn(liveSbn);
125
+ const expired = wasmDecoder.cleanup_by_ss_start(liveSbn);
160
126
  for (const sbn of expired) {
161
127
  const block = blocks.get(sbn);
162
128
  if (!block || isTerminalBlock(block)) {
@@ -167,7 +133,7 @@ function synchronizeDecoderHorizon() {
167
133
  blocksFailed++;
168
134
  emitBlockUpdate(block);
169
135
  }
170
- if (iso) retireUnplacedSources();
136
+ retireUnplacedSources();
171
137
  trimBlockRetention();
172
138
  }
173
139
  function retireUnplacedSources() {
@@ -192,8 +158,9 @@ function getOrCreateBlock(sbn, isoSsbLength) {
192
158
  repairCount: config.repairCount,
193
159
  firstSymbolTs: now,
194
160
  lastSymbolTs: now,
161
+ // A positive interleaveMs makes this the catalog completion deadline;
162
+ // zero makes deliveryWindowMs a receiver-local cleanup bound.
195
163
  deadlineTs: now + config.deliveryWindowMs,
196
- altaVerified: 0,
197
164
  relayBlockSigValid: null
198
165
  };
199
166
  if (isoSsbLength !== void 0) block.ssbLength = isoSsbLength;
@@ -217,7 +184,7 @@ function buildStatsSnapshot() {
217
184
  const avgRecoveryMs = recoveryTimes.length > 0 ? recoveryTimes.reduce((a, b) => a + b, 0) / recoveryTimes.length : 0;
218
185
  const maxRecoveryMs = recoveryTimes.length > 0 ? Math.max(...recoveryTimes) : 0;
219
186
  const maxBlocks = Math.max(config.interleaveDepth * 3, 24);
220
- const blockArray = Array.from(blocks.values()).sort((a, b) => b.sbn - a.sbn).slice(0, maxBlocks);
187
+ const blockArray = Array.from(blocks.values()).sort((a, b) => serialDistance(a.sbn, liveSbn) - serialDistance(b.sbn, liveSbn)).slice(0, maxBlocks);
221
188
  return {
222
189
  config,
223
190
  sourceSymbols,
@@ -228,15 +195,6 @@ function buildStatsSnapshot() {
228
195
  recoveryRate: blocksComplete + blocksRecovered > 0 ? Math.round(
229
196
  blocksRecovered / (blocksRecovered + blocksFailed) * 100
230
197
  ) || 0 : 0,
231
- altaVerified,
232
- altaFailed,
233
- altaPending,
234
- altaPendingEvictedCap,
235
- altaPendingEvictedTtl,
236
- altaError,
237
- altaInitFailed,
238
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
239
- altaFailedDetails: altaFailedDetails.slice(),
240
198
  relayBlocksVerified,
241
199
  relayBlocksFailed,
242
200
  liveSbn,
@@ -248,7 +206,7 @@ function buildStatsSnapshot() {
248
206
  sourceDroppedRetired,
249
207
  sourceDroppedTerminal,
250
208
  sourceDroppedDuplicate,
251
- ...config.blockProfile === "iso-ssbg1-v1" ? { sourceUnplacedRetired } : {},
209
+ sourceUnplacedRetired,
252
210
  decoder
253
211
  };
254
212
  }
@@ -280,25 +238,19 @@ function emitRecoveredSymbols(sbn, recoveredBlock, block) {
280
238
  });
281
239
  return;
282
240
  }
283
- const iso = config.blockProfile === "iso-ssbg1-v1";
284
241
  for (let i = 0; i < ssbLength; i++) {
285
242
  const symbol = recoveredBlock.subarray(i * symbolSize, (i + 1) * symbolSize);
286
- if (iso) {
287
- const invalid = invalidSsbg1Symbol(symbol, symbolSize);
288
- if (invalid !== null) {
289
- emit({
290
- type: "error",
291
- code: "recovered-ssbg1-symbol-invalid",
292
- message: `[FecWorker] Dropping recovered ssbg_mode1 symbol (ssStart=${sbn}, esi=${i}, SSB_length=${ssbLength}): ${invalid}`
293
- });
294
- continue;
295
- }
243
+ const invalid = invalidSsbg1Symbol(symbol, symbolSize);
244
+ if (invalid !== null) {
245
+ emit({
246
+ type: "error",
247
+ code: "recovered-ssbg1-symbol-invalid",
248
+ message: `[FecWorker] Dropping recovered ssbg_mode1 symbol (ssStart=${sbn}, esi=${i}, SSB_length=${ssbLength}): ${invalid}`
249
+ });
250
+ continue;
296
251
  }
297
- const recoveredAltaVerified = null;
298
- if (altaEnabled) altaPending++;
299
252
  const buf = toOwnedArrayBuffer(symbol);
300
253
  const meta = {
301
- altaVerified: recoveredAltaVerified,
302
254
  recovered: true,
303
255
  sbn,
304
256
  esi: i,
@@ -411,7 +363,6 @@ function feedIsoSource(cmd, view, decoder, cfg) {
411
363
  advanceMediaHorizon(cmd.ssId);
412
364
  unplacedSources.set(cmd.ssId, performance.now());
413
365
  sourceSymbols++;
414
- if (altaEnabled) altaPending++;
415
366
  if (result2 && result2.byteLength > 0) {
416
367
  emit({
417
368
  type: "error",
@@ -442,7 +393,6 @@ function feedIsoSource(cmd, view, decoder, cfg) {
442
393
  block.sourceReceived++;
443
394
  block.lastSymbolTs = performance.now();
444
395
  sourceSymbols++;
445
- if (altaEnabled) altaPending++;
446
396
  settleSourceArrival(key, block, result);
447
397
  }
448
398
  function findOverlappingIsoBlock(ssStart, ssbLength) {
@@ -510,22 +460,23 @@ async function handleConfigure(cmd) {
510
460
  const blockProfile = cmd.config.blockProfile;
511
461
  if (blockProfile === void 0) {
512
462
  throw new Error(
513
- '[FecWorker] configure: blockProfile is required: name the FEC block profile ("k-padded-v1" or "iso-ssbg1-v1")'
463
+ '[FecWorker] configure: blockProfile is required: name the FEC block profile ("iso-ssbg1-v1")'
514
464
  );
515
465
  }
516
- if (blockProfile !== "k-padded-v1" && blockProfile !== "iso-ssbg1-v1") {
466
+ if (blockProfile !== "iso-ssbg1-v1") {
517
467
  throw new Error(
518
- `[FecWorker] configure: blockProfile must be "k-padded-v1" or "iso-ssbg1-v1" (got ${JSON.stringify(blockProfile)})`
468
+ `[FecWorker] configure: blockProfile must be "iso-ssbg1-v1" (got ${JSON.stringify(blockProfile)})`
519
469
  );
520
470
  }
471
+ const algorithm = cmd.config.algorithm === "reed-solomon" ? "reed-solomon" : "raptorq";
521
472
  if (!Number.isFinite(cmd.config.interleaveDepth) || !Number.isInteger(cmd.config.interleaveDepth) || cmd.config.interleaveDepth <= 0 || cmd.config.interleaveDepth > MAX_INTERLEAVE_DEPTH) {
522
473
  throw new Error(
523
474
  `[FecWorker] configure: interleaveDepth must be an integer in 1..${MAX_INTERLEAVE_DEPTH} (got ${cmd.config.interleaveDepth})`
524
475
  );
525
476
  }
526
- if (!Number.isFinite(cmd.config.interleaveMs) || cmd.config.interleaveMs <= 0) {
477
+ if (!Number.isFinite(cmd.config.interleaveMs) || !Number.isSafeInteger(cmd.config.interleaveMs) || cmd.config.interleaveMs < 0) {
527
478
  throw new Error(
528
- `[FecWorker] configure: interleaveMs must be finite and > 0 (got ${cmd.config.interleaveMs})`
479
+ `[FecWorker] configure: interleaveMs must be a finite non-negative integer (got ${cmd.config.interleaveMs})`
529
480
  );
530
481
  }
531
482
  if (!Number.isFinite(cmd.config.deliveryWindowMs) || cmd.config.deliveryWindowMs <= 0) {
@@ -533,14 +484,13 @@ async function handleConfigure(cmd) {
533
484
  `[FecWorker] configure: deliveryWindowMs must be > 0 (got ${cmd.config.deliveryWindowMs})`
534
485
  );
535
486
  }
536
- if (!Number.isInteger(cmd.config.k) || cmd.config.k <= 0 || cmd.config.k > MAX_RAPTORQ_SOURCE_SYMBOLS_PER_BLOCK) {
537
- throw new Error(
538
- `[FecWorker] configure: k must be an integer in 1..${MAX_RAPTORQ_SOURCE_SYMBOLS_PER_BLOCK} (got ${cmd.config.k})`
539
- );
487
+ const maxK = algorithm === "raptorq" ? MAX_RAPTORQ_SOURCE_SYMBOLS_PER_BLOCK : MAX_REED_SOLOMON_SOURCE_SYMBOLS_PER_BLOCK;
488
+ if (!Number.isInteger(cmd.config.k) || cmd.config.k <= 0 || cmd.config.k > maxK) {
489
+ throw new Error(`[FecWorker] configure: ${algorithm} k must be an integer in 1..${maxK} (got ${cmd.config.k})`);
540
490
  }
541
- if (!Number.isInteger(cmd.config.symbolSize) || cmd.config.symbolSize <= 0 || cmd.config.symbolSize > MAX_SYMBOL_SIZE || cmd.config.symbolSize % 8 !== 0) {
491
+ if (!Number.isInteger(cmd.config.symbolSize) || cmd.config.symbolSize <= 0 || cmd.config.symbolSize > MAX_SYMBOL_SIZE || algorithm === "raptorq" && cmd.config.symbolSize % 8 !== 0) {
542
492
  throw new Error(
543
- `[FecWorker] configure: symbolSize must be an 8-byte-aligned integer in 8..${MAX_SYMBOL_SIZE} (got ${cmd.config.symbolSize})`
493
+ `[FecWorker] configure: ${algorithm} symbolSize must be ${algorithm === "raptorq" ? "an 8-byte-aligned integer in 8" : "an integer in 1"}..${MAX_SYMBOL_SIZE} (got ${cmd.config.symbolSize})`
544
494
  );
545
495
  }
546
496
  const wasm = resolveWasmBindings();
@@ -548,32 +498,15 @@ async function handleConfigure(cmd) {
548
498
  wasmDecoder?.free();
549
499
  wasmDecoder = null;
550
500
  clearBlockTracking();
551
- const decoder = new wasm.MmtFecDecoder(cmd.config.interleaveDepth, blockProfile);
501
+ const decoder = new wasm.MmtFecDecoder(cmd.config.interleaveDepth, blockProfile, algorithm);
552
502
  verifyDecoderProfile(decoder, blockProfile);
503
+ const decoderAlgorithm = decoder.get_algorithm?.() ?? "raptorq";
504
+ if (decoderAlgorithm !== algorithm) {
505
+ decoder.free();
506
+ throw new Error(`[FecWorker] configure: decoder runs ${JSON.stringify(decoderAlgorithm)}, not the configured "${algorithm}"`);
507
+ }
553
508
  wasmDecoder = decoder;
554
509
  config = cmd.config;
555
- altaEnabled = !!cmd.altaPublicKey;
556
- pendingVerifyCap = Math.ceil(config.interleaveDepth * 1.5);
557
- pendingVerifyTtlMs = Math.ceil(config.interleaveMs * config.k * 1.5);
558
- altaVerifier = null;
559
- altaInitFailed = false;
560
- if (cmd.altaPublicKey && cmd.altaWasmModule) {
561
- try {
562
- const altaGlueUrl = "/wasm/alta/alta_rs.js";
563
- const altaGlue = await import(
564
- /* webpackIgnore: true */
565
- altaGlueUrl
566
- );
567
- altaGlue.initSync({ module: cmd.altaWasmModule });
568
- const keyBytes = new Uint8Array(cmd.altaPublicKey);
569
- altaVerifier = new altaGlue.JsAltaVerifier(keyBytes);
570
- } catch (e) {
571
- console.warn("[FecWorker] ALTA WASM init failed, verification disabled:", e);
572
- altaVerifier = null;
573
- altaEnabled = false;
574
- altaInitFailed = true;
575
- }
576
- }
577
510
  wasmDecoder.configure_params(config.k, config.symbolSize);
578
511
  emit({ type: "capabilities", commands: ["feedSymbols", "subscribeBlockUpdates"] });
579
512
  startSnapshotTimer();
@@ -589,40 +522,7 @@ function handleFeedSource(cmd) {
589
522
  if (!isUint32(cmd.ssId) || !(cmd.data instanceof ArrayBuffer)) {
590
523
  throw new Error("[FecWorker] feedSource: invalid source symbol");
591
524
  }
592
- const view = new Uint8Array(cmd.data);
593
- if (config.blockProfile === "iso-ssbg1-v1") {
594
- feedIsoSource(cmd, view, wasmDecoder, config);
595
- return;
596
- }
597
- const sbn = config.k > 0 ? Math.floor(cmd.ssId / config.k) : cmd.ssId;
598
- const esi = cmd.ssId % config.k;
599
- if (isRetiredSbn(sbn)) {
600
- sourceDroppedRetired++;
601
- return;
602
- }
603
- const existingBlock = blocks.get(sbn);
604
- if (existingBlock && isTerminalBlock(existingBlock)) {
605
- sourceDroppedTerminal++;
606
- return;
607
- }
608
- if (acceptedSourceEsis.get(sbn)?.has(esi)) {
609
- sourceDroppedDuplicate++;
610
- return;
611
- }
612
- const result = wasmDecoder.add_source(cmd.ssId, view, cmd.ts);
613
- advanceMediaHorizon(sbn);
614
- let sourceEsis = acceptedSourceEsis.get(sbn);
615
- if (!sourceEsis) {
616
- sourceEsis = /* @__PURE__ */ new Set();
617
- acceptedSourceEsis.set(sbn, sourceEsis);
618
- }
619
- sourceEsis.add(esi);
620
- const block = getOrCreateBlock(sbn);
621
- block.sourceReceived++;
622
- block.lastSymbolTs = performance.now();
623
- sourceSymbols++;
624
- if (altaEnabled) altaPending++;
625
- settleSourceArrival(sbn, block, result);
525
+ feedIsoSource(cmd, new Uint8Array(cmd.data), wasmDecoder, config);
626
526
  }
627
527
  function handleFeedRepair(cmd) {
628
528
  if (!wasmDecoder) {
@@ -631,8 +531,7 @@ function handleFeedRepair(cmd) {
631
531
  if (!config) {
632
532
  throw new Error("[FecWorker] feedRepair: config missing");
633
533
  }
634
- const iso = config.blockProfile === "iso-ssbg1-v1";
635
- if (!isUint32(cmd.ssStart) || !isUint32(cmd.ssbLength) || cmd.ssbLength <= 0 || cmd.ssbLength > config.k || !iso && cmd.ssStart % config.k !== 0 || !isUint32(cmd.rsId) || (iso ? cmd.ssbLength : config.k) + cmd.rsId > UINT24_MAX || !(cmd.data instanceof ArrayBuffer)) {
534
+ if (!isUint32(cmd.ssStart) || !isUint32(cmd.ssbLength) || cmd.ssbLength <= 0 || cmd.ssbLength > config.k || !isUint32(cmd.rsId) || cmd.ssbLength + cmd.rsId > UINT24_MAX || !(cmd.data instanceof ArrayBuffer)) {
636
535
  throw new Error("[FecWorker] feedRepair: invalid repair symbol");
637
536
  }
638
537
  const view = new Uint8Array(cmd.data);
@@ -647,44 +546,7 @@ function handleFeedRepair(cmd) {
647
546
  }
648
547
  return;
649
548
  }
650
- if (iso) {
651
- feedIsoRepair(cmd, view, wasmDecoder);
652
- return;
653
- }
654
- const sbn = Math.floor(cmd.ssStart / config.k);
655
- const repairEsi = config.k + cmd.rsId;
656
- if (isRetiredSbn(sbn)) return;
657
- const existingBlock = blocks.get(sbn);
658
- if (existingBlock && isTerminalBlock(existingBlock)) return;
659
- if (acceptedRepairEsis.get(sbn)?.has(repairEsi)) return;
660
- if (existingBlock?.ssbLength !== void 0 && existingBlock.ssbLength !== cmd.ssbLength) {
661
- emit({
662
- type: "error",
663
- code: "repair-ssb-length-conflict",
664
- message: `[FecWorker] Dropping repair symbol whose SSB_length ${cmd.ssbLength} conflicts with ${existingBlock.ssbLength} (sbn=${sbn})`
665
- });
666
- return;
667
- }
668
- const result = wasmDecoder.add_repair(
669
- cmd.ssStart,
670
- cmd.ssbLength,
671
- cmd.rsId,
672
- view,
673
- cmd.ts
674
- );
675
- advanceMediaHorizon(sbn);
676
- let repairEsis = acceptedRepairEsis.get(sbn);
677
- if (!repairEsis) {
678
- repairEsis = /* @__PURE__ */ new Set();
679
- acceptedRepairEsis.set(sbn, repairEsis);
680
- }
681
- repairEsis.add(repairEsi);
682
- const block = getOrCreateBlock(sbn);
683
- block.ssbLength = cmd.ssbLength;
684
- block.repairReceived++;
685
- block.lastSymbolTs = performance.now();
686
- repairSymbols++;
687
- settleRepairArrival(sbn, block, cmd.ssbLength, result);
549
+ feedIsoRepair(cmd, view, wasmDecoder);
688
550
  }
689
551
  function handleRelayBlockSig(cmd) {
690
552
  const block = blocks.get(cmd.sbn);
@@ -713,7 +575,7 @@ function handleCleanup(cmd) {
713
575
  continue;
714
576
  }
715
577
  currentBlock ??= getOrCreateBlock(sbn);
716
- const authoredLength = isIsoProfile() ? currentBlock.ssbLength : currentBlock.k;
578
+ const authoredLength = currentBlock.ssbLength;
717
579
  if (authoredLength !== void 0 && currentBlock.sourceReceived >= authoredLength) {
718
580
  markBlockTerminal(currentBlock, "complete");
719
581
  blocksComplete++;
@@ -732,20 +594,10 @@ function handleDispose() {
732
594
  clearInterval(snapshotTimer);
733
595
  snapshotTimer = null;
734
596
  }
735
- if (altaVerifier) {
736
- try {
737
- altaVerifier.free();
738
- } catch (_e) {
739
- }
740
- altaVerifier = null;
741
- }
742
597
  if (wasmDecoder) {
743
598
  wasmDecoder.free();
744
599
  wasmDecoder = null;
745
600
  }
746
- pendingVerify.clear();
747
- pendingVerifyCap = 0;
748
- pendingVerifyTtlMs = 0;
749
601
  config = null;
750
602
  clearBlockTracking();
751
603
  }
@@ -767,13 +619,6 @@ function handleReset() {
767
619
  blocksComplete = 0;
768
620
  blocksRecovered = 0;
769
621
  blocksFailed = 0;
770
- altaVerified = 0;
771
- altaFailed = 0;
772
- altaFailedDetails.length = 0;
773
- altaPending = 0;
774
- altaPendingEvictedCap = 0;
775
- altaPendingEvictedTtl = 0;
776
- altaError = 0;
777
622
  relayBlocksVerified = 0;
778
623
  relayBlocksFailed = 0;
779
624
  repairSymbolSizeMismatch = 0;