@typeberry/jam 0.2.0-8017bfd → 0.2.0-adde0dd

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/index.js CHANGED
@@ -24603,7 +24603,7 @@ function resultToString(res) {
24603
24603
  if (res.isOk) {
24604
24604
  return `OK: ${typeof res.ok === "symbol" ? res.ok.toString() : res.ok}`;
24605
24605
  }
24606
- return `${res.details}\nError: ${maybeTaggedErrorToString(res.error)}`;
24606
+ return `${res.details()}\nError: ${maybeTaggedErrorToString(res.error)}`;
24607
24607
  }
24608
24608
  /** An indication of two possible outcomes returned from a function. */
24609
24609
  const result_Result = {
@@ -24617,7 +24617,7 @@ const result_Result = {
24617
24617
  };
24618
24618
  },
24619
24619
  /** Create new [`Result`] with `Error` status. */
24620
- error: (error, details = "") => {
24620
+ error: (error, details) => {
24621
24621
  debug_check `${error !== undefined} 'Error' type cannot be undefined.`;
24622
24622
  return {
24623
24623
  isOk: false,
@@ -24736,7 +24736,7 @@ function deepEqual(actual, expected, { context = [], errorsCollector, ignore = [
24736
24736
  }
24737
24737
  if (actual.isError && expected.isError) {
24738
24738
  deepEqual(actual.error, expected.error, { context: ctx.concat(["error"]), errorsCollector: errors, ignore });
24739
- deepEqual(actual.details, expected.details, {
24739
+ deepEqual(actual.details(), expected.details(), {
24740
24740
  context: ctx.concat(["details"]),
24741
24741
  errorsCollector: errors,
24742
24742
  // display details when error does not match
@@ -33499,7 +33499,7 @@ class in_memory_state_InMemoryState extends WithDebug {
33499
33499
  const { kind } = update.action;
33500
33500
  const service = this.services.get(serviceId);
33501
33501
  if (service === undefined) {
33502
- return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update storage of non-existing service: ${serviceId}`);
33502
+ return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update storage of non-existing service: ${serviceId}`);
33503
33503
  }
33504
33504
  if (kind === UpdateStorageKind.Set) {
33505
33505
  const { key, value } = update.action.storage;
@@ -33527,14 +33527,14 @@ class in_memory_state_InMemoryState extends WithDebug {
33527
33527
  for (const [serviceId, updates] of preimagesUpdates.entries()) {
33528
33528
  const service = this.services.get(serviceId);
33529
33529
  if (service === undefined) {
33530
- return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update preimage of non-existing service: ${serviceId}`);
33530
+ return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update preimage of non-existing service: ${serviceId}`);
33531
33531
  }
33532
33532
  for (const update of updates) {
33533
33533
  const { kind } = update.action;
33534
33534
  if (kind === UpdatePreimageKind.Provide) {
33535
33535
  const { preimage, slot } = update.action;
33536
33536
  if (service.data.preimages.has(preimage.hash)) {
33537
- return result_Result.error(in_memory_state_UpdateError.PreimageExists, `Overwriting existing preimage at ${serviceId}: ${preimage}`);
33537
+ return result_Result.error(in_memory_state_UpdateError.PreimageExists, () => `Overwriting existing preimage at ${serviceId}: ${preimage}`);
33538
33538
  }
33539
33539
  service.data.preimages.set(preimage.hash, preimage);
33540
33540
  if (slot !== null) {
@@ -33585,7 +33585,7 @@ class in_memory_state_InMemoryState extends WithDebug {
33585
33585
  if (kind === UpdateServiceKind.Create) {
33586
33586
  const { lookupHistory } = update.action;
33587
33587
  if (this.services.has(serviceId)) {
33588
- return result_Result.error(in_memory_state_UpdateError.DuplicateService, `${serviceId} already exists!`);
33588
+ return result_Result.error(in_memory_state_UpdateError.DuplicateService, () => `${serviceId} already exists!`);
33589
33589
  }
33590
33590
  this.services.set(serviceId, new InMemoryService(serviceId, {
33591
33591
  info: account,
@@ -33597,7 +33597,7 @@ class in_memory_state_InMemoryState extends WithDebug {
33597
33597
  else if (kind === UpdateServiceKind.Update) {
33598
33598
  const existingService = this.services.get(serviceId);
33599
33599
  if (existingService === undefined) {
33600
- return result_Result.error(in_memory_state_UpdateError.NoService, `Cannot update ${serviceId} because it does not exist.`);
33600
+ return result_Result.error(in_memory_state_UpdateError.NoService, () => `Cannot update ${serviceId} because it does not exist.`);
33601
33601
  }
33602
33602
  existingService.data.info = account;
33603
33603
  }
@@ -35227,13 +35227,13 @@ class LeafDb {
35227
35227
  */
35228
35228
  static fromLeavesBlob(blob, db) {
35229
35229
  if (blob.length % TRIE_NODE_BYTES !== 0) {
35230
- return result_Result.error(LeafDbError.InvalidLeafData, `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
35230
+ return result_Result.error(LeafDbError.InvalidLeafData, () => `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
35231
35231
  }
35232
35232
  const leaves = SortedSet.fromArray(leafComparator, []);
35233
35233
  for (const nodeData of blob.chunks(TRIE_NODE_BYTES)) {
35234
35234
  const node = new TrieNode(nodeData.raw);
35235
35235
  if (node.getNodeType() === NodeType.Branch) {
35236
- return result_Result.error(LeafDbError.InvalidLeafData, `Branch node detected: ${nodeData}`);
35236
+ return result_Result.error(LeafDbError.InvalidLeafData, () => `Branch node detected: ${nodeData}`);
35237
35237
  }
35238
35238
  leaves.insert(node.asLeafNode());
35239
35239
  }
@@ -35626,7 +35626,7 @@ class LmdbStates {
35626
35626
  }
35627
35627
  catch (e) {
35628
35628
  states_logger.error `${e}`;
35629
- return result_Result.error(StateUpdateError.Commit);
35629
+ return result_Result.error(StateUpdateError.Commit, () => `Failed to commit state update: ${e}`);
35630
35630
  }
35631
35631
  return result_Result.ok(result_OK);
35632
35632
  }
@@ -36558,7 +36558,7 @@ const importBlockResultCodec = descriptors_codec.custom({
36558
36558
  }
36559
36559
  if (kind === 1) {
36560
36560
  const error = d.bytesBlob();
36561
- return result_Result.error(error.asText());
36561
+ return result_Result.error(error.asText(), () => error.asText());
36562
36562
  }
36563
36563
  throw new Error(`Invalid Result: ${kind}`);
36564
36564
  }, (s) => {
@@ -36609,7 +36609,7 @@ class MainReady extends State {
36609
36609
  if (res instanceof Uint8Array) {
36610
36610
  return decoder_Decoder.decodeObject(importBlockResultCodec, res);
36611
36611
  }
36612
- return result_Result.error("Invalid worker response.");
36612
+ return result_Result.error("Invalid worker response.", () => "Invalid worker response: expected Uint8Array");
36613
36613
  }
36614
36614
  async getStateEntries(port, hash) {
36615
36615
  const res = await port.sendRequest("getStateEntries", hash, [hash.buffer]);
@@ -36721,13 +36721,13 @@ class ImporterReady extends State {
36721
36721
  response = result_Result.ok(this.importer.getBestStateRootHash() ?? ZERO_HASH.asOpaque());
36722
36722
  }
36723
36723
  else {
36724
- response = result_Result.error(resultToString(res));
36724
+ response = result_Result.error(resultToString(res), () => resultToString(res));
36725
36725
  }
36726
36726
  }
36727
36727
  catch (e) {
36728
36728
  state_machine_logger.error `Failed to import block: ${e}`;
36729
36729
  state_machine_logger.error `${e instanceof Error ? e.stack : ""}`;
36730
- response = result_Result.error(`${e}`);
36730
+ response = result_Result.error(`${e}`, () => `${e}`);
36731
36731
  }
36732
36732
  const encoded = encoder_Encoder.encodeObject(importBlockResultCodec, response);
36733
36733
  return {
@@ -37005,7 +37005,7 @@ class Preimages {
37005
37005
  }
37006
37006
  if (prevPreimage.requester > currPreimage.requester ||
37007
37007
  currPreimage.blob.compare(prevPreimage.blob).isLessOrEqual()) {
37008
- return result_Result.error(PreimagesErrorCode.PreimagesNotSortedUnique);
37008
+ return result_Result.error(PreimagesErrorCode.PreimagesNotSortedUnique, () => `Preimages not sorted/unique at index ${i}`);
37009
37009
  }
37010
37010
  }
37011
37011
  const { preimages, slot } = input;
@@ -37016,14 +37016,14 @@ class Preimages {
37016
37016
  const hash = this.blake2b.hashBytes(blob).asOpaque();
37017
37017
  const service = this.state.getService(requester);
37018
37018
  if (service === null) {
37019
- return result_Result.error(PreimagesErrorCode.AccountNotFound);
37019
+ return result_Result.error(PreimagesErrorCode.AccountNotFound, () => `Service not found: ${requester}`);
37020
37020
  }
37021
37021
  const hasPreimage = service.hasPreimage(hash);
37022
37022
  const slots = service.getLookupHistory(hash, numbers_tryAsU32(blob.length));
37023
37023
  // https://graypaper.fluffylabs.dev/#/5f542d7/181800181900
37024
37024
  // https://graypaper.fluffylabs.dev/#/5f542d7/116f0011a500
37025
37025
  if (hasPreimage || slots === null || !LookupHistoryItem.isRequested(slots)) {
37026
- return result_Result.error(PreimagesErrorCode.PreimageUnneeded);
37026
+ return result_Result.error(PreimagesErrorCode.PreimageUnneeded, () => `Preimage unneeded: requester=${requester}, hash=${hash}, hasPreimage=${hasPreimage}, isRequested=${slots !== null && LookupHistoryItem.isRequested(slots)}`);
37027
37027
  }
37028
37028
  // https://graypaper.fluffylabs.dev/#/5f542d7/18c00018f300
37029
37029
  const updates = pendingChanges.get(requester) ?? [];
@@ -38294,20 +38294,20 @@ async function verifyCertificate(certs) {
38294
38294
  // Must present exactly one cert
38295
38295
  if (certs.length !== 1) {
38296
38296
  certificate_logger.log `Rejecting peer: expected exactly one certificate, got: ${certs.length}`;
38297
- return result_Result.error(VerifyCertError.NoCertificate);
38297
+ return result_Result.error(VerifyCertError.NoCertificate, () => `Certificate validation failed: expected exactly one certificate, got ${certs.length}`);
38298
38298
  }
38299
38299
  // Parse with Node's X509Certificate (accepts PEM or DER)
38300
38300
  const xc = new (external_node_crypto_default()).X509Certificate(certs[0]);
38301
38301
  // Must be Ed25519 key
38302
38302
  if (xc.publicKey.asymmetricKeyType !== CURVE_NAME.toLowerCase()) {
38303
38303
  certificate_logger.log `Rejecting peer using non-ed25519 certificate: ${xc.publicKey.asymmetricKeyType}`;
38304
- return result_Result.error(VerifyCertError.NotEd25519);
38304
+ return result_Result.error(VerifyCertError.NotEd25519, () => `Certificate validation failed: expected Ed25519 key, got ${xc.publicKey.asymmetricKeyType}`);
38305
38305
  }
38306
38306
  // Extract raw public key via JWK export
38307
38307
  const jwk = xc.publicKey.export({ format: "jwk" });
38308
38308
  if (jwk.kty !== KEY_TYPE || jwk.crv !== CURVE_NAME) {
38309
38309
  certificate_logger.log `Public key type mismatch: ${jwk.kty}, ${jwk.crv}`;
38310
- return result_Result.error(VerifyCertError.PublicKeyTypeMismatch);
38310
+ return result_Result.error(VerifyCertError.PublicKeyTypeMismatch, () => `Certificate validation failed: public key type mismatch (kty: ${jwk.kty}, crv: ${jwk.crv})`);
38311
38311
  }
38312
38312
  // SAN must be exactly 'e'+base32(rawPub)
38313
38313
  const expectedSan = altNameJwk(jwk);
@@ -38315,11 +38315,11 @@ async function verifyCertificate(certs) {
38315
38315
  const m = sanField.match(/DNS:([^,]+)/);
38316
38316
  if (m === null || m[1] !== expectedSan) {
38317
38317
  certificate_logger.log `AltName mismatch. Expected: '${expectedSan}', got: '${m?.[1]}'`;
38318
- return result_Result.error(VerifyCertError.AltNameMismatch);
38318
+ return result_Result.error(VerifyCertError.AltNameMismatch, () => `Certificate validation failed: altName mismatch (expected: ${expectedSan}, got: ${m?.[1] ?? "none"})`);
38319
38319
  }
38320
38320
  const key = Buffer.from(jwk.x ?? "", "base64url");
38321
38321
  if (!xc.verify(xc.publicKey)) {
38322
- return result_Result.error(VerifyCertError.IncorrectSignature);
38322
+ return result_Result.error(VerifyCertError.IncorrectSignature, () => "Certificate validation failed: incorrect signature");
38323
38323
  }
38324
38324
  const publicKey = bytes_Bytes.fromBlob(new Uint8Array(key), ED25519_KEY_BYTES);
38325
38325
  return result_Result.ok({
@@ -39353,7 +39353,7 @@ function handleGetBlockSequence(chainSpec, blocks, startHash, direction, limit)
39353
39353
  };
39354
39354
  const startBlock = getBlockView(startHash);
39355
39355
  if (startBlock === null) {
39356
- return result_Result.error(BlockSequenceError.NoStartBlock);
39356
+ return result_Result.error(BlockSequenceError.NoStartBlock, () => `Block sequence error: start block ${startHash} not found`);
39357
39357
  }
39358
39358
  if (direction === Direction.AscExcl) {
39359
39359
  // Since we don't have an index of all blocks, we need to start from
@@ -39365,7 +39365,7 @@ function handleGetBlockSequence(chainSpec, blocks, startHash, direction, limit)
39365
39365
  const currentHeader = blocks.getHeader(currentHash);
39366
39366
  // some errornuous situation, we didn't really reach the block?
39367
39367
  if (currentHeader === null || currentHeader.timeSlotIndex.materialize() < startIndex) {
39368
- return result_Result.error(BlockSequenceError.BlockOnFork);
39368
+ return result_Result.error(BlockSequenceError.BlockOnFork, () => `Block sequence error: start block ${startHash} appears to be on a fork`);
39369
39369
  }
39370
39370
  // we have everything we need, let's return it now
39371
39371
  if (startHash.isEqualTo(currentHash)) {
@@ -40770,8 +40770,8 @@ class FuzzHandler {
40770
40770
  if (res.isOk) {
40771
40771
  return res;
40772
40772
  }
40773
- ipc_logger.log `Rejecting block with error: ${res.error}. ${res.details}`;
40774
- return result_Result.error(ErrorMessage.create({ message: res.error }));
40773
+ ipc_logger.log `Rejecting block with error: ${res.error}. ${res.details()}`;
40774
+ return result_Result.error(ErrorMessage.create({ message: res.error }), res.details);
40775
40775
  }
40776
40776
  async getPeerInfo(value) {
40777
40777
  ipc_logger.info `Fuzzer ${value} connected.`;
@@ -41026,7 +41026,7 @@ class BlockVerifier {
41026
41026
  const headerHash = this.hasher.header(headerView);
41027
41027
  // check if current block is already imported
41028
41028
  if (this.blocks.getHeader(headerHash.hash) !== null) {
41029
- return result_Result.error(BlockVerifierError.AlreadyImported, `Block ${headerHash.hash} is already imported.`);
41029
+ return result_Result.error(BlockVerifierError.AlreadyImported, () => `Block ${headerHash.hash} is already imported.`);
41030
41030
  }
41031
41031
  // Check if parent block exists.
41032
41032
  // https://graypaper.fluffylabs.dev/#/cc517d7/0c82000c8200?v=0.6.5
@@ -41036,14 +41036,14 @@ class BlockVerifier {
41036
41036
  if (!parentHash.isEqualTo(block_verifier_ZERO_HASH)) {
41037
41037
  const parentBlock = this.blocks.getHeader(parentHash);
41038
41038
  if (parentBlock === null) {
41039
- return result_Result.error(BlockVerifierError.ParentNotFound, `Parent ${parentHash.toString()} not found`);
41039
+ return result_Result.error(BlockVerifierError.ParentNotFound, () => `Parent ${parentHash.toString()} not found`);
41040
41040
  }
41041
41041
  // Check if the time slot index is consecutive and not from future.
41042
41042
  // https://graypaper.fluffylabs.dev/#/cc517d7/0c02010c0201?v=0.6.5
41043
41043
  const timeslot = headerView.timeSlotIndex.materialize();
41044
41044
  const parentTimeslot = parentBlock.timeSlotIndex.materialize();
41045
41045
  if (timeslot <= parentTimeslot) {
41046
- return result_Result.error(BlockVerifierError.InvalidTimeSlot, `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
41046
+ return result_Result.error(BlockVerifierError.InvalidTimeSlot, () => `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
41047
41047
  }
41048
41048
  }
41049
41049
  // Check if extrinsic is valid.
@@ -41051,17 +41051,17 @@ class BlockVerifier {
41051
41051
  const extrinsicHash = headerView.extrinsicHash.materialize();
41052
41052
  const extrinsicMerkleCommitment = this.hasher.extrinsic(block.extrinsic.view());
41053
41053
  if (!extrinsicHash.isEqualTo(extrinsicMerkleCommitment.hash)) {
41054
- return result_Result.error(BlockVerifierError.InvalidExtrinsic, `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
41054
+ return result_Result.error(BlockVerifierError.InvalidExtrinsic, () => `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
41055
41055
  }
41056
41056
  // Check if the state root is valid.
41057
41057
  // https://graypaper.fluffylabs.dev/#/cc517d7/0c18010c1801?v=0.6.5
41058
41058
  const stateRoot = headerView.priorStateRoot.materialize();
41059
41059
  const posteriorStateRoot = this.blocks.getPostStateRoot(parentHash);
41060
41060
  if (posteriorStateRoot === null) {
41061
- return result_Result.error(BlockVerifierError.StateRootNotFound, `Posterior state root ${parentHash.toString()} not found`);
41061
+ return result_Result.error(BlockVerifierError.StateRootNotFound, () => `Posterior state root ${parentHash.toString()} not found`);
41062
41062
  }
41063
41063
  if (!stateRoot.isEqualTo(posteriorStateRoot)) {
41064
- return result_Result.error(BlockVerifierError.InvalidStateRoot, `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
41064
+ return result_Result.error(BlockVerifierError.InvalidStateRoot, () => `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
41065
41065
  }
41066
41066
  return result_Result.ok(headerHash.hash);
41067
41067
  }
@@ -41186,7 +41186,7 @@ class Disputes {
41186
41186
  // check if culprits are sorted by key
41187
41187
  // https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
41188
41188
  if (!isUniqueSortedBy(disputes.culprits, "key")) {
41189
- return result_Result.error(DisputesErrorCode.CulpritsNotSortedUnique);
41189
+ return result_Result.error(DisputesErrorCode.CulpritsNotSortedUnique, () => "Culprits are not uniquely sorted by key");
41190
41190
  }
41191
41191
  const culpritsLength = disputes.culprits.length;
41192
41192
  for (let i = 0; i < culpritsLength; i++) {
@@ -41195,24 +41195,24 @@ class Disputes {
41195
41195
  // https://graypaper.fluffylabs.dev/#/579bd12/125501125501
41196
41196
  const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
41197
41197
  if (isInPunishSet) {
41198
- return result_Result.error(DisputesErrorCode.OffenderAlreadyReported);
41198
+ return result_Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: culprit ${i}, key=${key}`);
41199
41199
  }
41200
41200
  // check if the guarantor key is correct
41201
41201
  // https://graypaper.fluffylabs.dev/#/85129da/125501125501?v=0.6.3
41202
41202
  if (!allValidatorKeys.has(key)) {
41203
- return result_Result.error(DisputesErrorCode.BadGuarantorKey);
41203
+ return result_Result.error(DisputesErrorCode.BadGuarantorKey, () => `Bad guarantor key: culprit ${i}, key=${key}`);
41204
41204
  }
41205
41205
  // verify if the culprit will be in new bad set
41206
41206
  // https://graypaper.fluffylabs.dev/#/579bd12/124601124601
41207
41207
  const isInNewBadSet = newItems.asDictionaries().badSet.has(workReportHash);
41208
41208
  if (!isInNewBadSet) {
41209
- return result_Result.error(DisputesErrorCode.CulpritsVerdictNotBad);
41209
+ return result_Result.error(DisputesErrorCode.CulpritsVerdictNotBad, () => `Culprit verdict not bad: culprit ${i}, work report=${workReportHash}`);
41210
41210
  }
41211
41211
  // verify culprit signature
41212
41212
  // https://graypaper.fluffylabs.dev/#/579bd12/125c01125c01
41213
41213
  const result = verificationResult.culprits[i];
41214
41214
  if (!result?.isValid) {
41215
- return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for culprit: ${i}`);
41215
+ return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for culprit: ${i}`);
41216
41216
  }
41217
41217
  }
41218
41218
  return result_Result.ok(null);
@@ -41221,7 +41221,7 @@ class Disputes {
41221
41221
  // check if faults are sorted by key
41222
41222
  // https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
41223
41223
  if (!isUniqueSortedBy(disputes.faults, "key")) {
41224
- return result_Result.error(DisputesErrorCode.FaultsNotSortedUnique);
41224
+ return result_Result.error(DisputesErrorCode.FaultsNotSortedUnique, () => "Faults are not uniquely sorted by key");
41225
41225
  }
41226
41226
  const faultsLength = disputes.faults.length;
41227
41227
  for (let i = 0; i < faultsLength; i++) {
@@ -41230,12 +41230,12 @@ class Disputes {
41230
41230
  // https://graypaper.fluffylabs.dev/#/579bd12/12a20112a201
41231
41231
  const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
41232
41232
  if (isInPunishSet) {
41233
- return result_Result.error(DisputesErrorCode.OffenderAlreadyReported);
41233
+ return result_Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: fault ${i}, key=${key}`);
41234
41234
  }
41235
41235
  // check if the auditor key is correct
41236
41236
  // https://graypaper.fluffylabs.dev/#/85129da/12a20112a201?v=0.6.3
41237
41237
  if (!allValidatorKeys.has(key)) {
41238
- return result_Result.error(DisputesErrorCode.BadAuditorKey);
41238
+ return result_Result.error(DisputesErrorCode.BadAuditorKey, () => `Bad auditor key: fault ${i}, key=${key}`);
41239
41239
  }
41240
41240
  // verify if the fault will be included in new good/bad set
41241
41241
  // it may be not correct as in GP there is "iff" what means it should be rather
@@ -41247,14 +41247,14 @@ class Disputes {
41247
41247
  const isInNewGoodSet = goodSet.has(workReportHash);
41248
41248
  const isInNewBadSet = badSet.has(workReportHash);
41249
41249
  if (isInNewGoodSet || !isInNewBadSet) {
41250
- return result_Result.error(DisputesErrorCode.FaultVerdictWrong);
41250
+ return result_Result.error(DisputesErrorCode.FaultVerdictWrong, () => `Fault verdict wrong: fault ${i}, work report=${workReportHash}, inGood=${isInNewGoodSet}, inBad=${isInNewBadSet}`);
41251
41251
  }
41252
41252
  }
41253
41253
  // verify fault signature. Verification was done earlier, here we only check the result.
41254
41254
  // https://graypaper.fluffylabs.dev/#/579bd12/12a90112a901
41255
41255
  const result = verificationResult.faults[i];
41256
41256
  if (!result.isValid) {
41257
- return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for fault: ${i}`);
41257
+ return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for fault: ${i}`);
41258
41258
  }
41259
41259
  }
41260
41260
  return result_Result.ok(null);
@@ -41263,32 +41263,32 @@ class Disputes {
41263
41263
  // check if verdicts are correctly sorted
41264
41264
  // https://graypaper.fluffylabs.dev/#/579bd12/12c40112c401
41265
41265
  if (!isUniqueSortedBy(disputes.verdicts, "workReportHash")) {
41266
- return result_Result.error(DisputesErrorCode.VerdictsNotSortedUnique);
41266
+ return result_Result.error(DisputesErrorCode.VerdictsNotSortedUnique, () => "Verdicts are not uniquely sorted by work report hash");
41267
41267
  }
41268
41268
  // check if judgement are correctly sorted
41269
41269
  // https://graypaper.fluffylabs.dev/#/579bd12/123702123802
41270
41270
  if (disputes.verdicts.some((verdict) => !isUniqueSortedByIndex(verdict.votes))) {
41271
- return result_Result.error(DisputesErrorCode.JudgementsNotSortedUnique);
41271
+ return result_Result.error(DisputesErrorCode.JudgementsNotSortedUnique, () => "Judgements are not uniquely sorted by index");
41272
41272
  }
41273
41273
  const currentEpoch = Math.floor(this.state.timeslot / this.chainSpec.epochLength);
41274
41274
  let voteSignatureIndex = 0;
41275
41275
  for (const { votesEpoch, votes } of disputes.verdicts) {
41276
41276
  // https://graypaper.fluffylabs.dev/#/579bd12/12bb0012bc00
41277
41277
  if (votesEpoch !== currentEpoch && votesEpoch + 1 !== currentEpoch) {
41278
- return result_Result.error(DisputesErrorCode.BadJudgementAge);
41278
+ return result_Result.error(DisputesErrorCode.BadJudgementAge, () => `Bad judgement age: epoch=${votesEpoch}, current=${currentEpoch}`);
41279
41279
  }
41280
41280
  const k = votesEpoch === currentEpoch ? this.state.currentValidatorData : this.state.previousValidatorData;
41281
41281
  for (const { index } of votes) {
41282
41282
  const key = k[index]?.ed25519;
41283
41283
  // no particular GP fragment but I think we don't believe in ghosts
41284
41284
  if (key === undefined) {
41285
- return result_Result.error(DisputesErrorCode.BadValidatorIndex);
41285
+ return result_Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index: ${index} in epoch ${votesEpoch}`);
41286
41286
  }
41287
41287
  // verify vote signature. Verification was done earlier, here we only check the result.
41288
41288
  // https://graypaper.fluffylabs.dev/#/579bd12/12cd0012cd00
41289
41289
  const result = verificationResult.judgements[voteSignatureIndex];
41290
41290
  if (!result.isValid) {
41291
- return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for judgement: ${voteSignatureIndex}`);
41291
+ return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for judgement: ${voteSignatureIndex}`);
41292
41292
  }
41293
41293
  voteSignatureIndex += 1;
41294
41294
  }
@@ -41304,7 +41304,7 @@ class Disputes {
41304
41304
  const isInBadSet = badSet.has(verdict.workReportHash);
41305
41305
  const isInWonkySet = wonkySet.has(verdict.workReportHash);
41306
41306
  if (isInGoodSet || isInBadSet || isInWonkySet) {
41307
- return result_Result.error(DisputesErrorCode.AlreadyJudged);
41307
+ return result_Result.error(DisputesErrorCode.AlreadyJudged, () => `Work report already judged: ${verdict.workReportHash}`);
41308
41308
  }
41309
41309
  }
41310
41310
  return result_Result.ok(null);
@@ -41335,7 +41335,7 @@ class Disputes {
41335
41335
  // https://graypaper.fluffylabs.dev/#/579bd12/12f10212fc02
41336
41336
  const f = disputes.faults.find((x) => x.workReportHash.isEqualTo(r));
41337
41337
  if (f === undefined) {
41338
- return result_Result.error(DisputesErrorCode.NotEnoughFaults);
41338
+ return result_Result.error(DisputesErrorCode.NotEnoughFaults, () => `Not enough faults for work report: ${r}`);
41339
41339
  }
41340
41340
  }
41341
41341
  else if (sum === 0) {
@@ -41344,13 +41344,13 @@ class Disputes {
41344
41344
  const c1 = disputes.culprits.find((x) => x.workReportHash.isEqualTo(r));
41345
41345
  const c2 = disputes.culprits.findLast((x) => x.workReportHash.isEqualTo(r));
41346
41346
  if (c1 === c2) {
41347
- return result_Result.error(DisputesErrorCode.NotEnoughCulprits);
41347
+ return result_Result.error(DisputesErrorCode.NotEnoughCulprits, () => `Not enough culprits for work report: ${r}`);
41348
41348
  }
41349
41349
  }
41350
41350
  else if (sum !== this.chainSpec.thirdOfValidators) {
41351
41351
  // positive votes count is not correct
41352
41352
  // https://graypaper.fluffylabs.dev/#/579bd12/125002128102
41353
- return result_Result.error(DisputesErrorCode.BadVoteSplit);
41353
+ return result_Result.error(DisputesErrorCode.BadVoteSplit, () => `Bad vote split: sum=${sum}, expected=${this.chainSpec.thirdOfValidators} for work report ${r}`);
41354
41354
  }
41355
41355
  }
41356
41356
  return result_Result.ok(null);
@@ -41438,7 +41438,7 @@ class Disputes {
41438
41438
  const validator = k[j.index];
41439
41439
  // no particular GP fragment but I think we don't believe in ghosts
41440
41440
  if (validator === undefined) {
41441
- return result_Result.error(DisputesErrorCode.BadValidatorIndex);
41441
+ return result_Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index in signature verification: ${j.index}`);
41442
41442
  }
41443
41443
  const key = validator.ed25519;
41444
41444
  // verify vote signature
@@ -41546,7 +41546,7 @@ const ringCommitmentCache = [];
41546
41546
  async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUnsealedHeader) {
41547
41547
  const sealResult = await bandersnatch.verifySeal(authorKey.raw, signature.raw, payload.raw, encodedUnsealedHeader.raw);
41548
41548
  if (sealResult[RESULT_INDEX] === ResultValues.Error) {
41549
- return result_Result.error(null);
41549
+ return result_Result.error(null, () => "Bandersnatch VRF seal verification failed");
41550
41550
  }
41551
41551
  return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
41552
41552
  }
@@ -41572,7 +41572,7 @@ function getRingCommitment(bandersnatch, validators) {
41572
41572
  async function getRingCommitmentNoCache(bandersnatch, keys) {
41573
41573
  const commitmentResult = await bandersnatch.getRingCommitment(keys.raw);
41574
41574
  if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
41575
- return result_Result.error(null);
41575
+ return result_Result.error(null, () => "Bandersnatch ring commitment calculation failed");
41576
41576
  }
41577
41577
  return result_Result.ok(bytes_Bytes.fromBlob(commitmentResult.subarray(1), bandersnatch_BANDERSNATCH_RING_ROOT_BYTES).asOpaque());
41578
41578
  }
@@ -41747,7 +41747,7 @@ class Safrole {
41747
41747
  epochRoot: epochRootResult.ok,
41748
41748
  });
41749
41749
  }
41750
- return result_Result.error(SafroleErrorCode.IncorrectData);
41750
+ return result_Result.error(SafroleErrorCode.IncorrectData, () => "Safrole: failed to get epoch root for validator keys");
41751
41751
  }
41752
41752
  /**
41753
41753
  * Ticket sequencer that is used in standard mode
@@ -41838,10 +41838,10 @@ class Safrole {
41838
41838
  for (let i = 1; i < ticketsLength; i++) {
41839
41839
  const order = tickets[i - 1].id.compare(tickets[i].id);
41840
41840
  if (order.isEqual()) {
41841
- return result_Result.error(SafroleErrorCode.DuplicateTicket);
41841
+ return result_Result.error(SafroleErrorCode.DuplicateTicket, () => `Safrole: duplicate ticket found at index ${i}`);
41842
41842
  }
41843
41843
  if (order.isGreater()) {
41844
- return result_Result.error(SafroleErrorCode.BadTicketOrder);
41844
+ return result_Result.error(SafroleErrorCode.BadTicketOrder, () => `Safrole: bad ticket order at index ${i}`);
41845
41845
  }
41846
41846
  }
41847
41847
  return result_Result.ok(null);
@@ -41868,7 +41868,7 @@ class Safrole {
41868
41868
  attempt: ticket.attempt,
41869
41869
  }));
41870
41870
  if (!verificationResult.every((x) => x.isValid)) {
41871
- return result_Result.error(SafroleErrorCode.BadTicketProof);
41871
+ return result_Result.error(SafroleErrorCode.BadTicketProof, () => "Safrole: invalid ticket proof in extrinsic");
41872
41872
  }
41873
41873
  /**
41874
41874
  * Verify if tickets are sorted and unique
@@ -41877,7 +41877,7 @@ class Safrole {
41877
41877
  */
41878
41878
  const ticketsVerifcationResult = this.verifyTickets(tickets);
41879
41879
  if (ticketsVerifcationResult.isError) {
41880
- return result_Result.error(ticketsVerifcationResult.error);
41880
+ return result_Result.error(ticketsVerifcationResult.error, ticketsVerifcationResult.details);
41881
41881
  }
41882
41882
  if (this.isEpochChanged(timeslot)) {
41883
41883
  return result_Result.ok(tickets);
@@ -41886,7 +41886,7 @@ class Safrole {
41886
41886
  const ticketsFromExtrinsic = SortedSet.fromSortedArray(ticketComparator, tickets);
41887
41887
  const mergedTickets = SortedSet.fromTwoSortedCollections(ticketsFromState, ticketsFromExtrinsic);
41888
41888
  if (ticketsFromState.length + ticketsFromExtrinsic.length !== mergedTickets.length) {
41889
- return result_Result.error(SafroleErrorCode.DuplicateTicket);
41889
+ return result_Result.error(SafroleErrorCode.DuplicateTicket, () => "Safrole: duplicate ticket when merging state and extrinsic tickets");
41890
41890
  }
41891
41891
  /**
41892
41892
  * Remove tickets if size of accumulator exceeds E (epoch length).
@@ -41955,24 +41955,24 @@ class Safrole {
41955
41955
  }
41956
41956
  async transition(input) {
41957
41957
  if (this.state.timeslot >= input.slot) {
41958
- return result_Result.error(SafroleErrorCode.BadSlot);
41958
+ return result_Result.error(SafroleErrorCode.BadSlot, () => `Safrole: bad slot, state timeslot ${this.state.timeslot} >= input slot ${input.slot}`);
41959
41959
  }
41960
41960
  if (!this.isExtrinsicLengthValid(input.slot, input.extrinsic)) {
41961
- return result_Result.error(SafroleErrorCode.UnexpectedTicket);
41961
+ return result_Result.error(SafroleErrorCode.UnexpectedTicket, () => `Safrole: unexpected ticket, invalid extrinsic length ${input.extrinsic.length}`);
41962
41962
  }
41963
41963
  if (!this.areTicketAttemptsValid(input.extrinsic)) {
41964
- return result_Result.error(SafroleErrorCode.BadTicketAttempt);
41964
+ return result_Result.error(SafroleErrorCode.BadTicketAttempt, () => "Safrole: bad ticket attempt value in extrinsic");
41965
41965
  }
41966
41966
  const validatorKeysResult = await this.getValidatorKeys(input.slot, input.punishSet);
41967
41967
  if (validatorKeysResult.isError) {
41968
- return result_Result.error(validatorKeysResult.error);
41968
+ return result_Result.error(validatorKeysResult.error, validatorKeysResult.details);
41969
41969
  }
41970
41970
  const { nextValidatorData, currentValidatorData, previousValidatorData, epochRoot } = validatorKeysResult.ok;
41971
41971
  const entropy = this.getEntropy(input.slot, input.entropy);
41972
41972
  const sealingKeySeries = this.getSlotKeySequence(input.slot, currentValidatorData, entropy[2]);
41973
41973
  const newTicketsAccumulatorResult = await this.getNewTicketAccumulator(input.slot, input.extrinsic, this.state.nextValidatorData, epochRoot, entropy[2]);
41974
41974
  if (newTicketsAccumulatorResult.isError) {
41975
- return result_Result.error(newTicketsAccumulatorResult.error);
41975
+ return result_Result.error(newTicketsAccumulatorResult.error, newTicketsAccumulatorResult.details);
41976
41976
  }
41977
41977
  const stateUpdate = {
41978
41978
  nextValidatorData,
@@ -42006,14 +42006,14 @@ function compareWithEncoding(chainSpec, error, actual, expected, codec) {
42006
42006
  if (actual === null || expected === null) {
42007
42007
  // if one of them is `null`, both need to be.
42008
42008
  if (actual !== expected) {
42009
- return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
42009
+ return result_Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
42010
42010
  }
42011
42011
  return result_Result.ok(result_OK);
42012
42012
  }
42013
42013
  // compare the literal encoding.
42014
42014
  const encoded = encoder_Encoder.encodeObject(codec, actual, chainSpec);
42015
42015
  if (!encoded.isEqualTo(expected.encoded())) {
42016
- return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
42016
+ return result_Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
42017
42017
  }
42018
42018
  return result_Result.ok(result_OK);
42019
42019
  }
@@ -42056,7 +42056,7 @@ class SafroleSeal {
42056
42056
  const blockAuthorKey = state.currentValidatorData.at(blockAuthorIndex)?.bandersnatch;
42057
42057
  const entropySourceResult = await bandersnatch_vrf.verifySeal(await this.bandersnatch, blockAuthorKey ?? BANDERSNATCH_ZERO_KEY, headerView.entropySource.materialize(), payload, bytes_BytesBlob.blobFromNumbers([]));
42058
42058
  if (entropySourceResult.isError) {
42059
- return result_Result.error(SafroleSealError.IncorrectEntropySource);
42059
+ return result_Result.error(SafroleSealError.IncorrectEntropySource, () => "Safrole: incorrect entropy source in header seal");
42060
42060
  }
42061
42061
  return result_Result.ok(entropySourceResult.ok);
42062
42062
  }
@@ -42065,7 +42065,7 @@ class SafroleSeal {
42065
42065
  const validatorIndex = headerView.bandersnatchBlockAuthorIndex.materialize();
42066
42066
  const authorKeys = state.currentValidatorData.at(validatorIndex);
42067
42067
  if (authorKeys === undefined) {
42068
- return result_Result.error(SafroleSealError.InvalidValidatorIndex);
42068
+ return result_Result.error(SafroleSealError.InvalidValidatorIndex, () => `Safrole: invalid validator index ${validatorIndex}`);
42069
42069
  }
42070
42070
  const timeSlot = headerView.timeSlotIndex.materialize();
42071
42071
  const sealingKeys = state.sealingKeySeries;
@@ -42084,10 +42084,10 @@ class SafroleSeal {
42084
42084
  const authorKey = validatorData.bandersnatch;
42085
42085
  const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, authorKey ?? BANDERSNATCH_ZERO_KEY, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
42086
42086
  if (result.isError) {
42087
- return result_Result.error(SafroleSealError.IncorrectSeal);
42087
+ return result_Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with ticket");
42088
42088
  }
42089
42089
  if (ticket === undefined || !ticket.id.isEqualTo(result.ok)) {
42090
- return result_Result.error(SafroleSealError.InvalidTicket);
42090
+ return result_Result.error(SafroleSealError.InvalidTicket, () => `Safrole: invalid ticket, expected ${ticket?.id} got ${result.ok}`);
42091
42091
  }
42092
42092
  return result_Result.ok(result.ok);
42093
42093
  }
@@ -42097,13 +42097,13 @@ class SafroleSeal {
42097
42097
  const sealingKey = keys.at(index);
42098
42098
  const authorBandersnatchKey = authorKey.bandersnatch;
42099
42099
  if (sealingKey === undefined || !sealingKey.isEqualTo(authorBandersnatchKey)) {
42100
- return result_Result.error(SafroleSealError.InvalidValidator, `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
42100
+ return result_Result.error(SafroleSealError.InvalidValidator, () => `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
42101
42101
  }
42102
42102
  // verify seal correctness
42103
42103
  const payload = bytes_BytesBlob.blobFromParts(JAM_FALLBACK_SEAL, entropy.raw);
42104
42104
  const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, authorBandersnatchKey, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
42105
42105
  if (result.isError) {
42106
- return result_Result.error(SafroleSealError.IncorrectSeal);
42106
+ return result_Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with keys");
42107
42107
  }
42108
42108
  return result_Result.ok(result.ok);
42109
42109
  }
@@ -42376,11 +42376,11 @@ class PartiallyUpdatedState {
42376
42376
  const overflowBytes = !isU64(bytes);
42377
42377
  // TODO [ToDr] this is not specified in GP, but it seems sensible.
42378
42378
  if (overflowItems || overflowBytes) {
42379
- return result_Result.error(InsufficientFundsError);
42379
+ return result_Result.error(InsufficientFundsError, () => `Storage utilisation overflow: items=${overflowItems}, bytes=${overflowBytes}`);
42380
42380
  }
42381
42381
  const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(items, bytes, serviceInfo.gratisStorage);
42382
42382
  if (serviceInfo.balance < thresholdBalance) {
42383
- return result_Result.error(InsufficientFundsError);
42383
+ return result_Result.error(InsufficientFundsError, () => `Service balance (${serviceInfo.balance}) below threshold (${thresholdBalance})`);
42384
42384
  }
42385
42385
  // Update service info with new details.
42386
42386
  this.updateServiceInfo(serviceId, ServiceAccountInfo.create({
@@ -43883,7 +43883,7 @@ class ReadablePage extends MemoryPage {
43883
43883
  loadInto(result, startIndex, length) {
43884
43884
  const endIndex = startIndex + length;
43885
43885
  if (endIndex > PAGE_SIZE) {
43886
- return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE));
43886
+ return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE}`);
43887
43887
  }
43888
43888
  const bytes = this.data.subarray(startIndex, endIndex);
43889
43889
  // we zero the bytes, since data might not yet be initialized at `endIndex`.
@@ -43892,7 +43892,7 @@ class ReadablePage extends MemoryPage {
43892
43892
  return result_Result.ok(result_OK);
43893
43893
  }
43894
43894
  storeFrom(_address, _data) {
43895
- return result_Result.error(PageFault.fromMemoryIndex(this.start, true));
43895
+ return result_Result.error(PageFault.fromMemoryIndex(this.start, true), () => `Page fault: attempted to write to read-only page at ${this.start}`);
43896
43896
  }
43897
43897
  setData(pageIndex, data) {
43898
43898
  this.data.set(data, pageIndex);
@@ -43926,7 +43926,7 @@ class WriteablePage extends MemoryPage {
43926
43926
  loadInto(result, startIndex, length) {
43927
43927
  const endIndex = startIndex + length;
43928
43928
  if (endIndex > PAGE_SIZE) {
43929
- return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE));
43929
+ return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE}`);
43930
43930
  }
43931
43931
  const bytes = this.view.subarray(startIndex, endIndex);
43932
43932
  // we zero the bytes, since the view might not yet be initialized at `endIndex`.
@@ -44012,7 +44012,7 @@ class Memory {
44012
44012
  memory_logger.insane `MEM[${address}] <- ${bytes_BytesBlob.blobFrom(bytes)}`;
44013
44013
  const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
44014
44014
  if (pagesResult.isError) {
44015
- return result_Result.error(pagesResult.error);
44015
+ return result_Result.error(pagesResult.error, pagesResult.details);
44016
44016
  }
44017
44017
  const pages = pagesResult.ok;
44018
44018
  let currentPosition = address;
@@ -44037,14 +44037,14 @@ class Memory {
44037
44037
  const pages = [];
44038
44038
  for (const pageNumber of pageRange) {
44039
44039
  if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
44040
- return result_Result.error(PageFault.fromPageNumber(pageNumber, true));
44040
+ return result_Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
44041
44041
  }
44042
44042
  const page = this.memory.get(pageNumber);
44043
44043
  if (page === undefined) {
44044
- return result_Result.error(PageFault.fromPageNumber(pageNumber));
44044
+ return result_Result.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
44045
44045
  }
44046
44046
  if (accessType === AccessType.WRITE && !page.isWriteable()) {
44047
- return result_Result.error(PageFault.fromPageNumber(pageNumber, true));
44047
+ return result_Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
44048
44048
  }
44049
44049
  pages.push(page);
44050
44050
  }
@@ -44062,7 +44062,7 @@ class Memory {
44062
44062
  }
44063
44063
  const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
44064
44064
  if (pagesResult.isError) {
44065
- return result_Result.error(pagesResult.error);
44065
+ return result_Result.error(pagesResult.error, pagesResult.details);
44066
44066
  }
44067
44067
  const pages = pagesResult.ok;
44068
44068
  let currentPosition = startAddress;
@@ -46001,7 +46001,7 @@ class ProgramDecoder {
46001
46001
  }
46002
46002
  catch (e) {
46003
46003
  program_decoder_logger.error `Invalid program: ${e}`;
46004
- return result_Result.error(ProgramDecoderError.InvalidProgramError);
46004
+ return result_Result.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
46005
46005
  }
46006
46006
  }
46007
46007
  }
@@ -46744,10 +46744,10 @@ class AccumulateExternalities {
46744
46744
  const len = existingPreimage.slots.length;
46745
46745
  // https://graypaper.fluffylabs.dev/#/9a08063/380901380901?v=0.6.6
46746
46746
  if (len === PreimageStatusKind.Requested) {
46747
- return result_Result.error(RequestPreimageError.AlreadyRequested);
46747
+ return result_Result.error(RequestPreimageError.AlreadyRequested, () => `Preimage already requested: hash=${hash}`);
46748
46748
  }
46749
46749
  if (len === PreimageStatusKind.Available || len === PreimageStatusKind.Reavailable) {
46750
- return result_Result.error(RequestPreimageError.AlreadyAvailable);
46750
+ return result_Result.error(RequestPreimageError.AlreadyAvailable, () => `Preimage already available: hash=${hash}`);
46751
46751
  }
46752
46752
  // TODO [ToDr] Not sure if we should update the service info in that case,
46753
46753
  // but for now we let that case fall-through.
@@ -46788,7 +46788,7 @@ class AccumulateExternalities {
46788
46788
  const serviceId = this.currentServiceId;
46789
46789
  const status = this.updatedState.getLookupHistory(this.currentTimeslot, this.currentServiceId, hash, length);
46790
46790
  if (status === null) {
46791
- return result_Result.error(ForgetPreimageError.NotFound);
46791
+ return result_Result.error(ForgetPreimageError.NotFound, () => `Preimage not found: hash=${hash}, length=${length}`);
46792
46792
  }
46793
46793
  const s = slotsToPreimageStatus(status.slots);
46794
46794
  const updateStorageUtilisation = () => {
@@ -46801,7 +46801,7 @@ class AccumulateExternalities {
46801
46801
  if (s.status === PreimageStatusKind.Requested) {
46802
46802
  const res = updateStorageUtilisation();
46803
46803
  if (res.isError) {
46804
- return result_Result.error(ForgetPreimageError.StorageUtilisationError);
46804
+ return result_Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
46805
46805
  }
46806
46806
  this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
46807
46807
  hash: status.hash,
@@ -46816,7 +46816,7 @@ class AccumulateExternalities {
46816
46816
  if (y < t - this.chainSpec.preimageExpungePeriod) {
46817
46817
  const res = updateStorageUtilisation();
46818
46818
  if (res.isError) {
46819
- return result_Result.error(ForgetPreimageError.StorageUtilisationError);
46819
+ return result_Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
46820
46820
  }
46821
46821
  this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
46822
46822
  hash: status.hash,
@@ -46824,7 +46824,7 @@ class AccumulateExternalities {
46824
46824
  }));
46825
46825
  return result_Result.ok(result_OK);
46826
46826
  }
46827
- return result_Result.error(ForgetPreimageError.NotExpired);
46827
+ return result_Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
46828
46828
  }
46829
46829
  // https://graypaper.fluffylabs.dev/#/9a08063/38c80138c801?v=0.6.6
46830
46830
  if (s.status === PreimageStatusKind.Available) {
@@ -46842,7 +46842,7 @@ class AccumulateExternalities {
46842
46842
  }));
46843
46843
  return result_Result.ok(result_OK);
46844
46844
  }
46845
- return result_Result.error(ForgetPreimageError.NotExpired);
46845
+ return result_Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
46846
46846
  }
46847
46847
  debug_assertNever(s);
46848
46848
  }
@@ -46851,17 +46851,17 @@ class AccumulateExternalities {
46851
46851
  const destination = this.getServiceInfo(destinationId);
46852
46852
  /** https://graypaper.fluffylabs.dev/#/9a08063/370401370401?v=0.6.6 */
46853
46853
  if (destination === null || destinationId === null) {
46854
- return result_Result.error(TransferError.DestinationNotFound);
46854
+ return result_Result.error(TransferError.DestinationNotFound, () => `Destination service not found: ${destinationId}`);
46855
46855
  }
46856
46856
  /** https://graypaper.fluffylabs.dev/#/9a08063/371301371301?v=0.6.6 */
46857
46857
  if (gas < destination.onTransferMinGas) {
46858
- return result_Result.error(TransferError.GasTooLow);
46858
+ return result_Result.error(TransferError.GasTooLow, () => `Gas ${gas} below minimum ${destination.onTransferMinGas}`);
46859
46859
  }
46860
46860
  /** https://graypaper.fluffylabs.dev/#/9a08063/371b01371b01?v=0.6.6 */
46861
46861
  const newBalance = source.balance - amount;
46862
46862
  const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(source.storageUtilisationCount, source.storageUtilisationBytes, source.gratisStorage);
46863
46863
  if (newBalance < thresholdBalance) {
46864
- return result_Result.error(TransferError.BalanceBelowThreshold);
46864
+ return result_Result.error(TransferError.BalanceBelowThreshold, () => `Balance ${newBalance} below threshold ${thresholdBalance}`);
46865
46865
  }
46866
46866
  // outgoing transfer
46867
46867
  this.updatedState.stateUpdate.transfers.push(PendingTransfer.create({
@@ -46888,7 +46888,7 @@ class AccumulateExternalities {
46888
46888
  // check if we are priviledged to set gratis storage
46889
46889
  // https://graypaper.fluffylabs.dev/#/7e6ff6a/369203369603?v=0.6.7
46890
46890
  if (gratisStorage !== numbers_tryAsU64(0) && this.currentServiceId !== this.updatedState.getPrivilegedServices().manager) {
46891
- return result_Result.error(NewServiceError.UnprivilegedService);
46891
+ return result_Result.error(NewServiceError.UnprivilegedService, () => `Service ${this.currentServiceId} not privileged to set gratis storage`);
46892
46892
  }
46893
46893
  // check if we have enough balance
46894
46894
  // https://graypaper.fluffylabs.dev/#/7e6ff6a/369e0336a303?v=0.6.7
@@ -46897,7 +46897,7 @@ class AccumulateExternalities {
46897
46897
  const thresholdForCurrent = ServiceAccountInfo.calculateThresholdBalance(currentService.storageUtilisationCount, currentService.storageUtilisationBytes, currentService.gratisStorage);
46898
46898
  const balanceLeftForCurrent = currentService.balance - thresholdForNew;
46899
46899
  if (balanceLeftForCurrent < thresholdForCurrent || bytes.overflow) {
46900
- return result_Result.error(NewServiceError.InsufficientFunds);
46900
+ return result_Result.error(NewServiceError.InsufficientFunds, () => `Insufficient funds: balance=${currentService.balance}, required=${thresholdForNew}, overflow=${bytes.overflow}`);
46901
46901
  }
46902
46902
  // `a`: https://graypaper.fluffylabs.dev/#/ab2cdbd/366b02366d02?v=0.7.2
46903
46903
  const newAccount = ServiceAccountInfo.create({
@@ -46924,7 +46924,7 @@ class AccumulateExternalities {
46924
46924
  // NOTE: It's safe to cast to `Number` here, bcs here service ID cannot be bigger than 2**16
46925
46925
  const newServiceId = tryAsServiceId(Number(wantedServiceId));
46926
46926
  if (this.getServiceInfo(newServiceId) !== null) {
46927
- return result_Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken);
46927
+ return result_Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken, () => `Service ID ${newServiceId} already taken`);
46928
46928
  }
46929
46929
  // add the new service with selected ID
46930
46930
  // https://graypaper.fluffylabs.dev/#/ab2cdbd/36be0336c003?v=0.7.2
@@ -46964,7 +46964,7 @@ class AccumulateExternalities {
46964
46964
  const currentDelegator = this.updatedState.getPrivilegedServices().delegator;
46965
46965
  if (currentDelegator !== this.currentServiceId) {
46966
46966
  accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not a validators manager. (expected: ${currentDelegator}) and cannot update validators data. Ignoring`;
46967
- return result_Result.error(UnprivilegedError);
46967
+ return result_Result.error(UnprivilegedError, () => `Service ${this.currentServiceId} is not delegator (expected: ${currentDelegator})`);
46968
46968
  }
46969
46969
  this.updatedState.stateUpdate.validatorsData = validatorsData;
46970
46970
  return result_Result.ok(result_OK);
@@ -46979,11 +46979,11 @@ class AccumulateExternalities {
46979
46979
  const currentAssigners = this.updatedState.getPrivilegedServices().assigners[coreIndex];
46980
46980
  if (currentAssigners !== this.currentServiceId) {
46981
46981
  accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not an auth manager of core ${coreIndex} (expected: ${currentAssigners}) and cannot update authorization queue.`;
46982
- return result_Result.error(UpdatePrivilegesError.UnprivilegedService);
46982
+ return result_Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} not assigner for core ${coreIndex} (expected: ${currentAssigners})`);
46983
46983
  }
46984
46984
  if (assigners === null && Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)) {
46985
46985
  accumulate_externalities_logger.trace `The new auth manager is not a valid service id.`;
46986
- return result_Result.error(UpdatePrivilegesError.InvalidServiceId);
46986
+ return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => `New auth manager is null for core ${coreIndex}`);
46987
46987
  }
46988
46988
  this.updatedState.stateUpdate.authorizationQueues.set(coreIndex, authQueue);
46989
46989
  return result_Result.ok(result_OK);
@@ -47016,10 +47016,10 @@ class AccumulateExternalities {
47016
47016
  const isManager = current.manager === this.currentServiceId;
47017
47017
  if (Compatibility.isLessThan(GpVersion.V0_7_1)) {
47018
47018
  if (!isManager) {
47019
- return result_Result.error(UpdatePrivilegesError.UnprivilegedService);
47019
+ return result_Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} is not manager`);
47020
47020
  }
47021
47021
  if (manager === null || delegator === null) {
47022
- return result_Result.error(UpdatePrivilegesError.InvalidServiceId, "Either manager or delegator is not a valid service id.");
47022
+ return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator is not a valid service id.");
47023
47023
  }
47024
47024
  this.updatedState.stateUpdate.privilegedServices = PrivilegedServices.create({
47025
47025
  manager,
@@ -47032,7 +47032,7 @@ class AccumulateExternalities {
47032
47032
  }
47033
47033
  const original = this.updatedState.state.privilegedServices;
47034
47034
  if (manager === null || delegator === null || registrar === null) {
47035
- return result_Result.error(UpdatePrivilegesError.InvalidServiceId, "Either manager or delegator or registrar is not a valid service id.");
47035
+ return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator or registrar is not a valid service id.");
47036
47036
  }
47037
47037
  const newDelegator = this.updatePrivilegedServiceId(delegator, current.delegator, {
47038
47038
  isManager,
@@ -47072,19 +47072,19 @@ class AccumulateExternalities {
47072
47072
  // TODO [ToDr] what about newly created services?
47073
47073
  const service = serviceId === null ? null : this.updatedState.state.getService(serviceId);
47074
47074
  if (service === null || serviceId === null) {
47075
- return result_Result.error(ProvidePreimageError.ServiceNotFound);
47075
+ return result_Result.error(ProvidePreimageError.ServiceNotFound, () => `Service not found: ${serviceId}`);
47076
47076
  }
47077
47077
  // calculating the hash
47078
47078
  const preimageHash = this.blake2b.hashBytes(preimage).asOpaque();
47079
47079
  // checking service internal lookup
47080
47080
  const stateLookup = this.updatedState.getLookupHistory(this.currentTimeslot, serviceId, preimageHash, numbers_tryAsU64(preimage.length));
47081
47081
  if (stateLookup === null || !LookupHistoryItem.isRequested(stateLookup)) {
47082
- return result_Result.error(ProvidePreimageError.WasNotRequested);
47082
+ return result_Result.error(ProvidePreimageError.WasNotRequested, () => `Preimage was not requested: hash=${preimageHash}, service=${serviceId}`);
47083
47083
  }
47084
47084
  // checking already provided preimages
47085
47085
  const hasPreimage = this.updatedState.hasPreimage(serviceId, preimageHash);
47086
47086
  if (hasPreimage) {
47087
- return result_Result.error(ProvidePreimageError.AlreadyProvided);
47087
+ return result_Result.error(ProvidePreimageError.AlreadyProvided, () => `Preimage already provided: hash=${preimageHash}, service=${serviceId}`);
47088
47088
  }
47089
47089
  // setting up the new preimage
47090
47090
  this.updatedState.updatePreimage(serviceId, UpdatePreimage.provide({
@@ -47099,31 +47099,31 @@ class AccumulateExternalities {
47099
47099
  eject(destination, previousCodeHash) {
47100
47100
  const service = this.getServiceInfo(destination);
47101
47101
  if (service === null || destination === null) {
47102
- return result_Result.error(EjectError.InvalidService, "Service missing");
47102
+ return result_Result.error(EjectError.InvalidService, () => "Service missing");
47103
47103
  }
47104
47104
  const currentService = this.getCurrentServiceInfo();
47105
47105
  // check if the service expects to be ejected by us:
47106
47106
  const expectedCodeHash = bytes_Bytes.zero(hash_HASH_SIZE).asOpaque();
47107
47107
  writeServiceIdAsLeBytes(this.currentServiceId, expectedCodeHash.raw);
47108
47108
  if (!service.codeHash.isEqualTo(expectedCodeHash)) {
47109
- return result_Result.error(EjectError.InvalidService, "Invalid code hash");
47109
+ return result_Result.error(EjectError.InvalidService, () => "Invalid code hash");
47110
47110
  }
47111
47111
  // make sure the service only has required number of storage items?
47112
47112
  if (service.storageUtilisationCount !== REQUIRED_NUMBER_OF_STORAGE_ITEMS_FOR_EJECT) {
47113
- return result_Result.error(EjectError.InvalidPreimage, "Too many storage items");
47113
+ return result_Result.error(EjectError.InvalidPreimage, () => "Too many storage items");
47114
47114
  }
47115
47115
  // storage items length
47116
47116
  const l = numbers_tryAsU64(maxU64(service.storageUtilisationBytes, LOOKUP_HISTORY_ENTRY_BYTES) - LOOKUP_HISTORY_ENTRY_BYTES);
47117
47117
  // check if we have a preimage with the entire storage.
47118
47118
  const [isPreviousCodeExpired, errorReason] = this.isPreviousCodeExpired(destination, previousCodeHash, l);
47119
47119
  if (!isPreviousCodeExpired) {
47120
- return result_Result.error(EjectError.InvalidPreimage, `Previous code available: ${errorReason}`);
47120
+ return result_Result.error(EjectError.InvalidPreimage, () => `Previous code available: ${errorReason}`);
47121
47121
  }
47122
47122
  // compute new balance of the service.
47123
47123
  const newBalance = sumU64(currentService.balance, service.balance);
47124
47124
  // TODO [ToDr] what to do in case of overflow?
47125
47125
  if (newBalance.overflow) {
47126
- return result_Result.error(EjectError.InvalidService, "Balance overflow");
47126
+ return result_Result.error(EjectError.InvalidService, () => "Balance overflow");
47127
47127
  }
47128
47128
  // update current service.
47129
47129
  this.updatedState.updateServiceInfo(this.currentServiceId, ServiceAccountInfo.create({
@@ -47318,10 +47318,10 @@ class Assurances {
47318
47318
  for (const assurance of assurances) {
47319
47319
  const { anchor, validatorIndex, bitfield } = assurance;
47320
47320
  if (!anchor.isEqualTo(input.parentHash)) {
47321
- return result_Result.error(AssurancesError.InvalidAnchor, `anchor: expected: ${input.parentHash}, got ${anchor}`);
47321
+ return result_Result.error(AssurancesError.InvalidAnchor, () => `anchor: expected: ${input.parentHash}, got ${anchor}`);
47322
47322
  }
47323
47323
  if (prevValidatorIndex >= validatorIndex) {
47324
- return result_Result.error(AssurancesError.InvalidOrder, `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
47324
+ return result_Result.error(AssurancesError.InvalidOrder, () => `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
47325
47325
  }
47326
47326
  prevValidatorIndex = assurance.validatorIndex;
47327
47327
  debug_check `${bitfield.bitLength === coresCount} Invalid bitfield length of ${bitfield.bitLength}`;
@@ -47344,7 +47344,7 @@ class Assurances {
47344
47344
  * https://graypaper.fluffylabs.dev/#/579bd12/14e90014ea00
47345
47345
  */
47346
47346
  if (noOfAssurances > 0 && !isReportPending) {
47347
- return result_Result.error(AssurancesError.NoReportPending, `no report pending for core ${c} yet we got an assurance`);
47347
+ return result_Result.error(AssurancesError.NoReportPending, () => `no report pending for core ${c} yet we got an assurance`);
47348
47348
  }
47349
47349
  /**
47350
47350
  * Remove work report if it's became available or timed out.
@@ -47390,7 +47390,7 @@ class Assurances {
47390
47390
  const v = assurance.view();
47391
47391
  const key = validatorData[v.validatorIndex.materialize()];
47392
47392
  if (key === undefined) {
47393
- return result_Result.error(AssurancesError.InvalidValidatorIndex);
47393
+ return result_Result.error(AssurancesError.InvalidValidatorIndex, () => `Invalid validator index: ${v.validatorIndex.materialize()}`);
47394
47394
  }
47395
47395
  signatures.push({
47396
47396
  signature: v.signature.materialize(),
@@ -47402,7 +47402,7 @@ class Assurances {
47402
47402
  const isAllSignaturesValid = signaturesValid.every((x) => x);
47403
47403
  if (!isAllSignaturesValid) {
47404
47404
  const invalidIndices = signaturesValid.reduce((acc, isValid, idx) => (isValid ? acc : acc.concat(idx)), []);
47405
- return result_Result.error(AssurancesError.InvalidSignature, `invalid signatures at ${invalidIndices.join(", ")}`);
47405
+ return result_Result.error(AssurancesError.InvalidSignature, () => `invalid signatures at ${invalidIndices.join(", ")}`);
47406
47406
  }
47407
47407
  return result_Result.ok(result_OK);
47408
47408
  }
@@ -48013,7 +48013,7 @@ class HostCallMemory {
48013
48013
  return result_Result.ok(result_OK);
48014
48014
  }
48015
48015
  if (address + numbers_tryAsU64(bytes.length) > MEMORY_SIZE) {
48016
- return result_Result.error(new OutOfBounds());
48016
+ return result_Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`);
48017
48017
  }
48018
48018
  return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
48019
48019
  }
@@ -48022,7 +48022,7 @@ class HostCallMemory {
48022
48022
  return result_Result.ok(result_OK);
48023
48023
  }
48024
48024
  if (startAddress + numbers_tryAsU64(result.length) > MEMORY_SIZE) {
48025
- return result_Result.error(new OutOfBounds());
48025
+ return result_Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`);
48026
48026
  }
48027
48027
  return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
48028
48028
  }
@@ -49965,18 +49965,18 @@ class Accumulate {
49965
49965
  const serviceInfo = updatedState.getServiceInfo(serviceId);
49966
49966
  if (serviceInfo === null) {
49967
49967
  accumulate_logger.log `Service with id ${serviceId} not found.`;
49968
- return result_Result.error(PvmInvocationError.NoService);
49968
+ return result_Result.error(PvmInvocationError.NoService, () => `Accumulate: service ${serviceId} not found`);
49969
49969
  }
49970
49970
  const codeHash = serviceInfo.codeHash;
49971
49971
  // TODO [ToDr] Should we check that the preimage is still available?
49972
49972
  const code = updatedState.getPreimage(serviceId, codeHash.asOpaque());
49973
49973
  if (code === null) {
49974
49974
  accumulate_logger.log `Code with hash ${codeHash} not found for service ${serviceId}.`;
49975
- return result_Result.error(PvmInvocationError.NoPreimage);
49975
+ return result_Result.error(PvmInvocationError.NoPreimage, () => `Accumulate: code with hash ${codeHash} not found for service ${serviceId}`);
49976
49976
  }
49977
49977
  if (code.length > W_C) {
49978
49978
  accumulate_logger.log `Code with hash ${codeHash} is too long for service ${serviceId}.`;
49979
- return result_Result.error(PvmInvocationError.PreimageTooLong);
49979
+ return result_Result.error(PvmInvocationError.PreimageTooLong, () => `Accumulate: code length ${code.length} exceeds max ${W_C} for service ${serviceId}`);
49980
49980
  }
49981
49981
  const nextServiceId = generateNextServiceId({ serviceId, entropy, timeslot: slot }, this.chainSpec, this.blake2b);
49982
49982
  const partialState = new AccumulateExternalities(this.chainSpec, this.blake2b, updatedState, serviceId, nextServiceId, slot);
@@ -50264,7 +50264,7 @@ class Accumulate {
50264
50264
  assertEmpty(stateUpdateRest);
50265
50265
  if (this.hasDuplicatedServiceIdCreated(services.created)) {
50266
50266
  accumulate_logger.trace `Duplicated Service creation detected. Block is invalid.`;
50267
- return result_Result.error(ACCUMULATION_ERROR);
50267
+ return result_Result.error(ACCUMULATION_ERROR, () => "Accumulate: duplicate service created");
50268
50268
  }
50269
50269
  const accStateUpdate = this.getAccumulationStateUpdate(accumulated.toArray(), toAccumulateLater, slot, Array.from(statistics.keys()), services);
50270
50270
  const accumulationOutputUnsorted = Array.from(yieldedRoots.entries()).map(([serviceId, root]) => {
@@ -50345,13 +50345,13 @@ class DeferredTransfers {
50345
50345
  .toSorted((a, b) => a.source - b.source);
50346
50346
  const info = partiallyUpdatedState.getServiceInfo(serviceId);
50347
50347
  if (info === null) {
50348
- return result_Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist);
50348
+ return result_Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist, () => `Deferred transfers: service info not found for ${serviceId}`);
50349
50349
  }
50350
50350
  const codeHash = info.codeHash;
50351
50351
  const code = partiallyUpdatedState.getPreimage(serviceId, codeHash.asOpaque());
50352
50352
  const newBalance = sumU64(info.balance, ...transfers.map((item) => item.amount));
50353
50353
  if (newBalance.overflow) {
50354
- return result_Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow);
50354
+ return result_Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow, () => `Deferred transfers: balance overflow for service ${serviceId}`);
50355
50355
  }
50356
50356
  const newInfo = ServiceAccountInfo.create({ ...info, balance: newBalance.value });
50357
50357
  partiallyUpdatedState.updateServiceInfo(serviceId, newInfo);
@@ -50829,7 +50829,7 @@ function verifyReportsBasic(input) {
50829
50829
  const noOfPrerequisites = reportView.context.view().prerequisites.view().length;
50830
50830
  const noOfSegmentRootLookups = reportView.segmentRootLookup.view().length;
50831
50831
  if (noOfPrerequisites + noOfSegmentRootLookups > MAX_REPORT_DEPENDENCIES) {
50832
- return result_Result.error(ReportsError.TooManyDependencies, `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
50832
+ return result_Result.error(ReportsError.TooManyDependencies, () => `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
50833
50833
  }
50834
50834
  /**
50835
50835
  * In order to ensure fair use of a block’s extrinsic space,
@@ -50848,7 +50848,7 @@ function verifyReportsBasic(input) {
50848
50848
  totalOutputsSize += item.view().result.view().okBlob?.raw.length ?? 0;
50849
50849
  }
50850
50850
  if (authOutputSize + totalOutputsSize > MAX_WORK_REPORT_SIZE_BYTES) {
50851
- return result_Result.error(ReportsError.WorkReportTooBig, `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
50851
+ return result_Result.error(ReportsError.WorkReportTooBig, () => `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
50852
50852
  }
50853
50853
  }
50854
50854
  return result_Result.ok(result_OK);
@@ -50882,12 +50882,12 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
50882
50882
  for (const result of guarantee.report.results) {
50883
50883
  const service = state.getService(result.serviceId);
50884
50884
  if (service === null) {
50885
- return result_Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
50885
+ return result_Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
50886
50886
  }
50887
50887
  // check service code hash
50888
50888
  // https://graypaper.fluffylabs.dev/#/5f542d7/154b02154b02
50889
50889
  if (!result.codeHash.isEqualTo(service.getInfo().codeHash)) {
50890
- return result_Result.error(ReportsError.BadCodeHash, `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
50890
+ return result_Result.error(ReportsError.BadCodeHash, () => `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
50891
50891
  }
50892
50892
  }
50893
50893
  }
@@ -50898,7 +50898,7 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
50898
50898
  * https://graypaper.fluffylabs.dev/#/5f542d7/151f01152101
50899
50899
  */
50900
50900
  if (currentWorkPackages.size !== input.guarantees.length) {
50901
- return result_Result.error(ReportsError.DuplicatePackage, "Duplicate work package detected.");
50901
+ return result_Result.error(ReportsError.DuplicatePackage, () => "Duplicate work package detected.");
50902
50902
  }
50903
50903
  const minLookupSlot = Math.max(0, input.slot - maxLookupAnchorAge);
50904
50904
  const contextResult = verifyRefineContexts(minLookupSlot, contexts, input.recentBlocksPartialUpdate, headerChain);
@@ -50943,7 +50943,7 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
50943
50943
  : undefined;
50944
50944
  }
50945
50945
  if (root === undefined || !root.segmentTreeRoot.isEqualTo(lookup.segmentTreeRoot)) {
50946
- return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
50946
+ return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
50947
50947
  }
50948
50948
  }
50949
50949
  }
@@ -50966,16 +50966,16 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
50966
50966
  */
50967
50967
  const recentBlock = recentBlocks.get(context.anchor);
50968
50968
  if (recentBlock === undefined) {
50969
- return result_Result.error(ReportsError.AnchorNotRecent, `Anchor block ${context.anchor} not found in recent blocks.`);
50969
+ return result_Result.error(ReportsError.AnchorNotRecent, () => `Anchor block ${context.anchor} not found in recent blocks.`);
50970
50970
  }
50971
50971
  // check state root
50972
50972
  if (!recentBlock.postStateRoot.isEqualTo(context.stateRoot)) {
50973
- return result_Result.error(ReportsError.BadStateRoot, `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
50973
+ return result_Result.error(ReportsError.BadStateRoot, () => `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
50974
50974
  }
50975
50975
  // check beefy root
50976
50976
  const beefyRoot = recentBlock.accumulationResult;
50977
50977
  if (!beefyRoot.isEqualTo(context.beefyRoot)) {
50978
- return result_Result.error(ReportsError.BadBeefyMmrRoot, `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
50978
+ return result_Result.error(ReportsError.BadBeefyMmrRoot, () => `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
50979
50979
  }
50980
50980
  /**
50981
50981
  * We require that each lookup-anchor block be within the
@@ -50984,7 +50984,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
50984
50984
  * https://graypaper.fluffylabs.dev/#/5f542d7/154601154701
50985
50985
  */
50986
50986
  if (context.lookupAnchorSlot < minLookupSlot) {
50987
- return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
50987
+ return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
50988
50988
  }
50989
50989
  /**
50990
50990
  * We also require that we have a record of it; this is one of
@@ -51001,7 +51001,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
51001
51001
  verify_contextual_logger.warn `Lookup anchor check for ${context.lookupAnchor} would fail, but override is active.`;
51002
51002
  }
51003
51003
  else {
51004
- return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
51004
+ return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
51005
51005
  }
51006
51006
  }
51007
51007
  }
@@ -51024,7 +51024,7 @@ function verifyDependencies({ currentWorkPackages, recentlyReported, prerequisit
51024
51024
  if (recentlyReported.has(preReqHash)) {
51025
51025
  continue;
51026
51026
  }
51027
- return result_Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, `Missing work package ${preReqHash} in current extrinsic or recent history.`);
51027
+ return result_Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, () => `Missing work package ${preReqHash} in current extrinsic or recent history.`);
51028
51028
  }
51029
51029
  return result_Result.ok(result_OK);
51030
51030
  };
@@ -51072,7 +51072,7 @@ function verifyWorkPackagesUniqueness(workPackageHashes, state) {
51072
51072
  // let's check if any of our packages is in the pipeline
51073
51073
  const intersection = packagesInPipeline.intersection(workPackageHashes);
51074
51074
  for (const packageHash of intersection) {
51075
- return result_Result.error(ReportsError.DuplicatePackage, `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
51075
+ return result_Result.error(ReportsError.DuplicatePackage, () => `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
51076
51076
  }
51077
51077
  return result_Result.ok(result_OK);
51078
51078
  }
@@ -51111,7 +51111,7 @@ workReportHashes, slot, getGuarantorAssignment) {
51111
51111
  const credentialsView = guaranteeView.credentials.view();
51112
51112
  if (credentialsView.length < REQUIRED_CREDENTIALS_RANGE[0] ||
51113
51113
  credentialsView.length > REQUIRED_CREDENTIALS_RANGE[1]) {
51114
- return result_Result.error(ReportsError.InsufficientGuarantees, `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
51114
+ return result_Result.error(ReportsError.InsufficientGuarantees, () => `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
51115
51115
  }
51116
51116
  /** Retrieve current core assignment. */
51117
51117
  const timeSlot = guaranteeView.slot.materialize();
@@ -51126,20 +51126,20 @@ workReportHashes, slot, getGuarantorAssignment) {
51126
51126
  const credentialView = credential.view();
51127
51127
  const validatorIndex = credentialView.validatorIndex.materialize();
51128
51128
  if (lastValidatorIndex >= validatorIndex) {
51129
- return result_Result.error(ReportsError.NotSortedOrUniqueGuarantors, `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
51129
+ return result_Result.error(ReportsError.NotSortedOrUniqueGuarantors, () => `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
51130
51130
  }
51131
51131
  lastValidatorIndex = validatorIndex;
51132
51132
  const signature = credentialView.signature.materialize();
51133
51133
  const guarantorData = guarantorAssignments[validatorIndex];
51134
51134
  if (guarantorData === undefined) {
51135
- return result_Result.error(ReportsError.BadValidatorIndex, `Invalid validator index: ${validatorIndex}`);
51135
+ return result_Result.error(ReportsError.BadValidatorIndex, () => `Invalid validator index: ${validatorIndex}`);
51136
51136
  }
51137
51137
  /**
51138
51138
  * Verify core assignment.
51139
51139
  * https://graypaper.fluffylabs.dev/#/5f542d7/14e40214e602
51140
51140
  */
51141
51141
  if (guarantorData.core !== coreIndex) {
51142
- return result_Result.error(ReportsError.WrongAssignment, `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
51142
+ return result_Result.error(ReportsError.WrongAssignment, () => `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
51143
51143
  }
51144
51144
  signaturesToVerify.push({
51145
51145
  signature,
@@ -51177,10 +51177,10 @@ function verifyReportsOrder(input, chainSpec) {
51177
51177
  const reportView = guarantee.view().report.view();
51178
51178
  const coreIndex = reportView.coreIndex.materialize();
51179
51179
  if (lastCoreIndex >= coreIndex) {
51180
- return result_Result.error(ReportsError.OutOfOrderGuarantee, `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
51180
+ return result_Result.error(ReportsError.OutOfOrderGuarantee, () => `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
51181
51181
  }
51182
51182
  if (coreIndex >= noOfCores) {
51183
- return result_Result.error(ReportsError.BadCoreIndex, `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
51183
+ return result_Result.error(ReportsError.BadCoreIndex, () => `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
51184
51184
  }
51185
51185
  lastCoreIndex = coreIndex;
51186
51186
  }
@@ -51205,7 +51205,7 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
51205
51205
  * https://graypaper.fluffylabs.dev/#/5f542d7/15ea0015ea00
51206
51206
  */
51207
51207
  if (availabilityAssignment[coreIndex] !== null) {
51208
- return result_Result.error(ReportsError.CoreEngaged, `Report pending availability at core: ${coreIndex}`);
51208
+ return result_Result.error(ReportsError.CoreEngaged, () => `Report pending availability at core: ${coreIndex}`);
51209
51209
  }
51210
51210
  /**
51211
51211
  * A report is valid only if the authorizer hash is present
@@ -51218,7 +51218,7 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
51218
51218
  const authorizerPool = authPools.get(coreIndex);
51219
51219
  const pool = authorizerPool?.materialize() ?? [];
51220
51220
  if (pool.find((hash) => hash.isEqualTo(authorizerHash)) === undefined) {
51221
- return result_Result.error(ReportsError.CoreUnauthorized, `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
51221
+ return result_Result.error(ReportsError.CoreUnauthorized, () => `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
51222
51222
  }
51223
51223
  /**
51224
51224
  * We require that the gas allotted for accumulation of each
@@ -51230,17 +51230,17 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
51230
51230
  for (const result of report.results) {
51231
51231
  const service = services(result.serviceId);
51232
51232
  if (service === null) {
51233
- return result_Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
51233
+ return result_Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
51234
51234
  }
51235
51235
  const info = service.getInfo();
51236
51236
  // check minimal accumulation gas
51237
51237
  if (result.gas < info.accumulateMinGas) {
51238
- return result_Result.error(ReportsError.ServiceItemGasTooLow, `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
51238
+ return result_Result.error(ReportsError.ServiceItemGasTooLow, () => `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
51239
51239
  }
51240
51240
  }
51241
51241
  const totalGas = sumU64(...report.results.map((x) => x.gas));
51242
51242
  if (totalGas.overflow || totalGas.value > G_A) {
51243
- return result_Result.error(ReportsError.WorkReportGasTooHigh, `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
51243
+ return result_Result.error(ReportsError.WorkReportGasTooHigh, () => `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
51244
51244
  }
51245
51245
  }
51246
51246
  return result_Result.ok(result_OK);
@@ -51326,7 +51326,7 @@ class Reports {
51326
51326
  }
51327
51327
  const reporters = SortedSet.fromArray(bytesBlobComparator, signaturesToVerify.ok.map((x) => x.key)).slice();
51328
51328
  if (hasAnyOffenders(reporters, input.offenders)) {
51329
- return result_Result.error(ReportsError.BannedValidator);
51329
+ return result_Result.error(ReportsError.BannedValidator, () => "One or more reporters are banned validators");
51330
51330
  }
51331
51331
  return result_Result.ok({
51332
51332
  stateUpdate: {
@@ -51366,7 +51366,7 @@ class Reports {
51366
51366
  return signaturesToVerify[idx].key;
51367
51367
  })
51368
51368
  .filter((x) => x !== null);
51369
- return result_Result.error(ReportsError.BadSignature, `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
51369
+ return result_Result.error(ReportsError.BadSignature, () => `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
51370
51370
  }
51371
51371
  /**
51372
51372
  * Get the guarantor assignment (both core and validator data)
@@ -51382,10 +51382,10 @@ class Reports {
51382
51382
  const minTimeSlot = Math.max(0, headerRotation - 1) * rotationPeriod;
51383
51383
  // https://graypaper.fluffylabs.dev/#/5f542d7/155e00156900
51384
51384
  if (guaranteeTimeSlot > headerTimeSlot) {
51385
- return result_Result.error(ReportsError.FutureReportSlot, `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
51385
+ return result_Result.error(ReportsError.FutureReportSlot, () => `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
51386
51386
  }
51387
51387
  if (guaranteeTimeSlot < minTimeSlot) {
51388
- return result_Result.error(ReportsError.ReportEpochBeforeLast, `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
51388
+ return result_Result.error(ReportsError.ReportEpochBeforeLast, () => `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
51389
51389
  }
51390
51390
  // TODO [ToDr] [opti] below code needs cache.
51391
51391
  // The `G` and `G*` sets should only be computed once per rotation.
@@ -52001,11 +52001,11 @@ class OnChain {
52001
52001
  }
52002
52002
  function checkOffendersMatch(offendersMark, headerOffendersMark) {
52003
52003
  if (offendersMark.size !== headerOffendersMark.length) {
52004
- return result_Result.error(OFFENDERS_ERROR, `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
52004
+ return result_Result.error(OFFENDERS_ERROR, () => `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
52005
52005
  }
52006
52006
  for (const key of headerOffendersMark) {
52007
52007
  if (!offendersMark.has(key)) {
52008
- return result_Result.error(OFFENDERS_ERROR, `Missing key: ${key}`);
52008
+ return result_Result.error(OFFENDERS_ERROR, () => `Missing key: ${key}`);
52009
52009
  }
52010
52010
  }
52011
52011
  return result_Result.ok(result_OK);
@@ -52087,7 +52087,7 @@ class Importer {
52087
52087
  if (!this.currentHash.isEqualTo(parentHash)) {
52088
52088
  const state = this.states.getState(parentHash);
52089
52089
  if (state === null) {
52090
- const e = result_Result.error(BlockVerifierError.StateRootNotFound);
52090
+ const e = result_Result.error(BlockVerifierError.StateRootNotFound, () => `State not found for parent block ${parentHash}`);
52091
52091
  if (!e.isError) {
52092
52092
  throw new Error("unreachable, just adding to make compiler happy");
52093
52093
  }
@@ -52267,7 +52267,7 @@ async function mainImporter(config, withRelPath) {
52267
52267
  if (res !== null && res !== undefined) {
52268
52268
  return decoder_Decoder.decodeObject(importBlockResultCodec, res);
52269
52269
  }
52270
- return result_Result.error("");
52270
+ return result_Result.error("invalid response", () => "Importer: import block response was null or undefined");
52271
52271
  },
52272
52272
  async getStateEntries(hash) {
52273
52273
  return importer.getStateEntries(hash);
@@ -52316,7 +52316,7 @@ async function mainFuzz(fuzzConfig, withRelPath) {
52316
52316
  chainSpec,
52317
52317
  importBlock: async (blockView) => {
52318
52318
  if (runningNode === null) {
52319
- return result_Result.error("node not running");
52319
+ return result_Result.error("node not running", () => "Fuzzer: node not running when importing block");
52320
52320
  }
52321
52321
  const importResult = await runningNode.importBlock(blockView);
52322
52322
  return importResult;