@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/bootstrap-generator.mjs +14 -14
- package/bootstrap-generator.mjs.map +1 -1
- package/bootstrap-importer.mjs +147 -147
- package/bootstrap-importer.mjs.map +1 -1
- package/bootstrap-network.mjs +18 -18
- package/bootstrap-network.mjs.map +1 -1
- package/index.js +158 -158
- package/index.js.map +1 -1
- package/package.json +1 -1
package/bootstrap-importer.mjs
CHANGED
|
@@ -3840,7 +3840,7 @@ function resultToString(res) {
|
|
|
3840
3840
|
if (res.isOk) {
|
|
3841
3841
|
return `OK: ${typeof res.ok === "symbol" ? res.ok.toString() : res.ok}`;
|
|
3842
3842
|
}
|
|
3843
|
-
return `${res.details}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
3843
|
+
return `${res.details()}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
3844
3844
|
}
|
|
3845
3845
|
/** An indication of two possible outcomes returned from a function. */
|
|
3846
3846
|
const result_Result = {
|
|
@@ -3854,7 +3854,7 @@ const result_Result = {
|
|
|
3854
3854
|
};
|
|
3855
3855
|
},
|
|
3856
3856
|
/** Create new [`Result`] with `Error` status. */
|
|
3857
|
-
error: (error, details
|
|
3857
|
+
error: (error, details) => {
|
|
3858
3858
|
debug_check `${error !== undefined} 'Error' type cannot be undefined.`;
|
|
3859
3859
|
return {
|
|
3860
3860
|
isOk: false,
|
|
@@ -3973,7 +3973,7 @@ function deepEqual(actual, expected, { context = [], errorsCollector, ignore = [
|
|
|
3973
3973
|
}
|
|
3974
3974
|
if (actual.isError && expected.isError) {
|
|
3975
3975
|
deepEqual(actual.error, expected.error, { context: ctx.concat(["error"]), errorsCollector: errors, ignore });
|
|
3976
|
-
deepEqual(actual.details, expected.details, {
|
|
3976
|
+
deepEqual(actual.details(), expected.details(), {
|
|
3977
3977
|
context: ctx.concat(["details"]),
|
|
3978
3978
|
errorsCollector: errors,
|
|
3979
3979
|
// display details when error does not match
|
|
@@ -10943,7 +10943,7 @@ class in_memory_state_InMemoryState extends WithDebug {
|
|
|
10943
10943
|
const { kind } = update.action;
|
|
10944
10944
|
const service = this.services.get(serviceId);
|
|
10945
10945
|
if (service === undefined) {
|
|
10946
|
-
return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update storage of non-existing service: ${serviceId}`);
|
|
10946
|
+
return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update storage of non-existing service: ${serviceId}`);
|
|
10947
10947
|
}
|
|
10948
10948
|
if (kind === UpdateStorageKind.Set) {
|
|
10949
10949
|
const { key, value } = update.action.storage;
|
|
@@ -10971,14 +10971,14 @@ class in_memory_state_InMemoryState extends WithDebug {
|
|
|
10971
10971
|
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
10972
10972
|
const service = this.services.get(serviceId);
|
|
10973
10973
|
if (service === undefined) {
|
|
10974
|
-
return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update preimage of non-existing service: ${serviceId}`);
|
|
10974
|
+
return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update preimage of non-existing service: ${serviceId}`);
|
|
10975
10975
|
}
|
|
10976
10976
|
for (const update of updates) {
|
|
10977
10977
|
const { kind } = update.action;
|
|
10978
10978
|
if (kind === UpdatePreimageKind.Provide) {
|
|
10979
10979
|
const { preimage, slot } = update.action;
|
|
10980
10980
|
if (service.data.preimages.has(preimage.hash)) {
|
|
10981
|
-
return result_Result.error(in_memory_state_UpdateError.PreimageExists, `Overwriting existing preimage at ${serviceId}: ${preimage}`);
|
|
10981
|
+
return result_Result.error(in_memory_state_UpdateError.PreimageExists, () => `Overwriting existing preimage at ${serviceId}: ${preimage}`);
|
|
10982
10982
|
}
|
|
10983
10983
|
service.data.preimages.set(preimage.hash, preimage);
|
|
10984
10984
|
if (slot !== null) {
|
|
@@ -11029,7 +11029,7 @@ class in_memory_state_InMemoryState extends WithDebug {
|
|
|
11029
11029
|
if (kind === UpdateServiceKind.Create) {
|
|
11030
11030
|
const { lookupHistory } = update.action;
|
|
11031
11031
|
if (this.services.has(serviceId)) {
|
|
11032
|
-
return result_Result.error(in_memory_state_UpdateError.DuplicateService, `${serviceId} already exists!`);
|
|
11032
|
+
return result_Result.error(in_memory_state_UpdateError.DuplicateService, () => `${serviceId} already exists!`);
|
|
11033
11033
|
}
|
|
11034
11034
|
this.services.set(serviceId, new InMemoryService(serviceId, {
|
|
11035
11035
|
info: account,
|
|
@@ -11041,7 +11041,7 @@ class in_memory_state_InMemoryState extends WithDebug {
|
|
|
11041
11041
|
else if (kind === UpdateServiceKind.Update) {
|
|
11042
11042
|
const existingService = this.services.get(serviceId);
|
|
11043
11043
|
if (existingService === undefined) {
|
|
11044
|
-
return result_Result.error(in_memory_state_UpdateError.NoService, `Cannot update ${serviceId} because it does not exist.`);
|
|
11044
|
+
return result_Result.error(in_memory_state_UpdateError.NoService, () => `Cannot update ${serviceId} because it does not exist.`);
|
|
11045
11045
|
}
|
|
11046
11046
|
existingService.data.info = account;
|
|
11047
11047
|
}
|
|
@@ -12671,13 +12671,13 @@ class LeafDb {
|
|
|
12671
12671
|
*/
|
|
12672
12672
|
static fromLeavesBlob(blob, db) {
|
|
12673
12673
|
if (blob.length % TRIE_NODE_BYTES !== 0) {
|
|
12674
|
-
return result_Result.error(LeafDbError.InvalidLeafData, `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
|
|
12674
|
+
return result_Result.error(LeafDbError.InvalidLeafData, () => `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
|
|
12675
12675
|
}
|
|
12676
12676
|
const leaves = SortedSet.fromArray(leafComparator, []);
|
|
12677
12677
|
for (const nodeData of blob.chunks(TRIE_NODE_BYTES)) {
|
|
12678
12678
|
const node = new TrieNode(nodeData.raw);
|
|
12679
12679
|
if (node.getNodeType() === NodeType.Branch) {
|
|
12680
|
-
return result_Result.error(LeafDbError.InvalidLeafData, `Branch node detected: ${nodeData}`);
|
|
12680
|
+
return result_Result.error(LeafDbError.InvalidLeafData, () => `Branch node detected: ${nodeData}`);
|
|
12681
12681
|
}
|
|
12682
12682
|
leaves.insert(node.asLeafNode());
|
|
12683
12683
|
}
|
|
@@ -13396,7 +13396,7 @@ class LmdbStates {
|
|
|
13396
13396
|
}
|
|
13397
13397
|
catch (e) {
|
|
13398
13398
|
logger.error `${e}`;
|
|
13399
|
-
return result_Result.error(StateUpdateError.Commit);
|
|
13399
|
+
return result_Result.error(StateUpdateError.Commit, () => `Failed to commit state update: ${e}`);
|
|
13400
13400
|
}
|
|
13401
13401
|
return result_Result.ok(result_OK);
|
|
13402
13402
|
}
|
|
@@ -14116,7 +14116,7 @@ class Preimages {
|
|
|
14116
14116
|
}
|
|
14117
14117
|
if (prevPreimage.requester > currPreimage.requester ||
|
|
14118
14118
|
currPreimage.blob.compare(prevPreimage.blob).isLessOrEqual()) {
|
|
14119
|
-
return result_Result.error(PreimagesErrorCode.PreimagesNotSortedUnique);
|
|
14119
|
+
return result_Result.error(PreimagesErrorCode.PreimagesNotSortedUnique, () => `Preimages not sorted/unique at index ${i}`);
|
|
14120
14120
|
}
|
|
14121
14121
|
}
|
|
14122
14122
|
const { preimages, slot } = input;
|
|
@@ -14127,14 +14127,14 @@ class Preimages {
|
|
|
14127
14127
|
const hash = this.blake2b.hashBytes(blob).asOpaque();
|
|
14128
14128
|
const service = this.state.getService(requester);
|
|
14129
14129
|
if (service === null) {
|
|
14130
|
-
return result_Result.error(PreimagesErrorCode.AccountNotFound);
|
|
14130
|
+
return result_Result.error(PreimagesErrorCode.AccountNotFound, () => `Service not found: ${requester}`);
|
|
14131
14131
|
}
|
|
14132
14132
|
const hasPreimage = service.hasPreimage(hash);
|
|
14133
14133
|
const slots = service.getLookupHistory(hash, numbers_tryAsU32(blob.length));
|
|
14134
14134
|
// https://graypaper.fluffylabs.dev/#/5f542d7/181800181900
|
|
14135
14135
|
// https://graypaper.fluffylabs.dev/#/5f542d7/116f0011a500
|
|
14136
14136
|
if (hasPreimage || slots === null || !LookupHistoryItem.isRequested(slots)) {
|
|
14137
|
-
return result_Result.error(PreimagesErrorCode.PreimageUnneeded);
|
|
14137
|
+
return result_Result.error(PreimagesErrorCode.PreimageUnneeded, () => `Preimage unneeded: requester=${requester}, hash=${hash}, hasPreimage=${hasPreimage}, isRequested=${slots !== null && LookupHistoryItem.isRequested(slots)}`);
|
|
14138
14138
|
}
|
|
14139
14139
|
// https://graypaper.fluffylabs.dev/#/5f542d7/18c00018f300
|
|
14140
14140
|
const updates = pendingChanges.get(requester) ?? [];
|
|
@@ -14180,7 +14180,7 @@ class BlockVerifier {
|
|
|
14180
14180
|
const headerHash = this.hasher.header(headerView);
|
|
14181
14181
|
// check if current block is already imported
|
|
14182
14182
|
if (this.blocks.getHeader(headerHash.hash) !== null) {
|
|
14183
|
-
return result_Result.error(BlockVerifierError.AlreadyImported, `Block ${headerHash.hash} is already imported.`);
|
|
14183
|
+
return result_Result.error(BlockVerifierError.AlreadyImported, () => `Block ${headerHash.hash} is already imported.`);
|
|
14184
14184
|
}
|
|
14185
14185
|
// Check if parent block exists.
|
|
14186
14186
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0c82000c8200?v=0.6.5
|
|
@@ -14190,14 +14190,14 @@ class BlockVerifier {
|
|
|
14190
14190
|
if (!parentHash.isEqualTo(block_verifier_ZERO_HASH)) {
|
|
14191
14191
|
const parentBlock = this.blocks.getHeader(parentHash);
|
|
14192
14192
|
if (parentBlock === null) {
|
|
14193
|
-
return result_Result.error(BlockVerifierError.ParentNotFound, `Parent ${parentHash.toString()} not found`);
|
|
14193
|
+
return result_Result.error(BlockVerifierError.ParentNotFound, () => `Parent ${parentHash.toString()} not found`);
|
|
14194
14194
|
}
|
|
14195
14195
|
// Check if the time slot index is consecutive and not from future.
|
|
14196
14196
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0c02010c0201?v=0.6.5
|
|
14197
14197
|
const timeslot = headerView.timeSlotIndex.materialize();
|
|
14198
14198
|
const parentTimeslot = parentBlock.timeSlotIndex.materialize();
|
|
14199
14199
|
if (timeslot <= parentTimeslot) {
|
|
14200
|
-
return result_Result.error(BlockVerifierError.InvalidTimeSlot, `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
|
|
14200
|
+
return result_Result.error(BlockVerifierError.InvalidTimeSlot, () => `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
|
|
14201
14201
|
}
|
|
14202
14202
|
}
|
|
14203
14203
|
// Check if extrinsic is valid.
|
|
@@ -14205,17 +14205,17 @@ class BlockVerifier {
|
|
|
14205
14205
|
const extrinsicHash = headerView.extrinsicHash.materialize();
|
|
14206
14206
|
const extrinsicMerkleCommitment = this.hasher.extrinsic(block.extrinsic.view());
|
|
14207
14207
|
if (!extrinsicHash.isEqualTo(extrinsicMerkleCommitment.hash)) {
|
|
14208
|
-
return result_Result.error(BlockVerifierError.InvalidExtrinsic, `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
|
|
14208
|
+
return result_Result.error(BlockVerifierError.InvalidExtrinsic, () => `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
|
|
14209
14209
|
}
|
|
14210
14210
|
// Check if the state root is valid.
|
|
14211
14211
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0c18010c1801?v=0.6.5
|
|
14212
14212
|
const stateRoot = headerView.priorStateRoot.materialize();
|
|
14213
14213
|
const posteriorStateRoot = this.blocks.getPostStateRoot(parentHash);
|
|
14214
14214
|
if (posteriorStateRoot === null) {
|
|
14215
|
-
return result_Result.error(BlockVerifierError.StateRootNotFound, `Posterior state root ${parentHash.toString()} not found`);
|
|
14215
|
+
return result_Result.error(BlockVerifierError.StateRootNotFound, () => `Posterior state root ${parentHash.toString()} not found`);
|
|
14216
14216
|
}
|
|
14217
14217
|
if (!stateRoot.isEqualTo(posteriorStateRoot)) {
|
|
14218
|
-
return result_Result.error(BlockVerifierError.InvalidStateRoot, `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
|
|
14218
|
+
return result_Result.error(BlockVerifierError.InvalidStateRoot, () => `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
|
|
14219
14219
|
}
|
|
14220
14220
|
return result_Result.ok(headerHash.hash);
|
|
14221
14221
|
}
|
|
@@ -14340,7 +14340,7 @@ class Disputes {
|
|
|
14340
14340
|
// check if culprits are sorted by key
|
|
14341
14341
|
// https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
|
|
14342
14342
|
if (!isUniqueSortedBy(disputes.culprits, "key")) {
|
|
14343
|
-
return result_Result.error(DisputesErrorCode.CulpritsNotSortedUnique);
|
|
14343
|
+
return result_Result.error(DisputesErrorCode.CulpritsNotSortedUnique, () => "Culprits are not uniquely sorted by key");
|
|
14344
14344
|
}
|
|
14345
14345
|
const culpritsLength = disputes.culprits.length;
|
|
14346
14346
|
for (let i = 0; i < culpritsLength; i++) {
|
|
@@ -14349,24 +14349,24 @@ class Disputes {
|
|
|
14349
14349
|
// https://graypaper.fluffylabs.dev/#/579bd12/125501125501
|
|
14350
14350
|
const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
|
|
14351
14351
|
if (isInPunishSet) {
|
|
14352
|
-
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported);
|
|
14352
|
+
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: culprit ${i}, key=${key}`);
|
|
14353
14353
|
}
|
|
14354
14354
|
// check if the guarantor key is correct
|
|
14355
14355
|
// https://graypaper.fluffylabs.dev/#/85129da/125501125501?v=0.6.3
|
|
14356
14356
|
if (!allValidatorKeys.has(key)) {
|
|
14357
|
-
return result_Result.error(DisputesErrorCode.BadGuarantorKey);
|
|
14357
|
+
return result_Result.error(DisputesErrorCode.BadGuarantorKey, () => `Bad guarantor key: culprit ${i}, key=${key}`);
|
|
14358
14358
|
}
|
|
14359
14359
|
// verify if the culprit will be in new bad set
|
|
14360
14360
|
// https://graypaper.fluffylabs.dev/#/579bd12/124601124601
|
|
14361
14361
|
const isInNewBadSet = newItems.asDictionaries().badSet.has(workReportHash);
|
|
14362
14362
|
if (!isInNewBadSet) {
|
|
14363
|
-
return result_Result.error(DisputesErrorCode.CulpritsVerdictNotBad);
|
|
14363
|
+
return result_Result.error(DisputesErrorCode.CulpritsVerdictNotBad, () => `Culprit verdict not bad: culprit ${i}, work report=${workReportHash}`);
|
|
14364
14364
|
}
|
|
14365
14365
|
// verify culprit signature
|
|
14366
14366
|
// https://graypaper.fluffylabs.dev/#/579bd12/125c01125c01
|
|
14367
14367
|
const result = verificationResult.culprits[i];
|
|
14368
14368
|
if (!result?.isValid) {
|
|
14369
|
-
return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for culprit: ${i}`);
|
|
14369
|
+
return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for culprit: ${i}`);
|
|
14370
14370
|
}
|
|
14371
14371
|
}
|
|
14372
14372
|
return result_Result.ok(null);
|
|
@@ -14375,7 +14375,7 @@ class Disputes {
|
|
|
14375
14375
|
// check if faults are sorted by key
|
|
14376
14376
|
// https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
|
|
14377
14377
|
if (!isUniqueSortedBy(disputes.faults, "key")) {
|
|
14378
|
-
return result_Result.error(DisputesErrorCode.FaultsNotSortedUnique);
|
|
14378
|
+
return result_Result.error(DisputesErrorCode.FaultsNotSortedUnique, () => "Faults are not uniquely sorted by key");
|
|
14379
14379
|
}
|
|
14380
14380
|
const faultsLength = disputes.faults.length;
|
|
14381
14381
|
for (let i = 0; i < faultsLength; i++) {
|
|
@@ -14384,12 +14384,12 @@ class Disputes {
|
|
|
14384
14384
|
// https://graypaper.fluffylabs.dev/#/579bd12/12a20112a201
|
|
14385
14385
|
const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
|
|
14386
14386
|
if (isInPunishSet) {
|
|
14387
|
-
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported);
|
|
14387
|
+
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: fault ${i}, key=${key}`);
|
|
14388
14388
|
}
|
|
14389
14389
|
// check if the auditor key is correct
|
|
14390
14390
|
// https://graypaper.fluffylabs.dev/#/85129da/12a20112a201?v=0.6.3
|
|
14391
14391
|
if (!allValidatorKeys.has(key)) {
|
|
14392
|
-
return result_Result.error(DisputesErrorCode.BadAuditorKey);
|
|
14392
|
+
return result_Result.error(DisputesErrorCode.BadAuditorKey, () => `Bad auditor key: fault ${i}, key=${key}`);
|
|
14393
14393
|
}
|
|
14394
14394
|
// verify if the fault will be included in new good/bad set
|
|
14395
14395
|
// it may be not correct as in GP there is "iff" what means it should be rather
|
|
@@ -14401,14 +14401,14 @@ class Disputes {
|
|
|
14401
14401
|
const isInNewGoodSet = goodSet.has(workReportHash);
|
|
14402
14402
|
const isInNewBadSet = badSet.has(workReportHash);
|
|
14403
14403
|
if (isInNewGoodSet || !isInNewBadSet) {
|
|
14404
|
-
return result_Result.error(DisputesErrorCode.FaultVerdictWrong);
|
|
14404
|
+
return result_Result.error(DisputesErrorCode.FaultVerdictWrong, () => `Fault verdict wrong: fault ${i}, work report=${workReportHash}, inGood=${isInNewGoodSet}, inBad=${isInNewBadSet}`);
|
|
14405
14405
|
}
|
|
14406
14406
|
}
|
|
14407
14407
|
// verify fault signature. Verification was done earlier, here we only check the result.
|
|
14408
14408
|
// https://graypaper.fluffylabs.dev/#/579bd12/12a90112a901
|
|
14409
14409
|
const result = verificationResult.faults[i];
|
|
14410
14410
|
if (!result.isValid) {
|
|
14411
|
-
return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for fault: ${i}`);
|
|
14411
|
+
return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for fault: ${i}`);
|
|
14412
14412
|
}
|
|
14413
14413
|
}
|
|
14414
14414
|
return result_Result.ok(null);
|
|
@@ -14417,32 +14417,32 @@ class Disputes {
|
|
|
14417
14417
|
// check if verdicts are correctly sorted
|
|
14418
14418
|
// https://graypaper.fluffylabs.dev/#/579bd12/12c40112c401
|
|
14419
14419
|
if (!isUniqueSortedBy(disputes.verdicts, "workReportHash")) {
|
|
14420
|
-
return result_Result.error(DisputesErrorCode.VerdictsNotSortedUnique);
|
|
14420
|
+
return result_Result.error(DisputesErrorCode.VerdictsNotSortedUnique, () => "Verdicts are not uniquely sorted by work report hash");
|
|
14421
14421
|
}
|
|
14422
14422
|
// check if judgement are correctly sorted
|
|
14423
14423
|
// https://graypaper.fluffylabs.dev/#/579bd12/123702123802
|
|
14424
14424
|
if (disputes.verdicts.some((verdict) => !isUniqueSortedByIndex(verdict.votes))) {
|
|
14425
|
-
return result_Result.error(DisputesErrorCode.JudgementsNotSortedUnique);
|
|
14425
|
+
return result_Result.error(DisputesErrorCode.JudgementsNotSortedUnique, () => "Judgements are not uniquely sorted by index");
|
|
14426
14426
|
}
|
|
14427
14427
|
const currentEpoch = Math.floor(this.state.timeslot / this.chainSpec.epochLength);
|
|
14428
14428
|
let voteSignatureIndex = 0;
|
|
14429
14429
|
for (const { votesEpoch, votes } of disputes.verdicts) {
|
|
14430
14430
|
// https://graypaper.fluffylabs.dev/#/579bd12/12bb0012bc00
|
|
14431
14431
|
if (votesEpoch !== currentEpoch && votesEpoch + 1 !== currentEpoch) {
|
|
14432
|
-
return result_Result.error(DisputesErrorCode.BadJudgementAge);
|
|
14432
|
+
return result_Result.error(DisputesErrorCode.BadJudgementAge, () => `Bad judgement age: epoch=${votesEpoch}, current=${currentEpoch}`);
|
|
14433
14433
|
}
|
|
14434
14434
|
const k = votesEpoch === currentEpoch ? this.state.currentValidatorData : this.state.previousValidatorData;
|
|
14435
14435
|
for (const { index } of votes) {
|
|
14436
14436
|
const key = k[index]?.ed25519;
|
|
14437
14437
|
// no particular GP fragment but I think we don't believe in ghosts
|
|
14438
14438
|
if (key === undefined) {
|
|
14439
|
-
return result_Result.error(DisputesErrorCode.BadValidatorIndex);
|
|
14439
|
+
return result_Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index: ${index} in epoch ${votesEpoch}`);
|
|
14440
14440
|
}
|
|
14441
14441
|
// verify vote signature. Verification was done earlier, here we only check the result.
|
|
14442
14442
|
// https://graypaper.fluffylabs.dev/#/579bd12/12cd0012cd00
|
|
14443
14443
|
const result = verificationResult.judgements[voteSignatureIndex];
|
|
14444
14444
|
if (!result.isValid) {
|
|
14445
|
-
return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for judgement: ${voteSignatureIndex}`);
|
|
14445
|
+
return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for judgement: ${voteSignatureIndex}`);
|
|
14446
14446
|
}
|
|
14447
14447
|
voteSignatureIndex += 1;
|
|
14448
14448
|
}
|
|
@@ -14458,7 +14458,7 @@ class Disputes {
|
|
|
14458
14458
|
const isInBadSet = badSet.has(verdict.workReportHash);
|
|
14459
14459
|
const isInWonkySet = wonkySet.has(verdict.workReportHash);
|
|
14460
14460
|
if (isInGoodSet || isInBadSet || isInWonkySet) {
|
|
14461
|
-
return result_Result.error(DisputesErrorCode.AlreadyJudged);
|
|
14461
|
+
return result_Result.error(DisputesErrorCode.AlreadyJudged, () => `Work report already judged: ${verdict.workReportHash}`);
|
|
14462
14462
|
}
|
|
14463
14463
|
}
|
|
14464
14464
|
return result_Result.ok(null);
|
|
@@ -14489,7 +14489,7 @@ class Disputes {
|
|
|
14489
14489
|
// https://graypaper.fluffylabs.dev/#/579bd12/12f10212fc02
|
|
14490
14490
|
const f = disputes.faults.find((x) => x.workReportHash.isEqualTo(r));
|
|
14491
14491
|
if (f === undefined) {
|
|
14492
|
-
return result_Result.error(DisputesErrorCode.NotEnoughFaults);
|
|
14492
|
+
return result_Result.error(DisputesErrorCode.NotEnoughFaults, () => `Not enough faults for work report: ${r}`);
|
|
14493
14493
|
}
|
|
14494
14494
|
}
|
|
14495
14495
|
else if (sum === 0) {
|
|
@@ -14498,13 +14498,13 @@ class Disputes {
|
|
|
14498
14498
|
const c1 = disputes.culprits.find((x) => x.workReportHash.isEqualTo(r));
|
|
14499
14499
|
const c2 = disputes.culprits.findLast((x) => x.workReportHash.isEqualTo(r));
|
|
14500
14500
|
if (c1 === c2) {
|
|
14501
|
-
return result_Result.error(DisputesErrorCode.NotEnoughCulprits);
|
|
14501
|
+
return result_Result.error(DisputesErrorCode.NotEnoughCulprits, () => `Not enough culprits for work report: ${r}`);
|
|
14502
14502
|
}
|
|
14503
14503
|
}
|
|
14504
14504
|
else if (sum !== this.chainSpec.thirdOfValidators) {
|
|
14505
14505
|
// positive votes count is not correct
|
|
14506
14506
|
// https://graypaper.fluffylabs.dev/#/579bd12/125002128102
|
|
14507
|
-
return result_Result.error(DisputesErrorCode.BadVoteSplit);
|
|
14507
|
+
return result_Result.error(DisputesErrorCode.BadVoteSplit, () => `Bad vote split: sum=${sum}, expected=${this.chainSpec.thirdOfValidators} for work report ${r}`);
|
|
14508
14508
|
}
|
|
14509
14509
|
}
|
|
14510
14510
|
return result_Result.ok(null);
|
|
@@ -14592,7 +14592,7 @@ class Disputes {
|
|
|
14592
14592
|
const validator = k[j.index];
|
|
14593
14593
|
// no particular GP fragment but I think we don't believe in ghosts
|
|
14594
14594
|
if (validator === undefined) {
|
|
14595
|
-
return result_Result.error(DisputesErrorCode.BadValidatorIndex);
|
|
14595
|
+
return result_Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index in signature verification: ${j.index}`);
|
|
14596
14596
|
}
|
|
14597
14597
|
const key = validator.ed25519;
|
|
14598
14598
|
// verify vote signature
|
|
@@ -14700,7 +14700,7 @@ const ringCommitmentCache = [];
|
|
|
14700
14700
|
async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUnsealedHeader) {
|
|
14701
14701
|
const sealResult = await bandersnatch.verifySeal(authorKey.raw, signature.raw, payload.raw, encodedUnsealedHeader.raw);
|
|
14702
14702
|
if (sealResult[RESULT_INDEX] === ResultValues.Error) {
|
|
14703
|
-
return result_Result.error(null);
|
|
14703
|
+
return result_Result.error(null, () => "Bandersnatch VRF seal verification failed");
|
|
14704
14704
|
}
|
|
14705
14705
|
return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
|
|
14706
14706
|
}
|
|
@@ -14726,7 +14726,7 @@ function getRingCommitment(bandersnatch, validators) {
|
|
|
14726
14726
|
async function getRingCommitmentNoCache(bandersnatch, keys) {
|
|
14727
14727
|
const commitmentResult = await bandersnatch.getRingCommitment(keys.raw);
|
|
14728
14728
|
if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
|
|
14729
|
-
return result_Result.error(null);
|
|
14729
|
+
return result_Result.error(null, () => "Bandersnatch ring commitment calculation failed");
|
|
14730
14730
|
}
|
|
14731
14731
|
return result_Result.ok(bytes_Bytes.fromBlob(commitmentResult.subarray(1), bandersnatch_BANDERSNATCH_RING_ROOT_BYTES).asOpaque());
|
|
14732
14732
|
}
|
|
@@ -14901,7 +14901,7 @@ class Safrole {
|
|
|
14901
14901
|
epochRoot: epochRootResult.ok,
|
|
14902
14902
|
});
|
|
14903
14903
|
}
|
|
14904
|
-
return result_Result.error(SafroleErrorCode.IncorrectData);
|
|
14904
|
+
return result_Result.error(SafroleErrorCode.IncorrectData, () => "Safrole: failed to get epoch root for validator keys");
|
|
14905
14905
|
}
|
|
14906
14906
|
/**
|
|
14907
14907
|
* Ticket sequencer that is used in standard mode
|
|
@@ -14992,10 +14992,10 @@ class Safrole {
|
|
|
14992
14992
|
for (let i = 1; i < ticketsLength; i++) {
|
|
14993
14993
|
const order = tickets[i - 1].id.compare(tickets[i].id);
|
|
14994
14994
|
if (order.isEqual()) {
|
|
14995
|
-
return result_Result.error(SafroleErrorCode.DuplicateTicket);
|
|
14995
|
+
return result_Result.error(SafroleErrorCode.DuplicateTicket, () => `Safrole: duplicate ticket found at index ${i}`);
|
|
14996
14996
|
}
|
|
14997
14997
|
if (order.isGreater()) {
|
|
14998
|
-
return result_Result.error(SafroleErrorCode.BadTicketOrder);
|
|
14998
|
+
return result_Result.error(SafroleErrorCode.BadTicketOrder, () => `Safrole: bad ticket order at index ${i}`);
|
|
14999
14999
|
}
|
|
15000
15000
|
}
|
|
15001
15001
|
return result_Result.ok(null);
|
|
@@ -15022,7 +15022,7 @@ class Safrole {
|
|
|
15022
15022
|
attempt: ticket.attempt,
|
|
15023
15023
|
}));
|
|
15024
15024
|
if (!verificationResult.every((x) => x.isValid)) {
|
|
15025
|
-
return result_Result.error(SafroleErrorCode.BadTicketProof);
|
|
15025
|
+
return result_Result.error(SafroleErrorCode.BadTicketProof, () => "Safrole: invalid ticket proof in extrinsic");
|
|
15026
15026
|
}
|
|
15027
15027
|
/**
|
|
15028
15028
|
* Verify if tickets are sorted and unique
|
|
@@ -15031,7 +15031,7 @@ class Safrole {
|
|
|
15031
15031
|
*/
|
|
15032
15032
|
const ticketsVerifcationResult = this.verifyTickets(tickets);
|
|
15033
15033
|
if (ticketsVerifcationResult.isError) {
|
|
15034
|
-
return result_Result.error(ticketsVerifcationResult.error);
|
|
15034
|
+
return result_Result.error(ticketsVerifcationResult.error, ticketsVerifcationResult.details);
|
|
15035
15035
|
}
|
|
15036
15036
|
if (this.isEpochChanged(timeslot)) {
|
|
15037
15037
|
return result_Result.ok(tickets);
|
|
@@ -15040,7 +15040,7 @@ class Safrole {
|
|
|
15040
15040
|
const ticketsFromExtrinsic = SortedSet.fromSortedArray(ticketComparator, tickets);
|
|
15041
15041
|
const mergedTickets = SortedSet.fromTwoSortedCollections(ticketsFromState, ticketsFromExtrinsic);
|
|
15042
15042
|
if (ticketsFromState.length + ticketsFromExtrinsic.length !== mergedTickets.length) {
|
|
15043
|
-
return result_Result.error(SafroleErrorCode.DuplicateTicket);
|
|
15043
|
+
return result_Result.error(SafroleErrorCode.DuplicateTicket, () => "Safrole: duplicate ticket when merging state and extrinsic tickets");
|
|
15044
15044
|
}
|
|
15045
15045
|
/**
|
|
15046
15046
|
* Remove tickets if size of accumulator exceeds E (epoch length).
|
|
@@ -15109,24 +15109,24 @@ class Safrole {
|
|
|
15109
15109
|
}
|
|
15110
15110
|
async transition(input) {
|
|
15111
15111
|
if (this.state.timeslot >= input.slot) {
|
|
15112
|
-
return result_Result.error(SafroleErrorCode.BadSlot);
|
|
15112
|
+
return result_Result.error(SafroleErrorCode.BadSlot, () => `Safrole: bad slot, state timeslot ${this.state.timeslot} >= input slot ${input.slot}`);
|
|
15113
15113
|
}
|
|
15114
15114
|
if (!this.isExtrinsicLengthValid(input.slot, input.extrinsic)) {
|
|
15115
|
-
return result_Result.error(SafroleErrorCode.UnexpectedTicket);
|
|
15115
|
+
return result_Result.error(SafroleErrorCode.UnexpectedTicket, () => `Safrole: unexpected ticket, invalid extrinsic length ${input.extrinsic.length}`);
|
|
15116
15116
|
}
|
|
15117
15117
|
if (!this.areTicketAttemptsValid(input.extrinsic)) {
|
|
15118
|
-
return result_Result.error(SafroleErrorCode.BadTicketAttempt);
|
|
15118
|
+
return result_Result.error(SafroleErrorCode.BadTicketAttempt, () => "Safrole: bad ticket attempt value in extrinsic");
|
|
15119
15119
|
}
|
|
15120
15120
|
const validatorKeysResult = await this.getValidatorKeys(input.slot, input.punishSet);
|
|
15121
15121
|
if (validatorKeysResult.isError) {
|
|
15122
|
-
return result_Result.error(validatorKeysResult.error);
|
|
15122
|
+
return result_Result.error(validatorKeysResult.error, validatorKeysResult.details);
|
|
15123
15123
|
}
|
|
15124
15124
|
const { nextValidatorData, currentValidatorData, previousValidatorData, epochRoot } = validatorKeysResult.ok;
|
|
15125
15125
|
const entropy = this.getEntropy(input.slot, input.entropy);
|
|
15126
15126
|
const sealingKeySeries = this.getSlotKeySequence(input.slot, currentValidatorData, entropy[2]);
|
|
15127
15127
|
const newTicketsAccumulatorResult = await this.getNewTicketAccumulator(input.slot, input.extrinsic, this.state.nextValidatorData, epochRoot, entropy[2]);
|
|
15128
15128
|
if (newTicketsAccumulatorResult.isError) {
|
|
15129
|
-
return result_Result.error(newTicketsAccumulatorResult.error);
|
|
15129
|
+
return result_Result.error(newTicketsAccumulatorResult.error, newTicketsAccumulatorResult.details);
|
|
15130
15130
|
}
|
|
15131
15131
|
const stateUpdate = {
|
|
15132
15132
|
nextValidatorData,
|
|
@@ -15160,14 +15160,14 @@ function compareWithEncoding(chainSpec, error, actual, expected, codec) {
|
|
|
15160
15160
|
if (actual === null || expected === null) {
|
|
15161
15161
|
// if one of them is `null`, both need to be.
|
|
15162
15162
|
if (actual !== expected) {
|
|
15163
|
-
return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
|
|
15163
|
+
return result_Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
|
|
15164
15164
|
}
|
|
15165
15165
|
return result_Result.ok(result_OK);
|
|
15166
15166
|
}
|
|
15167
15167
|
// compare the literal encoding.
|
|
15168
15168
|
const encoded = encoder_Encoder.encodeObject(codec, actual, chainSpec);
|
|
15169
15169
|
if (!encoded.isEqualTo(expected.encoded())) {
|
|
15170
|
-
return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
|
|
15170
|
+
return result_Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
|
|
15171
15171
|
}
|
|
15172
15172
|
return result_Result.ok(result_OK);
|
|
15173
15173
|
}
|
|
@@ -15210,7 +15210,7 @@ class SafroleSeal {
|
|
|
15210
15210
|
const blockAuthorKey = state.currentValidatorData.at(blockAuthorIndex)?.bandersnatch;
|
|
15211
15211
|
const entropySourceResult = await bandersnatch_vrf.verifySeal(await this.bandersnatch, blockAuthorKey ?? BANDERSNATCH_ZERO_KEY, headerView.entropySource.materialize(), payload, bytes_BytesBlob.blobFromNumbers([]));
|
|
15212
15212
|
if (entropySourceResult.isError) {
|
|
15213
|
-
return result_Result.error(SafroleSealError.IncorrectEntropySource);
|
|
15213
|
+
return result_Result.error(SafroleSealError.IncorrectEntropySource, () => "Safrole: incorrect entropy source in header seal");
|
|
15214
15214
|
}
|
|
15215
15215
|
return result_Result.ok(entropySourceResult.ok);
|
|
15216
15216
|
}
|
|
@@ -15219,7 +15219,7 @@ class SafroleSeal {
|
|
|
15219
15219
|
const validatorIndex = headerView.bandersnatchBlockAuthorIndex.materialize();
|
|
15220
15220
|
const authorKeys = state.currentValidatorData.at(validatorIndex);
|
|
15221
15221
|
if (authorKeys === undefined) {
|
|
15222
|
-
return result_Result.error(SafroleSealError.InvalidValidatorIndex);
|
|
15222
|
+
return result_Result.error(SafroleSealError.InvalidValidatorIndex, () => `Safrole: invalid validator index ${validatorIndex}`);
|
|
15223
15223
|
}
|
|
15224
15224
|
const timeSlot = headerView.timeSlotIndex.materialize();
|
|
15225
15225
|
const sealingKeys = state.sealingKeySeries;
|
|
@@ -15238,10 +15238,10 @@ class SafroleSeal {
|
|
|
15238
15238
|
const authorKey = validatorData.bandersnatch;
|
|
15239
15239
|
const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, authorKey ?? BANDERSNATCH_ZERO_KEY, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
|
|
15240
15240
|
if (result.isError) {
|
|
15241
|
-
return result_Result.error(SafroleSealError.IncorrectSeal);
|
|
15241
|
+
return result_Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with ticket");
|
|
15242
15242
|
}
|
|
15243
15243
|
if (ticket === undefined || !ticket.id.isEqualTo(result.ok)) {
|
|
15244
|
-
return result_Result.error(SafroleSealError.InvalidTicket);
|
|
15244
|
+
return result_Result.error(SafroleSealError.InvalidTicket, () => `Safrole: invalid ticket, expected ${ticket?.id} got ${result.ok}`);
|
|
15245
15245
|
}
|
|
15246
15246
|
return result_Result.ok(result.ok);
|
|
15247
15247
|
}
|
|
@@ -15251,13 +15251,13 @@ class SafroleSeal {
|
|
|
15251
15251
|
const sealingKey = keys.at(index);
|
|
15252
15252
|
const authorBandersnatchKey = authorKey.bandersnatch;
|
|
15253
15253
|
if (sealingKey === undefined || !sealingKey.isEqualTo(authorBandersnatchKey)) {
|
|
15254
|
-
return result_Result.error(SafroleSealError.InvalidValidator, `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
|
|
15254
|
+
return result_Result.error(SafroleSealError.InvalidValidator, () => `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
|
|
15255
15255
|
}
|
|
15256
15256
|
// verify seal correctness
|
|
15257
15257
|
const payload = bytes_BytesBlob.blobFromParts(JAM_FALLBACK_SEAL, entropy.raw);
|
|
15258
15258
|
const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, authorBandersnatchKey, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
|
|
15259
15259
|
if (result.isError) {
|
|
15260
|
-
return result_Result.error(SafroleSealError.IncorrectSeal);
|
|
15260
|
+
return result_Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with keys");
|
|
15261
15261
|
}
|
|
15262
15262
|
return result_Result.ok(result.ok);
|
|
15263
15263
|
}
|
|
@@ -15530,11 +15530,11 @@ class PartiallyUpdatedState {
|
|
|
15530
15530
|
const overflowBytes = !isU64(bytes);
|
|
15531
15531
|
// TODO [ToDr] this is not specified in GP, but it seems sensible.
|
|
15532
15532
|
if (overflowItems || overflowBytes) {
|
|
15533
|
-
return result_Result.error(InsufficientFundsError);
|
|
15533
|
+
return result_Result.error(InsufficientFundsError, () => `Storage utilisation overflow: items=${overflowItems}, bytes=${overflowBytes}`);
|
|
15534
15534
|
}
|
|
15535
15535
|
const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(items, bytes, serviceInfo.gratisStorage);
|
|
15536
15536
|
if (serviceInfo.balance < thresholdBalance) {
|
|
15537
|
-
return result_Result.error(InsufficientFundsError);
|
|
15537
|
+
return result_Result.error(InsufficientFundsError, () => `Service balance (${serviceInfo.balance}) below threshold (${thresholdBalance})`);
|
|
15538
15538
|
}
|
|
15539
15539
|
// Update service info with new details.
|
|
15540
15540
|
this.updateServiceInfo(serviceId, ServiceAccountInfo.create({
|
|
@@ -17037,7 +17037,7 @@ class ReadablePage extends MemoryPage {
|
|
|
17037
17037
|
loadInto(result, startIndex, length) {
|
|
17038
17038
|
const endIndex = startIndex + length;
|
|
17039
17039
|
if (endIndex > PAGE_SIZE) {
|
|
17040
|
-
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE));
|
|
17040
|
+
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE}`);
|
|
17041
17041
|
}
|
|
17042
17042
|
const bytes = this.data.subarray(startIndex, endIndex);
|
|
17043
17043
|
// we zero the bytes, since data might not yet be initialized at `endIndex`.
|
|
@@ -17046,7 +17046,7 @@ class ReadablePage extends MemoryPage {
|
|
|
17046
17046
|
return result_Result.ok(result_OK);
|
|
17047
17047
|
}
|
|
17048
17048
|
storeFrom(_address, _data) {
|
|
17049
|
-
return result_Result.error(PageFault.fromMemoryIndex(this.start, true));
|
|
17049
|
+
return result_Result.error(PageFault.fromMemoryIndex(this.start, true), () => `Page fault: attempted to write to read-only page at ${this.start}`);
|
|
17050
17050
|
}
|
|
17051
17051
|
setData(pageIndex, data) {
|
|
17052
17052
|
this.data.set(data, pageIndex);
|
|
@@ -17080,7 +17080,7 @@ class WriteablePage extends MemoryPage {
|
|
|
17080
17080
|
loadInto(result, startIndex, length) {
|
|
17081
17081
|
const endIndex = startIndex + length;
|
|
17082
17082
|
if (endIndex > PAGE_SIZE) {
|
|
17083
|
-
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE));
|
|
17083
|
+
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE}`);
|
|
17084
17084
|
}
|
|
17085
17085
|
const bytes = this.view.subarray(startIndex, endIndex);
|
|
17086
17086
|
// we zero the bytes, since the view might not yet be initialized at `endIndex`.
|
|
@@ -17166,7 +17166,7 @@ class Memory {
|
|
|
17166
17166
|
memory_logger.insane `MEM[${address}] <- ${bytes_BytesBlob.blobFrom(bytes)}`;
|
|
17167
17167
|
const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
|
|
17168
17168
|
if (pagesResult.isError) {
|
|
17169
|
-
return result_Result.error(pagesResult.error);
|
|
17169
|
+
return result_Result.error(pagesResult.error, pagesResult.details);
|
|
17170
17170
|
}
|
|
17171
17171
|
const pages = pagesResult.ok;
|
|
17172
17172
|
let currentPosition = address;
|
|
@@ -17191,14 +17191,14 @@ class Memory {
|
|
|
17191
17191
|
const pages = [];
|
|
17192
17192
|
for (const pageNumber of pageRange) {
|
|
17193
17193
|
if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
|
|
17194
|
-
return result_Result.error(PageFault.fromPageNumber(pageNumber, true));
|
|
17194
|
+
return result_Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
|
|
17195
17195
|
}
|
|
17196
17196
|
const page = this.memory.get(pageNumber);
|
|
17197
17197
|
if (page === undefined) {
|
|
17198
|
-
return result_Result.error(PageFault.fromPageNumber(pageNumber));
|
|
17198
|
+
return result_Result.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
|
|
17199
17199
|
}
|
|
17200
17200
|
if (accessType === AccessType.WRITE && !page.isWriteable()) {
|
|
17201
|
-
return result_Result.error(PageFault.fromPageNumber(pageNumber, true));
|
|
17201
|
+
return result_Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
|
|
17202
17202
|
}
|
|
17203
17203
|
pages.push(page);
|
|
17204
17204
|
}
|
|
@@ -17216,7 +17216,7 @@ class Memory {
|
|
|
17216
17216
|
}
|
|
17217
17217
|
const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
|
|
17218
17218
|
if (pagesResult.isError) {
|
|
17219
|
-
return result_Result.error(pagesResult.error);
|
|
17219
|
+
return result_Result.error(pagesResult.error, pagesResult.details);
|
|
17220
17220
|
}
|
|
17221
17221
|
const pages = pagesResult.ok;
|
|
17222
17222
|
let currentPosition = startAddress;
|
|
@@ -19155,7 +19155,7 @@ class ProgramDecoder {
|
|
|
19155
19155
|
}
|
|
19156
19156
|
catch (e) {
|
|
19157
19157
|
program_decoder_logger.error `Invalid program: ${e}`;
|
|
19158
|
-
return result_Result.error(ProgramDecoderError.InvalidProgramError);
|
|
19158
|
+
return result_Result.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
|
|
19159
19159
|
}
|
|
19160
19160
|
}
|
|
19161
19161
|
}
|
|
@@ -19898,10 +19898,10 @@ class AccumulateExternalities {
|
|
|
19898
19898
|
const len = existingPreimage.slots.length;
|
|
19899
19899
|
// https://graypaper.fluffylabs.dev/#/9a08063/380901380901?v=0.6.6
|
|
19900
19900
|
if (len === PreimageStatusKind.Requested) {
|
|
19901
|
-
return result_Result.error(RequestPreimageError.AlreadyRequested);
|
|
19901
|
+
return result_Result.error(RequestPreimageError.AlreadyRequested, () => `Preimage already requested: hash=${hash}`);
|
|
19902
19902
|
}
|
|
19903
19903
|
if (len === PreimageStatusKind.Available || len === PreimageStatusKind.Reavailable) {
|
|
19904
|
-
return result_Result.error(RequestPreimageError.AlreadyAvailable);
|
|
19904
|
+
return result_Result.error(RequestPreimageError.AlreadyAvailable, () => `Preimage already available: hash=${hash}`);
|
|
19905
19905
|
}
|
|
19906
19906
|
// TODO [ToDr] Not sure if we should update the service info in that case,
|
|
19907
19907
|
// but for now we let that case fall-through.
|
|
@@ -19942,7 +19942,7 @@ class AccumulateExternalities {
|
|
|
19942
19942
|
const serviceId = this.currentServiceId;
|
|
19943
19943
|
const status = this.updatedState.getLookupHistory(this.currentTimeslot, this.currentServiceId, hash, length);
|
|
19944
19944
|
if (status === null) {
|
|
19945
|
-
return result_Result.error(ForgetPreimageError.NotFound);
|
|
19945
|
+
return result_Result.error(ForgetPreimageError.NotFound, () => `Preimage not found: hash=${hash}, length=${length}`);
|
|
19946
19946
|
}
|
|
19947
19947
|
const s = slotsToPreimageStatus(status.slots);
|
|
19948
19948
|
const updateStorageUtilisation = () => {
|
|
@@ -19955,7 +19955,7 @@ class AccumulateExternalities {
|
|
|
19955
19955
|
if (s.status === PreimageStatusKind.Requested) {
|
|
19956
19956
|
const res = updateStorageUtilisation();
|
|
19957
19957
|
if (res.isError) {
|
|
19958
|
-
return result_Result.error(ForgetPreimageError.StorageUtilisationError);
|
|
19958
|
+
return result_Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
|
|
19959
19959
|
}
|
|
19960
19960
|
this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
|
|
19961
19961
|
hash: status.hash,
|
|
@@ -19970,7 +19970,7 @@ class AccumulateExternalities {
|
|
|
19970
19970
|
if (y < t - this.chainSpec.preimageExpungePeriod) {
|
|
19971
19971
|
const res = updateStorageUtilisation();
|
|
19972
19972
|
if (res.isError) {
|
|
19973
|
-
return result_Result.error(ForgetPreimageError.StorageUtilisationError);
|
|
19973
|
+
return result_Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
|
|
19974
19974
|
}
|
|
19975
19975
|
this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
|
|
19976
19976
|
hash: status.hash,
|
|
@@ -19978,7 +19978,7 @@ class AccumulateExternalities {
|
|
|
19978
19978
|
}));
|
|
19979
19979
|
return result_Result.ok(result_OK);
|
|
19980
19980
|
}
|
|
19981
|
-
return result_Result.error(ForgetPreimageError.NotExpired);
|
|
19981
|
+
return result_Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
|
|
19982
19982
|
}
|
|
19983
19983
|
// https://graypaper.fluffylabs.dev/#/9a08063/38c80138c801?v=0.6.6
|
|
19984
19984
|
if (s.status === PreimageStatusKind.Available) {
|
|
@@ -19996,7 +19996,7 @@ class AccumulateExternalities {
|
|
|
19996
19996
|
}));
|
|
19997
19997
|
return result_Result.ok(result_OK);
|
|
19998
19998
|
}
|
|
19999
|
-
return result_Result.error(ForgetPreimageError.NotExpired);
|
|
19999
|
+
return result_Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
|
|
20000
20000
|
}
|
|
20001
20001
|
debug_assertNever(s);
|
|
20002
20002
|
}
|
|
@@ -20005,17 +20005,17 @@ class AccumulateExternalities {
|
|
|
20005
20005
|
const destination = this.getServiceInfo(destinationId);
|
|
20006
20006
|
/** https://graypaper.fluffylabs.dev/#/9a08063/370401370401?v=0.6.6 */
|
|
20007
20007
|
if (destination === null || destinationId === null) {
|
|
20008
|
-
return result_Result.error(TransferError.DestinationNotFound);
|
|
20008
|
+
return result_Result.error(TransferError.DestinationNotFound, () => `Destination service not found: ${destinationId}`);
|
|
20009
20009
|
}
|
|
20010
20010
|
/** https://graypaper.fluffylabs.dev/#/9a08063/371301371301?v=0.6.6 */
|
|
20011
20011
|
if (gas < destination.onTransferMinGas) {
|
|
20012
|
-
return result_Result.error(TransferError.GasTooLow);
|
|
20012
|
+
return result_Result.error(TransferError.GasTooLow, () => `Gas ${gas} below minimum ${destination.onTransferMinGas}`);
|
|
20013
20013
|
}
|
|
20014
20014
|
/** https://graypaper.fluffylabs.dev/#/9a08063/371b01371b01?v=0.6.6 */
|
|
20015
20015
|
const newBalance = source.balance - amount;
|
|
20016
20016
|
const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(source.storageUtilisationCount, source.storageUtilisationBytes, source.gratisStorage);
|
|
20017
20017
|
if (newBalance < thresholdBalance) {
|
|
20018
|
-
return result_Result.error(TransferError.BalanceBelowThreshold);
|
|
20018
|
+
return result_Result.error(TransferError.BalanceBelowThreshold, () => `Balance ${newBalance} below threshold ${thresholdBalance}`);
|
|
20019
20019
|
}
|
|
20020
20020
|
// outgoing transfer
|
|
20021
20021
|
this.updatedState.stateUpdate.transfers.push(PendingTransfer.create({
|
|
@@ -20042,7 +20042,7 @@ class AccumulateExternalities {
|
|
|
20042
20042
|
// check if we are priviledged to set gratis storage
|
|
20043
20043
|
// https://graypaper.fluffylabs.dev/#/7e6ff6a/369203369603?v=0.6.7
|
|
20044
20044
|
if (gratisStorage !== numbers_tryAsU64(0) && this.currentServiceId !== this.updatedState.getPrivilegedServices().manager) {
|
|
20045
|
-
return result_Result.error(NewServiceError.UnprivilegedService);
|
|
20045
|
+
return result_Result.error(NewServiceError.UnprivilegedService, () => `Service ${this.currentServiceId} not privileged to set gratis storage`);
|
|
20046
20046
|
}
|
|
20047
20047
|
// check if we have enough balance
|
|
20048
20048
|
// https://graypaper.fluffylabs.dev/#/7e6ff6a/369e0336a303?v=0.6.7
|
|
@@ -20051,7 +20051,7 @@ class AccumulateExternalities {
|
|
|
20051
20051
|
const thresholdForCurrent = ServiceAccountInfo.calculateThresholdBalance(currentService.storageUtilisationCount, currentService.storageUtilisationBytes, currentService.gratisStorage);
|
|
20052
20052
|
const balanceLeftForCurrent = currentService.balance - thresholdForNew;
|
|
20053
20053
|
if (balanceLeftForCurrent < thresholdForCurrent || bytes.overflow) {
|
|
20054
|
-
return result_Result.error(NewServiceError.InsufficientFunds);
|
|
20054
|
+
return result_Result.error(NewServiceError.InsufficientFunds, () => `Insufficient funds: balance=${currentService.balance}, required=${thresholdForNew}, overflow=${bytes.overflow}`);
|
|
20055
20055
|
}
|
|
20056
20056
|
// `a`: https://graypaper.fluffylabs.dev/#/ab2cdbd/366b02366d02?v=0.7.2
|
|
20057
20057
|
const newAccount = ServiceAccountInfo.create({
|
|
@@ -20078,7 +20078,7 @@ class AccumulateExternalities {
|
|
|
20078
20078
|
// NOTE: It's safe to cast to `Number` here, bcs here service ID cannot be bigger than 2**16
|
|
20079
20079
|
const newServiceId = tryAsServiceId(Number(wantedServiceId));
|
|
20080
20080
|
if (this.getServiceInfo(newServiceId) !== null) {
|
|
20081
|
-
return result_Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken);
|
|
20081
|
+
return result_Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken, () => `Service ID ${newServiceId} already taken`);
|
|
20082
20082
|
}
|
|
20083
20083
|
// add the new service with selected ID
|
|
20084
20084
|
// https://graypaper.fluffylabs.dev/#/ab2cdbd/36be0336c003?v=0.7.2
|
|
@@ -20118,7 +20118,7 @@ class AccumulateExternalities {
|
|
|
20118
20118
|
const currentDelegator = this.updatedState.getPrivilegedServices().delegator;
|
|
20119
20119
|
if (currentDelegator !== this.currentServiceId) {
|
|
20120
20120
|
accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not a validators manager. (expected: ${currentDelegator}) and cannot update validators data. Ignoring`;
|
|
20121
|
-
return result_Result.error(UnprivilegedError);
|
|
20121
|
+
return result_Result.error(UnprivilegedError, () => `Service ${this.currentServiceId} is not delegator (expected: ${currentDelegator})`);
|
|
20122
20122
|
}
|
|
20123
20123
|
this.updatedState.stateUpdate.validatorsData = validatorsData;
|
|
20124
20124
|
return result_Result.ok(result_OK);
|
|
@@ -20133,11 +20133,11 @@ class AccumulateExternalities {
|
|
|
20133
20133
|
const currentAssigners = this.updatedState.getPrivilegedServices().assigners[coreIndex];
|
|
20134
20134
|
if (currentAssigners !== this.currentServiceId) {
|
|
20135
20135
|
accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not an auth manager of core ${coreIndex} (expected: ${currentAssigners}) and cannot update authorization queue.`;
|
|
20136
|
-
return result_Result.error(UpdatePrivilegesError.UnprivilegedService);
|
|
20136
|
+
return result_Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} not assigner for core ${coreIndex} (expected: ${currentAssigners})`);
|
|
20137
20137
|
}
|
|
20138
20138
|
if (assigners === null && Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)) {
|
|
20139
20139
|
accumulate_externalities_logger.trace `The new auth manager is not a valid service id.`;
|
|
20140
|
-
return result_Result.error(UpdatePrivilegesError.InvalidServiceId);
|
|
20140
|
+
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => `New auth manager is null for core ${coreIndex}`);
|
|
20141
20141
|
}
|
|
20142
20142
|
this.updatedState.stateUpdate.authorizationQueues.set(coreIndex, authQueue);
|
|
20143
20143
|
return result_Result.ok(result_OK);
|
|
@@ -20170,10 +20170,10 @@ class AccumulateExternalities {
|
|
|
20170
20170
|
const isManager = current.manager === this.currentServiceId;
|
|
20171
20171
|
if (Compatibility.isLessThan(GpVersion.V0_7_1)) {
|
|
20172
20172
|
if (!isManager) {
|
|
20173
|
-
return result_Result.error(UpdatePrivilegesError.UnprivilegedService);
|
|
20173
|
+
return result_Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} is not manager`);
|
|
20174
20174
|
}
|
|
20175
20175
|
if (manager === null || delegator === null) {
|
|
20176
|
-
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, "Either manager or delegator is not a valid service id.");
|
|
20176
|
+
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator is not a valid service id.");
|
|
20177
20177
|
}
|
|
20178
20178
|
this.updatedState.stateUpdate.privilegedServices = PrivilegedServices.create({
|
|
20179
20179
|
manager,
|
|
@@ -20186,7 +20186,7 @@ class AccumulateExternalities {
|
|
|
20186
20186
|
}
|
|
20187
20187
|
const original = this.updatedState.state.privilegedServices;
|
|
20188
20188
|
if (manager === null || delegator === null || registrar === null) {
|
|
20189
|
-
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, "Either manager or delegator or registrar is not a valid service id.");
|
|
20189
|
+
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator or registrar is not a valid service id.");
|
|
20190
20190
|
}
|
|
20191
20191
|
const newDelegator = this.updatePrivilegedServiceId(delegator, current.delegator, {
|
|
20192
20192
|
isManager,
|
|
@@ -20226,19 +20226,19 @@ class AccumulateExternalities {
|
|
|
20226
20226
|
// TODO [ToDr] what about newly created services?
|
|
20227
20227
|
const service = serviceId === null ? null : this.updatedState.state.getService(serviceId);
|
|
20228
20228
|
if (service === null || serviceId === null) {
|
|
20229
|
-
return result_Result.error(ProvidePreimageError.ServiceNotFound);
|
|
20229
|
+
return result_Result.error(ProvidePreimageError.ServiceNotFound, () => `Service not found: ${serviceId}`);
|
|
20230
20230
|
}
|
|
20231
20231
|
// calculating the hash
|
|
20232
20232
|
const preimageHash = this.blake2b.hashBytes(preimage).asOpaque();
|
|
20233
20233
|
// checking service internal lookup
|
|
20234
20234
|
const stateLookup = this.updatedState.getLookupHistory(this.currentTimeslot, serviceId, preimageHash, numbers_tryAsU64(preimage.length));
|
|
20235
20235
|
if (stateLookup === null || !LookupHistoryItem.isRequested(stateLookup)) {
|
|
20236
|
-
return result_Result.error(ProvidePreimageError.WasNotRequested);
|
|
20236
|
+
return result_Result.error(ProvidePreimageError.WasNotRequested, () => `Preimage was not requested: hash=${preimageHash}, service=${serviceId}`);
|
|
20237
20237
|
}
|
|
20238
20238
|
// checking already provided preimages
|
|
20239
20239
|
const hasPreimage = this.updatedState.hasPreimage(serviceId, preimageHash);
|
|
20240
20240
|
if (hasPreimage) {
|
|
20241
|
-
return result_Result.error(ProvidePreimageError.AlreadyProvided);
|
|
20241
|
+
return result_Result.error(ProvidePreimageError.AlreadyProvided, () => `Preimage already provided: hash=${preimageHash}, service=${serviceId}`);
|
|
20242
20242
|
}
|
|
20243
20243
|
// setting up the new preimage
|
|
20244
20244
|
this.updatedState.updatePreimage(serviceId, UpdatePreimage.provide({
|
|
@@ -20253,31 +20253,31 @@ class AccumulateExternalities {
|
|
|
20253
20253
|
eject(destination, previousCodeHash) {
|
|
20254
20254
|
const service = this.getServiceInfo(destination);
|
|
20255
20255
|
if (service === null || destination === null) {
|
|
20256
|
-
return result_Result.error(EjectError.InvalidService, "Service missing");
|
|
20256
|
+
return result_Result.error(EjectError.InvalidService, () => "Service missing");
|
|
20257
20257
|
}
|
|
20258
20258
|
const currentService = this.getCurrentServiceInfo();
|
|
20259
20259
|
// check if the service expects to be ejected by us:
|
|
20260
20260
|
const expectedCodeHash = bytes_Bytes.zero(hash_HASH_SIZE).asOpaque();
|
|
20261
20261
|
writeServiceIdAsLeBytes(this.currentServiceId, expectedCodeHash.raw);
|
|
20262
20262
|
if (!service.codeHash.isEqualTo(expectedCodeHash)) {
|
|
20263
|
-
return result_Result.error(EjectError.InvalidService, "Invalid code hash");
|
|
20263
|
+
return result_Result.error(EjectError.InvalidService, () => "Invalid code hash");
|
|
20264
20264
|
}
|
|
20265
20265
|
// make sure the service only has required number of storage items?
|
|
20266
20266
|
if (service.storageUtilisationCount !== REQUIRED_NUMBER_OF_STORAGE_ITEMS_FOR_EJECT) {
|
|
20267
|
-
return result_Result.error(EjectError.InvalidPreimage, "Too many storage items");
|
|
20267
|
+
return result_Result.error(EjectError.InvalidPreimage, () => "Too many storage items");
|
|
20268
20268
|
}
|
|
20269
20269
|
// storage items length
|
|
20270
20270
|
const l = numbers_tryAsU64(maxU64(service.storageUtilisationBytes, LOOKUP_HISTORY_ENTRY_BYTES) - LOOKUP_HISTORY_ENTRY_BYTES);
|
|
20271
20271
|
// check if we have a preimage with the entire storage.
|
|
20272
20272
|
const [isPreviousCodeExpired, errorReason] = this.isPreviousCodeExpired(destination, previousCodeHash, l);
|
|
20273
20273
|
if (!isPreviousCodeExpired) {
|
|
20274
|
-
return result_Result.error(EjectError.InvalidPreimage, `Previous code available: ${errorReason}`);
|
|
20274
|
+
return result_Result.error(EjectError.InvalidPreimage, () => `Previous code available: ${errorReason}`);
|
|
20275
20275
|
}
|
|
20276
20276
|
// compute new balance of the service.
|
|
20277
20277
|
const newBalance = sumU64(currentService.balance, service.balance);
|
|
20278
20278
|
// TODO [ToDr] what to do in case of overflow?
|
|
20279
20279
|
if (newBalance.overflow) {
|
|
20280
|
-
return result_Result.error(EjectError.InvalidService, "Balance overflow");
|
|
20280
|
+
return result_Result.error(EjectError.InvalidService, () => "Balance overflow");
|
|
20281
20281
|
}
|
|
20282
20282
|
// update current service.
|
|
20283
20283
|
this.updatedState.updateServiceInfo(this.currentServiceId, ServiceAccountInfo.create({
|
|
@@ -20472,10 +20472,10 @@ class Assurances {
|
|
|
20472
20472
|
for (const assurance of assurances) {
|
|
20473
20473
|
const { anchor, validatorIndex, bitfield } = assurance;
|
|
20474
20474
|
if (!anchor.isEqualTo(input.parentHash)) {
|
|
20475
|
-
return result_Result.error(AssurancesError.InvalidAnchor, `anchor: expected: ${input.parentHash}, got ${anchor}`);
|
|
20475
|
+
return result_Result.error(AssurancesError.InvalidAnchor, () => `anchor: expected: ${input.parentHash}, got ${anchor}`);
|
|
20476
20476
|
}
|
|
20477
20477
|
if (prevValidatorIndex >= validatorIndex) {
|
|
20478
|
-
return result_Result.error(AssurancesError.InvalidOrder, `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
|
|
20478
|
+
return result_Result.error(AssurancesError.InvalidOrder, () => `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
|
|
20479
20479
|
}
|
|
20480
20480
|
prevValidatorIndex = assurance.validatorIndex;
|
|
20481
20481
|
debug_check `${bitfield.bitLength === coresCount} Invalid bitfield length of ${bitfield.bitLength}`;
|
|
@@ -20498,7 +20498,7 @@ class Assurances {
|
|
|
20498
20498
|
* https://graypaper.fluffylabs.dev/#/579bd12/14e90014ea00
|
|
20499
20499
|
*/
|
|
20500
20500
|
if (noOfAssurances > 0 && !isReportPending) {
|
|
20501
|
-
return result_Result.error(AssurancesError.NoReportPending, `no report pending for core ${c} yet we got an assurance`);
|
|
20501
|
+
return result_Result.error(AssurancesError.NoReportPending, () => `no report pending for core ${c} yet we got an assurance`);
|
|
20502
20502
|
}
|
|
20503
20503
|
/**
|
|
20504
20504
|
* Remove work report if it's became available or timed out.
|
|
@@ -20544,7 +20544,7 @@ class Assurances {
|
|
|
20544
20544
|
const v = assurance.view();
|
|
20545
20545
|
const key = validatorData[v.validatorIndex.materialize()];
|
|
20546
20546
|
if (key === undefined) {
|
|
20547
|
-
return result_Result.error(AssurancesError.InvalidValidatorIndex);
|
|
20547
|
+
return result_Result.error(AssurancesError.InvalidValidatorIndex, () => `Invalid validator index: ${v.validatorIndex.materialize()}`);
|
|
20548
20548
|
}
|
|
20549
20549
|
signatures.push({
|
|
20550
20550
|
signature: v.signature.materialize(),
|
|
@@ -20556,7 +20556,7 @@ class Assurances {
|
|
|
20556
20556
|
const isAllSignaturesValid = signaturesValid.every((x) => x);
|
|
20557
20557
|
if (!isAllSignaturesValid) {
|
|
20558
20558
|
const invalidIndices = signaturesValid.reduce((acc, isValid, idx) => (isValid ? acc : acc.concat(idx)), []);
|
|
20559
|
-
return result_Result.error(AssurancesError.InvalidSignature, `invalid signatures at ${invalidIndices.join(", ")}`);
|
|
20559
|
+
return result_Result.error(AssurancesError.InvalidSignature, () => `invalid signatures at ${invalidIndices.join(", ")}`);
|
|
20560
20560
|
}
|
|
20561
20561
|
return result_Result.ok(result_OK);
|
|
20562
20562
|
}
|
|
@@ -21167,7 +21167,7 @@ class HostCallMemory {
|
|
|
21167
21167
|
return result_Result.ok(result_OK);
|
|
21168
21168
|
}
|
|
21169
21169
|
if (address + numbers_tryAsU64(bytes.length) > MEMORY_SIZE) {
|
|
21170
|
-
return result_Result.error(new OutOfBounds());
|
|
21170
|
+
return result_Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`);
|
|
21171
21171
|
}
|
|
21172
21172
|
return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
|
|
21173
21173
|
}
|
|
@@ -21176,7 +21176,7 @@ class HostCallMemory {
|
|
|
21176
21176
|
return result_Result.ok(result_OK);
|
|
21177
21177
|
}
|
|
21178
21178
|
if (startAddress + numbers_tryAsU64(result.length) > MEMORY_SIZE) {
|
|
21179
|
-
return result_Result.error(new OutOfBounds());
|
|
21179
|
+
return result_Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`);
|
|
21180
21180
|
}
|
|
21181
21181
|
return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
|
|
21182
21182
|
}
|
|
@@ -23119,18 +23119,18 @@ class Accumulate {
|
|
|
23119
23119
|
const serviceInfo = updatedState.getServiceInfo(serviceId);
|
|
23120
23120
|
if (serviceInfo === null) {
|
|
23121
23121
|
accumulate_logger.log `Service with id ${serviceId} not found.`;
|
|
23122
|
-
return result_Result.error(PvmInvocationError.NoService);
|
|
23122
|
+
return result_Result.error(PvmInvocationError.NoService, () => `Accumulate: service ${serviceId} not found`);
|
|
23123
23123
|
}
|
|
23124
23124
|
const codeHash = serviceInfo.codeHash;
|
|
23125
23125
|
// TODO [ToDr] Should we check that the preimage is still available?
|
|
23126
23126
|
const code = updatedState.getPreimage(serviceId, codeHash.asOpaque());
|
|
23127
23127
|
if (code === null) {
|
|
23128
23128
|
accumulate_logger.log `Code with hash ${codeHash} not found for service ${serviceId}.`;
|
|
23129
|
-
return result_Result.error(PvmInvocationError.NoPreimage);
|
|
23129
|
+
return result_Result.error(PvmInvocationError.NoPreimage, () => `Accumulate: code with hash ${codeHash} not found for service ${serviceId}`);
|
|
23130
23130
|
}
|
|
23131
23131
|
if (code.length > W_C) {
|
|
23132
23132
|
accumulate_logger.log `Code with hash ${codeHash} is too long for service ${serviceId}.`;
|
|
23133
|
-
return result_Result.error(PvmInvocationError.PreimageTooLong);
|
|
23133
|
+
return result_Result.error(PvmInvocationError.PreimageTooLong, () => `Accumulate: code length ${code.length} exceeds max ${W_C} for service ${serviceId}`);
|
|
23134
23134
|
}
|
|
23135
23135
|
const nextServiceId = generateNextServiceId({ serviceId, entropy, timeslot: slot }, this.chainSpec, this.blake2b);
|
|
23136
23136
|
const partialState = new AccumulateExternalities(this.chainSpec, this.blake2b, updatedState, serviceId, nextServiceId, slot);
|
|
@@ -23418,7 +23418,7 @@ class Accumulate {
|
|
|
23418
23418
|
assertEmpty(stateUpdateRest);
|
|
23419
23419
|
if (this.hasDuplicatedServiceIdCreated(services.created)) {
|
|
23420
23420
|
accumulate_logger.trace `Duplicated Service creation detected. Block is invalid.`;
|
|
23421
|
-
return result_Result.error(ACCUMULATION_ERROR);
|
|
23421
|
+
return result_Result.error(ACCUMULATION_ERROR, () => "Accumulate: duplicate service created");
|
|
23422
23422
|
}
|
|
23423
23423
|
const accStateUpdate = this.getAccumulationStateUpdate(accumulated.toArray(), toAccumulateLater, slot, Array.from(statistics.keys()), services);
|
|
23424
23424
|
const accumulationOutputUnsorted = Array.from(yieldedRoots.entries()).map(([serviceId, root]) => {
|
|
@@ -23499,13 +23499,13 @@ class DeferredTransfers {
|
|
|
23499
23499
|
.toSorted((a, b) => a.source - b.source);
|
|
23500
23500
|
const info = partiallyUpdatedState.getServiceInfo(serviceId);
|
|
23501
23501
|
if (info === null) {
|
|
23502
|
-
return result_Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist);
|
|
23502
|
+
return result_Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist, () => `Deferred transfers: service info not found for ${serviceId}`);
|
|
23503
23503
|
}
|
|
23504
23504
|
const codeHash = info.codeHash;
|
|
23505
23505
|
const code = partiallyUpdatedState.getPreimage(serviceId, codeHash.asOpaque());
|
|
23506
23506
|
const newBalance = sumU64(info.balance, ...transfers.map((item) => item.amount));
|
|
23507
23507
|
if (newBalance.overflow) {
|
|
23508
|
-
return result_Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow);
|
|
23508
|
+
return result_Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow, () => `Deferred transfers: balance overflow for service ${serviceId}`);
|
|
23509
23509
|
}
|
|
23510
23510
|
const newInfo = ServiceAccountInfo.create({ ...info, balance: newBalance.value });
|
|
23511
23511
|
partiallyUpdatedState.updateServiceInfo(serviceId, newInfo);
|
|
@@ -23983,7 +23983,7 @@ function verifyReportsBasic(input) {
|
|
|
23983
23983
|
const noOfPrerequisites = reportView.context.view().prerequisites.view().length;
|
|
23984
23984
|
const noOfSegmentRootLookups = reportView.segmentRootLookup.view().length;
|
|
23985
23985
|
if (noOfPrerequisites + noOfSegmentRootLookups > MAX_REPORT_DEPENDENCIES) {
|
|
23986
|
-
return result_Result.error(ReportsError.TooManyDependencies, `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
|
|
23986
|
+
return result_Result.error(ReportsError.TooManyDependencies, () => `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
|
|
23987
23987
|
}
|
|
23988
23988
|
/**
|
|
23989
23989
|
* In order to ensure fair use of a block’s extrinsic space,
|
|
@@ -24002,7 +24002,7 @@ function verifyReportsBasic(input) {
|
|
|
24002
24002
|
totalOutputsSize += item.view().result.view().okBlob?.raw.length ?? 0;
|
|
24003
24003
|
}
|
|
24004
24004
|
if (authOutputSize + totalOutputsSize > MAX_WORK_REPORT_SIZE_BYTES) {
|
|
24005
|
-
return result_Result.error(ReportsError.WorkReportTooBig, `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
|
|
24005
|
+
return result_Result.error(ReportsError.WorkReportTooBig, () => `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
|
|
24006
24006
|
}
|
|
24007
24007
|
}
|
|
24008
24008
|
return result_Result.ok(result_OK);
|
|
@@ -24036,12 +24036,12 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
|
|
|
24036
24036
|
for (const result of guarantee.report.results) {
|
|
24037
24037
|
const service = state.getService(result.serviceId);
|
|
24038
24038
|
if (service === null) {
|
|
24039
|
-
return result_Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
|
|
24039
|
+
return result_Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
|
|
24040
24040
|
}
|
|
24041
24041
|
// check service code hash
|
|
24042
24042
|
// https://graypaper.fluffylabs.dev/#/5f542d7/154b02154b02
|
|
24043
24043
|
if (!result.codeHash.isEqualTo(service.getInfo().codeHash)) {
|
|
24044
|
-
return result_Result.error(ReportsError.BadCodeHash, `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
|
|
24044
|
+
return result_Result.error(ReportsError.BadCodeHash, () => `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
|
|
24045
24045
|
}
|
|
24046
24046
|
}
|
|
24047
24047
|
}
|
|
@@ -24052,7 +24052,7 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
|
|
|
24052
24052
|
* https://graypaper.fluffylabs.dev/#/5f542d7/151f01152101
|
|
24053
24053
|
*/
|
|
24054
24054
|
if (currentWorkPackages.size !== input.guarantees.length) {
|
|
24055
|
-
return result_Result.error(ReportsError.DuplicatePackage, "Duplicate work package detected.");
|
|
24055
|
+
return result_Result.error(ReportsError.DuplicatePackage, () => "Duplicate work package detected.");
|
|
24056
24056
|
}
|
|
24057
24057
|
const minLookupSlot = Math.max(0, input.slot - maxLookupAnchorAge);
|
|
24058
24058
|
const contextResult = verifyRefineContexts(minLookupSlot, contexts, input.recentBlocksPartialUpdate, headerChain);
|
|
@@ -24097,7 +24097,7 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
|
|
|
24097
24097
|
: undefined;
|
|
24098
24098
|
}
|
|
24099
24099
|
if (root === undefined || !root.segmentTreeRoot.isEqualTo(lookup.segmentTreeRoot)) {
|
|
24100
|
-
return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
|
|
24100
|
+
return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
|
|
24101
24101
|
}
|
|
24102
24102
|
}
|
|
24103
24103
|
}
|
|
@@ -24120,16 +24120,16 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
|
|
|
24120
24120
|
*/
|
|
24121
24121
|
const recentBlock = recentBlocks.get(context.anchor);
|
|
24122
24122
|
if (recentBlock === undefined) {
|
|
24123
|
-
return result_Result.error(ReportsError.AnchorNotRecent, `Anchor block ${context.anchor} not found in recent blocks.`);
|
|
24123
|
+
return result_Result.error(ReportsError.AnchorNotRecent, () => `Anchor block ${context.anchor} not found in recent blocks.`);
|
|
24124
24124
|
}
|
|
24125
24125
|
// check state root
|
|
24126
24126
|
if (!recentBlock.postStateRoot.isEqualTo(context.stateRoot)) {
|
|
24127
|
-
return result_Result.error(ReportsError.BadStateRoot, `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
|
|
24127
|
+
return result_Result.error(ReportsError.BadStateRoot, () => `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
|
|
24128
24128
|
}
|
|
24129
24129
|
// check beefy root
|
|
24130
24130
|
const beefyRoot = recentBlock.accumulationResult;
|
|
24131
24131
|
if (!beefyRoot.isEqualTo(context.beefyRoot)) {
|
|
24132
|
-
return result_Result.error(ReportsError.BadBeefyMmrRoot, `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
|
|
24132
|
+
return result_Result.error(ReportsError.BadBeefyMmrRoot, () => `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
|
|
24133
24133
|
}
|
|
24134
24134
|
/**
|
|
24135
24135
|
* We require that each lookup-anchor block be within the
|
|
@@ -24138,7 +24138,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
|
|
|
24138
24138
|
* https://graypaper.fluffylabs.dev/#/5f542d7/154601154701
|
|
24139
24139
|
*/
|
|
24140
24140
|
if (context.lookupAnchorSlot < minLookupSlot) {
|
|
24141
|
-
return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
|
|
24141
|
+
return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
|
|
24142
24142
|
}
|
|
24143
24143
|
/**
|
|
24144
24144
|
* We also require that we have a record of it; this is one of
|
|
@@ -24155,7 +24155,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
|
|
|
24155
24155
|
verify_contextual_logger.warn `Lookup anchor check for ${context.lookupAnchor} would fail, but override is active.`;
|
|
24156
24156
|
}
|
|
24157
24157
|
else {
|
|
24158
|
-
return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
|
|
24158
|
+
return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
|
|
24159
24159
|
}
|
|
24160
24160
|
}
|
|
24161
24161
|
}
|
|
@@ -24178,7 +24178,7 @@ function verifyDependencies({ currentWorkPackages, recentlyReported, prerequisit
|
|
|
24178
24178
|
if (recentlyReported.has(preReqHash)) {
|
|
24179
24179
|
continue;
|
|
24180
24180
|
}
|
|
24181
|
-
return result_Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, `Missing work package ${preReqHash} in current extrinsic or recent history.`);
|
|
24181
|
+
return result_Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, () => `Missing work package ${preReqHash} in current extrinsic or recent history.`);
|
|
24182
24182
|
}
|
|
24183
24183
|
return result_Result.ok(result_OK);
|
|
24184
24184
|
};
|
|
@@ -24226,7 +24226,7 @@ function verifyWorkPackagesUniqueness(workPackageHashes, state) {
|
|
|
24226
24226
|
// let's check if any of our packages is in the pipeline
|
|
24227
24227
|
const intersection = packagesInPipeline.intersection(workPackageHashes);
|
|
24228
24228
|
for (const packageHash of intersection) {
|
|
24229
|
-
return result_Result.error(ReportsError.DuplicatePackage, `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
|
|
24229
|
+
return result_Result.error(ReportsError.DuplicatePackage, () => `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
|
|
24230
24230
|
}
|
|
24231
24231
|
return result_Result.ok(result_OK);
|
|
24232
24232
|
}
|
|
@@ -24265,7 +24265,7 @@ workReportHashes, slot, getGuarantorAssignment) {
|
|
|
24265
24265
|
const credentialsView = guaranteeView.credentials.view();
|
|
24266
24266
|
if (credentialsView.length < REQUIRED_CREDENTIALS_RANGE[0] ||
|
|
24267
24267
|
credentialsView.length > REQUIRED_CREDENTIALS_RANGE[1]) {
|
|
24268
|
-
return result_Result.error(ReportsError.InsufficientGuarantees, `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
|
|
24268
|
+
return result_Result.error(ReportsError.InsufficientGuarantees, () => `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
|
|
24269
24269
|
}
|
|
24270
24270
|
/** Retrieve current core assignment. */
|
|
24271
24271
|
const timeSlot = guaranteeView.slot.materialize();
|
|
@@ -24280,20 +24280,20 @@ workReportHashes, slot, getGuarantorAssignment) {
|
|
|
24280
24280
|
const credentialView = credential.view();
|
|
24281
24281
|
const validatorIndex = credentialView.validatorIndex.materialize();
|
|
24282
24282
|
if (lastValidatorIndex >= validatorIndex) {
|
|
24283
|
-
return result_Result.error(ReportsError.NotSortedOrUniqueGuarantors, `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
|
|
24283
|
+
return result_Result.error(ReportsError.NotSortedOrUniqueGuarantors, () => `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
|
|
24284
24284
|
}
|
|
24285
24285
|
lastValidatorIndex = validatorIndex;
|
|
24286
24286
|
const signature = credentialView.signature.materialize();
|
|
24287
24287
|
const guarantorData = guarantorAssignments[validatorIndex];
|
|
24288
24288
|
if (guarantorData === undefined) {
|
|
24289
|
-
return result_Result.error(ReportsError.BadValidatorIndex, `Invalid validator index: ${validatorIndex}`);
|
|
24289
|
+
return result_Result.error(ReportsError.BadValidatorIndex, () => `Invalid validator index: ${validatorIndex}`);
|
|
24290
24290
|
}
|
|
24291
24291
|
/**
|
|
24292
24292
|
* Verify core assignment.
|
|
24293
24293
|
* https://graypaper.fluffylabs.dev/#/5f542d7/14e40214e602
|
|
24294
24294
|
*/
|
|
24295
24295
|
if (guarantorData.core !== coreIndex) {
|
|
24296
|
-
return result_Result.error(ReportsError.WrongAssignment, `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
|
|
24296
|
+
return result_Result.error(ReportsError.WrongAssignment, () => `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
|
|
24297
24297
|
}
|
|
24298
24298
|
signaturesToVerify.push({
|
|
24299
24299
|
signature,
|
|
@@ -24331,10 +24331,10 @@ function verifyReportsOrder(input, chainSpec) {
|
|
|
24331
24331
|
const reportView = guarantee.view().report.view();
|
|
24332
24332
|
const coreIndex = reportView.coreIndex.materialize();
|
|
24333
24333
|
if (lastCoreIndex >= coreIndex) {
|
|
24334
|
-
return result_Result.error(ReportsError.OutOfOrderGuarantee, `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
|
|
24334
|
+
return result_Result.error(ReportsError.OutOfOrderGuarantee, () => `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
|
|
24335
24335
|
}
|
|
24336
24336
|
if (coreIndex >= noOfCores) {
|
|
24337
|
-
return result_Result.error(ReportsError.BadCoreIndex, `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
|
|
24337
|
+
return result_Result.error(ReportsError.BadCoreIndex, () => `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
|
|
24338
24338
|
}
|
|
24339
24339
|
lastCoreIndex = coreIndex;
|
|
24340
24340
|
}
|
|
@@ -24359,7 +24359,7 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
|
|
|
24359
24359
|
* https://graypaper.fluffylabs.dev/#/5f542d7/15ea0015ea00
|
|
24360
24360
|
*/
|
|
24361
24361
|
if (availabilityAssignment[coreIndex] !== null) {
|
|
24362
|
-
return result_Result.error(ReportsError.CoreEngaged, `Report pending availability at core: ${coreIndex}`);
|
|
24362
|
+
return result_Result.error(ReportsError.CoreEngaged, () => `Report pending availability at core: ${coreIndex}`);
|
|
24363
24363
|
}
|
|
24364
24364
|
/**
|
|
24365
24365
|
* A report is valid only if the authorizer hash is present
|
|
@@ -24372,7 +24372,7 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
|
|
|
24372
24372
|
const authorizerPool = authPools.get(coreIndex);
|
|
24373
24373
|
const pool = authorizerPool?.materialize() ?? [];
|
|
24374
24374
|
if (pool.find((hash) => hash.isEqualTo(authorizerHash)) === undefined) {
|
|
24375
|
-
return result_Result.error(ReportsError.CoreUnauthorized, `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
|
|
24375
|
+
return result_Result.error(ReportsError.CoreUnauthorized, () => `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
|
|
24376
24376
|
}
|
|
24377
24377
|
/**
|
|
24378
24378
|
* We require that the gas allotted for accumulation of each
|
|
@@ -24384,17 +24384,17 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
|
|
|
24384
24384
|
for (const result of report.results) {
|
|
24385
24385
|
const service = services(result.serviceId);
|
|
24386
24386
|
if (service === null) {
|
|
24387
|
-
return result_Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
|
|
24387
|
+
return result_Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
|
|
24388
24388
|
}
|
|
24389
24389
|
const info = service.getInfo();
|
|
24390
24390
|
// check minimal accumulation gas
|
|
24391
24391
|
if (result.gas < info.accumulateMinGas) {
|
|
24392
|
-
return result_Result.error(ReportsError.ServiceItemGasTooLow, `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
|
|
24392
|
+
return result_Result.error(ReportsError.ServiceItemGasTooLow, () => `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
|
|
24393
24393
|
}
|
|
24394
24394
|
}
|
|
24395
24395
|
const totalGas = sumU64(...report.results.map((x) => x.gas));
|
|
24396
24396
|
if (totalGas.overflow || totalGas.value > G_A) {
|
|
24397
|
-
return result_Result.error(ReportsError.WorkReportGasTooHigh, `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
|
|
24397
|
+
return result_Result.error(ReportsError.WorkReportGasTooHigh, () => `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
|
|
24398
24398
|
}
|
|
24399
24399
|
}
|
|
24400
24400
|
return result_Result.ok(result_OK);
|
|
@@ -24480,7 +24480,7 @@ class Reports {
|
|
|
24480
24480
|
}
|
|
24481
24481
|
const reporters = SortedSet.fromArray(bytesBlobComparator, signaturesToVerify.ok.map((x) => x.key)).slice();
|
|
24482
24482
|
if (hasAnyOffenders(reporters, input.offenders)) {
|
|
24483
|
-
return result_Result.error(ReportsError.BannedValidator);
|
|
24483
|
+
return result_Result.error(ReportsError.BannedValidator, () => "One or more reporters are banned validators");
|
|
24484
24484
|
}
|
|
24485
24485
|
return result_Result.ok({
|
|
24486
24486
|
stateUpdate: {
|
|
@@ -24520,7 +24520,7 @@ class Reports {
|
|
|
24520
24520
|
return signaturesToVerify[idx].key;
|
|
24521
24521
|
})
|
|
24522
24522
|
.filter((x) => x !== null);
|
|
24523
|
-
return result_Result.error(ReportsError.BadSignature, `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
|
|
24523
|
+
return result_Result.error(ReportsError.BadSignature, () => `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
|
|
24524
24524
|
}
|
|
24525
24525
|
/**
|
|
24526
24526
|
* Get the guarantor assignment (both core and validator data)
|
|
@@ -24536,10 +24536,10 @@ class Reports {
|
|
|
24536
24536
|
const minTimeSlot = Math.max(0, headerRotation - 1) * rotationPeriod;
|
|
24537
24537
|
// https://graypaper.fluffylabs.dev/#/5f542d7/155e00156900
|
|
24538
24538
|
if (guaranteeTimeSlot > headerTimeSlot) {
|
|
24539
|
-
return result_Result.error(ReportsError.FutureReportSlot, `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24539
|
+
return result_Result.error(ReportsError.FutureReportSlot, () => `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24540
24540
|
}
|
|
24541
24541
|
if (guaranteeTimeSlot < minTimeSlot) {
|
|
24542
|
-
return result_Result.error(ReportsError.ReportEpochBeforeLast, `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24542
|
+
return result_Result.error(ReportsError.ReportEpochBeforeLast, () => `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24543
24543
|
}
|
|
24544
24544
|
// TODO [ToDr] [opti] below code needs cache.
|
|
24545
24545
|
// The `G` and `G*` sets should only be computed once per rotation.
|
|
@@ -25155,11 +25155,11 @@ class OnChain {
|
|
|
25155
25155
|
}
|
|
25156
25156
|
function checkOffendersMatch(offendersMark, headerOffendersMark) {
|
|
25157
25157
|
if (offendersMark.size !== headerOffendersMark.length) {
|
|
25158
|
-
return result_Result.error(OFFENDERS_ERROR, `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
|
|
25158
|
+
return result_Result.error(OFFENDERS_ERROR, () => `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
|
|
25159
25159
|
}
|
|
25160
25160
|
for (const key of headerOffendersMark) {
|
|
25161
25161
|
if (!offendersMark.has(key)) {
|
|
25162
|
-
return result_Result.error(OFFENDERS_ERROR, `Missing key: ${key}`);
|
|
25162
|
+
return result_Result.error(OFFENDERS_ERROR, () => `Missing key: ${key}`);
|
|
25163
25163
|
}
|
|
25164
25164
|
}
|
|
25165
25165
|
return result_Result.ok(result_OK);
|
|
@@ -25241,7 +25241,7 @@ class Importer {
|
|
|
25241
25241
|
if (!this.currentHash.isEqualTo(parentHash)) {
|
|
25242
25242
|
const state = this.states.getState(parentHash);
|
|
25243
25243
|
if (state === null) {
|
|
25244
|
-
const e = result_Result.error(BlockVerifierError.StateRootNotFound);
|
|
25244
|
+
const e = result_Result.error(BlockVerifierError.StateRootNotFound, () => `State not found for parent block ${parentHash}`);
|
|
25245
25245
|
if (!e.isError) {
|
|
25246
25246
|
throw new Error("unreachable, just adding to make compiler happy");
|
|
25247
25247
|
}
|
|
@@ -25437,7 +25437,7 @@ const importBlockResultCodec = descriptors_codec.custom({
|
|
|
25437
25437
|
}
|
|
25438
25438
|
if (kind === 1) {
|
|
25439
25439
|
const error = d.bytesBlob();
|
|
25440
|
-
return result_Result.error(error.asText());
|
|
25440
|
+
return result_Result.error(error.asText(), () => error.asText());
|
|
25441
25441
|
}
|
|
25442
25442
|
throw new Error(`Invalid Result: ${kind}`);
|
|
25443
25443
|
}, (s) => {
|
|
@@ -25488,7 +25488,7 @@ class MainReady extends State {
|
|
|
25488
25488
|
if (res instanceof Uint8Array) {
|
|
25489
25489
|
return decoder_Decoder.decodeObject(importBlockResultCodec, res);
|
|
25490
25490
|
}
|
|
25491
|
-
return result_Result.error("Invalid worker response.");
|
|
25491
|
+
return result_Result.error("Invalid worker response.", () => "Invalid worker response: expected Uint8Array");
|
|
25492
25492
|
}
|
|
25493
25493
|
async getStateEntries(port, hash) {
|
|
25494
25494
|
const res = await port.sendRequest("getStateEntries", hash, [hash.buffer]);
|
|
@@ -25600,13 +25600,13 @@ class ImporterReady extends State {
|
|
|
25600
25600
|
response = result_Result.ok(this.importer.getBestStateRootHash() ?? ZERO_HASH.asOpaque());
|
|
25601
25601
|
}
|
|
25602
25602
|
else {
|
|
25603
|
-
response = result_Result.error(resultToString(res));
|
|
25603
|
+
response = result_Result.error(resultToString(res), () => resultToString(res));
|
|
25604
25604
|
}
|
|
25605
25605
|
}
|
|
25606
25606
|
catch (e) {
|
|
25607
25607
|
state_machine_logger.error `Failed to import block: ${e}`;
|
|
25608
25608
|
state_machine_logger.error `${e instanceof Error ? e.stack : ""}`;
|
|
25609
|
-
response = result_Result.error(`${e}`);
|
|
25609
|
+
response = result_Result.error(`${e}`, () => `${e}`);
|
|
25610
25610
|
}
|
|
25611
25611
|
const encoded = encoder_Encoder.encodeObject(importBlockResultCodec, response);
|
|
25612
25612
|
return {
|