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