@typeberry/convert 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.
Files changed (3) hide show
  1. package/index.js +141 -141
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -4544,7 +4544,7 @@ function result_resultToString(res) {
4544
4544
  if (res.isOk) {
4545
4545
  return `OK: ${typeof res.ok === "symbol" ? res.ok.toString() : res.ok}`;
4546
4546
  }
4547
- return `${res.details}\nError: ${maybeTaggedErrorToString(res.error)}`;
4547
+ return `${res.details()}\nError: ${maybeTaggedErrorToString(res.error)}`;
4548
4548
  }
4549
4549
  /** An indication of two possible outcomes returned from a function. */
4550
4550
  const result_Result = {
@@ -4558,7 +4558,7 @@ const result_Result = {
4558
4558
  };
4559
4559
  },
4560
4560
  /** Create new [`Result`] with `Error` status. */
4561
- error: (error, details = "") => {
4561
+ error: (error, details) => {
4562
4562
  debug_check `${error !== undefined} 'Error' type cannot be undefined.`;
4563
4563
  return {
4564
4564
  isOk: false,
@@ -4677,7 +4677,7 @@ function test_deepEqual(actual, expected, { context = [], errorsCollector, ignor
4677
4677
  }
4678
4678
  if (actual.isError && expected.isError) {
4679
4679
  test_deepEqual(actual.error, expected.error, { context: ctx.concat(["error"]), errorsCollector: errors, ignore });
4680
- test_deepEqual(actual.details, expected.details, {
4680
+ test_deepEqual(actual.details(), expected.details(), {
4681
4681
  context: ctx.concat(["details"]),
4682
4682
  errorsCollector: errors,
4683
4683
  // display details when error does not match
@@ -12938,7 +12938,7 @@ class InMemoryState extends WithDebug {
12938
12938
  const { kind } = update.action;
12939
12939
  const service = this.services.get(serviceId);
12940
12940
  if (service === undefined) {
12941
- return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update storage of non-existing service: ${serviceId}`);
12941
+ return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update storage of non-existing service: ${serviceId}`);
12942
12942
  }
12943
12943
  if (kind === state_update_UpdateStorageKind.Set) {
12944
12944
  const { key, value } = update.action.storage;
@@ -12966,14 +12966,14 @@ class InMemoryState extends WithDebug {
12966
12966
  for (const [serviceId, updates] of preimagesUpdates.entries()) {
12967
12967
  const service = this.services.get(serviceId);
12968
12968
  if (service === undefined) {
12969
- return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update preimage of non-existing service: ${serviceId}`);
12969
+ return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update preimage of non-existing service: ${serviceId}`);
12970
12970
  }
12971
12971
  for (const update of updates) {
12972
12972
  const { kind } = update.action;
12973
12973
  if (kind === state_update_UpdatePreimageKind.Provide) {
12974
12974
  const { preimage, slot } = update.action;
12975
12975
  if (service.data.preimages.has(preimage.hash)) {
12976
- return result_Result.error(in_memory_state_UpdateError.PreimageExists, `Overwriting existing preimage at ${serviceId}: ${preimage}`);
12976
+ return result_Result.error(in_memory_state_UpdateError.PreimageExists, () => `Overwriting existing preimage at ${serviceId}: ${preimage}`);
12977
12977
  }
12978
12978
  service.data.preimages.set(preimage.hash, preimage);
12979
12979
  if (slot !== null) {
@@ -13024,7 +13024,7 @@ class InMemoryState extends WithDebug {
13024
13024
  if (kind === state_update_UpdateServiceKind.Create) {
13025
13025
  const { lookupHistory } = update.action;
13026
13026
  if (this.services.has(serviceId)) {
13027
- return result_Result.error(in_memory_state_UpdateError.DuplicateService, `${serviceId} already exists!`);
13027
+ return result_Result.error(in_memory_state_UpdateError.DuplicateService, () => `${serviceId} already exists!`);
13028
13028
  }
13029
13029
  this.services.set(serviceId, new InMemoryService(serviceId, {
13030
13030
  info: account,
@@ -13036,7 +13036,7 @@ class InMemoryState extends WithDebug {
13036
13036
  else if (kind === state_update_UpdateServiceKind.Update) {
13037
13037
  const existingService = this.services.get(serviceId);
13038
13038
  if (existingService === undefined) {
13039
- return result_Result.error(in_memory_state_UpdateError.NoService, `Cannot update ${serviceId} because it does not exist.`);
13039
+ return result_Result.error(in_memory_state_UpdateError.NoService, () => `Cannot update ${serviceId} because it does not exist.`);
13040
13040
  }
13041
13041
  existingService.data.info = account;
13042
13042
  }
@@ -15534,13 +15534,13 @@ class LeafDb {
15534
15534
  */
15535
15535
  static fromLeavesBlob(blob, db) {
15536
15536
  if (blob.length % TRIE_NODE_BYTES !== 0) {
15537
- return Result.error(LeafDbError.InvalidLeafData, `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
15537
+ return Result.error(LeafDbError.InvalidLeafData, () => `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
15538
15538
  }
15539
15539
  const leaves = SortedSet.fromArray(leafComparator, []);
15540
15540
  for (const nodeData of blob.chunks(TRIE_NODE_BYTES)) {
15541
15541
  const node = new TrieNode(nodeData.raw);
15542
15542
  if (node.getNodeType() === NodeType.Branch) {
15543
- return Result.error(LeafDbError.InvalidLeafData, `Branch node detected: ${nodeData}`);
15543
+ return Result.error(LeafDbError.InvalidLeafData, () => `Branch node detected: ${nodeData}`);
15544
15544
  }
15545
15545
  leaves.insert(node.asLeafNode());
15546
15546
  }
@@ -15761,7 +15761,7 @@ class preimages_Preimages {
15761
15761
  }
15762
15762
  if (prevPreimage.requester > currPreimage.requester ||
15763
15763
  currPreimage.blob.compare(prevPreimage.blob).isLessOrEqual()) {
15764
- return Result.error(PreimagesErrorCode.PreimagesNotSortedUnique);
15764
+ return Result.error(PreimagesErrorCode.PreimagesNotSortedUnique, () => `Preimages not sorted/unique at index ${i}`);
15765
15765
  }
15766
15766
  }
15767
15767
  const { preimages, slot } = input;
@@ -15772,14 +15772,14 @@ class preimages_Preimages {
15772
15772
  const hash = this.blake2b.hashBytes(blob).asOpaque();
15773
15773
  const service = this.state.getService(requester);
15774
15774
  if (service === null) {
15775
- return Result.error(PreimagesErrorCode.AccountNotFound);
15775
+ return Result.error(PreimagesErrorCode.AccountNotFound, () => `Service not found: ${requester}`);
15776
15776
  }
15777
15777
  const hasPreimage = service.hasPreimage(hash);
15778
15778
  const slots = service.getLookupHistory(hash, tryAsU32(blob.length));
15779
15779
  // https://graypaper.fluffylabs.dev/#/5f542d7/181800181900
15780
15780
  // https://graypaper.fluffylabs.dev/#/5f542d7/116f0011a500
15781
15781
  if (hasPreimage || slots === null || !LookupHistoryItem.isRequested(slots)) {
15782
- return Result.error(PreimagesErrorCode.PreimageUnneeded);
15782
+ return Result.error(PreimagesErrorCode.PreimageUnneeded, () => `Preimage unneeded: requester=${requester}, hash=${hash}, hasPreimage=${hasPreimage}, isRequested=${slots !== null && LookupHistoryItem.isRequested(slots)}`);
15783
15783
  }
15784
15784
  // https://graypaper.fluffylabs.dev/#/5f542d7/18c00018f300
15785
15785
  const updates = pendingChanges.get(requester) ?? [];
@@ -15825,7 +15825,7 @@ class block_verifier_BlockVerifier {
15825
15825
  const headerHash = this.hasher.header(headerView);
15826
15826
  // check if current block is already imported
15827
15827
  if (this.blocks.getHeader(headerHash.hash) !== null) {
15828
- return Result.error(BlockVerifierError.AlreadyImported, `Block ${headerHash.hash} is already imported.`);
15828
+ return Result.error(BlockVerifierError.AlreadyImported, () => `Block ${headerHash.hash} is already imported.`);
15829
15829
  }
15830
15830
  // Check if parent block exists.
15831
15831
  // https://graypaper.fluffylabs.dev/#/cc517d7/0c82000c8200?v=0.6.5
@@ -15835,14 +15835,14 @@ class block_verifier_BlockVerifier {
15835
15835
  if (!parentHash.isEqualTo(block_verifier_ZERO_HASH)) {
15836
15836
  const parentBlock = this.blocks.getHeader(parentHash);
15837
15837
  if (parentBlock === null) {
15838
- return Result.error(BlockVerifierError.ParentNotFound, `Parent ${parentHash.toString()} not found`);
15838
+ return Result.error(BlockVerifierError.ParentNotFound, () => `Parent ${parentHash.toString()} not found`);
15839
15839
  }
15840
15840
  // Check if the time slot index is consecutive and not from future.
15841
15841
  // https://graypaper.fluffylabs.dev/#/cc517d7/0c02010c0201?v=0.6.5
15842
15842
  const timeslot = headerView.timeSlotIndex.materialize();
15843
15843
  const parentTimeslot = parentBlock.timeSlotIndex.materialize();
15844
15844
  if (timeslot <= parentTimeslot) {
15845
- return Result.error(BlockVerifierError.InvalidTimeSlot, `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
15845
+ return Result.error(BlockVerifierError.InvalidTimeSlot, () => `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
15846
15846
  }
15847
15847
  }
15848
15848
  // Check if extrinsic is valid.
@@ -15850,17 +15850,17 @@ class block_verifier_BlockVerifier {
15850
15850
  const extrinsicHash = headerView.extrinsicHash.materialize();
15851
15851
  const extrinsicMerkleCommitment = this.hasher.extrinsic(block.extrinsic.view());
15852
15852
  if (!extrinsicHash.isEqualTo(extrinsicMerkleCommitment.hash)) {
15853
- return Result.error(BlockVerifierError.InvalidExtrinsic, `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
15853
+ return Result.error(BlockVerifierError.InvalidExtrinsic, () => `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
15854
15854
  }
15855
15855
  // Check if the state root is valid.
15856
15856
  // https://graypaper.fluffylabs.dev/#/cc517d7/0c18010c1801?v=0.6.5
15857
15857
  const stateRoot = headerView.priorStateRoot.materialize();
15858
15858
  const posteriorStateRoot = this.blocks.getPostStateRoot(parentHash);
15859
15859
  if (posteriorStateRoot === null) {
15860
- return Result.error(BlockVerifierError.StateRootNotFound, `Posterior state root ${parentHash.toString()} not found`);
15860
+ return Result.error(BlockVerifierError.StateRootNotFound, () => `Posterior state root ${parentHash.toString()} not found`);
15861
15861
  }
15862
15862
  if (!stateRoot.isEqualTo(posteriorStateRoot)) {
15863
- return Result.error(BlockVerifierError.InvalidStateRoot, `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
15863
+ return Result.error(BlockVerifierError.InvalidStateRoot, () => `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
15864
15864
  }
15865
15865
  return Result.ok(headerHash.hash);
15866
15866
  }
@@ -15961,7 +15961,7 @@ class disputes_Disputes {
15961
15961
  // check if culprits are sorted by key
15962
15962
  // https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
15963
15963
  if (!isUniqueSortedBy(disputes.culprits, "key")) {
15964
- return Result.error(DisputesErrorCode.CulpritsNotSortedUnique);
15964
+ return Result.error(DisputesErrorCode.CulpritsNotSortedUnique, () => "Culprits are not uniquely sorted by key");
15965
15965
  }
15966
15966
  const culpritsLength = disputes.culprits.length;
15967
15967
  for (let i = 0; i < culpritsLength; i++) {
@@ -15970,24 +15970,24 @@ class disputes_Disputes {
15970
15970
  // https://graypaper.fluffylabs.dev/#/579bd12/125501125501
15971
15971
  const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
15972
15972
  if (isInPunishSet) {
15973
- return Result.error(DisputesErrorCode.OffenderAlreadyReported);
15973
+ return Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: culprit ${i}, key=${key}`);
15974
15974
  }
15975
15975
  // check if the guarantor key is correct
15976
15976
  // https://graypaper.fluffylabs.dev/#/85129da/125501125501?v=0.6.3
15977
15977
  if (!allValidatorKeys.has(key)) {
15978
- return Result.error(DisputesErrorCode.BadGuarantorKey);
15978
+ return Result.error(DisputesErrorCode.BadGuarantorKey, () => `Bad guarantor key: culprit ${i}, key=${key}`);
15979
15979
  }
15980
15980
  // verify if the culprit will be in new bad set
15981
15981
  // https://graypaper.fluffylabs.dev/#/579bd12/124601124601
15982
15982
  const isInNewBadSet = newItems.asDictionaries().badSet.has(workReportHash);
15983
15983
  if (!isInNewBadSet) {
15984
- return Result.error(DisputesErrorCode.CulpritsVerdictNotBad);
15984
+ return Result.error(DisputesErrorCode.CulpritsVerdictNotBad, () => `Culprit verdict not bad: culprit ${i}, work report=${workReportHash}`);
15985
15985
  }
15986
15986
  // verify culprit signature
15987
15987
  // https://graypaper.fluffylabs.dev/#/579bd12/125c01125c01
15988
15988
  const result = verificationResult.culprits[i];
15989
15989
  if (!result?.isValid) {
15990
- return Result.error(DisputesErrorCode.BadSignature, `Invalid signature for culprit: ${i}`);
15990
+ return Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for culprit: ${i}`);
15991
15991
  }
15992
15992
  }
15993
15993
  return Result.ok(null);
@@ -15996,7 +15996,7 @@ class disputes_Disputes {
15996
15996
  // check if faults are sorted by key
15997
15997
  // https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
15998
15998
  if (!isUniqueSortedBy(disputes.faults, "key")) {
15999
- return Result.error(DisputesErrorCode.FaultsNotSortedUnique);
15999
+ return Result.error(DisputesErrorCode.FaultsNotSortedUnique, () => "Faults are not uniquely sorted by key");
16000
16000
  }
16001
16001
  const faultsLength = disputes.faults.length;
16002
16002
  for (let i = 0; i < faultsLength; i++) {
@@ -16005,12 +16005,12 @@ class disputes_Disputes {
16005
16005
  // https://graypaper.fluffylabs.dev/#/579bd12/12a20112a201
16006
16006
  const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
16007
16007
  if (isInPunishSet) {
16008
- return Result.error(DisputesErrorCode.OffenderAlreadyReported);
16008
+ return Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: fault ${i}, key=${key}`);
16009
16009
  }
16010
16010
  // check if the auditor key is correct
16011
16011
  // https://graypaper.fluffylabs.dev/#/85129da/12a20112a201?v=0.6.3
16012
16012
  if (!allValidatorKeys.has(key)) {
16013
- return Result.error(DisputesErrorCode.BadAuditorKey);
16013
+ return Result.error(DisputesErrorCode.BadAuditorKey, () => `Bad auditor key: fault ${i}, key=${key}`);
16014
16014
  }
16015
16015
  // verify if the fault will be included in new good/bad set
16016
16016
  // it may be not correct as in GP there is "iff" what means it should be rather
@@ -16022,14 +16022,14 @@ class disputes_Disputes {
16022
16022
  const isInNewGoodSet = goodSet.has(workReportHash);
16023
16023
  const isInNewBadSet = badSet.has(workReportHash);
16024
16024
  if (isInNewGoodSet || !isInNewBadSet) {
16025
- return Result.error(DisputesErrorCode.FaultVerdictWrong);
16025
+ return Result.error(DisputesErrorCode.FaultVerdictWrong, () => `Fault verdict wrong: fault ${i}, work report=${workReportHash}, inGood=${isInNewGoodSet}, inBad=${isInNewBadSet}`);
16026
16026
  }
16027
16027
  }
16028
16028
  // verify fault signature. Verification was done earlier, here we only check the result.
16029
16029
  // https://graypaper.fluffylabs.dev/#/579bd12/12a90112a901
16030
16030
  const result = verificationResult.faults[i];
16031
16031
  if (!result.isValid) {
16032
- return Result.error(DisputesErrorCode.BadSignature, `Invalid signature for fault: ${i}`);
16032
+ return Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for fault: ${i}`);
16033
16033
  }
16034
16034
  }
16035
16035
  return Result.ok(null);
@@ -16038,32 +16038,32 @@ class disputes_Disputes {
16038
16038
  // check if verdicts are correctly sorted
16039
16039
  // https://graypaper.fluffylabs.dev/#/579bd12/12c40112c401
16040
16040
  if (!isUniqueSortedBy(disputes.verdicts, "workReportHash")) {
16041
- return Result.error(DisputesErrorCode.VerdictsNotSortedUnique);
16041
+ return Result.error(DisputesErrorCode.VerdictsNotSortedUnique, () => "Verdicts are not uniquely sorted by work report hash");
16042
16042
  }
16043
16043
  // check if judgement are correctly sorted
16044
16044
  // https://graypaper.fluffylabs.dev/#/579bd12/123702123802
16045
16045
  if (disputes.verdicts.some((verdict) => !isUniqueSortedByIndex(verdict.votes))) {
16046
- return Result.error(DisputesErrorCode.JudgementsNotSortedUnique);
16046
+ return Result.error(DisputesErrorCode.JudgementsNotSortedUnique, () => "Judgements are not uniquely sorted by index");
16047
16047
  }
16048
16048
  const currentEpoch = Math.floor(this.state.timeslot / this.chainSpec.epochLength);
16049
16049
  let voteSignatureIndex = 0;
16050
16050
  for (const { votesEpoch, votes } of disputes.verdicts) {
16051
16051
  // https://graypaper.fluffylabs.dev/#/579bd12/12bb0012bc00
16052
16052
  if (votesEpoch !== currentEpoch && votesEpoch + 1 !== currentEpoch) {
16053
- return Result.error(DisputesErrorCode.BadJudgementAge);
16053
+ return Result.error(DisputesErrorCode.BadJudgementAge, () => `Bad judgement age: epoch=${votesEpoch}, current=${currentEpoch}`);
16054
16054
  }
16055
16055
  const k = votesEpoch === currentEpoch ? this.state.currentValidatorData : this.state.previousValidatorData;
16056
16056
  for (const { index } of votes) {
16057
16057
  const key = k[index]?.ed25519;
16058
16058
  // no particular GP fragment but I think we don't believe in ghosts
16059
16059
  if (key === undefined) {
16060
- return Result.error(DisputesErrorCode.BadValidatorIndex);
16060
+ return Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index: ${index} in epoch ${votesEpoch}`);
16061
16061
  }
16062
16062
  // verify vote signature. Verification was done earlier, here we only check the result.
16063
16063
  // https://graypaper.fluffylabs.dev/#/579bd12/12cd0012cd00
16064
16064
  const result = verificationResult.judgements[voteSignatureIndex];
16065
16065
  if (!result.isValid) {
16066
- return Result.error(DisputesErrorCode.BadSignature, `Invalid signature for judgement: ${voteSignatureIndex}`);
16066
+ return Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for judgement: ${voteSignatureIndex}`);
16067
16067
  }
16068
16068
  voteSignatureIndex += 1;
16069
16069
  }
@@ -16079,7 +16079,7 @@ class disputes_Disputes {
16079
16079
  const isInBadSet = badSet.has(verdict.workReportHash);
16080
16080
  const isInWonkySet = wonkySet.has(verdict.workReportHash);
16081
16081
  if (isInGoodSet || isInBadSet || isInWonkySet) {
16082
- return Result.error(DisputesErrorCode.AlreadyJudged);
16082
+ return Result.error(DisputesErrorCode.AlreadyJudged, () => `Work report already judged: ${verdict.workReportHash}`);
16083
16083
  }
16084
16084
  }
16085
16085
  return Result.ok(null);
@@ -16110,7 +16110,7 @@ class disputes_Disputes {
16110
16110
  // https://graypaper.fluffylabs.dev/#/579bd12/12f10212fc02
16111
16111
  const f = disputes.faults.find((x) => x.workReportHash.isEqualTo(r));
16112
16112
  if (f === undefined) {
16113
- return Result.error(DisputesErrorCode.NotEnoughFaults);
16113
+ return Result.error(DisputesErrorCode.NotEnoughFaults, () => `Not enough faults for work report: ${r}`);
16114
16114
  }
16115
16115
  }
16116
16116
  else if (sum === 0) {
@@ -16119,13 +16119,13 @@ class disputes_Disputes {
16119
16119
  const c1 = disputes.culprits.find((x) => x.workReportHash.isEqualTo(r));
16120
16120
  const c2 = disputes.culprits.findLast((x) => x.workReportHash.isEqualTo(r));
16121
16121
  if (c1 === c2) {
16122
- return Result.error(DisputesErrorCode.NotEnoughCulprits);
16122
+ return Result.error(DisputesErrorCode.NotEnoughCulprits, () => `Not enough culprits for work report: ${r}`);
16123
16123
  }
16124
16124
  }
16125
16125
  else if (sum !== this.chainSpec.thirdOfValidators) {
16126
16126
  // positive votes count is not correct
16127
16127
  // https://graypaper.fluffylabs.dev/#/579bd12/125002128102
16128
- return Result.error(DisputesErrorCode.BadVoteSplit);
16128
+ return Result.error(DisputesErrorCode.BadVoteSplit, () => `Bad vote split: sum=${sum}, expected=${this.chainSpec.thirdOfValidators} for work report ${r}`);
16129
16129
  }
16130
16130
  }
16131
16131
  return Result.ok(null);
@@ -16213,7 +16213,7 @@ class disputes_Disputes {
16213
16213
  const validator = k[j.index];
16214
16214
  // no particular GP fragment but I think we don't believe in ghosts
16215
16215
  if (validator === undefined) {
16216
- return Result.error(DisputesErrorCode.BadValidatorIndex);
16216
+ return Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index in signature verification: ${j.index}`);
16217
16217
  }
16218
16218
  const key = validator.ed25519;
16219
16219
  // verify vote signature
@@ -16321,7 +16321,7 @@ const ringCommitmentCache = [];
16321
16321
  async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUnsealedHeader) {
16322
16322
  const sealResult = await bandersnatch.verifySeal(authorKey.raw, signature.raw, payload.raw, encodedUnsealedHeader.raw);
16323
16323
  if (sealResult[RESULT_INDEX] === ResultValues.Error) {
16324
- return result_Result.error(null);
16324
+ return result_Result.error(null, () => "Bandersnatch VRF seal verification failed");
16325
16325
  }
16326
16326
  return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
16327
16327
  }
@@ -16347,7 +16347,7 @@ function getRingCommitment(bandersnatch, validators) {
16347
16347
  async function getRingCommitmentNoCache(bandersnatch, keys) {
16348
16348
  const commitmentResult = await bandersnatch.getRingCommitment(keys.raw);
16349
16349
  if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
16350
- return result_Result.error(null);
16350
+ return result_Result.error(null, () => "Bandersnatch ring commitment calculation failed");
16351
16351
  }
16352
16352
  return result_Result.ok(bytes_Bytes.fromBlob(commitmentResult.subarray(1), BANDERSNATCH_RING_ROOT_BYTES).asOpaque());
16353
16353
  }
@@ -16522,7 +16522,7 @@ class safrole_Safrole {
16522
16522
  epochRoot: epochRootResult.ok,
16523
16523
  });
16524
16524
  }
16525
- return Result.error(SafroleErrorCode.IncorrectData);
16525
+ return Result.error(SafroleErrorCode.IncorrectData, () => "Safrole: failed to get epoch root for validator keys");
16526
16526
  }
16527
16527
  /**
16528
16528
  * Ticket sequencer that is used in standard mode
@@ -16613,10 +16613,10 @@ class safrole_Safrole {
16613
16613
  for (let i = 1; i < ticketsLength; i++) {
16614
16614
  const order = tickets[i - 1].id.compare(tickets[i].id);
16615
16615
  if (order.isEqual()) {
16616
- return Result.error(SafroleErrorCode.DuplicateTicket);
16616
+ return Result.error(SafroleErrorCode.DuplicateTicket, () => `Safrole: duplicate ticket found at index ${i}`);
16617
16617
  }
16618
16618
  if (order.isGreater()) {
16619
- return Result.error(SafroleErrorCode.BadTicketOrder);
16619
+ return Result.error(SafroleErrorCode.BadTicketOrder, () => `Safrole: bad ticket order at index ${i}`);
16620
16620
  }
16621
16621
  }
16622
16622
  return Result.ok(null);
@@ -16643,7 +16643,7 @@ class safrole_Safrole {
16643
16643
  attempt: ticket.attempt,
16644
16644
  }));
16645
16645
  if (!verificationResult.every((x) => x.isValid)) {
16646
- return Result.error(SafroleErrorCode.BadTicketProof);
16646
+ return Result.error(SafroleErrorCode.BadTicketProof, () => "Safrole: invalid ticket proof in extrinsic");
16647
16647
  }
16648
16648
  /**
16649
16649
  * Verify if tickets are sorted and unique
@@ -16652,7 +16652,7 @@ class safrole_Safrole {
16652
16652
  */
16653
16653
  const ticketsVerifcationResult = this.verifyTickets(tickets);
16654
16654
  if (ticketsVerifcationResult.isError) {
16655
- return Result.error(ticketsVerifcationResult.error);
16655
+ return Result.error(ticketsVerifcationResult.error, ticketsVerifcationResult.details);
16656
16656
  }
16657
16657
  if (this.isEpochChanged(timeslot)) {
16658
16658
  return Result.ok(tickets);
@@ -16661,7 +16661,7 @@ class safrole_Safrole {
16661
16661
  const ticketsFromExtrinsic = SortedSet.fromSortedArray(ticketComparator, tickets);
16662
16662
  const mergedTickets = SortedSet.fromTwoSortedCollections(ticketsFromState, ticketsFromExtrinsic);
16663
16663
  if (ticketsFromState.length + ticketsFromExtrinsic.length !== mergedTickets.length) {
16664
- return Result.error(SafroleErrorCode.DuplicateTicket);
16664
+ return Result.error(SafroleErrorCode.DuplicateTicket, () => "Safrole: duplicate ticket when merging state and extrinsic tickets");
16665
16665
  }
16666
16666
  /**
16667
16667
  * Remove tickets if size of accumulator exceeds E (epoch length).
@@ -16730,24 +16730,24 @@ class safrole_Safrole {
16730
16730
  }
16731
16731
  async transition(input) {
16732
16732
  if (this.state.timeslot >= input.slot) {
16733
- return Result.error(SafroleErrorCode.BadSlot);
16733
+ return Result.error(SafroleErrorCode.BadSlot, () => `Safrole: bad slot, state timeslot ${this.state.timeslot} >= input slot ${input.slot}`);
16734
16734
  }
16735
16735
  if (!this.isExtrinsicLengthValid(input.slot, input.extrinsic)) {
16736
- return Result.error(SafroleErrorCode.UnexpectedTicket);
16736
+ return Result.error(SafroleErrorCode.UnexpectedTicket, () => `Safrole: unexpected ticket, invalid extrinsic length ${input.extrinsic.length}`);
16737
16737
  }
16738
16738
  if (!this.areTicketAttemptsValid(input.extrinsic)) {
16739
- return Result.error(SafroleErrorCode.BadTicketAttempt);
16739
+ return Result.error(SafroleErrorCode.BadTicketAttempt, () => "Safrole: bad ticket attempt value in extrinsic");
16740
16740
  }
16741
16741
  const validatorKeysResult = await this.getValidatorKeys(input.slot, input.punishSet);
16742
16742
  if (validatorKeysResult.isError) {
16743
- return Result.error(validatorKeysResult.error);
16743
+ return Result.error(validatorKeysResult.error, validatorKeysResult.details);
16744
16744
  }
16745
16745
  const { nextValidatorData, currentValidatorData, previousValidatorData, epochRoot } = validatorKeysResult.ok;
16746
16746
  const entropy = this.getEntropy(input.slot, input.entropy);
16747
16747
  const sealingKeySeries = this.getSlotKeySequence(input.slot, currentValidatorData, entropy[2]);
16748
16748
  const newTicketsAccumulatorResult = await this.getNewTicketAccumulator(input.slot, input.extrinsic, this.state.nextValidatorData, epochRoot, entropy[2]);
16749
16749
  if (newTicketsAccumulatorResult.isError) {
16750
- return Result.error(newTicketsAccumulatorResult.error);
16750
+ return Result.error(newTicketsAccumulatorResult.error, newTicketsAccumulatorResult.details);
16751
16751
  }
16752
16752
  const stateUpdate = {
16753
16753
  nextValidatorData,
@@ -16781,14 +16781,14 @@ function compareWithEncoding(chainSpec, error, actual, expected, codec) {
16781
16781
  if (actual === null || expected === null) {
16782
16782
  // if one of them is `null`, both need to be.
16783
16783
  if (actual !== expected) {
16784
- return Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
16784
+ return Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
16785
16785
  }
16786
16786
  return Result.ok(OK);
16787
16787
  }
16788
16788
  // compare the literal encoding.
16789
16789
  const encoded = Encoder.encodeObject(codec, actual, chainSpec);
16790
16790
  if (!encoded.isEqualTo(expected.encoded())) {
16791
- return Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
16791
+ return Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
16792
16792
  }
16793
16793
  return Result.ok(OK);
16794
16794
  }
@@ -16831,7 +16831,7 @@ class safrole_seal_SafroleSeal {
16831
16831
  const blockAuthorKey = state.currentValidatorData.at(blockAuthorIndex)?.bandersnatch;
16832
16832
  const entropySourceResult = await bandersnatchVrf.verifySeal(await this.bandersnatch, blockAuthorKey ?? BANDERSNATCH_ZERO_KEY, headerView.entropySource.materialize(), payload, BytesBlob.blobFromNumbers([]));
16833
16833
  if (entropySourceResult.isError) {
16834
- return Result.error(SafroleSealError.IncorrectEntropySource);
16834
+ return Result.error(SafroleSealError.IncorrectEntropySource, () => "Safrole: incorrect entropy source in header seal");
16835
16835
  }
16836
16836
  return Result.ok(entropySourceResult.ok);
16837
16837
  }
@@ -16840,7 +16840,7 @@ class safrole_seal_SafroleSeal {
16840
16840
  const validatorIndex = headerView.bandersnatchBlockAuthorIndex.materialize();
16841
16841
  const authorKeys = state.currentValidatorData.at(validatorIndex);
16842
16842
  if (authorKeys === undefined) {
16843
- return Result.error(SafroleSealError.InvalidValidatorIndex);
16843
+ return Result.error(SafroleSealError.InvalidValidatorIndex, () => `Safrole: invalid validator index ${validatorIndex}`);
16844
16844
  }
16845
16845
  const timeSlot = headerView.timeSlotIndex.materialize();
16846
16846
  const sealingKeys = state.sealingKeySeries;
@@ -16859,10 +16859,10 @@ class safrole_seal_SafroleSeal {
16859
16859
  const authorKey = validatorData.bandersnatch;
16860
16860
  const result = await bandersnatchVrf.verifySeal(await this.bandersnatch, authorKey ?? BANDERSNATCH_ZERO_KEY, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
16861
16861
  if (result.isError) {
16862
- return Result.error(SafroleSealError.IncorrectSeal);
16862
+ return Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with ticket");
16863
16863
  }
16864
16864
  if (ticket === undefined || !ticket.id.isEqualTo(result.ok)) {
16865
- return Result.error(SafroleSealError.InvalidTicket);
16865
+ return Result.error(SafroleSealError.InvalidTicket, () => `Safrole: invalid ticket, expected ${ticket?.id} got ${result.ok}`);
16866
16866
  }
16867
16867
  return Result.ok(result.ok);
16868
16868
  }
@@ -16872,13 +16872,13 @@ class safrole_seal_SafroleSeal {
16872
16872
  const sealingKey = keys.at(index);
16873
16873
  const authorBandersnatchKey = authorKey.bandersnatch;
16874
16874
  if (sealingKey === undefined || !sealingKey.isEqualTo(authorBandersnatchKey)) {
16875
- return Result.error(SafroleSealError.InvalidValidator, `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
16875
+ return Result.error(SafroleSealError.InvalidValidator, () => `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
16876
16876
  }
16877
16877
  // verify seal correctness
16878
16878
  const payload = BytesBlob.blobFromParts(JAM_FALLBACK_SEAL, entropy.raw);
16879
16879
  const result = await bandersnatchVrf.verifySeal(await this.bandersnatch, authorBandersnatchKey, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
16880
16880
  if (result.isError) {
16881
- return Result.error(SafroleSealError.IncorrectSeal);
16881
+ return Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with keys");
16882
16882
  }
16883
16883
  return Result.ok(result.ok);
16884
16884
  }
@@ -17151,11 +17151,11 @@ class state_update_PartiallyUpdatedState {
17151
17151
  const overflowBytes = !isU64(bytes);
17152
17152
  // TODO [ToDr] this is not specified in GP, but it seems sensible.
17153
17153
  if (overflowItems || overflowBytes) {
17154
- return Result.error(InsufficientFundsError);
17154
+ return Result.error(InsufficientFundsError, () => `Storage utilisation overflow: items=${overflowItems}, bytes=${overflowBytes}`);
17155
17155
  }
17156
17156
  const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(items, bytes, serviceInfo.gratisStorage);
17157
17157
  if (serviceInfo.balance < thresholdBalance) {
17158
- return Result.error(InsufficientFundsError);
17158
+ return Result.error(InsufficientFundsError, () => `Service balance (${serviceInfo.balance}) below threshold (${thresholdBalance})`);
17159
17159
  }
17160
17160
  // Update service info with new details.
17161
17161
  this.updateServiceInfo(serviceId, ServiceAccountInfo.create({
@@ -18544,7 +18544,7 @@ class readable_page_ReadablePage extends MemoryPage {
18544
18544
  loadInto(result, startIndex, length) {
18545
18545
  const endIndex = startIndex + length;
18546
18546
  if (endIndex > memory_consts_PAGE_SIZE) {
18547
- return result_Result.error(errors_PageFault.fromMemoryIndex(this.start + memory_consts_PAGE_SIZE));
18547
+ return result_Result.error(errors_PageFault.fromMemoryIndex(this.start + memory_consts_PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + memory_consts_PAGE_SIZE}`);
18548
18548
  }
18549
18549
  const bytes = this.data.subarray(startIndex, endIndex);
18550
18550
  // we zero the bytes, since data might not yet be initialized at `endIndex`.
@@ -18553,7 +18553,7 @@ class readable_page_ReadablePage extends MemoryPage {
18553
18553
  return result_Result.ok(result_OK);
18554
18554
  }
18555
18555
  storeFrom(_address, _data) {
18556
- return result_Result.error(errors_PageFault.fromMemoryIndex(this.start, true));
18556
+ return result_Result.error(errors_PageFault.fromMemoryIndex(this.start, true), () => `Page fault: attempted to write to read-only page at ${this.start}`);
18557
18557
  }
18558
18558
  setData(pageIndex, data) {
18559
18559
  this.data.set(data, pageIndex);
@@ -18587,7 +18587,7 @@ class writeable_page_WriteablePage extends MemoryPage {
18587
18587
  loadInto(result, startIndex, length) {
18588
18588
  const endIndex = startIndex + length;
18589
18589
  if (endIndex > memory_consts_PAGE_SIZE) {
18590
- return result_Result.error(errors_PageFault.fromMemoryIndex(this.start + memory_consts_PAGE_SIZE));
18590
+ return result_Result.error(errors_PageFault.fromMemoryIndex(this.start + memory_consts_PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + memory_consts_PAGE_SIZE}`);
18591
18591
  }
18592
18592
  const bytes = this.view.subarray(startIndex, endIndex);
18593
18593
  // we zero the bytes, since the view might not yet be initialized at `endIndex`.
@@ -18673,7 +18673,7 @@ class memory_Memory {
18673
18673
  memory_logger.insane `MEM[${address}] <- ${BytesBlob.blobFrom(bytes)}`;
18674
18674
  const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
18675
18675
  if (pagesResult.isError) {
18676
- return Result.error(pagesResult.error);
18676
+ return Result.error(pagesResult.error, pagesResult.details);
18677
18677
  }
18678
18678
  const pages = pagesResult.ok;
18679
18679
  let currentPosition = address;
@@ -18698,14 +18698,14 @@ class memory_Memory {
18698
18698
  const pages = [];
18699
18699
  for (const pageNumber of pageRange) {
18700
18700
  if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
18701
- return Result.error(PageFault.fromPageNumber(pageNumber, true));
18701
+ return Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
18702
18702
  }
18703
18703
  const page = this.memory.get(pageNumber);
18704
18704
  if (page === undefined) {
18705
- return Result.error(PageFault.fromPageNumber(pageNumber));
18705
+ return Result.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
18706
18706
  }
18707
18707
  if (accessType === AccessType.WRITE && !page.isWriteable()) {
18708
- return Result.error(PageFault.fromPageNumber(pageNumber, true));
18708
+ return Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
18709
18709
  }
18710
18710
  pages.push(page);
18711
18711
  }
@@ -18723,7 +18723,7 @@ class memory_Memory {
18723
18723
  }
18724
18724
  const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
18725
18725
  if (pagesResult.isError) {
18726
- return Result.error(pagesResult.error);
18726
+ return Result.error(pagesResult.error, pagesResult.details);
18727
18727
  }
18728
18728
  const pages = pagesResult.ok;
18729
18729
  let currentPosition = startAddress;
@@ -20476,7 +20476,7 @@ class program_decoder_ProgramDecoder {
20476
20476
  }
20477
20477
  catch (e) {
20478
20478
  program_decoder_logger.error `Invalid program: ${e}`;
20479
- return Result.error(ProgramDecoderError.InvalidProgramError);
20479
+ return Result.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
20480
20480
  }
20481
20481
  }
20482
20482
  }
@@ -21219,10 +21219,10 @@ class accumulate_externalities_AccumulateExternalities {
21219
21219
  const len = existingPreimage.slots.length;
21220
21220
  // https://graypaper.fluffylabs.dev/#/9a08063/380901380901?v=0.6.6
21221
21221
  if (len === PreimageStatusKind.Requested) {
21222
- return Result.error(RequestPreimageError.AlreadyRequested);
21222
+ return Result.error(RequestPreimageError.AlreadyRequested, () => `Preimage already requested: hash=${hash}`);
21223
21223
  }
21224
21224
  if (len === PreimageStatusKind.Available || len === PreimageStatusKind.Reavailable) {
21225
- return Result.error(RequestPreimageError.AlreadyAvailable);
21225
+ return Result.error(RequestPreimageError.AlreadyAvailable, () => `Preimage already available: hash=${hash}`);
21226
21226
  }
21227
21227
  // TODO [ToDr] Not sure if we should update the service info in that case,
21228
21228
  // but for now we let that case fall-through.
@@ -21263,7 +21263,7 @@ class accumulate_externalities_AccumulateExternalities {
21263
21263
  const serviceId = this.currentServiceId;
21264
21264
  const status = this.updatedState.getLookupHistory(this.currentTimeslot, this.currentServiceId, hash, length);
21265
21265
  if (status === null) {
21266
- return Result.error(ForgetPreimageError.NotFound);
21266
+ return Result.error(ForgetPreimageError.NotFound, () => `Preimage not found: hash=${hash}, length=${length}`);
21267
21267
  }
21268
21268
  const s = slotsToPreimageStatus(status.slots);
21269
21269
  const updateStorageUtilisation = () => {
@@ -21276,7 +21276,7 @@ class accumulate_externalities_AccumulateExternalities {
21276
21276
  if (s.status === PreimageStatusKind.Requested) {
21277
21277
  const res = updateStorageUtilisation();
21278
21278
  if (res.isError) {
21279
- return Result.error(ForgetPreimageError.StorageUtilisationError);
21279
+ return Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
21280
21280
  }
21281
21281
  this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
21282
21282
  hash: status.hash,
@@ -21291,7 +21291,7 @@ class accumulate_externalities_AccumulateExternalities {
21291
21291
  if (y < t - this.chainSpec.preimageExpungePeriod) {
21292
21292
  const res = updateStorageUtilisation();
21293
21293
  if (res.isError) {
21294
- return Result.error(ForgetPreimageError.StorageUtilisationError);
21294
+ return Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
21295
21295
  }
21296
21296
  this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
21297
21297
  hash: status.hash,
@@ -21299,7 +21299,7 @@ class accumulate_externalities_AccumulateExternalities {
21299
21299
  }));
21300
21300
  return Result.ok(OK);
21301
21301
  }
21302
- return Result.error(ForgetPreimageError.NotExpired);
21302
+ return Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
21303
21303
  }
21304
21304
  // https://graypaper.fluffylabs.dev/#/9a08063/38c80138c801?v=0.6.6
21305
21305
  if (s.status === PreimageStatusKind.Available) {
@@ -21317,7 +21317,7 @@ class accumulate_externalities_AccumulateExternalities {
21317
21317
  }));
21318
21318
  return Result.ok(OK);
21319
21319
  }
21320
- return Result.error(ForgetPreimageError.NotExpired);
21320
+ return Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
21321
21321
  }
21322
21322
  assertNever(s);
21323
21323
  }
@@ -21326,17 +21326,17 @@ class accumulate_externalities_AccumulateExternalities {
21326
21326
  const destination = this.getServiceInfo(destinationId);
21327
21327
  /** https://graypaper.fluffylabs.dev/#/9a08063/370401370401?v=0.6.6 */
21328
21328
  if (destination === null || destinationId === null) {
21329
- return Result.error(TransferError.DestinationNotFound);
21329
+ return Result.error(TransferError.DestinationNotFound, () => `Destination service not found: ${destinationId}`);
21330
21330
  }
21331
21331
  /** https://graypaper.fluffylabs.dev/#/9a08063/371301371301?v=0.6.6 */
21332
21332
  if (gas < destination.onTransferMinGas) {
21333
- return Result.error(TransferError.GasTooLow);
21333
+ return Result.error(TransferError.GasTooLow, () => `Gas ${gas} below minimum ${destination.onTransferMinGas}`);
21334
21334
  }
21335
21335
  /** https://graypaper.fluffylabs.dev/#/9a08063/371b01371b01?v=0.6.6 */
21336
21336
  const newBalance = source.balance - amount;
21337
21337
  const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(source.storageUtilisationCount, source.storageUtilisationBytes, source.gratisStorage);
21338
21338
  if (newBalance < thresholdBalance) {
21339
- return Result.error(TransferError.BalanceBelowThreshold);
21339
+ return Result.error(TransferError.BalanceBelowThreshold, () => `Balance ${newBalance} below threshold ${thresholdBalance}`);
21340
21340
  }
21341
21341
  // outgoing transfer
21342
21342
  this.updatedState.stateUpdate.transfers.push(PendingTransfer.create({
@@ -21363,7 +21363,7 @@ class accumulate_externalities_AccumulateExternalities {
21363
21363
  // check if we are priviledged to set gratis storage
21364
21364
  // https://graypaper.fluffylabs.dev/#/7e6ff6a/369203369603?v=0.6.7
21365
21365
  if (gratisStorage !== tryAsU64(0) && this.currentServiceId !== this.updatedState.getPrivilegedServices().manager) {
21366
- return Result.error(NewServiceError.UnprivilegedService);
21366
+ return Result.error(NewServiceError.UnprivilegedService, () => `Service ${this.currentServiceId} not privileged to set gratis storage`);
21367
21367
  }
21368
21368
  // check if we have enough balance
21369
21369
  // https://graypaper.fluffylabs.dev/#/7e6ff6a/369e0336a303?v=0.6.7
@@ -21372,7 +21372,7 @@ class accumulate_externalities_AccumulateExternalities {
21372
21372
  const thresholdForCurrent = ServiceAccountInfo.calculateThresholdBalance(currentService.storageUtilisationCount, currentService.storageUtilisationBytes, currentService.gratisStorage);
21373
21373
  const balanceLeftForCurrent = currentService.balance - thresholdForNew;
21374
21374
  if (balanceLeftForCurrent < thresholdForCurrent || bytes.overflow) {
21375
- return Result.error(NewServiceError.InsufficientFunds);
21375
+ return Result.error(NewServiceError.InsufficientFunds, () => `Insufficient funds: balance=${currentService.balance}, required=${thresholdForNew}, overflow=${bytes.overflow}`);
21376
21376
  }
21377
21377
  // `a`: https://graypaper.fluffylabs.dev/#/ab2cdbd/366b02366d02?v=0.7.2
21378
21378
  const newAccount = ServiceAccountInfo.create({
@@ -21399,7 +21399,7 @@ class accumulate_externalities_AccumulateExternalities {
21399
21399
  // NOTE: It's safe to cast to `Number` here, bcs here service ID cannot be bigger than 2**16
21400
21400
  const newServiceId = tryAsServiceId(Number(wantedServiceId));
21401
21401
  if (this.getServiceInfo(newServiceId) !== null) {
21402
- return Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken);
21402
+ return Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken, () => `Service ID ${newServiceId} already taken`);
21403
21403
  }
21404
21404
  // add the new service with selected ID
21405
21405
  // https://graypaper.fluffylabs.dev/#/ab2cdbd/36be0336c003?v=0.7.2
@@ -21439,7 +21439,7 @@ class accumulate_externalities_AccumulateExternalities {
21439
21439
  const currentDelegator = this.updatedState.getPrivilegedServices().delegator;
21440
21440
  if (currentDelegator !== this.currentServiceId) {
21441
21441
  accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not a validators manager. (expected: ${currentDelegator}) and cannot update validators data. Ignoring`;
21442
- return Result.error(UnprivilegedError);
21442
+ return Result.error(UnprivilegedError, () => `Service ${this.currentServiceId} is not delegator (expected: ${currentDelegator})`);
21443
21443
  }
21444
21444
  this.updatedState.stateUpdate.validatorsData = validatorsData;
21445
21445
  return Result.ok(OK);
@@ -21454,11 +21454,11 @@ class accumulate_externalities_AccumulateExternalities {
21454
21454
  const currentAssigners = this.updatedState.getPrivilegedServices().assigners[coreIndex];
21455
21455
  if (currentAssigners !== this.currentServiceId) {
21456
21456
  accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not an auth manager of core ${coreIndex} (expected: ${currentAssigners}) and cannot update authorization queue.`;
21457
- return Result.error(UpdatePrivilegesError.UnprivilegedService);
21457
+ return Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} not assigner for core ${coreIndex} (expected: ${currentAssigners})`);
21458
21458
  }
21459
21459
  if (assigners === null && Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)) {
21460
21460
  accumulate_externalities_logger.trace `The new auth manager is not a valid service id.`;
21461
- return Result.error(UpdatePrivilegesError.InvalidServiceId);
21461
+ return Result.error(UpdatePrivilegesError.InvalidServiceId, () => `New auth manager is null for core ${coreIndex}`);
21462
21462
  }
21463
21463
  this.updatedState.stateUpdate.authorizationQueues.set(coreIndex, authQueue);
21464
21464
  return Result.ok(OK);
@@ -21491,10 +21491,10 @@ class accumulate_externalities_AccumulateExternalities {
21491
21491
  const isManager = current.manager === this.currentServiceId;
21492
21492
  if (Compatibility.isLessThan(GpVersion.V0_7_1)) {
21493
21493
  if (!isManager) {
21494
- return Result.error(UpdatePrivilegesError.UnprivilegedService);
21494
+ return Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} is not manager`);
21495
21495
  }
21496
21496
  if (manager === null || delegator === null) {
21497
- return Result.error(UpdatePrivilegesError.InvalidServiceId, "Either manager or delegator is not a valid service id.");
21497
+ return Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator is not a valid service id.");
21498
21498
  }
21499
21499
  this.updatedState.stateUpdate.privilegedServices = PrivilegedServices.create({
21500
21500
  manager,
@@ -21507,7 +21507,7 @@ class accumulate_externalities_AccumulateExternalities {
21507
21507
  }
21508
21508
  const original = this.updatedState.state.privilegedServices;
21509
21509
  if (manager === null || delegator === null || registrar === null) {
21510
- return Result.error(UpdatePrivilegesError.InvalidServiceId, "Either manager or delegator or registrar is not a valid service id.");
21510
+ return Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator or registrar is not a valid service id.");
21511
21511
  }
21512
21512
  const newDelegator = this.updatePrivilegedServiceId(delegator, current.delegator, {
21513
21513
  isManager,
@@ -21547,19 +21547,19 @@ class accumulate_externalities_AccumulateExternalities {
21547
21547
  // TODO [ToDr] what about newly created services?
21548
21548
  const service = serviceId === null ? null : this.updatedState.state.getService(serviceId);
21549
21549
  if (service === null || serviceId === null) {
21550
- return Result.error(ProvidePreimageError.ServiceNotFound);
21550
+ return Result.error(ProvidePreimageError.ServiceNotFound, () => `Service not found: ${serviceId}`);
21551
21551
  }
21552
21552
  // calculating the hash
21553
21553
  const preimageHash = this.blake2b.hashBytes(preimage).asOpaque();
21554
21554
  // checking service internal lookup
21555
21555
  const stateLookup = this.updatedState.getLookupHistory(this.currentTimeslot, serviceId, preimageHash, tryAsU64(preimage.length));
21556
21556
  if (stateLookup === null || !LookupHistoryItem.isRequested(stateLookup)) {
21557
- return Result.error(ProvidePreimageError.WasNotRequested);
21557
+ return Result.error(ProvidePreimageError.WasNotRequested, () => `Preimage was not requested: hash=${preimageHash}, service=${serviceId}`);
21558
21558
  }
21559
21559
  // checking already provided preimages
21560
21560
  const hasPreimage = this.updatedState.hasPreimage(serviceId, preimageHash);
21561
21561
  if (hasPreimage) {
21562
- return Result.error(ProvidePreimageError.AlreadyProvided);
21562
+ return Result.error(ProvidePreimageError.AlreadyProvided, () => `Preimage already provided: hash=${preimageHash}, service=${serviceId}`);
21563
21563
  }
21564
21564
  // setting up the new preimage
21565
21565
  this.updatedState.updatePreimage(serviceId, UpdatePreimage.provide({
@@ -21574,31 +21574,31 @@ class accumulate_externalities_AccumulateExternalities {
21574
21574
  eject(destination, previousCodeHash) {
21575
21575
  const service = this.getServiceInfo(destination);
21576
21576
  if (service === null || destination === null) {
21577
- return Result.error(EjectError.InvalidService, "Service missing");
21577
+ return Result.error(EjectError.InvalidService, () => "Service missing");
21578
21578
  }
21579
21579
  const currentService = this.getCurrentServiceInfo();
21580
21580
  // check if the service expects to be ejected by us:
21581
21581
  const expectedCodeHash = Bytes.zero(HASH_SIZE).asOpaque();
21582
21582
  writeServiceIdAsLeBytes(this.currentServiceId, expectedCodeHash.raw);
21583
21583
  if (!service.codeHash.isEqualTo(expectedCodeHash)) {
21584
- return Result.error(EjectError.InvalidService, "Invalid code hash");
21584
+ return Result.error(EjectError.InvalidService, () => "Invalid code hash");
21585
21585
  }
21586
21586
  // make sure the service only has required number of storage items?
21587
21587
  if (service.storageUtilisationCount !== REQUIRED_NUMBER_OF_STORAGE_ITEMS_FOR_EJECT) {
21588
- return Result.error(EjectError.InvalidPreimage, "Too many storage items");
21588
+ return Result.error(EjectError.InvalidPreimage, () => "Too many storage items");
21589
21589
  }
21590
21590
  // storage items length
21591
21591
  const l = tryAsU64(maxU64(service.storageUtilisationBytes, LOOKUP_HISTORY_ENTRY_BYTES) - LOOKUP_HISTORY_ENTRY_BYTES);
21592
21592
  // check if we have a preimage with the entire storage.
21593
21593
  const [isPreviousCodeExpired, errorReason] = this.isPreviousCodeExpired(destination, previousCodeHash, l);
21594
21594
  if (!isPreviousCodeExpired) {
21595
- return Result.error(EjectError.InvalidPreimage, `Previous code available: ${errorReason}`);
21595
+ return Result.error(EjectError.InvalidPreimage, () => `Previous code available: ${errorReason}`);
21596
21596
  }
21597
21597
  // compute new balance of the service.
21598
21598
  const newBalance = sumU64(currentService.balance, service.balance);
21599
21599
  // TODO [ToDr] what to do in case of overflow?
21600
21600
  if (newBalance.overflow) {
21601
- return Result.error(EjectError.InvalidService, "Balance overflow");
21601
+ return Result.error(EjectError.InvalidService, () => "Balance overflow");
21602
21602
  }
21603
21603
  // update current service.
21604
21604
  this.updatedState.updateServiceInfo(this.currentServiceId, ServiceAccountInfo.create({
@@ -21789,10 +21789,10 @@ class assurances_Assurances {
21789
21789
  for (const assurance of assurances) {
21790
21790
  const { anchor, validatorIndex, bitfield } = assurance;
21791
21791
  if (!anchor.isEqualTo(input.parentHash)) {
21792
- return Result.error(AssurancesError.InvalidAnchor, `anchor: expected: ${input.parentHash}, got ${anchor}`);
21792
+ return Result.error(AssurancesError.InvalidAnchor, () => `anchor: expected: ${input.parentHash}, got ${anchor}`);
21793
21793
  }
21794
21794
  if (prevValidatorIndex >= validatorIndex) {
21795
- return Result.error(AssurancesError.InvalidOrder, `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
21795
+ return Result.error(AssurancesError.InvalidOrder, () => `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
21796
21796
  }
21797
21797
  prevValidatorIndex = assurance.validatorIndex;
21798
21798
  check `${bitfield.bitLength === coresCount} Invalid bitfield length of ${bitfield.bitLength}`;
@@ -21815,7 +21815,7 @@ class assurances_Assurances {
21815
21815
  * https://graypaper.fluffylabs.dev/#/579bd12/14e90014ea00
21816
21816
  */
21817
21817
  if (noOfAssurances > 0 && !isReportPending) {
21818
- return Result.error(AssurancesError.NoReportPending, `no report pending for core ${c} yet we got an assurance`);
21818
+ return Result.error(AssurancesError.NoReportPending, () => `no report pending for core ${c} yet we got an assurance`);
21819
21819
  }
21820
21820
  /**
21821
21821
  * Remove work report if it's became available or timed out.
@@ -21861,7 +21861,7 @@ class assurances_Assurances {
21861
21861
  const v = assurance.view();
21862
21862
  const key = validatorData[v.validatorIndex.materialize()];
21863
21863
  if (key === undefined) {
21864
- return Result.error(AssurancesError.InvalidValidatorIndex);
21864
+ return Result.error(AssurancesError.InvalidValidatorIndex, () => `Invalid validator index: ${v.validatorIndex.materialize()}`);
21865
21865
  }
21866
21866
  signatures.push({
21867
21867
  signature: v.signature.materialize(),
@@ -21873,7 +21873,7 @@ class assurances_Assurances {
21873
21873
  const isAllSignaturesValid = signaturesValid.every((x) => x);
21874
21874
  if (!isAllSignaturesValid) {
21875
21875
  const invalidIndices = signaturesValid.reduce((acc, isValid, idx) => (isValid ? acc : acc.concat(idx)), []);
21876
- return Result.error(AssurancesError.InvalidSignature, `invalid signatures at ${invalidIndices.join(", ")}`);
21876
+ return Result.error(AssurancesError.InvalidSignature, () => `invalid signatures at ${invalidIndices.join(", ")}`);
21877
21877
  }
21878
21878
  return Result.ok(OK);
21879
21879
  }
@@ -22484,7 +22484,7 @@ class host_call_memory_HostCallMemory {
22484
22484
  return Result.ok(OK);
22485
22485
  }
22486
22486
  if (address + tryAsU64(bytes.length) > MEMORY_SIZE) {
22487
- return Result.error(new OutOfBounds());
22487
+ return Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`);
22488
22488
  }
22489
22489
  return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
22490
22490
  }
@@ -22493,7 +22493,7 @@ class host_call_memory_HostCallMemory {
22493
22493
  return Result.ok(OK);
22494
22494
  }
22495
22495
  if (startAddress + tryAsU64(result.length) > MEMORY_SIZE) {
22496
- return Result.error(new OutOfBounds());
22496
+ return Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`);
22497
22497
  }
22498
22498
  return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
22499
22499
  }
@@ -24302,18 +24302,18 @@ class accumulate_Accumulate {
24302
24302
  const serviceInfo = updatedState.getServiceInfo(serviceId);
24303
24303
  if (serviceInfo === null) {
24304
24304
  accumulate_logger.log `Service with id ${serviceId} not found.`;
24305
- return Result.error(PvmInvocationError.NoService);
24305
+ return Result.error(PvmInvocationError.NoService, () => `Accumulate: service ${serviceId} not found`);
24306
24306
  }
24307
24307
  const codeHash = serviceInfo.codeHash;
24308
24308
  // TODO [ToDr] Should we check that the preimage is still available?
24309
24309
  const code = updatedState.getPreimage(serviceId, codeHash.asOpaque());
24310
24310
  if (code === null) {
24311
24311
  accumulate_logger.log `Code with hash ${codeHash} not found for service ${serviceId}.`;
24312
- return Result.error(PvmInvocationError.NoPreimage);
24312
+ return Result.error(PvmInvocationError.NoPreimage, () => `Accumulate: code with hash ${codeHash} not found for service ${serviceId}`);
24313
24313
  }
24314
24314
  if (code.length > W_C) {
24315
24315
  accumulate_logger.log `Code with hash ${codeHash} is too long for service ${serviceId}.`;
24316
- return Result.error(PvmInvocationError.PreimageTooLong);
24316
+ return Result.error(PvmInvocationError.PreimageTooLong, () => `Accumulate: code length ${code.length} exceeds max ${W_C} for service ${serviceId}`);
24317
24317
  }
24318
24318
  const nextServiceId = generateNextServiceId({ serviceId, entropy, timeslot: slot }, this.chainSpec, this.blake2b);
24319
24319
  const partialState = new AccumulateExternalities(this.chainSpec, this.blake2b, updatedState, serviceId, nextServiceId, slot);
@@ -24601,7 +24601,7 @@ class accumulate_Accumulate {
24601
24601
  assertEmpty(stateUpdateRest);
24602
24602
  if (this.hasDuplicatedServiceIdCreated(services.created)) {
24603
24603
  accumulate_logger.trace `Duplicated Service creation detected. Block is invalid.`;
24604
- return Result.error(ACCUMULATION_ERROR);
24604
+ return Result.error(ACCUMULATION_ERROR, () => "Accumulate: duplicate service created");
24605
24605
  }
24606
24606
  const accStateUpdate = this.getAccumulationStateUpdate(accumulated.toArray(), toAccumulateLater, slot, Array.from(statistics.keys()), services);
24607
24607
  const accumulationOutputUnsorted = Array.from(yieldedRoots.entries()).map(([serviceId, root]) => {
@@ -24682,13 +24682,13 @@ class deferred_transfers_DeferredTransfers {
24682
24682
  .toSorted((a, b) => a.source - b.source);
24683
24683
  const info = partiallyUpdatedState.getServiceInfo(serviceId);
24684
24684
  if (info === null) {
24685
- return Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist);
24685
+ return Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist, () => `Deferred transfers: service info not found for ${serviceId}`);
24686
24686
  }
24687
24687
  const codeHash = info.codeHash;
24688
24688
  const code = partiallyUpdatedState.getPreimage(serviceId, codeHash.asOpaque());
24689
24689
  const newBalance = sumU64(info.balance, ...transfers.map((item) => item.amount));
24690
24690
  if (newBalance.overflow) {
24691
- return Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow);
24691
+ return Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow, () => `Deferred transfers: balance overflow for service ${serviceId}`);
24692
24692
  }
24693
24693
  const newInfo = ServiceAccountInfo.create({ ...info, balance: newBalance.value });
24694
24694
  partiallyUpdatedState.updateServiceInfo(serviceId, newInfo);
@@ -25166,7 +25166,7 @@ function verify_basic_verifyReportsBasic(input) {
25166
25166
  const noOfPrerequisites = reportView.context.view().prerequisites.view().length;
25167
25167
  const noOfSegmentRootLookups = reportView.segmentRootLookup.view().length;
25168
25168
  if (noOfPrerequisites + noOfSegmentRootLookups > MAX_REPORT_DEPENDENCIES) {
25169
- return Result.error(ReportsError.TooManyDependencies, `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
25169
+ return Result.error(ReportsError.TooManyDependencies, () => `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
25170
25170
  }
25171
25171
  /**
25172
25172
  * In order to ensure fair use of a block’s extrinsic space,
@@ -25185,7 +25185,7 @@ function verify_basic_verifyReportsBasic(input) {
25185
25185
  totalOutputsSize += item.view().result.view().okBlob?.raw.length ?? 0;
25186
25186
  }
25187
25187
  if (authOutputSize + totalOutputsSize > MAX_WORK_REPORT_SIZE_BYTES) {
25188
- return Result.error(ReportsError.WorkReportTooBig, `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
25188
+ return Result.error(ReportsError.WorkReportTooBig, () => `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
25189
25189
  }
25190
25190
  }
25191
25191
  return Result.ok(OK);
@@ -25219,12 +25219,12 @@ function verify_contextual_verifyContextualValidity(input, state, headerChain, m
25219
25219
  for (const result of guarantee.report.results) {
25220
25220
  const service = state.getService(result.serviceId);
25221
25221
  if (service === null) {
25222
- return Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
25222
+ return Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
25223
25223
  }
25224
25224
  // check service code hash
25225
25225
  // https://graypaper.fluffylabs.dev/#/5f542d7/154b02154b02
25226
25226
  if (!result.codeHash.isEqualTo(service.getInfo().codeHash)) {
25227
- return Result.error(ReportsError.BadCodeHash, `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
25227
+ return Result.error(ReportsError.BadCodeHash, () => `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
25228
25228
  }
25229
25229
  }
25230
25230
  }
@@ -25235,7 +25235,7 @@ function verify_contextual_verifyContextualValidity(input, state, headerChain, m
25235
25235
  * https://graypaper.fluffylabs.dev/#/5f542d7/151f01152101
25236
25236
  */
25237
25237
  if (currentWorkPackages.size !== input.guarantees.length) {
25238
- return Result.error(ReportsError.DuplicatePackage, "Duplicate work package detected.");
25238
+ return Result.error(ReportsError.DuplicatePackage, () => "Duplicate work package detected.");
25239
25239
  }
25240
25240
  const minLookupSlot = Math.max(0, input.slot - maxLookupAnchorAge);
25241
25241
  const contextResult = verifyRefineContexts(minLookupSlot, contexts, input.recentBlocksPartialUpdate, headerChain);
@@ -25280,7 +25280,7 @@ function verify_contextual_verifyContextualValidity(input, state, headerChain, m
25280
25280
  : undefined;
25281
25281
  }
25282
25282
  if (root === undefined || !root.segmentTreeRoot.isEqualTo(lookup.segmentTreeRoot)) {
25283
- return Result.error(ReportsError.SegmentRootLookupInvalid, `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
25283
+ return Result.error(ReportsError.SegmentRootLookupInvalid, () => `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
25284
25284
  }
25285
25285
  }
25286
25286
  }
@@ -25303,16 +25303,16 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
25303
25303
  */
25304
25304
  const recentBlock = recentBlocks.get(context.anchor);
25305
25305
  if (recentBlock === undefined) {
25306
- return Result.error(ReportsError.AnchorNotRecent, `Anchor block ${context.anchor} not found in recent blocks.`);
25306
+ return Result.error(ReportsError.AnchorNotRecent, () => `Anchor block ${context.anchor} not found in recent blocks.`);
25307
25307
  }
25308
25308
  // check state root
25309
25309
  if (!recentBlock.postStateRoot.isEqualTo(context.stateRoot)) {
25310
- return Result.error(ReportsError.BadStateRoot, `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
25310
+ return Result.error(ReportsError.BadStateRoot, () => `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
25311
25311
  }
25312
25312
  // check beefy root
25313
25313
  const beefyRoot = recentBlock.accumulationResult;
25314
25314
  if (!beefyRoot.isEqualTo(context.beefyRoot)) {
25315
- return Result.error(ReportsError.BadBeefyMmrRoot, `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
25315
+ return Result.error(ReportsError.BadBeefyMmrRoot, () => `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
25316
25316
  }
25317
25317
  /**
25318
25318
  * We require that each lookup-anchor block be within the
@@ -25321,7 +25321,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
25321
25321
  * https://graypaper.fluffylabs.dev/#/5f542d7/154601154701
25322
25322
  */
25323
25323
  if (context.lookupAnchorSlot < minLookupSlot) {
25324
- return Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
25324
+ return Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
25325
25325
  }
25326
25326
  /**
25327
25327
  * We also require that we have a record of it; this is one of
@@ -25338,7 +25338,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
25338
25338
  verify_contextual_logger.warn `Lookup anchor check for ${context.lookupAnchor} would fail, but override is active.`;
25339
25339
  }
25340
25340
  else {
25341
- return Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
25341
+ return Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
25342
25342
  }
25343
25343
  }
25344
25344
  }
@@ -25361,7 +25361,7 @@ function verifyDependencies({ currentWorkPackages, recentlyReported, prerequisit
25361
25361
  if (recentlyReported.has(preReqHash)) {
25362
25362
  continue;
25363
25363
  }
25364
- return Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, `Missing work package ${preReqHash} in current extrinsic or recent history.`);
25364
+ return Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, () => `Missing work package ${preReqHash} in current extrinsic or recent history.`);
25365
25365
  }
25366
25366
  return Result.ok(OK);
25367
25367
  };
@@ -25409,7 +25409,7 @@ function verifyWorkPackagesUniqueness(workPackageHashes, state) {
25409
25409
  // let's check if any of our packages is in the pipeline
25410
25410
  const intersection = packagesInPipeline.intersection(workPackageHashes);
25411
25411
  for (const packageHash of intersection) {
25412
- return Result.error(ReportsError.DuplicatePackage, `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
25412
+ return Result.error(ReportsError.DuplicatePackage, () => `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
25413
25413
  }
25414
25414
  return Result.ok(OK);
25415
25415
  }
@@ -25448,7 +25448,7 @@ workReportHashes, slot, getGuarantorAssignment) {
25448
25448
  const credentialsView = guaranteeView.credentials.view();
25449
25449
  if (credentialsView.length < REQUIRED_CREDENTIALS_RANGE[0] ||
25450
25450
  credentialsView.length > REQUIRED_CREDENTIALS_RANGE[1]) {
25451
- return Result.error(ReportsError.InsufficientGuarantees, `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
25451
+ return Result.error(ReportsError.InsufficientGuarantees, () => `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
25452
25452
  }
25453
25453
  /** Retrieve current core assignment. */
25454
25454
  const timeSlot = guaranteeView.slot.materialize();
@@ -25463,20 +25463,20 @@ workReportHashes, slot, getGuarantorAssignment) {
25463
25463
  const credentialView = credential.view();
25464
25464
  const validatorIndex = credentialView.validatorIndex.materialize();
25465
25465
  if (lastValidatorIndex >= validatorIndex) {
25466
- return Result.error(ReportsError.NotSortedOrUniqueGuarantors, `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
25466
+ return Result.error(ReportsError.NotSortedOrUniqueGuarantors, () => `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
25467
25467
  }
25468
25468
  lastValidatorIndex = validatorIndex;
25469
25469
  const signature = credentialView.signature.materialize();
25470
25470
  const guarantorData = guarantorAssignments[validatorIndex];
25471
25471
  if (guarantorData === undefined) {
25472
- return Result.error(ReportsError.BadValidatorIndex, `Invalid validator index: ${validatorIndex}`);
25472
+ return Result.error(ReportsError.BadValidatorIndex, () => `Invalid validator index: ${validatorIndex}`);
25473
25473
  }
25474
25474
  /**
25475
25475
  * Verify core assignment.
25476
25476
  * https://graypaper.fluffylabs.dev/#/5f542d7/14e40214e602
25477
25477
  */
25478
25478
  if (guarantorData.core !== coreIndex) {
25479
- return Result.error(ReportsError.WrongAssignment, `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
25479
+ return Result.error(ReportsError.WrongAssignment, () => `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
25480
25480
  }
25481
25481
  signaturesToVerify.push({
25482
25482
  signature,
@@ -25514,10 +25514,10 @@ function verify_order_verifyReportsOrder(input, chainSpec) {
25514
25514
  const reportView = guarantee.view().report.view();
25515
25515
  const coreIndex = reportView.coreIndex.materialize();
25516
25516
  if (lastCoreIndex >= coreIndex) {
25517
- return Result.error(ReportsError.OutOfOrderGuarantee, `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
25517
+ return Result.error(ReportsError.OutOfOrderGuarantee, () => `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
25518
25518
  }
25519
25519
  if (coreIndex >= noOfCores) {
25520
- return Result.error(ReportsError.BadCoreIndex, `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
25520
+ return Result.error(ReportsError.BadCoreIndex, () => `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
25521
25521
  }
25522
25522
  lastCoreIndex = coreIndex;
25523
25523
  }
@@ -25542,7 +25542,7 @@ function verify_post_signature_verifyPostSignatureChecks(input, availabilityAssi
25542
25542
  * https://graypaper.fluffylabs.dev/#/5f542d7/15ea0015ea00
25543
25543
  */
25544
25544
  if (availabilityAssignment[coreIndex] !== null) {
25545
- return Result.error(ReportsError.CoreEngaged, `Report pending availability at core: ${coreIndex}`);
25545
+ return Result.error(ReportsError.CoreEngaged, () => `Report pending availability at core: ${coreIndex}`);
25546
25546
  }
25547
25547
  /**
25548
25548
  * A report is valid only if the authorizer hash is present
@@ -25555,7 +25555,7 @@ function verify_post_signature_verifyPostSignatureChecks(input, availabilityAssi
25555
25555
  const authorizerPool = authPools.get(coreIndex);
25556
25556
  const pool = authorizerPool?.materialize() ?? [];
25557
25557
  if (pool.find((hash) => hash.isEqualTo(authorizerHash)) === undefined) {
25558
- return Result.error(ReportsError.CoreUnauthorized, `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
25558
+ return Result.error(ReportsError.CoreUnauthorized, () => `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
25559
25559
  }
25560
25560
  /**
25561
25561
  * We require that the gas allotted for accumulation of each
@@ -25567,17 +25567,17 @@ function verify_post_signature_verifyPostSignatureChecks(input, availabilityAssi
25567
25567
  for (const result of report.results) {
25568
25568
  const service = services(result.serviceId);
25569
25569
  if (service === null) {
25570
- return Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
25570
+ return Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
25571
25571
  }
25572
25572
  const info = service.getInfo();
25573
25573
  // check minimal accumulation gas
25574
25574
  if (result.gas < info.accumulateMinGas) {
25575
- return Result.error(ReportsError.ServiceItemGasTooLow, `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
25575
+ return Result.error(ReportsError.ServiceItemGasTooLow, () => `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
25576
25576
  }
25577
25577
  }
25578
25578
  const totalGas = sumU64(...report.results.map((x) => x.gas));
25579
25579
  if (totalGas.overflow || totalGas.value > G_A) {
25580
- return Result.error(ReportsError.WorkReportGasTooHigh, `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
25580
+ return Result.error(ReportsError.WorkReportGasTooHigh, () => `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
25581
25581
  }
25582
25582
  }
25583
25583
  return Result.ok(OK);
@@ -25663,7 +25663,7 @@ class reports_Reports {
25663
25663
  }
25664
25664
  const reporters = SortedSet.fromArray(bytesBlobComparator, signaturesToVerify.ok.map((x) => x.key)).slice();
25665
25665
  if (hasAnyOffenders(reporters, input.offenders)) {
25666
- return Result.error(ReportsError.BannedValidator);
25666
+ return Result.error(ReportsError.BannedValidator, () => "One or more reporters are banned validators");
25667
25667
  }
25668
25668
  return Result.ok({
25669
25669
  stateUpdate: {
@@ -25703,7 +25703,7 @@ class reports_Reports {
25703
25703
  return signaturesToVerify[idx].key;
25704
25704
  })
25705
25705
  .filter((x) => x !== null);
25706
- return Result.error(ReportsError.BadSignature, `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
25706
+ return Result.error(ReportsError.BadSignature, () => `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
25707
25707
  }
25708
25708
  /**
25709
25709
  * Get the guarantor assignment (both core and validator data)
@@ -25719,10 +25719,10 @@ class reports_Reports {
25719
25719
  const minTimeSlot = Math.max(0, headerRotation - 1) * rotationPeriod;
25720
25720
  // https://graypaper.fluffylabs.dev/#/5f542d7/155e00156900
25721
25721
  if (guaranteeTimeSlot > headerTimeSlot) {
25722
- return Result.error(ReportsError.FutureReportSlot, `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
25722
+ return Result.error(ReportsError.FutureReportSlot, () => `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
25723
25723
  }
25724
25724
  if (guaranteeTimeSlot < minTimeSlot) {
25725
- return Result.error(ReportsError.ReportEpochBeforeLast, `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
25725
+ return Result.error(ReportsError.ReportEpochBeforeLast, () => `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
25726
25726
  }
25727
25727
  // TODO [ToDr] [opti] below code needs cache.
25728
25728
  // The `G` and `G*` sets should only be computed once per rotation.
@@ -26338,11 +26338,11 @@ class chain_stf_OnChain {
26338
26338
  }
26339
26339
  function checkOffendersMatch(offendersMark, headerOffendersMark) {
26340
26340
  if (offendersMark.size !== headerOffendersMark.length) {
26341
- return Result.error(OFFENDERS_ERROR, `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
26341
+ return Result.error(OFFENDERS_ERROR, () => `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
26342
26342
  }
26343
26343
  for (const key of headerOffendersMark) {
26344
26344
  if (!offendersMark.has(key)) {
26345
- return Result.error(OFFENDERS_ERROR, `Missing key: ${key}`);
26345
+ return Result.error(OFFENDERS_ERROR, () => `Missing key: ${key}`);
26346
26346
  }
26347
26347
  }
26348
26348
  return Result.ok(OK);