@typeberry/jam 0.1.3-ca63b35 → 0.2.0-0a3dfd4
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 +1245 -1029
- package/bootstrap-generator.mjs.map +1 -1
- package/bootstrap-importer.mjs +1613 -1271
- package/bootstrap-importer.mjs.map +1 -1
- package/bootstrap-network.mjs +1182 -967
- package/bootstrap-network.mjs.map +1 -1
- package/index.js +1694 -1276
- package/index.js.map +1 -1
- package/package.json +1 -1
package/bootstrap-importer.mjs
CHANGED
|
@@ -2753,7 +2753,7 @@ module.exports = __nccwpck_require__.p + "e2fdc1b646378dd96eda.js?ed25519_wasm_b
|
|
|
2753
2753
|
|
|
2754
2754
|
/***/ }),
|
|
2755
2755
|
|
|
2756
|
-
/***/
|
|
2756
|
+
/***/ 566:
|
|
2757
2757
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
2758
2758
|
|
|
2759
2759
|
module.exports = __nccwpck_require__.p + "ccf8ada94096a8f232f5.js?reed_solomon_wasm_bg.wasm";
|
|
@@ -3452,7 +3452,7 @@ async function __wbg_init(module_or_path) {
|
|
|
3452
3452
|
if (wasm !== void 0) return wasm;
|
|
3453
3453
|
if (typeof module_or_path !== "undefined") if (Object.getPrototypeOf(module_or_path) === Object.prototype) ({module_or_path} = module_or_path);
|
|
3454
3454
|
else console.warn("using deprecated parameters for the initialization function; pass a single object instead");
|
|
3455
|
-
if (typeof module_or_path === "undefined") module_or_path = new URL(/* asset import */ __nccwpck_require__(
|
|
3455
|
+
if (typeof module_or_path === "undefined") module_or_path = new URL(/* asset import */ __nccwpck_require__(566), __nccwpck_require__.b);
|
|
3456
3456
|
const imports = __wbg_get_imports();
|
|
3457
3457
|
if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) module_or_path = fetch(module_or_path);
|
|
3458
3458
|
__wbg_init_memory(imports);
|
|
@@ -3540,7 +3540,7 @@ var GpVersion;
|
|
|
3540
3540
|
(function (GpVersion) {
|
|
3541
3541
|
GpVersion["V0_6_7"] = "0.6.7";
|
|
3542
3542
|
GpVersion["V0_7_0"] = "0.7.0";
|
|
3543
|
-
GpVersion["V0_7_1"] = "0.7.1
|
|
3543
|
+
GpVersion["V0_7_1"] = "0.7.1";
|
|
3544
3544
|
GpVersion["V0_7_2"] = "0.7.2-preview";
|
|
3545
3545
|
})(GpVersion || (GpVersion = {}));
|
|
3546
3546
|
var TestSuite;
|
|
@@ -3549,11 +3549,11 @@ var TestSuite;
|
|
|
3549
3549
|
TestSuite["JAMDUNA"] = "jamduna";
|
|
3550
3550
|
})(TestSuite || (TestSuite = {}));
|
|
3551
3551
|
const DEFAULT_SUITE = TestSuite.W3F_DAVXY;
|
|
3552
|
-
const
|
|
3552
|
+
const DEFAULT_VERSION = GpVersion.V0_7_1;
|
|
3553
3553
|
const env = typeof process === "undefined" ? {} : process.env;
|
|
3554
|
-
const DEFAULT_VERSION = GpVersion.V0_7_0;
|
|
3555
3554
|
let CURRENT_VERSION = parseCurrentVersion(env.GP_VERSION) ?? DEFAULT_VERSION;
|
|
3556
3555
|
let CURRENT_SUITE = parseCurrentSuite(env.TEST_SUITE) ?? DEFAULT_SUITE;
|
|
3556
|
+
const ALL_VERSIONS_IN_ORDER = [GpVersion.V0_6_7, GpVersion.V0_7_0, GpVersion.V0_7_1, GpVersion.V0_7_2];
|
|
3557
3557
|
function parseCurrentVersion(env) {
|
|
3558
3558
|
if (env === undefined) {
|
|
3559
3559
|
return undefined;
|
|
@@ -3840,7 +3840,7 @@ function resultToString(res) {
|
|
|
3840
3840
|
if (res.isOk) {
|
|
3841
3841
|
return `OK: ${typeof res.ok === "symbol" ? res.ok.toString() : res.ok}`;
|
|
3842
3842
|
}
|
|
3843
|
-
return `${res.details}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
3843
|
+
return `${res.details()}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
3844
3844
|
}
|
|
3845
3845
|
/** An indication of two possible outcomes returned from a function. */
|
|
3846
3846
|
const result_Result = {
|
|
@@ -3854,7 +3854,7 @@ const result_Result = {
|
|
|
3854
3854
|
};
|
|
3855
3855
|
},
|
|
3856
3856
|
/** Create new [`Result`] with `Error` status. */
|
|
3857
|
-
error: (error, details
|
|
3857
|
+
error: (error, details) => {
|
|
3858
3858
|
debug_check `${error !== undefined} 'Error' type cannot be undefined.`;
|
|
3859
3859
|
return {
|
|
3860
3860
|
isOk: false,
|
|
@@ -3973,7 +3973,7 @@ function deepEqual(actual, expected, { context = [], errorsCollector, ignore = [
|
|
|
3973
3973
|
}
|
|
3974
3974
|
if (actual.isError && expected.isError) {
|
|
3975
3975
|
deepEqual(actual.error, expected.error, { context: ctx.concat(["error"]), errorsCollector: errors, ignore });
|
|
3976
|
-
deepEqual(actual.details, expected.details, {
|
|
3976
|
+
deepEqual(actual.details(), expected.details(), {
|
|
3977
3977
|
context: ctx.concat(["details"]),
|
|
3978
3978
|
errorsCollector: errors,
|
|
3979
3979
|
// display details when error does not match
|
|
@@ -4521,7 +4521,7 @@ const BANDERSNATCH_KEY_BYTES = 32;
|
|
|
4521
4521
|
/** Bandersnatch VRF signature size */
|
|
4522
4522
|
const BANDERSNATCH_VRF_SIGNATURE_BYTES = 96;
|
|
4523
4523
|
/** Bandersnatch ring commitment size */
|
|
4524
|
-
const
|
|
4524
|
+
const bandersnatch_BANDERSNATCH_RING_ROOT_BYTES = 144;
|
|
4525
4525
|
/** Bandersnatch proof size */
|
|
4526
4526
|
const BANDERSNATCH_PROOF_BYTES = 784;
|
|
4527
4527
|
/** BLS public key size. */
|
|
@@ -6198,6 +6198,9 @@ class ObjectView {
|
|
|
6198
6198
|
toString() {
|
|
6199
6199
|
return `View<${this.materializedConstructor.name}>(cache: ${this.cache.size})`;
|
|
6200
6200
|
}
|
|
6201
|
+
[TEST_COMPARE_USING]() {
|
|
6202
|
+
return this.materialize();
|
|
6203
|
+
}
|
|
6201
6204
|
}
|
|
6202
6205
|
/**
|
|
6203
6206
|
* A lazy-evaluated decoder of a sequence.
|
|
@@ -6330,7 +6333,7 @@ const TYPICAL_DICTIONARY_LENGTH = 32;
|
|
|
6330
6333
|
* It's not true in a general case, but should be good enough for us.
|
|
6331
6334
|
*
|
|
6332
6335
|
*/
|
|
6333
|
-
function
|
|
6336
|
+
function descriptors_readonlyArray(desc) {
|
|
6334
6337
|
return desc.convert((x) => {
|
|
6335
6338
|
debug_check `
|
|
6336
6339
|
${Array.isArray(x)}
|
|
@@ -6492,7 +6495,15 @@ var descriptors_codec;
|
|
|
6492
6495
|
/** Custom encoding / decoding logic. */
|
|
6493
6496
|
codec.custom = ({ name, sizeHint = { bytes: 0, isExact: false }, }, encode, decode, skip) => Descriptor.new(name, sizeHint, encode, decode, skip);
|
|
6494
6497
|
/** Choose a descriptor depending on the encoding/decoding context. */
|
|
6495
|
-
codec.select = ({ name, sizeHint, }, chooser) =>
|
|
6498
|
+
codec.select = ({ name, sizeHint, }, chooser) => {
|
|
6499
|
+
const Self = chooser(null);
|
|
6500
|
+
return Descriptor.withView(name, sizeHint, (e, x) => chooser(e.getContext()).encode(e, x), (d) => chooser(d.getContext()).decode(d), (s) => chooser(s.decoder.getContext()).skip(s), hasUniqueView(Self)
|
|
6501
|
+
? codec.select({
|
|
6502
|
+
name: Self.View.name,
|
|
6503
|
+
sizeHint: Self.View.sizeHint,
|
|
6504
|
+
}, (ctx) => chooser(ctx).View)
|
|
6505
|
+
: Self.View);
|
|
6506
|
+
};
|
|
6496
6507
|
/**
|
|
6497
6508
|
* A descriptor for a more complex POJO.
|
|
6498
6509
|
*
|
|
@@ -7610,9 +7621,9 @@ function codecWithContext(chooser) {
|
|
|
7610
7621
|
/** Codec for a known-size array with length validation. */
|
|
7611
7622
|
const codecKnownSizeArray = (val, options, _id) => {
|
|
7612
7623
|
if ("fixedLength" in options) {
|
|
7613
|
-
return
|
|
7624
|
+
return descriptors_readonlyArray(descriptors_codec.sequenceFixLen(val, options.fixedLength)).convert(seeThrough, sized_array_asKnownSize);
|
|
7614
7625
|
}
|
|
7615
|
-
return
|
|
7626
|
+
return descriptors_readonlyArray(descriptors_codec.sequenceVarLen(val, options)).convert(seeThrough, sized_array_asKnownSize);
|
|
7616
7627
|
};
|
|
7617
7628
|
/** Codec for a fixed-size array with length validation. */
|
|
7618
7629
|
const codecFixedSizeArray = (val, len) => {
|
|
@@ -7749,7 +7760,7 @@ function tryAsPerValidator(array, spec) {
|
|
|
7749
7760
|
`;
|
|
7750
7761
|
return sized_array_asKnownSize(array);
|
|
7751
7762
|
}
|
|
7752
|
-
const
|
|
7763
|
+
const common_codecPerValidator = (val) => codecWithContext((context) => {
|
|
7753
7764
|
return codecKnownSizeArray(val, {
|
|
7754
7765
|
fixedLength: context.validatorsCount,
|
|
7755
7766
|
});
|
|
@@ -7876,7 +7887,7 @@ class Verdict extends WithDebug {
|
|
|
7876
7887
|
workReportHash: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
7877
7888
|
votesEpoch: descriptors_codec.u32.asOpaque(),
|
|
7878
7889
|
votes: codecWithContext((context) => {
|
|
7879
|
-
return
|
|
7890
|
+
return descriptors_readonlyArray(descriptors_codec.sequenceFixLen(Judgement.Codec, context.validatorsSuperMajority)).convert(seeThrough, sized_array_asKnownSize);
|
|
7880
7891
|
}),
|
|
7881
7892
|
});
|
|
7882
7893
|
static create({ workReportHash, votesEpoch, votes }) {
|
|
@@ -8568,7 +8579,7 @@ const WorkReportCodec = descriptors_codec.Class(WorkReportNoCodec, {
|
|
|
8568
8579
|
authorizerHash: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
8569
8580
|
authorizationGasUsed: descriptors_codec.varU64.asOpaque(),
|
|
8570
8581
|
authorizationOutput: descriptors_codec.blob,
|
|
8571
|
-
segmentRootLookup:
|
|
8582
|
+
segmentRootLookup: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(WorkPackageInfo.Codec)),
|
|
8572
8583
|
results: descriptors_codec.sequenceVarLen(WorkResult.Codec).convert((x) => x, (items) => FixedSizeArray.new(items, tryAsWorkItemsCount(items.length))),
|
|
8573
8584
|
});
|
|
8574
8585
|
const WorkReportCodecPre070 = descriptors_codec.Class(WorkReportNoCodec, {
|
|
@@ -8582,7 +8593,7 @@ const WorkReportCodecPre070 = descriptors_codec.Class(WorkReportNoCodec, {
|
|
|
8582
8593
|
}),
|
|
8583
8594
|
authorizerHash: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
8584
8595
|
authorizationOutput: descriptors_codec.blob,
|
|
8585
|
-
segmentRootLookup:
|
|
8596
|
+
segmentRootLookup: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(WorkPackageInfo.Codec)),
|
|
8586
8597
|
results: descriptors_codec.sequenceVarLen(WorkResult.Codec).convert((x) => x, (items) => FixedSizeArray.new(items, tryAsWorkItemsCount(items.length))),
|
|
8587
8598
|
authorizationGasUsed: descriptors_codec.varU64.asOpaque(),
|
|
8588
8599
|
});
|
|
@@ -8700,16 +8711,16 @@ class SignedTicket extends WithDebug {
|
|
|
8700
8711
|
}
|
|
8701
8712
|
}
|
|
8702
8713
|
/** Anonymous? entry into the ticket contest. */
|
|
8703
|
-
class
|
|
8714
|
+
class tickets_Ticket extends WithDebug {
|
|
8704
8715
|
id;
|
|
8705
8716
|
attempt;
|
|
8706
|
-
static Codec = descriptors_codec.Class(
|
|
8717
|
+
static Codec = descriptors_codec.Class(tickets_Ticket, {
|
|
8707
8718
|
id: descriptors_codec.bytes(hash_HASH_SIZE),
|
|
8708
8719
|
// TODO [ToDr] we should verify that attempt is either 0|1|2.
|
|
8709
8720
|
attempt: descriptors_codec.u8.asOpaque(),
|
|
8710
8721
|
});
|
|
8711
8722
|
static create({ id, attempt }) {
|
|
8712
|
-
return new
|
|
8723
|
+
return new tickets_Ticket(id, attempt);
|
|
8713
8724
|
}
|
|
8714
8725
|
constructor(
|
|
8715
8726
|
/**
|
|
@@ -8778,7 +8789,7 @@ class ValidatorKeys extends WithDebug {
|
|
|
8778
8789
|
class TicketsMarker extends WithDebug {
|
|
8779
8790
|
tickets;
|
|
8780
8791
|
static Codec = descriptors_codec.Class(TicketsMarker, {
|
|
8781
|
-
tickets: codecPerEpochBlock(
|
|
8792
|
+
tickets: codecPerEpochBlock(tickets_Ticket.Codec),
|
|
8782
8793
|
});
|
|
8783
8794
|
static create({ tickets }) {
|
|
8784
8795
|
return new TicketsMarker(tickets);
|
|
@@ -8802,7 +8813,7 @@ class EpochMarker extends WithDebug {
|
|
|
8802
8813
|
static Codec = descriptors_codec.Class(EpochMarker, {
|
|
8803
8814
|
entropy: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
8804
8815
|
ticketsEntropy: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
8805
|
-
validators:
|
|
8816
|
+
validators: common_codecPerValidator(ValidatorKeys.Codec),
|
|
8806
8817
|
});
|
|
8807
8818
|
static create({ entropy, ticketsEntropy, validators }) {
|
|
8808
8819
|
return new EpochMarker(entropy, ticketsEntropy, validators);
|
|
@@ -9074,6 +9085,19 @@ function emptyBlock(slot = tryAsTimeSlot(0)) {
|
|
|
9074
9085
|
});
|
|
9075
9086
|
}
|
|
9076
9087
|
|
|
9088
|
+
;// CONCATENATED MODULE: ./packages/jam/block/utils.ts
|
|
9089
|
+
|
|
9090
|
+
/**
|
|
9091
|
+
* Take an input data and re-encode that data as view.
|
|
9092
|
+
*
|
|
9093
|
+
* NOTE: this function should NEVER be used in any production code,
|
|
9094
|
+
* it's only a test helper.
|
|
9095
|
+
*/
|
|
9096
|
+
function reencodeAsView(codec, object, chainSpec) {
|
|
9097
|
+
const encoded = encoder_Encoder.encodeObject(codec, object, chainSpec);
|
|
9098
|
+
return decoder_Decoder.decodeObject(codec.View, encoded, chainSpec);
|
|
9099
|
+
}
|
|
9100
|
+
|
|
9077
9101
|
;// CONCATENATED MODULE: ./packages/jam/block/index.ts
|
|
9078
9102
|
|
|
9079
9103
|
|
|
@@ -9092,6 +9116,7 @@ function emptyBlock(slot = tryAsTimeSlot(0)) {
|
|
|
9092
9116
|
|
|
9093
9117
|
|
|
9094
9118
|
|
|
9119
|
+
|
|
9095
9120
|
;// CONCATENATED MODULE: ./packages/jam/database-lmdb/blocks.ts
|
|
9096
9121
|
|
|
9097
9122
|
|
|
@@ -9443,10 +9468,129 @@ function accumulationOutputComparator(a, b) {
|
|
|
9443
9468
|
return Ordering.Equal;
|
|
9444
9469
|
}
|
|
9445
9470
|
|
|
9471
|
+
;// CONCATENATED MODULE: ./packages/jam/block/gp-constants.ts
|
|
9472
|
+
|
|
9473
|
+
|
|
9474
|
+
/**
|
|
9475
|
+
* This file lists all of the constants defined in the GrayPaper appendix.
|
|
9476
|
+
*
|
|
9477
|
+
* NOTE: Avoid using the constants directly, prefer "named" constants defined
|
|
9478
|
+
* in a semantical proximity to where they are used.
|
|
9479
|
+
*
|
|
9480
|
+
* NOTE: This file will most likely be removed in the future. The constants
|
|
9481
|
+
* here are only temporarily for convenience. When we figure out better names
|
|
9482
|
+
* and places for these this file will be eradicated.
|
|
9483
|
+
*
|
|
9484
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/442300442300?v=0.7.2
|
|
9485
|
+
*/
|
|
9486
|
+
/** `G_I`: The gas allocated to invoke a work-package’s Is-Authorized logic. */
|
|
9487
|
+
const G_I = 50_000_000;
|
|
9488
|
+
/** `I`: Maximum number of work items in a package. */
|
|
9489
|
+
const gp_constants_I = (/* unused pure expression or super */ null && (MAX_NUMBER_OF_WORK_ITEMS));
|
|
9490
|
+
/** `O`: Maximum number of items in the authorizations pool. */
|
|
9491
|
+
const O = 8;
|
|
9492
|
+
/** `Q`: The number of items in the authorizations queue. */
|
|
9493
|
+
const Q = 80;
|
|
9494
|
+
/** `S`: The maximum number of entries in the accumulation queue. */
|
|
9495
|
+
const S = 1024;
|
|
9496
|
+
/** `T`: The maximum number of extrinsics in a work-package. */
|
|
9497
|
+
const T = 128;
|
|
9498
|
+
/** `W_A`: The maximum size of is-authorized code in octets. */
|
|
9499
|
+
const W_A = 64_000;
|
|
9500
|
+
/** `W_B`: The maximum size of the concatenated variable-size blobs, extrinsics and imported segments of a work-package, in octets */
|
|
9501
|
+
const W_B = Compatibility.isGreaterOrEqual(GpVersion.V0_7_2) ? 13_791_360 : 13_794_305;
|
|
9502
|
+
/** `W_C`: The maximum size of service code in octets. */
|
|
9503
|
+
const W_C = 4_000_000;
|
|
9504
|
+
/** `W_M`: The maximum number of imports in a work-package. */
|
|
9505
|
+
const W_M = 3_072;
|
|
9506
|
+
/** `W_R`: The maximum total size of all output blobs in a work-report, in octets. */
|
|
9507
|
+
const W_R = 49_152;
|
|
9508
|
+
/** `W_T`: The size of a transfer memo in octets. */
|
|
9509
|
+
const W_T = 128;
|
|
9510
|
+
/** `W_M`: The maximum number of exports in a work-package. */
|
|
9511
|
+
const W_X = 3_072;
|
|
9512
|
+
// TODO [ToDr] Not sure where these should live yet :(
|
|
9513
|
+
/**
|
|
9514
|
+
* `S`: The minimum public service index.
|
|
9515
|
+
* Services of indices below these may only be created by the Registrar.
|
|
9516
|
+
*
|
|
9517
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/447a00447a00?v=0.7.2
|
|
9518
|
+
*/
|
|
9519
|
+
const MIN_PUBLIC_SERVICE_INDEX = 2 ** 16;
|
|
9520
|
+
/**
|
|
9521
|
+
* `J`: The maximum sum of dependency items in a work-report.
|
|
9522
|
+
*
|
|
9523
|
+
* https://graypaper.fluffylabs.dev/#/5f542d7/416a00416a00?v=0.6.2
|
|
9524
|
+
*/
|
|
9525
|
+
const MAX_REPORT_DEPENDENCIES = 8;
|
|
9526
|
+
|
|
9527
|
+
;// CONCATENATED MODULE: ./packages/jam/state/accumulation-queue.ts
|
|
9528
|
+
|
|
9529
|
+
|
|
9530
|
+
|
|
9531
|
+
|
|
9532
|
+
|
|
9533
|
+
|
|
9534
|
+
|
|
9535
|
+
/**
|
|
9536
|
+
* Ready (i.e. available and/or audited) but not-yet-accumulated work-reports.
|
|
9537
|
+
*
|
|
9538
|
+
* https://graypaper.fluffylabs.dev/#/5f542d7/165300165400
|
|
9539
|
+
*/
|
|
9540
|
+
class NotYetAccumulatedReport extends WithDebug {
|
|
9541
|
+
report;
|
|
9542
|
+
dependencies;
|
|
9543
|
+
static Codec = descriptors_codec.Class(NotYetAccumulatedReport, {
|
|
9544
|
+
report: WorkReport.Codec,
|
|
9545
|
+
dependencies: codecKnownSizeArray(descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(), {
|
|
9546
|
+
typicalLength: MAX_REPORT_DEPENDENCIES / 2,
|
|
9547
|
+
maxLength: MAX_REPORT_DEPENDENCIES,
|
|
9548
|
+
minLength: 0,
|
|
9549
|
+
}),
|
|
9550
|
+
});
|
|
9551
|
+
static create({ report, dependencies }) {
|
|
9552
|
+
return new NotYetAccumulatedReport(report, dependencies);
|
|
9553
|
+
}
|
|
9554
|
+
constructor(
|
|
9555
|
+
/**
|
|
9556
|
+
* Each of these were made available at most one epoch ago
|
|
9557
|
+
* but have or had unfulfilled dependencies.
|
|
9558
|
+
*/
|
|
9559
|
+
report,
|
|
9560
|
+
/**
|
|
9561
|
+
* Alongside the work-report itself, we retain its un-accumulated
|
|
9562
|
+
* dependencies, a set of work-package hashes.
|
|
9563
|
+
*
|
|
9564
|
+
* https://graypaper.fluffylabs.dev/#/5f542d7/165800165800
|
|
9565
|
+
*/
|
|
9566
|
+
dependencies) {
|
|
9567
|
+
super();
|
|
9568
|
+
this.report = report;
|
|
9569
|
+
this.dependencies = dependencies;
|
|
9570
|
+
}
|
|
9571
|
+
}
|
|
9572
|
+
const accumulationQueueCodec = codecPerEpochBlock(descriptors_readonlyArray(descriptors_codec.sequenceVarLen(NotYetAccumulatedReport.Codec)));
|
|
9573
|
+
|
|
9574
|
+
;// CONCATENATED MODULE: ./packages/jam/state/common.ts
|
|
9575
|
+
|
|
9576
|
+
|
|
9577
|
+
/** Check if given array has correct length before casting to the opaque type. */
|
|
9578
|
+
function tryAsPerCore(array, spec) {
|
|
9579
|
+
debug_check `
|
|
9580
|
+
${array.length === spec.coresCount}
|
|
9581
|
+
Invalid per-core array length. Expected ${spec.coresCount}, got: ${array.length}
|
|
9582
|
+
`;
|
|
9583
|
+
return opaque_asOpaqueType(array);
|
|
9584
|
+
}
|
|
9585
|
+
const codecPerCore = (val) => codecWithContext((context) => {
|
|
9586
|
+
return codecKnownSizeArray(val, { fixedLength: context.coresCount });
|
|
9587
|
+
});
|
|
9588
|
+
|
|
9446
9589
|
;// CONCATENATED MODULE: ./packages/jam/state/assurances.ts
|
|
9447
9590
|
|
|
9448
9591
|
|
|
9449
9592
|
|
|
9593
|
+
|
|
9450
9594
|
/**
|
|
9451
9595
|
* Assignment of particular work report to a core.
|
|
9452
9596
|
*
|
|
@@ -9475,27 +9619,30 @@ class AvailabilityAssignment extends WithDebug {
|
|
|
9475
9619
|
this.timeout = timeout;
|
|
9476
9620
|
}
|
|
9477
9621
|
}
|
|
9622
|
+
const availabilityAssignmentsCodec = codecPerCore(descriptors_codec.optional(AvailabilityAssignment.Codec));
|
|
9478
9623
|
|
|
9479
|
-
;// CONCATENATED MODULE: ./packages/jam/state/
|
|
9624
|
+
;// CONCATENATED MODULE: ./packages/jam/state/auth.ts
|
|
9480
9625
|
|
|
9481
9626
|
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
|
|
9627
|
+
|
|
9628
|
+
|
|
9629
|
+
|
|
9630
|
+
/** `O`: Maximal authorization pool size. */
|
|
9631
|
+
const MAX_AUTH_POOL_SIZE = O;
|
|
9632
|
+
/** `Q`: Size of the authorization queue. */
|
|
9633
|
+
const AUTHORIZATION_QUEUE_SIZE = Q;
|
|
9634
|
+
const authPoolsCodec = codecPerCore(codecKnownSizeArray(descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(), {
|
|
9635
|
+
minLength: 0,
|
|
9636
|
+
maxLength: MAX_AUTH_POOL_SIZE,
|
|
9637
|
+
typicalLength: MAX_AUTH_POOL_SIZE,
|
|
9638
|
+
}));
|
|
9639
|
+
const authQueuesCodec = codecPerCore(codecFixedSizeArray(descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(), AUTHORIZATION_QUEUE_SIZE));
|
|
9493
9640
|
|
|
9494
9641
|
;// CONCATENATED MODULE: ./packages/jam/state/disputes.ts
|
|
9495
9642
|
|
|
9496
9643
|
|
|
9497
9644
|
|
|
9498
|
-
const sortedSetCodec = () =>
|
|
9645
|
+
const sortedSetCodec = () => descriptors_readonlyArray(descriptors_codec.sequenceVarLen(descriptors_codec.bytes(hash_HASH_SIZE))).convert((input) => input.array, (output) => {
|
|
9499
9646
|
const typed = output.map((x) => x.asOpaque());
|
|
9500
9647
|
return SortedSet.fromSortedArray(hashComparator, typed);
|
|
9501
9648
|
});
|
|
@@ -9557,65 +9704,6 @@ function hashComparator(a, b) {
|
|
|
9557
9704
|
return a.compare(b);
|
|
9558
9705
|
}
|
|
9559
9706
|
|
|
9560
|
-
;// CONCATENATED MODULE: ./packages/jam/block/gp-constants.ts
|
|
9561
|
-
|
|
9562
|
-
/**
|
|
9563
|
-
* This file lists all of the constants defined in the GrayPaper appendix.
|
|
9564
|
-
*
|
|
9565
|
-
* NOTE: Avoid using the constants directly, prefer "named" constants defined
|
|
9566
|
-
* in a semantical proximity to where they are used.
|
|
9567
|
-
*
|
|
9568
|
-
* NOTE: This file will most likely be removed in the future. The constants
|
|
9569
|
-
* here are only temporarily for convenience. When we figure out better names
|
|
9570
|
-
* and places for these this file will be eradicated.
|
|
9571
|
-
*
|
|
9572
|
-
* https://graypaper.fluffylabs.dev/#/579bd12/413000413000
|
|
9573
|
-
*/
|
|
9574
|
-
/** `G_I`: The gas allocated to invoke a work-package’s Is-Authorized logic. */
|
|
9575
|
-
const G_I = 50_000_000;
|
|
9576
|
-
/** `I`: Maximum number of work items in a package. */
|
|
9577
|
-
const gp_constants_I = (/* unused pure expression or super */ null && (MAX_NUMBER_OF_WORK_ITEMS));
|
|
9578
|
-
/** `O`: Maximum number of items in the authorizations pool. */
|
|
9579
|
-
const O = 8;
|
|
9580
|
-
/** `Q`: The number of items in the authorizations queue. */
|
|
9581
|
-
const Q = 80;
|
|
9582
|
-
/** `S`: The maximum number of entries in the accumulation queue. */
|
|
9583
|
-
const S = 1024;
|
|
9584
|
-
/** `T`: The maximum number of extrinsics in a work-package. */
|
|
9585
|
-
const T = 128;
|
|
9586
|
-
/** `W_A`: The maximum size of is-authorized code in octets. */
|
|
9587
|
-
const W_A = 64_000;
|
|
9588
|
-
/** `W_B`: The maximum size of an encoded work-package with extrinsic data and imports. */
|
|
9589
|
-
const W_B = 13_794_305;
|
|
9590
|
-
/** `W_C`: The maximum size of service code in octets. */
|
|
9591
|
-
const W_C = 4_000_000;
|
|
9592
|
-
/** `W_M`: The maximum number of imports in a work-package. */
|
|
9593
|
-
const W_M = 3_072;
|
|
9594
|
-
/** `W_R`: The maximum total size of all output blobs in a work-report, in octets. */
|
|
9595
|
-
const W_R = 49_152;
|
|
9596
|
-
/** `W_T`: The size of a transfer memo in octets. */
|
|
9597
|
-
const W_T = 128;
|
|
9598
|
-
/** `W_M`: The maximum number of exports in a work-package. */
|
|
9599
|
-
const W_X = 3_072;
|
|
9600
|
-
// TODO [ToDr] Not sure where these should live yet :(
|
|
9601
|
-
/**
|
|
9602
|
-
* `S`: The minimum public service index.
|
|
9603
|
-
* Services of indices below these may only be created by the Registrar.
|
|
9604
|
-
*
|
|
9605
|
-
* https://graypaper.fluffylabs.dev/#/ab2cdbd/447a00447a00?v=0.7.2
|
|
9606
|
-
*/
|
|
9607
|
-
const MIN_PUBLIC_SERVICE_INDEX = 2 ** 16;
|
|
9608
|
-
/**
|
|
9609
|
-
* `J`: The maximum sum of dependency items in a work-report.
|
|
9610
|
-
*
|
|
9611
|
-
* https://graypaper.fluffylabs.dev/#/5f542d7/416a00416a00?v=0.6.2
|
|
9612
|
-
*/
|
|
9613
|
-
const MAX_REPORT_DEPENDENCIES = 8;
|
|
9614
|
-
/** `Q`: Size of the authorization queue. */
|
|
9615
|
-
const AUTHORIZATION_QUEUE_SIZE = Q;
|
|
9616
|
-
/** `O`: Maximal authorization pool size. */
|
|
9617
|
-
const MAX_AUTH_POOL_SIZE = O;
|
|
9618
|
-
|
|
9619
9707
|
;// CONCATENATED MODULE: ./packages/core/pvm-interpreter/ops/math-consts.ts
|
|
9620
9708
|
const MAX_VALUE = 4294967295;
|
|
9621
9709
|
const math_consts_MAX_VALUE_U64 = (/* unused pure expression or super */ null && (2n ** 63n));
|
|
@@ -9623,7 +9711,7 @@ const MIN_VALUE = -(2 ** 31);
|
|
|
9623
9711
|
const MAX_SHIFT_U32 = 32;
|
|
9624
9712
|
const MAX_SHIFT_U64 = 64n;
|
|
9625
9713
|
|
|
9626
|
-
;// CONCATENATED MODULE: ./packages/jam/state/
|
|
9714
|
+
;// CONCATENATED MODULE: ./packages/jam/state/recent-blocks.ts
|
|
9627
9715
|
|
|
9628
9716
|
|
|
9629
9717
|
|
|
@@ -9631,26 +9719,270 @@ const MAX_SHIFT_U64 = 64n;
|
|
|
9631
9719
|
|
|
9632
9720
|
|
|
9633
9721
|
/**
|
|
9634
|
-
* `
|
|
9635
|
-
*
|
|
9636
|
-
* https://graypaper.fluffylabs.dev/#/7e6ff6a/445800445800?v=0.6.7
|
|
9637
|
-
*/
|
|
9638
|
-
const BASE_SERVICE_BALANCE = 100n;
|
|
9639
|
-
/**
|
|
9640
|
-
* `B_I`: The additional minimum balance required per item of elective service state.
|
|
9722
|
+
* `H = 8`: The size of recent history, in blocks.
|
|
9641
9723
|
*
|
|
9642
|
-
* https://graypaper.fluffylabs.dev/#/
|
|
9724
|
+
* https://graypaper.fluffylabs.dev/#/579bd12/416300416500
|
|
9643
9725
|
*/
|
|
9644
|
-
const
|
|
9726
|
+
const MAX_RECENT_HISTORY = 8;
|
|
9727
|
+
/** Recent history of a single block. */
|
|
9728
|
+
class BlockState extends WithDebug {
|
|
9729
|
+
headerHash;
|
|
9730
|
+
accumulationResult;
|
|
9731
|
+
postStateRoot;
|
|
9732
|
+
reported;
|
|
9733
|
+
static Codec = descriptors_codec.Class(BlockState, {
|
|
9734
|
+
headerHash: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
9735
|
+
accumulationResult: descriptors_codec.bytes(hash_HASH_SIZE),
|
|
9736
|
+
postStateRoot: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
9737
|
+
reported: codecHashDictionary(WorkPackageInfo.Codec, (x) => x.workPackageHash),
|
|
9738
|
+
});
|
|
9739
|
+
static create({ headerHash, accumulationResult, postStateRoot, reported }) {
|
|
9740
|
+
return new BlockState(headerHash, accumulationResult, postStateRoot, reported);
|
|
9741
|
+
}
|
|
9742
|
+
constructor(
|
|
9743
|
+
/** Header hash. */
|
|
9744
|
+
headerHash,
|
|
9745
|
+
/** Merkle mountain belt of accumulation result. */
|
|
9746
|
+
accumulationResult,
|
|
9747
|
+
/** Posterior state root filled in with a 1-block delay. */
|
|
9748
|
+
postStateRoot,
|
|
9749
|
+
/** Reported work packages (no more than number of cores). */
|
|
9750
|
+
reported) {
|
|
9751
|
+
super();
|
|
9752
|
+
this.headerHash = headerHash;
|
|
9753
|
+
this.accumulationResult = accumulationResult;
|
|
9754
|
+
this.postStateRoot = postStateRoot;
|
|
9755
|
+
this.reported = reported;
|
|
9756
|
+
}
|
|
9757
|
+
}
|
|
9645
9758
|
/**
|
|
9646
|
-
*
|
|
9759
|
+
* Recent history of blocks.
|
|
9647
9760
|
*
|
|
9648
|
-
* https://graypaper.fluffylabs.dev/#/7e6ff6a/
|
|
9761
|
+
* https://graypaper.fluffylabs.dev/#/7e6ff6a/0fc9010fc901?v=0.6.7
|
|
9649
9762
|
*/
|
|
9650
|
-
|
|
9651
|
-
|
|
9652
|
-
|
|
9653
|
-
|
|
9763
|
+
class RecentBlocks extends WithDebug {
|
|
9764
|
+
blocks;
|
|
9765
|
+
accumulationLog;
|
|
9766
|
+
static Codec = descriptors_codec.Class(RecentBlocks, {
|
|
9767
|
+
blocks: codecKnownSizeArray(BlockState.Codec, {
|
|
9768
|
+
minLength: 0,
|
|
9769
|
+
maxLength: MAX_RECENT_HISTORY,
|
|
9770
|
+
typicalLength: MAX_RECENT_HISTORY,
|
|
9771
|
+
}),
|
|
9772
|
+
accumulationLog: descriptors_codec.object({
|
|
9773
|
+
peaks: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(descriptors_codec.optional(descriptors_codec.bytes(hash_HASH_SIZE)))),
|
|
9774
|
+
}),
|
|
9775
|
+
});
|
|
9776
|
+
static empty() {
|
|
9777
|
+
return new RecentBlocks(sized_array_asKnownSize([]), {
|
|
9778
|
+
peaks: [],
|
|
9779
|
+
});
|
|
9780
|
+
}
|
|
9781
|
+
static create(a) {
|
|
9782
|
+
return new RecentBlocks(a.blocks, a.accumulationLog);
|
|
9783
|
+
}
|
|
9784
|
+
constructor(
|
|
9785
|
+
/**
|
|
9786
|
+
* Most recent blocks.
|
|
9787
|
+
* https://graypaper.fluffylabs.dev/#/7e6ff6a/0fea010fea01?v=0.6.7
|
|
9788
|
+
*/
|
|
9789
|
+
blocks,
|
|
9790
|
+
/**
|
|
9791
|
+
* Accumulation output log.
|
|
9792
|
+
* https://graypaper.fluffylabs.dev/#/7e6ff6a/0f02020f0202?v=0.6.7
|
|
9793
|
+
*/
|
|
9794
|
+
accumulationLog) {
|
|
9795
|
+
super();
|
|
9796
|
+
this.blocks = blocks;
|
|
9797
|
+
this.accumulationLog = accumulationLog;
|
|
9798
|
+
}
|
|
9799
|
+
}
|
|
9800
|
+
|
|
9801
|
+
;// CONCATENATED MODULE: ./packages/jam/state/recently-accumulated.ts
|
|
9802
|
+
|
|
9803
|
+
|
|
9804
|
+
|
|
9805
|
+
|
|
9806
|
+
const recentlyAccumulatedCodec = codecPerEpochBlock(descriptors_codec.sequenceVarLen(descriptors_codec.bytes(hash_HASH_SIZE).asOpaque()).convert((x) => Array.from(x), (x) => HashSet.from(x)));
|
|
9807
|
+
|
|
9808
|
+
;// CONCATENATED MODULE: ./packages/jam/state/validator-data.ts
|
|
9809
|
+
|
|
9810
|
+
|
|
9811
|
+
|
|
9812
|
+
|
|
9813
|
+
/**
|
|
9814
|
+
* Fixed size of validator metadata.
|
|
9815
|
+
*
|
|
9816
|
+
* https://graypaper.fluffylabs.dev/#/5f542d7/0d55010d5501
|
|
9817
|
+
*/
|
|
9818
|
+
const VALIDATOR_META_BYTES = 128;
|
|
9819
|
+
/**
|
|
9820
|
+
* Details about validators' identity.
|
|
9821
|
+
*
|
|
9822
|
+
* https://graypaper.fluffylabs.dev/#/5f542d7/0d4b010d4c01
|
|
9823
|
+
*/
|
|
9824
|
+
class validator_data_ValidatorData extends WithDebug {
|
|
9825
|
+
bandersnatch;
|
|
9826
|
+
ed25519;
|
|
9827
|
+
bls;
|
|
9828
|
+
metadata;
|
|
9829
|
+
static Codec = descriptors_codec.Class(validator_data_ValidatorData, {
|
|
9830
|
+
bandersnatch: descriptors_codec.bytes(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
9831
|
+
ed25519: descriptors_codec.bytes(ED25519_KEY_BYTES).asOpaque(),
|
|
9832
|
+
bls: descriptors_codec.bytes(BLS_KEY_BYTES).asOpaque(),
|
|
9833
|
+
metadata: descriptors_codec.bytes(VALIDATOR_META_BYTES),
|
|
9834
|
+
});
|
|
9835
|
+
static create({ ed25519, bandersnatch, bls, metadata }) {
|
|
9836
|
+
return new validator_data_ValidatorData(bandersnatch, ed25519, bls, metadata);
|
|
9837
|
+
}
|
|
9838
|
+
constructor(
|
|
9839
|
+
/** Bandersnatch public key. */
|
|
9840
|
+
bandersnatch,
|
|
9841
|
+
/** ED25519 key data. */
|
|
9842
|
+
ed25519,
|
|
9843
|
+
/** BLS public key. */
|
|
9844
|
+
bls,
|
|
9845
|
+
/** Validator-defined additional metdata. */
|
|
9846
|
+
metadata) {
|
|
9847
|
+
super();
|
|
9848
|
+
this.bandersnatch = bandersnatch;
|
|
9849
|
+
this.ed25519 = ed25519;
|
|
9850
|
+
this.bls = bls;
|
|
9851
|
+
this.metadata = metadata;
|
|
9852
|
+
}
|
|
9853
|
+
}
|
|
9854
|
+
const validatorsDataCodec = common_codecPerValidator(validator_data_ValidatorData.Codec);
|
|
9855
|
+
|
|
9856
|
+
;// CONCATENATED MODULE: ./packages/jam/state/safrole-data.ts
|
|
9857
|
+
|
|
9858
|
+
|
|
9859
|
+
|
|
9860
|
+
|
|
9861
|
+
|
|
9862
|
+
|
|
9863
|
+
|
|
9864
|
+
|
|
9865
|
+
|
|
9866
|
+
|
|
9867
|
+
|
|
9868
|
+
var SafroleSealingKeysKind;
|
|
9869
|
+
(function (SafroleSealingKeysKind) {
|
|
9870
|
+
SafroleSealingKeysKind[SafroleSealingKeysKind["Tickets"] = 0] = "Tickets";
|
|
9871
|
+
SafroleSealingKeysKind[SafroleSealingKeysKind["Keys"] = 1] = "Keys";
|
|
9872
|
+
})(SafroleSealingKeysKind || (SafroleSealingKeysKind = {}));
|
|
9873
|
+
const codecBandersnatchKey = descriptors_codec.bytes(BANDERSNATCH_KEY_BYTES).asOpaque();
|
|
9874
|
+
class safrole_data_SafroleSealingKeysData extends WithDebug {
|
|
9875
|
+
kind;
|
|
9876
|
+
keys;
|
|
9877
|
+
tickets;
|
|
9878
|
+
static Codec = codecWithContext((context) => {
|
|
9879
|
+
return descriptors_codec.custom({
|
|
9880
|
+
name: "SafroleSealingKeys",
|
|
9881
|
+
sizeHint: { bytes: 1 + hash_HASH_SIZE * context.epochLength, isExact: false },
|
|
9882
|
+
}, (e, x) => {
|
|
9883
|
+
e.varU32(numbers_tryAsU32(x.kind));
|
|
9884
|
+
if (x.kind === SafroleSealingKeysKind.Keys) {
|
|
9885
|
+
e.sequenceFixLen(codecBandersnatchKey, x.keys);
|
|
9886
|
+
}
|
|
9887
|
+
else {
|
|
9888
|
+
e.sequenceFixLen(tickets_Ticket.Codec, x.tickets);
|
|
9889
|
+
}
|
|
9890
|
+
}, (d) => {
|
|
9891
|
+
const epochLength = context.epochLength;
|
|
9892
|
+
const kind = d.varU32();
|
|
9893
|
+
if (kind === SafroleSealingKeysKind.Keys) {
|
|
9894
|
+
const keys = d.sequenceFixLen(codecBandersnatchKey, epochLength);
|
|
9895
|
+
return safrole_data_SafroleSealingKeysData.keys(tryAsPerEpochBlock(keys, context));
|
|
9896
|
+
}
|
|
9897
|
+
if (kind === SafroleSealingKeysKind.Tickets) {
|
|
9898
|
+
const tickets = d.sequenceFixLen(tickets_Ticket.Codec, epochLength);
|
|
9899
|
+
return safrole_data_SafroleSealingKeysData.tickets(tryAsPerEpochBlock(tickets, context));
|
|
9900
|
+
}
|
|
9901
|
+
throw new Error(`Unexpected safrole sealing keys kind: ${kind}`);
|
|
9902
|
+
}, (s) => {
|
|
9903
|
+
const kind = s.decoder.varU32();
|
|
9904
|
+
if (kind === SafroleSealingKeysKind.Keys) {
|
|
9905
|
+
s.sequenceFixLen(codecBandersnatchKey, context.epochLength);
|
|
9906
|
+
return;
|
|
9907
|
+
}
|
|
9908
|
+
if (kind === SafroleSealingKeysKind.Tickets) {
|
|
9909
|
+
s.sequenceFixLen(tickets_Ticket.Codec, context.epochLength);
|
|
9910
|
+
return;
|
|
9911
|
+
}
|
|
9912
|
+
throw new Error(`Unexpected safrole sealing keys kind: ${kind}`);
|
|
9913
|
+
});
|
|
9914
|
+
});
|
|
9915
|
+
static keys(keys) {
|
|
9916
|
+
return new safrole_data_SafroleSealingKeysData(SafroleSealingKeysKind.Keys, keys, undefined);
|
|
9917
|
+
}
|
|
9918
|
+
static tickets(tickets) {
|
|
9919
|
+
return new safrole_data_SafroleSealingKeysData(SafroleSealingKeysKind.Tickets, undefined, tickets);
|
|
9920
|
+
}
|
|
9921
|
+
constructor(kind, keys, tickets) {
|
|
9922
|
+
super();
|
|
9923
|
+
this.kind = kind;
|
|
9924
|
+
this.keys = keys;
|
|
9925
|
+
this.tickets = tickets;
|
|
9926
|
+
}
|
|
9927
|
+
}
|
|
9928
|
+
class SafroleData {
|
|
9929
|
+
nextValidatorData;
|
|
9930
|
+
epochRoot;
|
|
9931
|
+
sealingKeySeries;
|
|
9932
|
+
ticketsAccumulator;
|
|
9933
|
+
static Codec = descriptors_codec.Class(SafroleData, {
|
|
9934
|
+
nextValidatorData: common_codecPerValidator(validator_data_ValidatorData.Codec),
|
|
9935
|
+
epochRoot: descriptors_codec.bytes(bandersnatch_BANDERSNATCH_RING_ROOT_BYTES).asOpaque(),
|
|
9936
|
+
sealingKeySeries: safrole_data_SafroleSealingKeysData.Codec,
|
|
9937
|
+
ticketsAccumulator: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(tickets_Ticket.Codec)).convert(seeThrough, sized_array_asKnownSize),
|
|
9938
|
+
});
|
|
9939
|
+
static create({ nextValidatorData, epochRoot, sealingKeySeries, ticketsAccumulator }) {
|
|
9940
|
+
return new SafroleData(nextValidatorData, epochRoot, sealingKeySeries, ticketsAccumulator);
|
|
9941
|
+
}
|
|
9942
|
+
constructor(
|
|
9943
|
+
/** gamma_k */
|
|
9944
|
+
nextValidatorData,
|
|
9945
|
+
/** gamma_z */
|
|
9946
|
+
epochRoot,
|
|
9947
|
+
/** gamma_s */
|
|
9948
|
+
sealingKeySeries,
|
|
9949
|
+
/** gamma_a */
|
|
9950
|
+
ticketsAccumulator) {
|
|
9951
|
+
this.nextValidatorData = nextValidatorData;
|
|
9952
|
+
this.epochRoot = epochRoot;
|
|
9953
|
+
this.sealingKeySeries = sealingKeySeries;
|
|
9954
|
+
this.ticketsAccumulator = ticketsAccumulator;
|
|
9955
|
+
}
|
|
9956
|
+
}
|
|
9957
|
+
|
|
9958
|
+
;// CONCATENATED MODULE: ./packages/jam/state/service.ts
|
|
9959
|
+
|
|
9960
|
+
|
|
9961
|
+
|
|
9962
|
+
|
|
9963
|
+
|
|
9964
|
+
|
|
9965
|
+
/**
|
|
9966
|
+
* `B_S`: The basic minimum balance which all services require.
|
|
9967
|
+
*
|
|
9968
|
+
* https://graypaper.fluffylabs.dev/#/7e6ff6a/445800445800?v=0.6.7
|
|
9969
|
+
*/
|
|
9970
|
+
const BASE_SERVICE_BALANCE = 100n;
|
|
9971
|
+
/**
|
|
9972
|
+
* `B_I`: The additional minimum balance required per item of elective service state.
|
|
9973
|
+
*
|
|
9974
|
+
* https://graypaper.fluffylabs.dev/#/7e6ff6a/445000445000?v=0.6.7
|
|
9975
|
+
*/
|
|
9976
|
+
const ELECTIVE_ITEM_BALANCE = 10n;
|
|
9977
|
+
/**
|
|
9978
|
+
* `B_L`: The additional minimum balance required per octet of elective service state.
|
|
9979
|
+
*
|
|
9980
|
+
* https://graypaper.fluffylabs.dev/#/7e6ff6a/445400445400?v=0.6.7
|
|
9981
|
+
*/
|
|
9982
|
+
const ELECTIVE_BYTE_BALANCE = 1n;
|
|
9983
|
+
const zeroSizeHint = {
|
|
9984
|
+
bytes: 0,
|
|
9985
|
+
isExact: true,
|
|
9654
9986
|
};
|
|
9655
9987
|
/** 0-byte read, return given default value */
|
|
9656
9988
|
const ignoreValueWithDefault = (defaultValue) => Descriptor.new("ignoreValue", zeroSizeHint, (_e, _v) => { }, (_d) => defaultValue, (_s) => { });
|
|
@@ -9813,358 +10145,418 @@ class LookupHistoryItem {
|
|
|
9813
10145
|
}
|
|
9814
10146
|
}
|
|
9815
10147
|
|
|
9816
|
-
;// CONCATENATED MODULE: ./packages/jam/state/
|
|
10148
|
+
;// CONCATENATED MODULE: ./packages/jam/state/statistics.ts
|
|
9817
10149
|
|
|
9818
10150
|
|
|
9819
10151
|
|
|
9820
10152
|
|
|
9821
10153
|
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
10154
|
+
|
|
10155
|
+
const codecServiceId = Compatibility.isSuite(TestSuite.W3F_DAVXY) || Compatibility.isSuite(TestSuite.JAMDUNA, GpVersion.V0_6_7)
|
|
10156
|
+
? descriptors_codec.u32.asOpaque()
|
|
10157
|
+
: descriptors_codec.varU32.convert((s) => numbers_tryAsU32(s), (i) => tryAsServiceId(i));
|
|
10158
|
+
/**
|
|
10159
|
+
* Activity Record of a single validator.
|
|
10160
|
+
*
|
|
10161
|
+
* https://graypaper.fluffylabs.dev/#/579bd12/183701183701
|
|
10162
|
+
*/
|
|
10163
|
+
class ValidatorStatistics {
|
|
10164
|
+
blocks;
|
|
10165
|
+
tickets;
|
|
10166
|
+
preImages;
|
|
10167
|
+
preImagesSize;
|
|
10168
|
+
guarantees;
|
|
10169
|
+
assurances;
|
|
10170
|
+
static Codec = descriptors_codec.Class(ValidatorStatistics, {
|
|
10171
|
+
blocks: descriptors_codec.u32,
|
|
10172
|
+
tickets: descriptors_codec.u32,
|
|
10173
|
+
preImages: descriptors_codec.u32,
|
|
10174
|
+
preImagesSize: descriptors_codec.u32,
|
|
10175
|
+
guarantees: descriptors_codec.u32,
|
|
10176
|
+
assurances: descriptors_codec.u32,
|
|
9829
10177
|
});
|
|
9830
|
-
static create({
|
|
9831
|
-
return new
|
|
10178
|
+
static create({ blocks, tickets, preImages, preImagesSize, guarantees, assurances, }) {
|
|
10179
|
+
return new ValidatorStatistics(blocks, tickets, preImages, preImagesSize, guarantees, assurances);
|
|
9832
10180
|
}
|
|
9833
10181
|
constructor(
|
|
9834
|
-
/**
|
|
9835
|
-
|
|
9836
|
-
/**
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
/**
|
|
9843
|
-
|
|
9844
|
-
*/
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
static Codec = descriptors_codec.Class(PrivilegedServices, {
|
|
9853
|
-
manager: descriptors_codec.u32.asOpaque(),
|
|
9854
|
-
assigners: codecPerCore(descriptors_codec.u32.asOpaque()),
|
|
9855
|
-
delegator: descriptors_codec.u32.asOpaque(),
|
|
9856
|
-
registrar: Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)
|
|
9857
|
-
? descriptors_codec.u32.asOpaque()
|
|
9858
|
-
: ignoreValueWithDefault(tryAsServiceId(2 ** 32 - 1)),
|
|
9859
|
-
autoAccumulateServices: readonlyArray(descriptors_codec.sequenceVarLen(AutoAccumulate.Codec)),
|
|
9860
|
-
});
|
|
9861
|
-
static create(a) {
|
|
9862
|
-
return new PrivilegedServices(a.manager, a.delegator, a.registrar, a.assigners, a.autoAccumulateServices);
|
|
10182
|
+
/** The number of blocks produced by the validator. */
|
|
10183
|
+
blocks,
|
|
10184
|
+
/** The number of tickets introduced by the validator. */
|
|
10185
|
+
tickets,
|
|
10186
|
+
/** The number of preimages introduced by the validator. */
|
|
10187
|
+
preImages,
|
|
10188
|
+
/** The total number of octets across all preimages introduced by the validator. */
|
|
10189
|
+
preImagesSize,
|
|
10190
|
+
/** The number of reports guaranteed by the validator. */
|
|
10191
|
+
guarantees,
|
|
10192
|
+
/** The number of availability assurances made by the validator. */
|
|
10193
|
+
assurances) {
|
|
10194
|
+
this.blocks = blocks;
|
|
10195
|
+
this.tickets = tickets;
|
|
10196
|
+
this.preImages = preImages;
|
|
10197
|
+
this.preImagesSize = preImagesSize;
|
|
10198
|
+
this.guarantees = guarantees;
|
|
10199
|
+
this.assurances = assurances;
|
|
9863
10200
|
}
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
* as well as bestow services with storage deposit credits.
|
|
9868
|
-
* https://graypaper.fluffylabs.dev/#/ab2cdbd/111502111902?v=0.7.2
|
|
9869
|
-
*/
|
|
9870
|
-
manager,
|
|
9871
|
-
/** `χ_V`: Managers validator keys. */
|
|
9872
|
-
delegator,
|
|
9873
|
-
/**
|
|
9874
|
-
* `χ_R`: Manages the creation of services in protected range.
|
|
9875
|
-
*
|
|
9876
|
-
* https://graypaper.fluffylabs.dev/#/ab2cdbd/111b02111d02?v=0.7.2
|
|
9877
|
-
*/
|
|
9878
|
-
registrar,
|
|
9879
|
-
/** `χ_A`: Manages authorization queue one for each core. */
|
|
9880
|
-
assigners,
|
|
9881
|
-
/** `χ_Z`: Dictionary of services that auto-accumulate every block with their gas limit. */
|
|
9882
|
-
autoAccumulateServices) {
|
|
9883
|
-
this.manager = manager;
|
|
9884
|
-
this.delegator = delegator;
|
|
9885
|
-
this.registrar = registrar;
|
|
9886
|
-
this.assigners = assigners;
|
|
9887
|
-
this.autoAccumulateServices = autoAccumulateServices;
|
|
10201
|
+
static empty() {
|
|
10202
|
+
const zero = numbers_tryAsU32(0);
|
|
10203
|
+
return new ValidatorStatistics(zero, zero, zero, zero, zero, zero);
|
|
9888
10204
|
}
|
|
9889
10205
|
}
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
10206
|
+
const codecVarU16 = descriptors_codec.varU32.convert((i) => numbers_tryAsU32(i), (o) => numbers_tryAsU16(o));
|
|
10207
|
+
/** Encode/decode unsigned gas. */
|
|
10208
|
+
const codecVarGas = descriptors_codec.varU64.convert((g) => numbers_tryAsU64(g), (i) => tryAsServiceGas(i));
|
|
9898
10209
|
/**
|
|
9899
|
-
*
|
|
10210
|
+
* Single core statistics.
|
|
10211
|
+
* Updated per block, based on incoming work reports (`w`).
|
|
9900
10212
|
*
|
|
9901
|
-
* https://graypaper.fluffylabs.dev/#/
|
|
10213
|
+
* https://graypaper.fluffylabs.dev/#/68eaa1f/18f10318f103?v=0.6.4
|
|
10214
|
+
* https://github.com/gavofyork/graypaper/blob/9bffb08f3ea7b67832019176754df4fb36b9557d/text/statistics.tex#L65
|
|
9902
10215
|
*/
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
10216
|
+
class CoreStatistics {
|
|
10217
|
+
dataAvailabilityLoad;
|
|
10218
|
+
popularity;
|
|
10219
|
+
imports;
|
|
10220
|
+
exports;
|
|
10221
|
+
extrinsicSize;
|
|
10222
|
+
extrinsicCount;
|
|
10223
|
+
bundleSize;
|
|
10224
|
+
gasUsed;
|
|
10225
|
+
static Codec = Compatibility.isGreaterOrEqual(GpVersion.V0_7_0)
|
|
10226
|
+
? descriptors_codec.Class(CoreStatistics, {
|
|
10227
|
+
dataAvailabilityLoad: descriptors_codec.varU32,
|
|
10228
|
+
popularity: codecVarU16,
|
|
10229
|
+
imports: codecVarU16,
|
|
10230
|
+
extrinsicCount: codecVarU16,
|
|
10231
|
+
extrinsicSize: descriptors_codec.varU32,
|
|
10232
|
+
exports: codecVarU16,
|
|
10233
|
+
bundleSize: descriptors_codec.varU32,
|
|
10234
|
+
gasUsed: codecVarGas,
|
|
10235
|
+
})
|
|
10236
|
+
: descriptors_codec.Class(CoreStatistics, {
|
|
10237
|
+
dataAvailabilityLoad: descriptors_codec.varU32,
|
|
10238
|
+
popularity: codecVarU16,
|
|
10239
|
+
imports: codecVarU16,
|
|
10240
|
+
exports: codecVarU16,
|
|
10241
|
+
extrinsicSize: descriptors_codec.varU32,
|
|
10242
|
+
extrinsicCount: codecVarU16,
|
|
10243
|
+
bundleSize: descriptors_codec.varU32,
|
|
10244
|
+
gasUsed: codecVarGas,
|
|
10245
|
+
});
|
|
10246
|
+
static create(v) {
|
|
10247
|
+
return new CoreStatistics(v.dataAvailabilityLoad, v.popularity, v.imports, v.exports, v.extrinsicSize, v.extrinsicCount, v.bundleSize, v.gasUsed);
|
|
9918
10248
|
}
|
|
9919
10249
|
constructor(
|
|
9920
|
-
/**
|
|
9921
|
-
|
|
9922
|
-
/**
|
|
9923
|
-
|
|
9924
|
-
/**
|
|
9925
|
-
|
|
9926
|
-
/**
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
accumulationLog: descriptors_codec.object({
|
|
9945
|
-
peaks: readonlyArray(descriptors_codec.sequenceVarLen(descriptors_codec.optional(descriptors_codec.bytes(hash_HASH_SIZE)))),
|
|
9946
|
-
}),
|
|
9947
|
-
});
|
|
9948
|
-
static create(a) {
|
|
9949
|
-
return new RecentBlocks(a.blocks, a.accumulationLog);
|
|
10250
|
+
/** `d` */
|
|
10251
|
+
dataAvailabilityLoad,
|
|
10252
|
+
/** `p` */
|
|
10253
|
+
popularity,
|
|
10254
|
+
/** `i` */
|
|
10255
|
+
imports,
|
|
10256
|
+
/** `e` */
|
|
10257
|
+
exports,
|
|
10258
|
+
/** `z` */
|
|
10259
|
+
extrinsicSize,
|
|
10260
|
+
/** `x` */
|
|
10261
|
+
extrinsicCount,
|
|
10262
|
+
/** `b` */
|
|
10263
|
+
bundleSize,
|
|
10264
|
+
/** `u` */
|
|
10265
|
+
gasUsed) {
|
|
10266
|
+
this.dataAvailabilityLoad = dataAvailabilityLoad;
|
|
10267
|
+
this.popularity = popularity;
|
|
10268
|
+
this.imports = imports;
|
|
10269
|
+
this.exports = exports;
|
|
10270
|
+
this.extrinsicSize = extrinsicSize;
|
|
10271
|
+
this.extrinsicCount = extrinsicCount;
|
|
10272
|
+
this.bundleSize = bundleSize;
|
|
10273
|
+
this.gasUsed = gasUsed;
|
|
9950
10274
|
}
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
blocks,
|
|
9957
|
-
/**
|
|
9958
|
-
* Accumulation output log.
|
|
9959
|
-
* https://graypaper.fluffylabs.dev/#/7e6ff6a/0f02020f0202?v=0.6.7
|
|
9960
|
-
*/
|
|
9961
|
-
accumulationLog) {
|
|
9962
|
-
super();
|
|
9963
|
-
this.blocks = blocks;
|
|
9964
|
-
this.accumulationLog = accumulationLog;
|
|
10275
|
+
static empty() {
|
|
10276
|
+
const zero = numbers_tryAsU32(0);
|
|
10277
|
+
const zero16 = numbers_tryAsU16(0);
|
|
10278
|
+
const zeroGas = tryAsServiceGas(0);
|
|
10279
|
+
return new CoreStatistics(zero, zero16, zero16, zero16, zero, zero16, zero, zeroGas);
|
|
9965
10280
|
}
|
|
9966
10281
|
}
|
|
9967
10282
|
/**
|
|
9968
|
-
*
|
|
10283
|
+
* Service statistics.
|
|
10284
|
+
* Updated per block, based on available work reports (`W`).
|
|
9969
10285
|
*
|
|
9970
|
-
* https://graypaper.fluffylabs.dev/#/
|
|
10286
|
+
* https://graypaper.fluffylabs.dev/#/1c979cb/199802199802?v=0.7.1
|
|
9971
10287
|
*/
|
|
9972
|
-
class
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
10288
|
+
class ServiceStatistics {
|
|
10289
|
+
providedCount;
|
|
10290
|
+
providedSize;
|
|
10291
|
+
refinementCount;
|
|
10292
|
+
refinementGasUsed;
|
|
10293
|
+
imports;
|
|
10294
|
+
exports;
|
|
10295
|
+
extrinsicSize;
|
|
10296
|
+
extrinsicCount;
|
|
10297
|
+
accumulateCount;
|
|
10298
|
+
accumulateGasUsed;
|
|
10299
|
+
onTransfersCount;
|
|
10300
|
+
onTransfersGasUsed;
|
|
10301
|
+
static Codec = Compatibility.selectIfGreaterOrEqual({
|
|
10302
|
+
fallback: descriptors_codec.Class(ServiceStatistics, {
|
|
10303
|
+
providedCount: codecVarU16,
|
|
10304
|
+
providedSize: descriptors_codec.varU32,
|
|
10305
|
+
refinementCount: descriptors_codec.varU32,
|
|
10306
|
+
refinementGasUsed: codecVarGas,
|
|
10307
|
+
imports: codecVarU16,
|
|
10308
|
+
exports: codecVarU16,
|
|
10309
|
+
extrinsicSize: descriptors_codec.varU32,
|
|
10310
|
+
extrinsicCount: codecVarU16,
|
|
10311
|
+
accumulateCount: descriptors_codec.varU32,
|
|
10312
|
+
accumulateGasUsed: codecVarGas,
|
|
10313
|
+
onTransfersCount: descriptors_codec.varU32,
|
|
10314
|
+
onTransfersGasUsed: codecVarGas,
|
|
10315
|
+
}),
|
|
10316
|
+
versions: {
|
|
10317
|
+
[GpVersion.V0_7_0]: descriptors_codec.Class(ServiceStatistics, {
|
|
10318
|
+
providedCount: codecVarU16,
|
|
10319
|
+
providedSize: descriptors_codec.varU32,
|
|
10320
|
+
refinementCount: descriptors_codec.varU32,
|
|
10321
|
+
refinementGasUsed: codecVarGas,
|
|
10322
|
+
imports: codecVarU16,
|
|
10323
|
+
extrinsicCount: codecVarU16,
|
|
10324
|
+
extrinsicSize: descriptors_codec.varU32,
|
|
10325
|
+
exports: codecVarU16,
|
|
10326
|
+
accumulateCount: descriptors_codec.varU32,
|
|
10327
|
+
accumulateGasUsed: codecVarGas,
|
|
10328
|
+
onTransfersCount: descriptors_codec.varU32,
|
|
10329
|
+
onTransfersGasUsed: codecVarGas,
|
|
10330
|
+
}),
|
|
10331
|
+
[GpVersion.V0_7_1]: descriptors_codec.Class(ServiceStatistics, {
|
|
10332
|
+
providedCount: codecVarU16,
|
|
10333
|
+
providedSize: descriptors_codec.varU32,
|
|
10334
|
+
refinementCount: descriptors_codec.varU32,
|
|
10335
|
+
refinementGasUsed: codecVarGas,
|
|
10336
|
+
imports: codecVarU16,
|
|
10337
|
+
extrinsicCount: codecVarU16,
|
|
10338
|
+
extrinsicSize: descriptors_codec.varU32,
|
|
10339
|
+
exports: codecVarU16,
|
|
10340
|
+
accumulateCount: descriptors_codec.varU32,
|
|
10341
|
+
accumulateGasUsed: codecVarGas,
|
|
10342
|
+
onTransfersCount: ignoreValueWithDefault(numbers_tryAsU32(0)),
|
|
10343
|
+
onTransfersGasUsed: ignoreValueWithDefault(tryAsServiceGas(0)),
|
|
10344
|
+
}),
|
|
10345
|
+
},
|
|
9979
10346
|
});
|
|
9980
|
-
static create(
|
|
9981
|
-
return new
|
|
10347
|
+
static create(v) {
|
|
10348
|
+
return new ServiceStatistics(v.providedCount, v.providedSize, v.refinementCount, v.refinementGasUsed, v.imports, v.exports, v.extrinsicSize, v.extrinsicCount, v.accumulateCount, v.accumulateGasUsed, v.onTransfersCount, v.onTransfersGasUsed);
|
|
10349
|
+
}
|
|
10350
|
+
constructor(
|
|
10351
|
+
/** `p.0` */
|
|
10352
|
+
providedCount,
|
|
10353
|
+
/** `p.1` */
|
|
10354
|
+
providedSize,
|
|
10355
|
+
/** `r.0` */
|
|
10356
|
+
refinementCount,
|
|
10357
|
+
/** `r.1` */
|
|
10358
|
+
refinementGasUsed,
|
|
10359
|
+
/** `i` */
|
|
10360
|
+
imports,
|
|
10361
|
+
/** `e` */
|
|
10362
|
+
exports,
|
|
10363
|
+
/** `z` */
|
|
10364
|
+
extrinsicSize,
|
|
10365
|
+
/** `x` */
|
|
10366
|
+
extrinsicCount,
|
|
10367
|
+
/** `a.0` */
|
|
10368
|
+
accumulateCount,
|
|
10369
|
+
/** `a.1` */
|
|
10370
|
+
accumulateGasUsed,
|
|
10371
|
+
/** `t.0` @deprecated since 0.7.1 */
|
|
10372
|
+
onTransfersCount,
|
|
10373
|
+
/** `t.1` @deprecated since 0.7.1 */
|
|
10374
|
+
onTransfersGasUsed) {
|
|
10375
|
+
this.providedCount = providedCount;
|
|
10376
|
+
this.providedSize = providedSize;
|
|
10377
|
+
this.refinementCount = refinementCount;
|
|
10378
|
+
this.refinementGasUsed = refinementGasUsed;
|
|
10379
|
+
this.imports = imports;
|
|
10380
|
+
this.exports = exports;
|
|
10381
|
+
this.extrinsicSize = extrinsicSize;
|
|
10382
|
+
this.extrinsicCount = extrinsicCount;
|
|
10383
|
+
this.accumulateCount = accumulateCount;
|
|
10384
|
+
this.accumulateGasUsed = accumulateGasUsed;
|
|
10385
|
+
this.onTransfersCount = onTransfersCount;
|
|
10386
|
+
this.onTransfersGasUsed = onTransfersGasUsed;
|
|
9982
10387
|
}
|
|
9983
10388
|
static empty() {
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
10389
|
+
const zero = numbers_tryAsU32(0);
|
|
10390
|
+
const zero16 = numbers_tryAsU16(0);
|
|
10391
|
+
const zeroGas = tryAsServiceGas(0);
|
|
10392
|
+
return new ServiceStatistics(zero16, zero, zero, zeroGas, zero16, zero16, zero, zero16, zero, zeroGas, zero, zeroGas);
|
|
9988
10393
|
}
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
10394
|
+
}
|
|
10395
|
+
/** `pi`: Statistics of each validator, cores statistics and services statistics. */
|
|
10396
|
+
class StatisticsData {
|
|
10397
|
+
current;
|
|
10398
|
+
previous;
|
|
10399
|
+
cores;
|
|
10400
|
+
services;
|
|
10401
|
+
static Codec = descriptors_codec.Class(StatisticsData, {
|
|
10402
|
+
current: common_codecPerValidator(ValidatorStatistics.Codec),
|
|
10403
|
+
previous: common_codecPerValidator(ValidatorStatistics.Codec),
|
|
10404
|
+
cores: codecPerCore(CoreStatistics.Codec),
|
|
10405
|
+
services: descriptors_codec.dictionary(codecServiceId, ServiceStatistics.Codec, {
|
|
10406
|
+
sortKeys: (a, b) => a - b,
|
|
10407
|
+
}),
|
|
10408
|
+
});
|
|
10409
|
+
static create(v) {
|
|
10410
|
+
return new StatisticsData(v.current, v.previous, v.cores, v.services);
|
|
9994
10411
|
}
|
|
9995
|
-
constructor(current) {
|
|
9996
|
-
super();
|
|
10412
|
+
constructor(current, previous, cores, services) {
|
|
9997
10413
|
this.current = current;
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
if (this.current !== null) {
|
|
10002
|
-
return this.current.blocks;
|
|
10003
|
-
}
|
|
10004
|
-
throw new Error("RecentBlocksHistory is in invalid state");
|
|
10005
|
-
}
|
|
10006
|
-
asCurrent() {
|
|
10007
|
-
if (this.current === null) {
|
|
10008
|
-
throw new Error("Cannot access current RecentBlocks format");
|
|
10009
|
-
}
|
|
10010
|
-
return this.current;
|
|
10011
|
-
}
|
|
10012
|
-
updateBlocks(blocks) {
|
|
10013
|
-
if (this.current !== null) {
|
|
10014
|
-
return RecentBlocksHistory.create(RecentBlocks.create({
|
|
10015
|
-
...this.current,
|
|
10016
|
-
blocks: opaque_asOpaqueType(blocks),
|
|
10017
|
-
}));
|
|
10018
|
-
}
|
|
10019
|
-
throw new Error("RecentBlocksHistory is in invalid state. Cannot be updated!");
|
|
10414
|
+
this.previous = previous;
|
|
10415
|
+
this.cores = cores;
|
|
10416
|
+
this.services = services;
|
|
10020
10417
|
}
|
|
10021
10418
|
}
|
|
10022
10419
|
|
|
10023
|
-
;// CONCATENATED MODULE: ./packages/jam/state/
|
|
10420
|
+
;// CONCATENATED MODULE: ./packages/jam/state/in-memory-state-view.ts
|
|
10024
10421
|
|
|
10025
10422
|
|
|
10026
10423
|
|
|
10027
|
-
/**
|
|
10028
|
-
* Fixed size of validator metadata.
|
|
10029
|
-
*
|
|
10030
|
-
* https://graypaper.fluffylabs.dev/#/5f542d7/0d55010d5501
|
|
10031
|
-
*/
|
|
10032
|
-
const VALIDATOR_META_BYTES = 128;
|
|
10033
|
-
/**
|
|
10034
|
-
* Details about validators' identity.
|
|
10035
|
-
*
|
|
10036
|
-
* https://graypaper.fluffylabs.dev/#/5f542d7/0d4b010d4c01
|
|
10037
|
-
*/
|
|
10038
|
-
class ValidatorData extends WithDebug {
|
|
10039
|
-
bandersnatch;
|
|
10040
|
-
ed25519;
|
|
10041
|
-
bls;
|
|
10042
|
-
metadata;
|
|
10043
|
-
static Codec = descriptors_codec.Class(ValidatorData, {
|
|
10044
|
-
bandersnatch: descriptors_codec.bytes(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
10045
|
-
ed25519: descriptors_codec.bytes(ED25519_KEY_BYTES).asOpaque(),
|
|
10046
|
-
bls: descriptors_codec.bytes(BLS_KEY_BYTES).asOpaque(),
|
|
10047
|
-
metadata: descriptors_codec.bytes(VALIDATOR_META_BYTES),
|
|
10048
|
-
});
|
|
10049
|
-
static create({ ed25519, bandersnatch, bls, metadata }) {
|
|
10050
|
-
return new ValidatorData(bandersnatch, ed25519, bls, metadata);
|
|
10051
|
-
}
|
|
10052
|
-
constructor(
|
|
10053
|
-
/** Bandersnatch public key. */
|
|
10054
|
-
bandersnatch,
|
|
10055
|
-
/** ED25519 key data. */
|
|
10056
|
-
ed25519,
|
|
10057
|
-
/** BLS public key. */
|
|
10058
|
-
bls,
|
|
10059
|
-
/** Validator-defined additional metdata. */
|
|
10060
|
-
metadata) {
|
|
10061
|
-
super();
|
|
10062
|
-
this.bandersnatch = bandersnatch;
|
|
10063
|
-
this.ed25519 = ed25519;
|
|
10064
|
-
this.bls = bls;
|
|
10065
|
-
this.metadata = metadata;
|
|
10066
|
-
}
|
|
10067
|
-
}
|
|
10068
10424
|
|
|
10069
|
-
;// CONCATENATED MODULE: ./packages/jam/state/safrole-data.ts
|
|
10070
10425
|
|
|
10071
10426
|
|
|
10072
10427
|
|
|
10073
10428
|
|
|
10074
10429
|
|
|
10075
10430
|
|
|
10431
|
+
class InMemoryStateView {
|
|
10432
|
+
chainSpec;
|
|
10433
|
+
state;
|
|
10434
|
+
constructor(chainSpec, state) {
|
|
10435
|
+
this.chainSpec = chainSpec;
|
|
10436
|
+
this.state = state;
|
|
10437
|
+
}
|
|
10438
|
+
availabilityAssignmentView() {
|
|
10439
|
+
return reencodeAsView(availabilityAssignmentsCodec, this.state.availabilityAssignment, this.chainSpec);
|
|
10440
|
+
}
|
|
10441
|
+
designatedValidatorDataView() {
|
|
10442
|
+
return reencodeAsView(validatorsDataCodec, this.state.designatedValidatorData, this.chainSpec);
|
|
10443
|
+
}
|
|
10444
|
+
currentValidatorDataView() {
|
|
10445
|
+
return reencodeAsView(validatorsDataCodec, this.state.currentValidatorData, this.chainSpec);
|
|
10446
|
+
}
|
|
10447
|
+
previousValidatorDataView() {
|
|
10448
|
+
return reencodeAsView(validatorsDataCodec, this.state.previousValidatorData, this.chainSpec);
|
|
10449
|
+
}
|
|
10450
|
+
authPoolsView() {
|
|
10451
|
+
return reencodeAsView(authPoolsCodec, this.state.authPools, this.chainSpec);
|
|
10452
|
+
}
|
|
10453
|
+
authQueuesView() {
|
|
10454
|
+
return reencodeAsView(authQueuesCodec, this.state.authQueues, this.chainSpec);
|
|
10455
|
+
}
|
|
10456
|
+
recentBlocksView() {
|
|
10457
|
+
return reencodeAsView(RecentBlocks.Codec, this.state.recentBlocks, this.chainSpec);
|
|
10458
|
+
}
|
|
10459
|
+
statisticsView() {
|
|
10460
|
+
return reencodeAsView(StatisticsData.Codec, this.state.statistics, this.chainSpec);
|
|
10461
|
+
}
|
|
10462
|
+
accumulationQueueView() {
|
|
10463
|
+
return reencodeAsView(accumulationQueueCodec, this.state.accumulationQueue, this.chainSpec);
|
|
10464
|
+
}
|
|
10465
|
+
recentlyAccumulatedView() {
|
|
10466
|
+
return reencodeAsView(recentlyAccumulatedCodec, this.state.recentlyAccumulated, this.chainSpec);
|
|
10467
|
+
}
|
|
10468
|
+
safroleDataView() {
|
|
10469
|
+
// TODO [ToDr] Consider exposting `safrole` from state
|
|
10470
|
+
// instead of individual fields
|
|
10471
|
+
const safrole = SafroleData.create({
|
|
10472
|
+
nextValidatorData: this.state.nextValidatorData,
|
|
10473
|
+
epochRoot: this.state.epochRoot,
|
|
10474
|
+
sealingKeySeries: this.state.sealingKeySeries,
|
|
10475
|
+
ticketsAccumulator: this.state.ticketsAccumulator,
|
|
10476
|
+
});
|
|
10477
|
+
return reencodeAsView(SafroleData.Codec, safrole, this.chainSpec);
|
|
10478
|
+
}
|
|
10479
|
+
getServiceInfoView(id) {
|
|
10480
|
+
const service = this.state.getService(id);
|
|
10481
|
+
if (service === null) {
|
|
10482
|
+
return null;
|
|
10483
|
+
}
|
|
10484
|
+
return reencodeAsView(ServiceAccountInfo.Codec, service.getInfo(), this.chainSpec);
|
|
10485
|
+
}
|
|
10486
|
+
}
|
|
10076
10487
|
|
|
10488
|
+
;// CONCATENATED MODULE: ./packages/jam/state/privileged-services.ts
|
|
10077
10489
|
|
|
10078
10490
|
|
|
10079
10491
|
|
|
10080
10492
|
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
keys;
|
|
10090
|
-
tickets;
|
|
10091
|
-
static Codec = codecWithContext((context) => {
|
|
10092
|
-
return descriptors_codec.custom({
|
|
10093
|
-
name: "SafroleSealingKeys",
|
|
10094
|
-
sizeHint: { bytes: 1 + hash_HASH_SIZE * context.epochLength, isExact: false },
|
|
10095
|
-
}, (e, x) => {
|
|
10096
|
-
e.varU32(numbers_tryAsU32(x.kind));
|
|
10097
|
-
if (x.kind === SafroleSealingKeysKind.Keys) {
|
|
10098
|
-
e.sequenceFixLen(codecBandersnatchKey, x.keys);
|
|
10099
|
-
}
|
|
10100
|
-
else {
|
|
10101
|
-
e.sequenceFixLen(Ticket.Codec, x.tickets);
|
|
10102
|
-
}
|
|
10103
|
-
}, (d) => {
|
|
10104
|
-
const epochLength = context.epochLength;
|
|
10105
|
-
const kind = d.varU32();
|
|
10106
|
-
if (kind === SafroleSealingKeysKind.Keys) {
|
|
10107
|
-
const keys = d.sequenceFixLen(codecBandersnatchKey, epochLength);
|
|
10108
|
-
return SafroleSealingKeysData.keys(tryAsPerEpochBlock(keys, context));
|
|
10109
|
-
}
|
|
10110
|
-
if (kind === SafroleSealingKeysKind.Tickets) {
|
|
10111
|
-
const tickets = d.sequenceFixLen(Ticket.Codec, epochLength);
|
|
10112
|
-
return SafroleSealingKeysData.tickets(tryAsPerEpochBlock(tickets, context));
|
|
10113
|
-
}
|
|
10114
|
-
throw new Error(`Unexpected safrole sealing keys kind: ${kind}`);
|
|
10115
|
-
}, (s) => {
|
|
10116
|
-
const kind = s.decoder.varU32();
|
|
10117
|
-
if (kind === SafroleSealingKeysKind.Keys) {
|
|
10118
|
-
s.sequenceFixLen(codecBandersnatchKey, context.epochLength);
|
|
10119
|
-
return;
|
|
10120
|
-
}
|
|
10121
|
-
if (kind === SafroleSealingKeysKind.Tickets) {
|
|
10122
|
-
s.sequenceFixLen(Ticket.Codec, context.epochLength);
|
|
10123
|
-
return;
|
|
10124
|
-
}
|
|
10125
|
-
throw new Error(`Unexpected safrole sealing keys kind: ${kind}`);
|
|
10126
|
-
});
|
|
10493
|
+
|
|
10494
|
+
/** Dictionary entry of services that auto-accumulate every block. */
|
|
10495
|
+
class AutoAccumulate {
|
|
10496
|
+
service;
|
|
10497
|
+
gasLimit;
|
|
10498
|
+
static Codec = descriptors_codec.Class(AutoAccumulate, {
|
|
10499
|
+
service: descriptors_codec.u32.asOpaque(),
|
|
10500
|
+
gasLimit: descriptors_codec.u64.asOpaque(),
|
|
10127
10501
|
});
|
|
10128
|
-
static
|
|
10129
|
-
return new
|
|
10130
|
-
}
|
|
10131
|
-
static tickets(tickets) {
|
|
10132
|
-
return new SafroleSealingKeysData(SafroleSealingKeysKind.Tickets, undefined, tickets);
|
|
10502
|
+
static create({ service, gasLimit }) {
|
|
10503
|
+
return new AutoAccumulate(service, gasLimit);
|
|
10133
10504
|
}
|
|
10134
|
-
constructor(
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10505
|
+
constructor(
|
|
10506
|
+
/** Service id that auto-accumulates. */
|
|
10507
|
+
service,
|
|
10508
|
+
/** Gas limit for auto-accumulation. */
|
|
10509
|
+
gasLimit) {
|
|
10510
|
+
this.service = service;
|
|
10511
|
+
this.gasLimit = gasLimit;
|
|
10139
10512
|
}
|
|
10140
10513
|
}
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10514
|
+
/**
|
|
10515
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/114402114402?v=0.7.2
|
|
10516
|
+
*/
|
|
10517
|
+
class PrivilegedServices {
|
|
10518
|
+
manager;
|
|
10519
|
+
delegator;
|
|
10520
|
+
registrar;
|
|
10521
|
+
assigners;
|
|
10522
|
+
autoAccumulateServices;
|
|
10523
|
+
/** https://graypaper.fluffylabs.dev/#/ab2cdbd/3bbd023bcb02?v=0.7.2 */
|
|
10524
|
+
static Codec = descriptors_codec.Class(PrivilegedServices, {
|
|
10525
|
+
manager: descriptors_codec.u32.asOpaque(),
|
|
10526
|
+
assigners: codecPerCore(descriptors_codec.u32.asOpaque()),
|
|
10527
|
+
delegator: descriptors_codec.u32.asOpaque(),
|
|
10528
|
+
registrar: Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)
|
|
10529
|
+
? descriptors_codec.u32.asOpaque()
|
|
10530
|
+
: ignoreValueWithDefault(tryAsServiceId(2 ** 32 - 1)),
|
|
10531
|
+
autoAccumulateServices: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(AutoAccumulate.Codec)),
|
|
10151
10532
|
});
|
|
10152
|
-
static create(
|
|
10153
|
-
return new
|
|
10533
|
+
static create(a) {
|
|
10534
|
+
return new PrivilegedServices(a.manager, a.delegator, a.registrar, a.assigners, a.autoAccumulateServices);
|
|
10154
10535
|
}
|
|
10155
10536
|
constructor(
|
|
10156
|
-
/**
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10162
|
-
/**
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10537
|
+
/**
|
|
10538
|
+
* `χ_M`: Manages alteration of χ from block to block,
|
|
10539
|
+
* as well as bestow services with storage deposit credits.
|
|
10540
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/111502111902?v=0.7.2
|
|
10541
|
+
*/
|
|
10542
|
+
manager,
|
|
10543
|
+
/** `χ_V`: Managers validator keys. */
|
|
10544
|
+
delegator,
|
|
10545
|
+
/**
|
|
10546
|
+
* `χ_R`: Manages the creation of services in protected range.
|
|
10547
|
+
*
|
|
10548
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/111b02111d02?v=0.7.2
|
|
10549
|
+
*/
|
|
10550
|
+
registrar,
|
|
10551
|
+
/** `χ_A`: Manages authorization queue one for each core. */
|
|
10552
|
+
assigners,
|
|
10553
|
+
/** `χ_Z`: Dictionary of services that auto-accumulate every block with their gas limit. */
|
|
10554
|
+
autoAccumulateServices) {
|
|
10555
|
+
this.manager = manager;
|
|
10556
|
+
this.delegator = delegator;
|
|
10557
|
+
this.registrar = registrar;
|
|
10558
|
+
this.assigners = assigners;
|
|
10559
|
+
this.autoAccumulateServices = autoAccumulateServices;
|
|
10168
10560
|
}
|
|
10169
10561
|
}
|
|
10170
10562
|
|
|
@@ -10205,31 +10597,29 @@ var UpdatePreimageKind;
|
|
|
10205
10597
|
* 3. Update `LookupHistory` with given value.
|
|
10206
10598
|
*/
|
|
10207
10599
|
class UpdatePreimage {
|
|
10208
|
-
serviceId;
|
|
10209
10600
|
action;
|
|
10210
|
-
constructor(
|
|
10211
|
-
this.serviceId = serviceId;
|
|
10601
|
+
constructor(action) {
|
|
10212
10602
|
this.action = action;
|
|
10213
10603
|
}
|
|
10214
10604
|
/** A preimage is provided. We should update the lookuphistory and add the preimage to db. */
|
|
10215
|
-
static provide({
|
|
10216
|
-
return new UpdatePreimage(
|
|
10605
|
+
static provide({ preimage, slot }) {
|
|
10606
|
+
return new UpdatePreimage({
|
|
10217
10607
|
kind: UpdatePreimageKind.Provide,
|
|
10218
10608
|
preimage,
|
|
10219
10609
|
slot,
|
|
10220
10610
|
});
|
|
10221
10611
|
}
|
|
10222
10612
|
/** The preimage should be removed completely from the database. */
|
|
10223
|
-
static remove({
|
|
10224
|
-
return new UpdatePreimage(
|
|
10613
|
+
static remove({ hash, length }) {
|
|
10614
|
+
return new UpdatePreimage({
|
|
10225
10615
|
kind: UpdatePreimageKind.Remove,
|
|
10226
10616
|
hash,
|
|
10227
10617
|
length,
|
|
10228
10618
|
});
|
|
10229
10619
|
}
|
|
10230
10620
|
/** Update the lookup history of some preimage or add a new one (request). */
|
|
10231
|
-
static updateOrAdd({
|
|
10232
|
-
return new UpdatePreimage(
|
|
10621
|
+
static updateOrAdd({ lookupHistory }) {
|
|
10622
|
+
return new UpdatePreimage({
|
|
10233
10623
|
kind: UpdatePreimageKind.UpdateOrAdd,
|
|
10234
10624
|
item: lookupHistory,
|
|
10235
10625
|
});
|
|
@@ -10266,23 +10656,21 @@ var UpdateServiceKind;
|
|
|
10266
10656
|
UpdateServiceKind[UpdateServiceKind["Create"] = 1] = "Create";
|
|
10267
10657
|
})(UpdateServiceKind || (UpdateServiceKind = {}));
|
|
10268
10658
|
/**
|
|
10269
|
-
* Update service info
|
|
10659
|
+
* Update service info or create a new one.
|
|
10270
10660
|
*/
|
|
10271
10661
|
class UpdateService {
|
|
10272
|
-
serviceId;
|
|
10273
10662
|
action;
|
|
10274
|
-
constructor(
|
|
10275
|
-
this.serviceId = serviceId;
|
|
10663
|
+
constructor(action) {
|
|
10276
10664
|
this.action = action;
|
|
10277
10665
|
}
|
|
10278
|
-
static update({
|
|
10279
|
-
return new UpdateService(
|
|
10666
|
+
static update({ serviceInfo }) {
|
|
10667
|
+
return new UpdateService({
|
|
10280
10668
|
kind: UpdateServiceKind.Update,
|
|
10281
10669
|
account: serviceInfo,
|
|
10282
10670
|
});
|
|
10283
10671
|
}
|
|
10284
|
-
static create({
|
|
10285
|
-
return new UpdateService(
|
|
10672
|
+
static create({ serviceInfo, lookupHistory, }) {
|
|
10673
|
+
return new UpdateService({
|
|
10286
10674
|
kind: UpdateServiceKind.Create,
|
|
10287
10675
|
account: serviceInfo,
|
|
10288
10676
|
lookupHistory,
|
|
@@ -10299,288 +10687,31 @@ var UpdateStorageKind;
|
|
|
10299
10687
|
})(UpdateStorageKind || (UpdateStorageKind = {}));
|
|
10300
10688
|
/**
|
|
10301
10689
|
* Update service storage item.
|
|
10302
|
-
*
|
|
10303
|
-
* Can either create/modify an entry or remove it.
|
|
10304
|
-
*/
|
|
10305
|
-
class UpdateStorage {
|
|
10306
|
-
|
|
10307
|
-
action
|
|
10308
|
-
|
|
10309
|
-
this.serviceId = serviceId;
|
|
10310
|
-
this.action = action;
|
|
10311
|
-
}
|
|
10312
|
-
static set({ serviceId, storage }) {
|
|
10313
|
-
return new UpdateStorage(serviceId, { kind: UpdateStorageKind.Set, storage });
|
|
10314
|
-
}
|
|
10315
|
-
static remove({ serviceId, key }) {
|
|
10316
|
-
return new UpdateStorage(serviceId, { kind: UpdateStorageKind.Remove, key });
|
|
10317
|
-
}
|
|
10318
|
-
get key() {
|
|
10319
|
-
if (this.action.kind === UpdateStorageKind.Remove) {
|
|
10320
|
-
return this.action.key;
|
|
10321
|
-
}
|
|
10322
|
-
return this.action.storage.key;
|
|
10323
|
-
}
|
|
10324
|
-
get value() {
|
|
10325
|
-
if (this.action.kind === UpdateStorageKind.Remove) {
|
|
10326
|
-
return null;
|
|
10327
|
-
}
|
|
10328
|
-
return this.action.storage.value;
|
|
10329
|
-
}
|
|
10330
|
-
}
|
|
10331
|
-
|
|
10332
|
-
;// CONCATENATED MODULE: ./packages/jam/state/statistics.ts
|
|
10333
|
-
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
const codecServiceId = Compatibility.isSuite(TestSuite.W3F_DAVXY) || Compatibility.isSuite(TestSuite.JAMDUNA, GpVersion.V0_6_7)
|
|
10339
|
-
? descriptors_codec.u32.asOpaque()
|
|
10340
|
-
: descriptors_codec.varU32.convert((s) => numbers_tryAsU32(s), (i) => tryAsServiceId(i));
|
|
10341
|
-
/**
|
|
10342
|
-
* Activity Record of a single validator.
|
|
10343
|
-
*
|
|
10344
|
-
* https://graypaper.fluffylabs.dev/#/579bd12/183701183701
|
|
10345
|
-
*/
|
|
10346
|
-
class ValidatorStatistics {
|
|
10347
|
-
blocks;
|
|
10348
|
-
tickets;
|
|
10349
|
-
preImages;
|
|
10350
|
-
preImagesSize;
|
|
10351
|
-
guarantees;
|
|
10352
|
-
assurances;
|
|
10353
|
-
static Codec = descriptors_codec.Class(ValidatorStatistics, {
|
|
10354
|
-
blocks: descriptors_codec.u32,
|
|
10355
|
-
tickets: descriptors_codec.u32,
|
|
10356
|
-
preImages: descriptors_codec.u32,
|
|
10357
|
-
preImagesSize: descriptors_codec.u32,
|
|
10358
|
-
guarantees: descriptors_codec.u32,
|
|
10359
|
-
assurances: descriptors_codec.u32,
|
|
10360
|
-
});
|
|
10361
|
-
static create({ blocks, tickets, preImages, preImagesSize, guarantees, assurances, }) {
|
|
10362
|
-
return new ValidatorStatistics(blocks, tickets, preImages, preImagesSize, guarantees, assurances);
|
|
10363
|
-
}
|
|
10364
|
-
constructor(
|
|
10365
|
-
/** The number of blocks produced by the validator. */
|
|
10366
|
-
blocks,
|
|
10367
|
-
/** The number of tickets introduced by the validator. */
|
|
10368
|
-
tickets,
|
|
10369
|
-
/** The number of preimages introduced by the validator. */
|
|
10370
|
-
preImages,
|
|
10371
|
-
/** The total number of octets across all preimages introduced by the validator. */
|
|
10372
|
-
preImagesSize,
|
|
10373
|
-
/** The number of reports guaranteed by the validator. */
|
|
10374
|
-
guarantees,
|
|
10375
|
-
/** The number of availability assurances made by the validator. */
|
|
10376
|
-
assurances) {
|
|
10377
|
-
this.blocks = blocks;
|
|
10378
|
-
this.tickets = tickets;
|
|
10379
|
-
this.preImages = preImages;
|
|
10380
|
-
this.preImagesSize = preImagesSize;
|
|
10381
|
-
this.guarantees = guarantees;
|
|
10382
|
-
this.assurances = assurances;
|
|
10383
|
-
}
|
|
10384
|
-
static empty() {
|
|
10385
|
-
const zero = numbers_tryAsU32(0);
|
|
10386
|
-
return new ValidatorStatistics(zero, zero, zero, zero, zero, zero);
|
|
10387
|
-
}
|
|
10388
|
-
}
|
|
10389
|
-
const codecVarU16 = descriptors_codec.varU32.convert((i) => numbers_tryAsU32(i), (o) => numbers_tryAsU16(o));
|
|
10390
|
-
/** Encode/decode unsigned gas. */
|
|
10391
|
-
const codecVarGas = descriptors_codec.varU64.convert((g) => numbers_tryAsU64(g), (i) => tryAsServiceGas(i));
|
|
10392
|
-
/**
|
|
10393
|
-
* Single core statistics.
|
|
10394
|
-
* Updated per block, based on incoming work reports (`w`).
|
|
10395
|
-
*
|
|
10396
|
-
* https://graypaper.fluffylabs.dev/#/68eaa1f/18f10318f103?v=0.6.4
|
|
10397
|
-
* https://github.com/gavofyork/graypaper/blob/9bffb08f3ea7b67832019176754df4fb36b9557d/text/statistics.tex#L65
|
|
10398
|
-
*/
|
|
10399
|
-
class CoreStatistics {
|
|
10400
|
-
dataAvailabilityLoad;
|
|
10401
|
-
popularity;
|
|
10402
|
-
imports;
|
|
10403
|
-
exports;
|
|
10404
|
-
extrinsicSize;
|
|
10405
|
-
extrinsicCount;
|
|
10406
|
-
bundleSize;
|
|
10407
|
-
gasUsed;
|
|
10408
|
-
static Codec = Compatibility.isGreaterOrEqual(GpVersion.V0_7_0)
|
|
10409
|
-
? descriptors_codec.Class(CoreStatistics, {
|
|
10410
|
-
dataAvailabilityLoad: descriptors_codec.varU32,
|
|
10411
|
-
popularity: codecVarU16,
|
|
10412
|
-
imports: codecVarU16,
|
|
10413
|
-
extrinsicCount: codecVarU16,
|
|
10414
|
-
extrinsicSize: descriptors_codec.varU32,
|
|
10415
|
-
exports: codecVarU16,
|
|
10416
|
-
bundleSize: descriptors_codec.varU32,
|
|
10417
|
-
gasUsed: codecVarGas,
|
|
10418
|
-
})
|
|
10419
|
-
: descriptors_codec.Class(CoreStatistics, {
|
|
10420
|
-
dataAvailabilityLoad: descriptors_codec.varU32,
|
|
10421
|
-
popularity: codecVarU16,
|
|
10422
|
-
imports: codecVarU16,
|
|
10423
|
-
exports: codecVarU16,
|
|
10424
|
-
extrinsicSize: descriptors_codec.varU32,
|
|
10425
|
-
extrinsicCount: codecVarU16,
|
|
10426
|
-
bundleSize: descriptors_codec.varU32,
|
|
10427
|
-
gasUsed: codecVarGas,
|
|
10428
|
-
});
|
|
10429
|
-
static create(v) {
|
|
10430
|
-
return new CoreStatistics(v.dataAvailabilityLoad, v.popularity, v.imports, v.exports, v.extrinsicSize, v.extrinsicCount, v.bundleSize, v.gasUsed);
|
|
10431
|
-
}
|
|
10432
|
-
constructor(
|
|
10433
|
-
/** `d` */
|
|
10434
|
-
dataAvailabilityLoad,
|
|
10435
|
-
/** `p` */
|
|
10436
|
-
popularity,
|
|
10437
|
-
/** `i` */
|
|
10438
|
-
imports,
|
|
10439
|
-
/** `e` */
|
|
10440
|
-
exports,
|
|
10441
|
-
/** `z` */
|
|
10442
|
-
extrinsicSize,
|
|
10443
|
-
/** `x` */
|
|
10444
|
-
extrinsicCount,
|
|
10445
|
-
/** `b` */
|
|
10446
|
-
bundleSize,
|
|
10447
|
-
/** `u` */
|
|
10448
|
-
gasUsed) {
|
|
10449
|
-
this.dataAvailabilityLoad = dataAvailabilityLoad;
|
|
10450
|
-
this.popularity = popularity;
|
|
10451
|
-
this.imports = imports;
|
|
10452
|
-
this.exports = exports;
|
|
10453
|
-
this.extrinsicSize = extrinsicSize;
|
|
10454
|
-
this.extrinsicCount = extrinsicCount;
|
|
10455
|
-
this.bundleSize = bundleSize;
|
|
10456
|
-
this.gasUsed = gasUsed;
|
|
10457
|
-
}
|
|
10458
|
-
static empty() {
|
|
10459
|
-
const zero = numbers_tryAsU32(0);
|
|
10460
|
-
const zero16 = numbers_tryAsU16(0);
|
|
10461
|
-
const zeroGas = tryAsServiceGas(0);
|
|
10462
|
-
return new CoreStatistics(zero, zero16, zero16, zero16, zero, zero16, zero, zeroGas);
|
|
10463
|
-
}
|
|
10464
|
-
}
|
|
10465
|
-
/**
|
|
10466
|
-
* Service statistics.
|
|
10467
|
-
* Updated per block, based on available work reports (`W`).
|
|
10468
|
-
*
|
|
10469
|
-
* https://graypaper.fluffylabs.dev/#/68eaa1f/185104185104?v=0.6.4
|
|
10470
|
-
* https://github.com/gavofyork/graypaper/blob/9bffb08f3ea7b67832019176754df4fb36b9557d/text/statistics.tex#L77
|
|
10471
|
-
*/
|
|
10472
|
-
class ServiceStatistics {
|
|
10473
|
-
providedCount;
|
|
10474
|
-
providedSize;
|
|
10475
|
-
refinementCount;
|
|
10476
|
-
refinementGasUsed;
|
|
10477
|
-
imports;
|
|
10478
|
-
exports;
|
|
10479
|
-
extrinsicSize;
|
|
10480
|
-
extrinsicCount;
|
|
10481
|
-
accumulateCount;
|
|
10482
|
-
accumulateGasUsed;
|
|
10483
|
-
onTransfersCount;
|
|
10484
|
-
onTransfersGasUsed;
|
|
10485
|
-
static Codec = Compatibility.isGreaterOrEqual(GpVersion.V0_7_0)
|
|
10486
|
-
? descriptors_codec.Class(ServiceStatistics, {
|
|
10487
|
-
providedCount: codecVarU16,
|
|
10488
|
-
providedSize: descriptors_codec.varU32,
|
|
10489
|
-
refinementCount: descriptors_codec.varU32,
|
|
10490
|
-
refinementGasUsed: codecVarGas,
|
|
10491
|
-
imports: codecVarU16,
|
|
10492
|
-
extrinsicCount: codecVarU16,
|
|
10493
|
-
extrinsicSize: descriptors_codec.varU32,
|
|
10494
|
-
exports: codecVarU16,
|
|
10495
|
-
accumulateCount: descriptors_codec.varU32,
|
|
10496
|
-
accumulateGasUsed: codecVarGas,
|
|
10497
|
-
onTransfersCount: descriptors_codec.varU32,
|
|
10498
|
-
onTransfersGasUsed: codecVarGas,
|
|
10499
|
-
})
|
|
10500
|
-
: descriptors_codec.Class(ServiceStatistics, {
|
|
10501
|
-
providedCount: codecVarU16,
|
|
10502
|
-
providedSize: descriptors_codec.varU32,
|
|
10503
|
-
refinementCount: descriptors_codec.varU32,
|
|
10504
|
-
refinementGasUsed: codecVarGas,
|
|
10505
|
-
imports: codecVarU16,
|
|
10506
|
-
exports: codecVarU16,
|
|
10507
|
-
extrinsicSize: descriptors_codec.varU32,
|
|
10508
|
-
extrinsicCount: codecVarU16,
|
|
10509
|
-
accumulateCount: descriptors_codec.varU32,
|
|
10510
|
-
accumulateGasUsed: codecVarGas,
|
|
10511
|
-
onTransfersCount: descriptors_codec.varU32,
|
|
10512
|
-
onTransfersGasUsed: codecVarGas,
|
|
10513
|
-
});
|
|
10514
|
-
static create(v) {
|
|
10515
|
-
return new ServiceStatistics(v.providedCount, v.providedSize, v.refinementCount, v.refinementGasUsed, v.imports, v.exports, v.extrinsicSize, v.extrinsicCount, v.accumulateCount, v.accumulateGasUsed, v.onTransfersCount, v.onTransfersGasUsed);
|
|
10516
|
-
}
|
|
10517
|
-
constructor(
|
|
10518
|
-
/** `p.0` */
|
|
10519
|
-
providedCount,
|
|
10520
|
-
/** `p.1` */
|
|
10521
|
-
providedSize,
|
|
10522
|
-
/** `r.0` */
|
|
10523
|
-
refinementCount,
|
|
10524
|
-
/** `r.1` */
|
|
10525
|
-
refinementGasUsed,
|
|
10526
|
-
/** `i` */
|
|
10527
|
-
imports,
|
|
10528
|
-
/** `e` */
|
|
10529
|
-
exports,
|
|
10530
|
-
/** `z` */
|
|
10531
|
-
extrinsicSize,
|
|
10532
|
-
/** `x` */
|
|
10533
|
-
extrinsicCount,
|
|
10534
|
-
/** `a.0` */
|
|
10535
|
-
accumulateCount,
|
|
10536
|
-
/** `a.1` */
|
|
10537
|
-
accumulateGasUsed,
|
|
10538
|
-
/** `t.0` */
|
|
10539
|
-
onTransfersCount,
|
|
10540
|
-
/** `t.1` */
|
|
10541
|
-
onTransfersGasUsed) {
|
|
10542
|
-
this.providedCount = providedCount;
|
|
10543
|
-
this.providedSize = providedSize;
|
|
10544
|
-
this.refinementCount = refinementCount;
|
|
10545
|
-
this.refinementGasUsed = refinementGasUsed;
|
|
10546
|
-
this.imports = imports;
|
|
10547
|
-
this.exports = exports;
|
|
10548
|
-
this.extrinsicSize = extrinsicSize;
|
|
10549
|
-
this.extrinsicCount = extrinsicCount;
|
|
10550
|
-
this.accumulateCount = accumulateCount;
|
|
10551
|
-
this.accumulateGasUsed = accumulateGasUsed;
|
|
10552
|
-
this.onTransfersCount = onTransfersCount;
|
|
10553
|
-
this.onTransfersGasUsed = onTransfersGasUsed;
|
|
10690
|
+
*
|
|
10691
|
+
* Can either create/modify an entry or remove it.
|
|
10692
|
+
*/
|
|
10693
|
+
class UpdateStorage {
|
|
10694
|
+
action;
|
|
10695
|
+
constructor(action) {
|
|
10696
|
+
this.action = action;
|
|
10554
10697
|
}
|
|
10555
|
-
static
|
|
10556
|
-
|
|
10557
|
-
const zero16 = numbers_tryAsU16(0);
|
|
10558
|
-
const zeroGas = tryAsServiceGas(0);
|
|
10559
|
-
return new ServiceStatistics(zero16, zero, zero, zeroGas, zero16, zero16, zero, zero16, zero, zeroGas, zero, zeroGas);
|
|
10698
|
+
static set({ storage }) {
|
|
10699
|
+
return new UpdateStorage({ kind: UpdateStorageKind.Set, storage });
|
|
10560
10700
|
}
|
|
10561
|
-
}
|
|
10562
|
-
|
|
10563
|
-
class StatisticsData {
|
|
10564
|
-
current;
|
|
10565
|
-
previous;
|
|
10566
|
-
cores;
|
|
10567
|
-
services;
|
|
10568
|
-
static Codec = descriptors_codec.Class(StatisticsData, {
|
|
10569
|
-
current: codecPerValidator(ValidatorStatistics.Codec),
|
|
10570
|
-
previous: codecPerValidator(ValidatorStatistics.Codec),
|
|
10571
|
-
cores: codecPerCore(CoreStatistics.Codec),
|
|
10572
|
-
services: descriptors_codec.dictionary(codecServiceId, ServiceStatistics.Codec, {
|
|
10573
|
-
sortKeys: (a, b) => a - b,
|
|
10574
|
-
}),
|
|
10575
|
-
});
|
|
10576
|
-
static create(v) {
|
|
10577
|
-
return new StatisticsData(v.current, v.previous, v.cores, v.services);
|
|
10701
|
+
static remove({ key }) {
|
|
10702
|
+
return new UpdateStorage({ kind: UpdateStorageKind.Remove, key });
|
|
10578
10703
|
}
|
|
10579
|
-
|
|
10580
|
-
this.
|
|
10581
|
-
|
|
10582
|
-
|
|
10583
|
-
this.
|
|
10704
|
+
get key() {
|
|
10705
|
+
if (this.action.kind === UpdateStorageKind.Remove) {
|
|
10706
|
+
return this.action.key;
|
|
10707
|
+
}
|
|
10708
|
+
return this.action.storage.key;
|
|
10709
|
+
}
|
|
10710
|
+
get value() {
|
|
10711
|
+
if (this.action.kind === UpdateStorageKind.Remove) {
|
|
10712
|
+
return null;
|
|
10713
|
+
}
|
|
10714
|
+
return this.action.storage.value;
|
|
10584
10715
|
}
|
|
10585
10716
|
}
|
|
10586
10717
|
|
|
@@ -10605,6 +10736,7 @@ class StatisticsData {
|
|
|
10605
10736
|
|
|
10606
10737
|
|
|
10607
10738
|
|
|
10739
|
+
|
|
10608
10740
|
|
|
10609
10741
|
|
|
10610
10742
|
var in_memory_state_UpdateError;
|
|
@@ -10705,10 +10837,11 @@ class InMemoryService extends WithDebug {
|
|
|
10705
10837
|
/**
|
|
10706
10838
|
* A special version of state, stored fully in-memory.
|
|
10707
10839
|
*/
|
|
10708
|
-
class
|
|
10840
|
+
class in_memory_state_InMemoryState extends WithDebug {
|
|
10841
|
+
chainSpec;
|
|
10709
10842
|
/** Create a new `InMemoryState` by providing all required fields. */
|
|
10710
|
-
static
|
|
10711
|
-
return new
|
|
10843
|
+
static new(chainSpec, state) {
|
|
10844
|
+
return new in_memory_state_InMemoryState(chainSpec, state);
|
|
10712
10845
|
}
|
|
10713
10846
|
/**
|
|
10714
10847
|
* Create a new `InMemoryState` with a partial state override.
|
|
@@ -10717,14 +10850,14 @@ class InMemoryState extends WithDebug {
|
|
|
10717
10850
|
* not-necessarily coherent values.
|
|
10718
10851
|
*/
|
|
10719
10852
|
static partial(spec, partial) {
|
|
10720
|
-
const state =
|
|
10853
|
+
const state = in_memory_state_InMemoryState.empty(spec);
|
|
10721
10854
|
Object.assign(state, partial);
|
|
10722
10855
|
return state;
|
|
10723
10856
|
}
|
|
10724
10857
|
/**
|
|
10725
10858
|
* Create a new `InMemoryState` from some other state object.
|
|
10726
10859
|
*/
|
|
10727
|
-
static copyFrom(other, servicesData) {
|
|
10860
|
+
static copyFrom(chainSpec, other, servicesData) {
|
|
10728
10861
|
const services = new Map();
|
|
10729
10862
|
for (const [id, entries] of servicesData.entries()) {
|
|
10730
10863
|
const service = other.getService(id);
|
|
@@ -10734,7 +10867,7 @@ class InMemoryState extends WithDebug {
|
|
|
10734
10867
|
const inMemService = InMemoryService.copyFrom(service, entries);
|
|
10735
10868
|
services.set(id, inMemService);
|
|
10736
10869
|
}
|
|
10737
|
-
return
|
|
10870
|
+
return in_memory_state_InMemoryState.new(chainSpec, {
|
|
10738
10871
|
availabilityAssignment: other.availabilityAssignment,
|
|
10739
10872
|
accumulationQueue: other.accumulationQueue,
|
|
10740
10873
|
designatedValidatorData: other.designatedValidatorData,
|
|
@@ -10775,12 +10908,12 @@ class InMemoryState extends WithDebug {
|
|
|
10775
10908
|
* Modify the state and apply a single state update.
|
|
10776
10909
|
*/
|
|
10777
10910
|
applyUpdate(update) {
|
|
10778
|
-
const {
|
|
10911
|
+
const { removed, created: _, updated, preimages, storage, ...rest } = update;
|
|
10779
10912
|
// just assign all other variables
|
|
10780
10913
|
Object.assign(this, rest);
|
|
10781
10914
|
// and update the services state
|
|
10782
10915
|
let result;
|
|
10783
|
-
result = this.updateServices(
|
|
10916
|
+
result = this.updateServices(updated);
|
|
10784
10917
|
if (result.isError) {
|
|
10785
10918
|
return result;
|
|
10786
10919
|
}
|
|
@@ -10792,7 +10925,7 @@ class InMemoryState extends WithDebug {
|
|
|
10792
10925
|
if (result.isError) {
|
|
10793
10926
|
return result;
|
|
10794
10927
|
}
|
|
10795
|
-
this.removeServices(
|
|
10928
|
+
this.removeServices(removed);
|
|
10796
10929
|
return result_Result.ok(result_OK);
|
|
10797
10930
|
}
|
|
10798
10931
|
removeServices(servicesRemoved) {
|
|
@@ -10801,89 +10934,102 @@ class InMemoryState extends WithDebug {
|
|
|
10801
10934
|
this.services.delete(serviceId);
|
|
10802
10935
|
}
|
|
10803
10936
|
}
|
|
10804
|
-
updateStorage(
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10937
|
+
updateStorage(storageUpdates) {
|
|
10938
|
+
if (storageUpdates === undefined) {
|
|
10939
|
+
return result_Result.ok(result_OK);
|
|
10940
|
+
}
|
|
10941
|
+
for (const [serviceId, updates] of storageUpdates.entries()) {
|
|
10942
|
+
for (const update of updates) {
|
|
10943
|
+
const { kind } = update.action;
|
|
10944
|
+
const service = this.services.get(serviceId);
|
|
10945
|
+
if (service === undefined) {
|
|
10946
|
+
return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update storage of non-existing service: ${serviceId}`);
|
|
10947
|
+
}
|
|
10948
|
+
if (kind === UpdateStorageKind.Set) {
|
|
10949
|
+
const { key, value } = update.action.storage;
|
|
10950
|
+
service.data.storage.set(key.toString(), StorageItem.create({ key, value }));
|
|
10951
|
+
}
|
|
10952
|
+
else if (kind === UpdateStorageKind.Remove) {
|
|
10953
|
+
const { key } = update.action;
|
|
10954
|
+
debug_check `
|
|
10818
10955
|
${service.data.storage.has(key.toString())}
|
|
10819
|
-
Attempting to remove non-existing storage item at ${serviceId}: ${action.key}
|
|
10956
|
+
Attempting to remove non-existing storage item at ${serviceId}: ${update.action.key}
|
|
10820
10957
|
`;
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10958
|
+
service.data.storage.delete(key.toString());
|
|
10959
|
+
}
|
|
10960
|
+
else {
|
|
10961
|
+
debug_assertNever(kind);
|
|
10962
|
+
}
|
|
10825
10963
|
}
|
|
10826
10964
|
}
|
|
10827
10965
|
return result_Result.ok(result_OK);
|
|
10828
10966
|
}
|
|
10829
|
-
updatePreimages(
|
|
10830
|
-
|
|
10967
|
+
updatePreimages(preimagesUpdates) {
|
|
10968
|
+
if (preimagesUpdates === undefined) {
|
|
10969
|
+
return result_Result.ok(result_OK);
|
|
10970
|
+
}
|
|
10971
|
+
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
10831
10972
|
const service = this.services.get(serviceId);
|
|
10832
10973
|
if (service === undefined) {
|
|
10833
|
-
return result_Result.error(in_memory_state_UpdateError.NoService, `Attempting to update preimage of non-existing service: ${serviceId}`);
|
|
10834
|
-
}
|
|
10835
|
-
const
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
|
|
10845
|
-
|
|
10846
|
-
|
|
10847
|
-
|
|
10848
|
-
|
|
10974
|
+
return result_Result.error(in_memory_state_UpdateError.NoService, () => `Attempting to update preimage of non-existing service: ${serviceId}`);
|
|
10975
|
+
}
|
|
10976
|
+
for (const update of updates) {
|
|
10977
|
+
const { kind } = update.action;
|
|
10978
|
+
if (kind === UpdatePreimageKind.Provide) {
|
|
10979
|
+
const { preimage, slot } = update.action;
|
|
10980
|
+
if (service.data.preimages.has(preimage.hash)) {
|
|
10981
|
+
return result_Result.error(in_memory_state_UpdateError.PreimageExists, () => `Overwriting existing preimage at ${serviceId}: ${preimage}`);
|
|
10982
|
+
}
|
|
10983
|
+
service.data.preimages.set(preimage.hash, preimage);
|
|
10984
|
+
if (slot !== null) {
|
|
10985
|
+
const lookupHistory = service.data.lookupHistory.get(preimage.hash);
|
|
10986
|
+
const length = numbers_tryAsU32(preimage.blob.length);
|
|
10987
|
+
const lookup = new LookupHistoryItem(preimage.hash, length, tryAsLookupHistorySlots([slot]));
|
|
10988
|
+
if (lookupHistory === undefined) {
|
|
10989
|
+
// no lookup history for that preimage at all (edge case, should be requested)
|
|
10990
|
+
service.data.lookupHistory.set(preimage.hash, [lookup]);
|
|
10991
|
+
}
|
|
10992
|
+
else {
|
|
10993
|
+
// insert or replace exiting entry
|
|
10994
|
+
const index = lookupHistory.map((x) => x.length).indexOf(length);
|
|
10995
|
+
lookupHistory.splice(index, index === -1 ? 0 : 1, lookup);
|
|
10996
|
+
}
|
|
10849
10997
|
}
|
|
10850
|
-
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
|
|
10998
|
+
}
|
|
10999
|
+
else if (kind === UpdatePreimageKind.Remove) {
|
|
11000
|
+
const { hash, length } = update.action;
|
|
11001
|
+
service.data.preimages.delete(hash);
|
|
11002
|
+
const history = service.data.lookupHistory.get(hash) ?? [];
|
|
11003
|
+
const idx = history.map((x) => x.length).indexOf(length);
|
|
11004
|
+
if (idx !== -1) {
|
|
11005
|
+
history.splice(idx, 1);
|
|
10854
11006
|
}
|
|
10855
11007
|
}
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
11008
|
+
else if (kind === UpdatePreimageKind.UpdateOrAdd) {
|
|
11009
|
+
const { item } = update.action;
|
|
11010
|
+
const history = service.data.lookupHistory.get(item.hash) ?? [];
|
|
11011
|
+
const existingIdx = history.map((x) => x.length).indexOf(item.length);
|
|
11012
|
+
const removeCount = existingIdx === -1 ? 0 : 1;
|
|
11013
|
+
history.splice(existingIdx, removeCount, item);
|
|
11014
|
+
service.data.lookupHistory.set(item.hash, history);
|
|
11015
|
+
}
|
|
11016
|
+
else {
|
|
11017
|
+
debug_assertNever(kind);
|
|
10864
11018
|
}
|
|
10865
|
-
}
|
|
10866
|
-
else if (kind === UpdatePreimageKind.UpdateOrAdd) {
|
|
10867
|
-
const { item } = action;
|
|
10868
|
-
const history = service.data.lookupHistory.get(item.hash) ?? [];
|
|
10869
|
-
const existingIdx = history.map((x) => x.length).indexOf(item.length);
|
|
10870
|
-
const removeCount = existingIdx === -1 ? 0 : 1;
|
|
10871
|
-
history.splice(existingIdx, removeCount, item);
|
|
10872
|
-
service.data.lookupHistory.set(item.hash, history);
|
|
10873
|
-
}
|
|
10874
|
-
else {
|
|
10875
|
-
debug_assertNever(kind);
|
|
10876
11019
|
}
|
|
10877
11020
|
}
|
|
10878
11021
|
return result_Result.ok(result_OK);
|
|
10879
11022
|
}
|
|
10880
11023
|
updateServices(servicesUpdates) {
|
|
10881
|
-
|
|
10882
|
-
|
|
11024
|
+
if (servicesUpdates === undefined) {
|
|
11025
|
+
return result_Result.ok(result_OK);
|
|
11026
|
+
}
|
|
11027
|
+
for (const [serviceId, update] of servicesUpdates.entries()) {
|
|
11028
|
+
const { kind, account } = update.action;
|
|
10883
11029
|
if (kind === UpdateServiceKind.Create) {
|
|
10884
|
-
const { lookupHistory } = action;
|
|
11030
|
+
const { lookupHistory } = update.action;
|
|
10885
11031
|
if (this.services.has(serviceId)) {
|
|
10886
|
-
return result_Result.error(in_memory_state_UpdateError.DuplicateService, `${serviceId} already exists!`);
|
|
11032
|
+
return result_Result.error(in_memory_state_UpdateError.DuplicateService, () => `${serviceId} already exists!`);
|
|
10887
11033
|
}
|
|
10888
11034
|
this.services.set(serviceId, new InMemoryService(serviceId, {
|
|
10889
11035
|
info: account,
|
|
@@ -10895,7 +11041,7 @@ class InMemoryState extends WithDebug {
|
|
|
10895
11041
|
else if (kind === UpdateServiceKind.Update) {
|
|
10896
11042
|
const existingService = this.services.get(serviceId);
|
|
10897
11043
|
if (existingService === undefined) {
|
|
10898
|
-
return result_Result.error(in_memory_state_UpdateError.NoService, `Cannot update ${serviceId} because it does not exist.`);
|
|
11044
|
+
return result_Result.error(in_memory_state_UpdateError.NoService, () => `Cannot update ${serviceId} because it does not exist.`);
|
|
10899
11045
|
}
|
|
10900
11046
|
existingService.data.info = account;
|
|
10901
11047
|
}
|
|
@@ -10931,8 +11077,9 @@ class InMemoryState extends WithDebug {
|
|
|
10931
11077
|
getService(id) {
|
|
10932
11078
|
return this.services.get(id) ?? null;
|
|
10933
11079
|
}
|
|
10934
|
-
constructor(s) {
|
|
11080
|
+
constructor(chainSpec, s) {
|
|
10935
11081
|
super();
|
|
11082
|
+
this.chainSpec = chainSpec;
|
|
10936
11083
|
this.availabilityAssignment = s.availabilityAssignment;
|
|
10937
11084
|
this.designatedValidatorData = s.designatedValidatorData;
|
|
10938
11085
|
this.nextValidatorData = s.nextValidatorData;
|
|
@@ -10954,31 +11101,34 @@ class InMemoryState extends WithDebug {
|
|
|
10954
11101
|
this.accumulationOutputLog = s.accumulationOutputLog;
|
|
10955
11102
|
this.services = s.services;
|
|
10956
11103
|
}
|
|
11104
|
+
view() {
|
|
11105
|
+
return new InMemoryStateView(this.chainSpec, this);
|
|
11106
|
+
}
|
|
10957
11107
|
/**
|
|
10958
11108
|
* Create an empty and possibly incoherent `InMemoryState`.
|
|
10959
11109
|
*/
|
|
10960
11110
|
static empty(spec) {
|
|
10961
|
-
return new
|
|
11111
|
+
return new in_memory_state_InMemoryState(spec, {
|
|
10962
11112
|
availabilityAssignment: tryAsPerCore(Array.from({ length: spec.coresCount }, () => null), spec),
|
|
10963
|
-
designatedValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () =>
|
|
11113
|
+
designatedValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () => validator_data_ValidatorData.create({
|
|
10964
11114
|
bandersnatch: bytes_Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
10965
11115
|
bls: bytes_Bytes.zero(BLS_KEY_BYTES).asOpaque(),
|
|
10966
11116
|
ed25519: bytes_Bytes.zero(ED25519_KEY_BYTES).asOpaque(),
|
|
10967
11117
|
metadata: bytes_Bytes.zero(VALIDATOR_META_BYTES).asOpaque(),
|
|
10968
11118
|
})), spec),
|
|
10969
|
-
nextValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () =>
|
|
11119
|
+
nextValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () => validator_data_ValidatorData.create({
|
|
10970
11120
|
bandersnatch: bytes_Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
10971
11121
|
bls: bytes_Bytes.zero(BLS_KEY_BYTES).asOpaque(),
|
|
10972
11122
|
ed25519: bytes_Bytes.zero(ED25519_KEY_BYTES).asOpaque(),
|
|
10973
11123
|
metadata: bytes_Bytes.zero(VALIDATOR_META_BYTES).asOpaque(),
|
|
10974
11124
|
})), spec),
|
|
10975
|
-
currentValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () =>
|
|
11125
|
+
currentValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () => validator_data_ValidatorData.create({
|
|
10976
11126
|
bandersnatch: bytes_Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
10977
11127
|
bls: bytes_Bytes.zero(BLS_KEY_BYTES).asOpaque(),
|
|
10978
11128
|
ed25519: bytes_Bytes.zero(ED25519_KEY_BYTES).asOpaque(),
|
|
10979
11129
|
metadata: bytes_Bytes.zero(VALIDATOR_META_BYTES).asOpaque(),
|
|
10980
11130
|
})), spec),
|
|
10981
|
-
previousValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () =>
|
|
11131
|
+
previousValidatorData: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () => validator_data_ValidatorData.create({
|
|
10982
11132
|
bandersnatch: bytes_Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
10983
11133
|
bls: bytes_Bytes.zero(BLS_KEY_BYTES).asOpaque(),
|
|
10984
11134
|
ed25519: bytes_Bytes.zero(ED25519_KEY_BYTES).asOpaque(),
|
|
@@ -10994,7 +11144,7 @@ class InMemoryState extends WithDebug {
|
|
|
10994
11144
|
entropy: FixedSizeArray.fill(() => bytes_Bytes.zero(hash_HASH_SIZE).asOpaque(), ENTROPY_ENTRIES),
|
|
10995
11145
|
authPools: tryAsPerCore(Array.from({ length: spec.coresCount }, () => sized_array_asKnownSize([])), spec),
|
|
10996
11146
|
authQueues: tryAsPerCore(Array.from({ length: spec.coresCount }, () => FixedSizeArray.fill(() => bytes_Bytes.zero(hash_HASH_SIZE).asOpaque(), AUTHORIZATION_QUEUE_SIZE)), spec),
|
|
10997
|
-
recentBlocks:
|
|
11147
|
+
recentBlocks: RecentBlocks.empty(),
|
|
10998
11148
|
statistics: StatisticsData.create({
|
|
10999
11149
|
current: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () => ValidatorStatistics.empty()), spec),
|
|
11000
11150
|
previous: tryAsPerValidator(Array.from({ length: spec.validatorsCount }, () => ValidatorStatistics.empty()), spec),
|
|
@@ -11004,8 +11154,8 @@ class InMemoryState extends WithDebug {
|
|
|
11004
11154
|
accumulationQueue: tryAsPerEpochBlock(Array.from({ length: spec.epochLength }, () => []), spec),
|
|
11005
11155
|
recentlyAccumulated: tryAsPerEpochBlock(Array.from({ length: spec.epochLength }, () => HashSet.new()), spec),
|
|
11006
11156
|
ticketsAccumulator: sized_array_asKnownSize([]),
|
|
11007
|
-
sealingKeySeries:
|
|
11008
|
-
epochRoot: bytes_Bytes.zero(
|
|
11157
|
+
sealingKeySeries: safrole_data_SafroleSealingKeysData.keys(tryAsPerEpochBlock(Array.from({ length: spec.epochLength }, () => bytes_Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque()), spec)),
|
|
11158
|
+
epochRoot: bytes_Bytes.zero(bandersnatch_BANDERSNATCH_RING_ROOT_BYTES).asOpaque(),
|
|
11009
11159
|
privilegedServices: PrivilegedServices.create({
|
|
11010
11160
|
manager: tryAsServiceId(0),
|
|
11011
11161
|
assigners: tryAsPerCore(new Array(spec.coresCount).fill(tryAsServiceId(0)), spec),
|
|
@@ -11045,51 +11195,10 @@ const serviceDataCodec = descriptors_codec.dictionary(descriptors_codec.u32.asOp
|
|
|
11045
11195
|
|
|
11046
11196
|
|
|
11047
11197
|
|
|
11048
|
-
;// CONCATENATED MODULE: ./packages/jam/state/not-yet-accumulated.ts
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
11198
|
|
|
11052
11199
|
|
|
11053
11200
|
|
|
11054
11201
|
|
|
11055
|
-
/**
|
|
11056
|
-
* Ready (i.e. available and/or audited) but not-yet-accumulated work-reports.
|
|
11057
|
-
*
|
|
11058
|
-
* https://graypaper.fluffylabs.dev/#/5f542d7/165300165400
|
|
11059
|
-
*/
|
|
11060
|
-
class NotYetAccumulatedReport extends WithDebug {
|
|
11061
|
-
report;
|
|
11062
|
-
dependencies;
|
|
11063
|
-
static Codec = descriptors_codec.Class(NotYetAccumulatedReport, {
|
|
11064
|
-
report: WorkReport.Codec,
|
|
11065
|
-
dependencies: codecKnownSizeArray(descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(), {
|
|
11066
|
-
typicalLength: MAX_REPORT_DEPENDENCIES / 2,
|
|
11067
|
-
maxLength: MAX_REPORT_DEPENDENCIES,
|
|
11068
|
-
minLength: 0,
|
|
11069
|
-
}),
|
|
11070
|
-
});
|
|
11071
|
-
static create({ report, dependencies }) {
|
|
11072
|
-
return new NotYetAccumulatedReport(report, dependencies);
|
|
11073
|
-
}
|
|
11074
|
-
constructor(
|
|
11075
|
-
/**
|
|
11076
|
-
* Each of these were made available at most one epoch ago
|
|
11077
|
-
* but have or had unfulfilled dependencies.
|
|
11078
|
-
*/
|
|
11079
|
-
report,
|
|
11080
|
-
/**
|
|
11081
|
-
* Alongside the work-report itself, we retain its un-accumulated
|
|
11082
|
-
* dependencies, a set of work-package hashes.
|
|
11083
|
-
*
|
|
11084
|
-
* https://graypaper.fluffylabs.dev/#/5f542d7/165800165800
|
|
11085
|
-
*/
|
|
11086
|
-
dependencies) {
|
|
11087
|
-
super();
|
|
11088
|
-
this.report = report;
|
|
11089
|
-
this.dependencies = dependencies;
|
|
11090
|
-
}
|
|
11091
|
-
}
|
|
11092
|
-
|
|
11093
11202
|
;// CONCATENATED MODULE: ./packages/jam/state-merkleization/serialize.ts
|
|
11094
11203
|
|
|
11095
11204
|
|
|
@@ -11102,26 +11211,19 @@ class NotYetAccumulatedReport extends WithDebug {
|
|
|
11102
11211
|
|
|
11103
11212
|
|
|
11104
11213
|
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
11214
|
/** Serialization for particular state entries. */
|
|
11109
|
-
var
|
|
11215
|
+
var serialize_serialize;
|
|
11110
11216
|
(function (serialize) {
|
|
11111
11217
|
/** C(1): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b15013b1501?v=0.6.7 */
|
|
11112
11218
|
serialize.authPools = {
|
|
11113
11219
|
key: stateKeys.index(StateKeyIdx.Alpha),
|
|
11114
|
-
Codec:
|
|
11115
|
-
minLength: 0,
|
|
11116
|
-
maxLength: MAX_AUTH_POOL_SIZE,
|
|
11117
|
-
typicalLength: MAX_AUTH_POOL_SIZE,
|
|
11118
|
-
})),
|
|
11220
|
+
Codec: authPoolsCodec,
|
|
11119
11221
|
extract: (s) => s.authPools,
|
|
11120
11222
|
};
|
|
11121
11223
|
/** C(2): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b31013b3101?v=0.6.7 */
|
|
11122
11224
|
serialize.authQueues = {
|
|
11123
11225
|
key: stateKeys.index(StateKeyIdx.Phi),
|
|
11124
|
-
Codec:
|
|
11226
|
+
Codec: authQueuesCodec,
|
|
11125
11227
|
extract: (s) => s.authQueues,
|
|
11126
11228
|
};
|
|
11127
11229
|
/**
|
|
@@ -11130,7 +11232,7 @@ var serialize;
|
|
|
11130
11232
|
*/
|
|
11131
11233
|
serialize.recentBlocks = {
|
|
11132
11234
|
key: stateKeys.index(StateKeyIdx.Beta),
|
|
11133
|
-
Codec:
|
|
11235
|
+
Codec: RecentBlocks.Codec,
|
|
11134
11236
|
extract: (s) => s.recentBlocks,
|
|
11135
11237
|
};
|
|
11136
11238
|
/** C(4): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b63013b6301?v=0.6.7 */
|
|
@@ -11159,25 +11261,25 @@ var serialize;
|
|
|
11159
11261
|
/** C(7): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b00023b0002?v=0.6.7 */
|
|
11160
11262
|
serialize.designatedValidators = {
|
|
11161
11263
|
key: stateKeys.index(StateKeyIdx.Iota),
|
|
11162
|
-
Codec:
|
|
11264
|
+
Codec: validatorsDataCodec,
|
|
11163
11265
|
extract: (s) => s.designatedValidatorData,
|
|
11164
11266
|
};
|
|
11165
11267
|
/** C(8): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b0d023b0d02?v=0.6.7 */
|
|
11166
11268
|
serialize.currentValidators = {
|
|
11167
11269
|
key: stateKeys.index(StateKeyIdx.Kappa),
|
|
11168
|
-
Codec:
|
|
11270
|
+
Codec: validatorsDataCodec,
|
|
11169
11271
|
extract: (s) => s.currentValidatorData,
|
|
11170
11272
|
};
|
|
11171
11273
|
/** C(9): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b1a023b1a02?v=0.6.7 */
|
|
11172
11274
|
serialize.previousValidators = {
|
|
11173
11275
|
key: stateKeys.index(StateKeyIdx.Lambda),
|
|
11174
|
-
Codec:
|
|
11276
|
+
Codec: validatorsDataCodec,
|
|
11175
11277
|
extract: (s) => s.previousValidatorData,
|
|
11176
11278
|
};
|
|
11177
11279
|
/** C(10): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b27023b2702?v=0.6.7 */
|
|
11178
11280
|
serialize.availabilityAssignment = {
|
|
11179
11281
|
key: stateKeys.index(StateKeyIdx.Rho),
|
|
11180
|
-
Codec:
|
|
11282
|
+
Codec: availabilityAssignmentsCodec,
|
|
11181
11283
|
extract: (s) => s.availabilityAssignment,
|
|
11182
11284
|
};
|
|
11183
11285
|
/** C(11): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b3e023b3e02?v=0.6.7 */
|
|
@@ -11201,13 +11303,13 @@ var serialize;
|
|
|
11201
11303
|
/** C(14): https://graypaper.fluffylabs.dev/#/1c979cb/3bf0023bf002?v=0.7.1 */
|
|
11202
11304
|
serialize.accumulationQueue = {
|
|
11203
11305
|
key: stateKeys.index(StateKeyIdx.Omega),
|
|
11204
|
-
Codec:
|
|
11306
|
+
Codec: accumulationQueueCodec,
|
|
11205
11307
|
extract: (s) => s.accumulationQueue,
|
|
11206
11308
|
};
|
|
11207
11309
|
/** C(15): https://graypaper.fluffylabs.dev/#/7e6ff6a/3b96023b9602?v=0.6.7 */
|
|
11208
11310
|
serialize.recentlyAccumulated = {
|
|
11209
11311
|
key: stateKeys.index(StateKeyIdx.Xi),
|
|
11210
|
-
Codec:
|
|
11312
|
+
Codec: recentlyAccumulatedCodec,
|
|
11211
11313
|
extract: (s) => s.recentlyAccumulated,
|
|
11212
11314
|
};
|
|
11213
11315
|
/** C(16): https://graypaper.fluffylabs.dev/#/38c4e62/3b46033b4603?v=0.7.0 */
|
|
@@ -11236,9 +11338,9 @@ var serialize;
|
|
|
11236
11338
|
/** https://graypaper.fluffylabs.dev/#/85129da/387603387603?v=0.6.3 */
|
|
11237
11339
|
serialize.serviceLookupHistory = (blake2b, serviceId, hash, len) => ({
|
|
11238
11340
|
key: stateKeys.serviceLookupHistory(blake2b, serviceId, hash, len),
|
|
11239
|
-
Codec:
|
|
11341
|
+
Codec: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(descriptors_codec.u32)),
|
|
11240
11342
|
});
|
|
11241
|
-
})(
|
|
11343
|
+
})(serialize_serialize || (serialize_serialize = {}));
|
|
11242
11344
|
/**
|
|
11243
11345
|
* Just dump the entire terminal blob as-is.
|
|
11244
11346
|
*
|
|
@@ -11248,6 +11350,87 @@ var serialize;
|
|
|
11248
11350
|
*/
|
|
11249
11351
|
const dumpCodec = Descriptor.new("Dump", { bytes: 64, isExact: false }, (e, v) => e.bytes(bytes_Bytes.fromBlob(v.raw, v.raw.length)), (d) => bytes_BytesBlob.blobFrom(d.bytes(d.source.length - d.bytesRead()).raw), (s) => s.bytes(s.decoder.source.length - s.decoder.bytesRead()));
|
|
11250
11352
|
|
|
11353
|
+
;// CONCATENATED MODULE: ./packages/jam/state-merkleization/serialized-state-view.ts
|
|
11354
|
+
|
|
11355
|
+
|
|
11356
|
+
class SerializedStateView {
|
|
11357
|
+
spec;
|
|
11358
|
+
backend;
|
|
11359
|
+
recentlyUsedServices;
|
|
11360
|
+
viewCache;
|
|
11361
|
+
constructor(spec, backend,
|
|
11362
|
+
/** Best-effort list of recently active services. */
|
|
11363
|
+
recentlyUsedServices, viewCache) {
|
|
11364
|
+
this.spec = spec;
|
|
11365
|
+
this.backend = backend;
|
|
11366
|
+
this.recentlyUsedServices = recentlyUsedServices;
|
|
11367
|
+
this.viewCache = viewCache;
|
|
11368
|
+
}
|
|
11369
|
+
retrieveView({ key, Codec }, description) {
|
|
11370
|
+
const cached = this.viewCache.get(key);
|
|
11371
|
+
if (cached !== undefined) {
|
|
11372
|
+
return cached;
|
|
11373
|
+
}
|
|
11374
|
+
const bytes = this.backend.get(key);
|
|
11375
|
+
if (bytes === null) {
|
|
11376
|
+
throw new Error(`Required state entry for ${description} is missing!. Accessing view of key: ${key}`);
|
|
11377
|
+
}
|
|
11378
|
+
// NOTE [ToDr] we are not using `Decoder.decodeObject` here because
|
|
11379
|
+
// it needs to get to the end of the data (skip), yet that's expensive.
|
|
11380
|
+
// we assume that the state data is correct and coherent anyway, so
|
|
11381
|
+
// for performance reasons we simply create the view here.
|
|
11382
|
+
const d = decoder_Decoder.fromBytesBlob(bytes);
|
|
11383
|
+
d.attachContext(this.spec);
|
|
11384
|
+
const view = Codec.View.decode(d);
|
|
11385
|
+
this.viewCache.set(key, view);
|
|
11386
|
+
return view;
|
|
11387
|
+
}
|
|
11388
|
+
availabilityAssignmentView() {
|
|
11389
|
+
return this.retrieveView(serialize_serialize.availabilityAssignment, "availabilityAssignmentView");
|
|
11390
|
+
}
|
|
11391
|
+
designatedValidatorDataView() {
|
|
11392
|
+
return this.retrieveView(serialize_serialize.designatedValidators, "designatedValidatorsView");
|
|
11393
|
+
}
|
|
11394
|
+
currentValidatorDataView() {
|
|
11395
|
+
return this.retrieveView(serialize_serialize.currentValidators, "currentValidatorsView");
|
|
11396
|
+
}
|
|
11397
|
+
previousValidatorDataView() {
|
|
11398
|
+
return this.retrieveView(serialize_serialize.previousValidators, "previousValidatorsView");
|
|
11399
|
+
}
|
|
11400
|
+
authPoolsView() {
|
|
11401
|
+
return this.retrieveView(serialize_serialize.authPools, "authPoolsView");
|
|
11402
|
+
}
|
|
11403
|
+
authQueuesView() {
|
|
11404
|
+
return this.retrieveView(serialize_serialize.authQueues, "authQueuesView");
|
|
11405
|
+
}
|
|
11406
|
+
recentBlocksView() {
|
|
11407
|
+
return this.retrieveView(serialize_serialize.recentBlocks, "recentBlocksView");
|
|
11408
|
+
}
|
|
11409
|
+
statisticsView() {
|
|
11410
|
+
return this.retrieveView(serialize_serialize.statistics, "statisticsView");
|
|
11411
|
+
}
|
|
11412
|
+
accumulationQueueView() {
|
|
11413
|
+
return this.retrieveView(serialize_serialize.accumulationQueue, "accumulationQueueView");
|
|
11414
|
+
}
|
|
11415
|
+
recentlyAccumulatedView() {
|
|
11416
|
+
return this.retrieveView(serialize_serialize.recentlyAccumulated, "recentlyAccumulatedView");
|
|
11417
|
+
}
|
|
11418
|
+
safroleDataView() {
|
|
11419
|
+
return this.retrieveView(serialize_serialize.safrole, "safroleDataView");
|
|
11420
|
+
}
|
|
11421
|
+
getServiceInfoView(id) {
|
|
11422
|
+
const serviceData = serialize_serialize.serviceData(id);
|
|
11423
|
+
const bytes = this.backend.get(serviceData.key);
|
|
11424
|
+
if (bytes === null) {
|
|
11425
|
+
return null;
|
|
11426
|
+
}
|
|
11427
|
+
if (!this.recentlyUsedServices.includes(id)) {
|
|
11428
|
+
this.recentlyUsedServices.push(id);
|
|
11429
|
+
}
|
|
11430
|
+
return decoder_Decoder.decodeObject(serviceData.Codec.View, bytes, this.spec);
|
|
11431
|
+
}
|
|
11432
|
+
}
|
|
11433
|
+
|
|
11251
11434
|
;// CONCATENATED MODULE: ./packages/jam/state-merkleization/serialized-state.ts
|
|
11252
11435
|
|
|
11253
11436
|
|
|
@@ -11256,6 +11439,8 @@ const dumpCodec = Descriptor.new("Dump", { bytes: 64, isExact: false }, (e, v) =
|
|
|
11256
11439
|
|
|
11257
11440
|
|
|
11258
11441
|
|
|
11442
|
+
|
|
11443
|
+
|
|
11259
11444
|
/**
|
|
11260
11445
|
* State object which reads it's entries from some backend.
|
|
11261
11446
|
*
|
|
@@ -11268,7 +11453,7 @@ class serialized_state_SerializedState {
|
|
|
11268
11453
|
spec;
|
|
11269
11454
|
blake2b;
|
|
11270
11455
|
backend;
|
|
11271
|
-
|
|
11456
|
+
recentlyUsedServices;
|
|
11272
11457
|
/** Create a state-like object from collection of serialized entries. */
|
|
11273
11458
|
static fromStateEntries(spec, blake2b, state, recentServices = []) {
|
|
11274
11459
|
return new serialized_state_SerializedState(spec, blake2b, state, recentServices);
|
|
@@ -11277,106 +11462,120 @@ class serialized_state_SerializedState {
|
|
|
11277
11462
|
static new(spec, blake2b, db, recentServices = []) {
|
|
11278
11463
|
return new serialized_state_SerializedState(spec, blake2b, db, recentServices);
|
|
11279
11464
|
}
|
|
11465
|
+
dataCache = hash_dictionary_HashDictionary.new();
|
|
11466
|
+
viewCache = hash_dictionary_HashDictionary.new();
|
|
11280
11467
|
constructor(spec, blake2b, backend,
|
|
11281
11468
|
/** Best-effort list of recently active services. */
|
|
11282
|
-
|
|
11469
|
+
recentlyUsedServices) {
|
|
11283
11470
|
this.spec = spec;
|
|
11284
11471
|
this.blake2b = blake2b;
|
|
11285
11472
|
this.backend = backend;
|
|
11286
|
-
this.
|
|
11473
|
+
this.recentlyUsedServices = recentlyUsedServices;
|
|
11287
11474
|
}
|
|
11288
11475
|
/** Comparing the serialized states, just means comparing their backends. */
|
|
11289
11476
|
[TEST_COMPARE_USING]() {
|
|
11290
11477
|
return this.backend;
|
|
11291
11478
|
}
|
|
11479
|
+
/** Return a non-decoding version of the state. */
|
|
11480
|
+
view() {
|
|
11481
|
+
return new SerializedStateView(this.spec, this.backend, this.recentlyUsedServices, this.viewCache);
|
|
11482
|
+
}
|
|
11292
11483
|
// TODO [ToDr] Temporary method to update the state,
|
|
11293
11484
|
// without changing references.
|
|
11294
11485
|
updateBackend(newBackend) {
|
|
11295
11486
|
this.backend = newBackend;
|
|
11487
|
+
this.dataCache = hash_dictionary_HashDictionary.new();
|
|
11488
|
+
this.viewCache = hash_dictionary_HashDictionary.new();
|
|
11296
11489
|
}
|
|
11297
11490
|
recentServiceIds() {
|
|
11298
|
-
return this.
|
|
11491
|
+
return this.recentlyUsedServices;
|
|
11299
11492
|
}
|
|
11300
11493
|
getService(id) {
|
|
11301
|
-
const serviceData = this.retrieveOptional(
|
|
11494
|
+
const serviceData = this.retrieveOptional(serialize_serialize.serviceData(id));
|
|
11302
11495
|
if (serviceData === undefined) {
|
|
11303
11496
|
return null;
|
|
11304
11497
|
}
|
|
11305
|
-
if (!this.
|
|
11306
|
-
this.
|
|
11498
|
+
if (!this.recentlyUsedServices.includes(id)) {
|
|
11499
|
+
this.recentlyUsedServices.push(id);
|
|
11307
11500
|
}
|
|
11308
11501
|
return new SerializedService(this.blake2b, id, serviceData, (key) => this.retrieveOptional(key));
|
|
11309
11502
|
}
|
|
11310
|
-
retrieve(
|
|
11311
|
-
const
|
|
11312
|
-
if (
|
|
11313
|
-
throw new Error(`Required state entry for ${description} is missing!. Accessing key: ${key}`);
|
|
11503
|
+
retrieve(k, description) {
|
|
11504
|
+
const data = this.retrieveOptional(k);
|
|
11505
|
+
if (data === undefined) {
|
|
11506
|
+
throw new Error(`Required state entry for ${description} is missing!. Accessing key: ${k.key}`);
|
|
11314
11507
|
}
|
|
11315
|
-
return
|
|
11508
|
+
return data;
|
|
11316
11509
|
}
|
|
11317
11510
|
retrieveOptional({ key, Codec }) {
|
|
11511
|
+
const cached = this.dataCache.get(key);
|
|
11512
|
+
if (cached !== undefined) {
|
|
11513
|
+
return cached;
|
|
11514
|
+
}
|
|
11318
11515
|
const bytes = this.backend.get(key);
|
|
11319
11516
|
if (bytes === null) {
|
|
11320
11517
|
return undefined;
|
|
11321
11518
|
}
|
|
11322
|
-
|
|
11519
|
+
const data = decoder_Decoder.decodeObject(Codec, bytes, this.spec);
|
|
11520
|
+
this.dataCache.set(key, data);
|
|
11521
|
+
return data;
|
|
11323
11522
|
}
|
|
11324
11523
|
get availabilityAssignment() {
|
|
11325
|
-
return this.retrieve(
|
|
11524
|
+
return this.retrieve(serialize_serialize.availabilityAssignment, "availabilityAssignment");
|
|
11326
11525
|
}
|
|
11327
11526
|
get designatedValidatorData() {
|
|
11328
|
-
return this.retrieve(
|
|
11527
|
+
return this.retrieve(serialize_serialize.designatedValidators, "designatedValidatorData");
|
|
11329
11528
|
}
|
|
11330
11529
|
get nextValidatorData() {
|
|
11331
|
-
return this.retrieve(
|
|
11530
|
+
return this.retrieve(serialize_serialize.safrole, "safroleData.nextValidatorData").nextValidatorData;
|
|
11332
11531
|
}
|
|
11333
11532
|
get currentValidatorData() {
|
|
11334
|
-
return this.retrieve(
|
|
11533
|
+
return this.retrieve(serialize_serialize.currentValidators, "currentValidators");
|
|
11335
11534
|
}
|
|
11336
11535
|
get previousValidatorData() {
|
|
11337
|
-
return this.retrieve(
|
|
11536
|
+
return this.retrieve(serialize_serialize.previousValidators, "previousValidators");
|
|
11338
11537
|
}
|
|
11339
11538
|
get disputesRecords() {
|
|
11340
|
-
return this.retrieve(
|
|
11539
|
+
return this.retrieve(serialize_serialize.disputesRecords, "disputesRecords");
|
|
11341
11540
|
}
|
|
11342
11541
|
get timeslot() {
|
|
11343
|
-
return this.retrieve(
|
|
11542
|
+
return this.retrieve(serialize_serialize.timeslot, "timeslot");
|
|
11344
11543
|
}
|
|
11345
11544
|
get entropy() {
|
|
11346
|
-
return this.retrieve(
|
|
11545
|
+
return this.retrieve(serialize_serialize.entropy, "entropy");
|
|
11347
11546
|
}
|
|
11348
11547
|
get authPools() {
|
|
11349
|
-
return this.retrieve(
|
|
11548
|
+
return this.retrieve(serialize_serialize.authPools, "authPools");
|
|
11350
11549
|
}
|
|
11351
11550
|
get authQueues() {
|
|
11352
|
-
return this.retrieve(
|
|
11551
|
+
return this.retrieve(serialize_serialize.authQueues, "authQueues");
|
|
11353
11552
|
}
|
|
11354
11553
|
get recentBlocks() {
|
|
11355
|
-
return this.retrieve(
|
|
11554
|
+
return this.retrieve(serialize_serialize.recentBlocks, "recentBlocks");
|
|
11356
11555
|
}
|
|
11357
11556
|
get statistics() {
|
|
11358
|
-
return this.retrieve(
|
|
11557
|
+
return this.retrieve(serialize_serialize.statistics, "statistics");
|
|
11359
11558
|
}
|
|
11360
11559
|
get accumulationQueue() {
|
|
11361
|
-
return this.retrieve(
|
|
11560
|
+
return this.retrieve(serialize_serialize.accumulationQueue, "accumulationQueue");
|
|
11362
11561
|
}
|
|
11363
11562
|
get recentlyAccumulated() {
|
|
11364
|
-
return this.retrieve(
|
|
11563
|
+
return this.retrieve(serialize_serialize.recentlyAccumulated, "recentlyAccumulated");
|
|
11365
11564
|
}
|
|
11366
11565
|
get ticketsAccumulator() {
|
|
11367
|
-
return this.retrieve(
|
|
11566
|
+
return this.retrieve(serialize_serialize.safrole, "safroleData.ticketsAccumulator").ticketsAccumulator;
|
|
11368
11567
|
}
|
|
11369
11568
|
get sealingKeySeries() {
|
|
11370
|
-
return this.retrieve(
|
|
11569
|
+
return this.retrieve(serialize_serialize.safrole, "safrole.sealingKeySeries").sealingKeySeries;
|
|
11371
11570
|
}
|
|
11372
11571
|
get epochRoot() {
|
|
11373
|
-
return this.retrieve(
|
|
11572
|
+
return this.retrieve(serialize_serialize.safrole, "safrole.epochRoot").epochRoot;
|
|
11374
11573
|
}
|
|
11375
11574
|
get privilegedServices() {
|
|
11376
|
-
return this.retrieve(
|
|
11575
|
+
return this.retrieve(serialize_serialize.privilegedServices, "privilegedServices");
|
|
11377
11576
|
}
|
|
11378
11577
|
get accumulationOutputLog() {
|
|
11379
|
-
return this.retrieve(
|
|
11578
|
+
return this.retrieve(serialize_serialize.accumulationOutputLog, "accumulationOutputLog");
|
|
11380
11579
|
}
|
|
11381
11580
|
}
|
|
11382
11581
|
/** Service data representation on a serialized state. */
|
|
@@ -11405,9 +11604,9 @@ class SerializedService {
|
|
|
11405
11604
|
serviceIdAndKey.set(numbers_u32AsLeBytes(this.serviceId));
|
|
11406
11605
|
serviceIdAndKey.set(rawKey.raw, SERVICE_ID_BYTES);
|
|
11407
11606
|
const key = opaque_asOpaqueType(bytes_BytesBlob.blobFrom(this.blake2b.hashBytes(serviceIdAndKey).raw));
|
|
11408
|
-
return this.retrieveOptional(
|
|
11607
|
+
return this.retrieveOptional(serialize_serialize.serviceStorage(this.blake2b, this.serviceId, key)) ?? null;
|
|
11409
11608
|
}
|
|
11410
|
-
return this.retrieveOptional(
|
|
11609
|
+
return this.retrieveOptional(serialize_serialize.serviceStorage(this.blake2b, this.serviceId, rawKey)) ?? null;
|
|
11411
11610
|
}
|
|
11412
11611
|
/**
|
|
11413
11612
|
* Check if preimage is present in the DB.
|
|
@@ -11416,15 +11615,15 @@ class SerializedService {
|
|
|
11416
11615
|
*/
|
|
11417
11616
|
hasPreimage(hash) {
|
|
11418
11617
|
// TODO [ToDr] consider optimizing to avoid fetching the whole data.
|
|
11419
|
-
return this.retrieveOptional(
|
|
11618
|
+
return this.retrieveOptional(serialize_serialize.servicePreimages(this.blake2b, this.serviceId, hash)) !== undefined;
|
|
11420
11619
|
}
|
|
11421
11620
|
/** Retrieve preimage from the DB. */
|
|
11422
11621
|
getPreimage(hash) {
|
|
11423
|
-
return this.retrieveOptional(
|
|
11622
|
+
return this.retrieveOptional(serialize_serialize.servicePreimages(this.blake2b, this.serviceId, hash)) ?? null;
|
|
11424
11623
|
}
|
|
11425
11624
|
/** Retrieve preimage lookup history. */
|
|
11426
11625
|
getLookupHistory(hash, len) {
|
|
11427
|
-
const rawSlots = this.retrieveOptional(
|
|
11626
|
+
const rawSlots = this.retrieveOptional(serialize_serialize.serviceLookupHistory(this.blake2b, this.serviceId, hash, len));
|
|
11428
11627
|
if (rawSlots === undefined) {
|
|
11429
11628
|
return null;
|
|
11430
11629
|
}
|
|
@@ -12089,7 +12288,6 @@ function getKeccakTrieHasher(hasher) {
|
|
|
12089
12288
|
|
|
12090
12289
|
|
|
12091
12290
|
|
|
12092
|
-
|
|
12093
12291
|
/** What should be done with that key? */
|
|
12094
12292
|
var StateEntryUpdateAction;
|
|
12095
12293
|
(function (StateEntryUpdateAction) {
|
|
@@ -12105,83 +12303,95 @@ function* serializeStateUpdate(spec, blake2b, update) {
|
|
|
12105
12303
|
yield* serializeBasicKeys(spec, update);
|
|
12106
12304
|
const encode = (codec, val) => encoder_Encoder.encodeObject(codec, val, spec);
|
|
12107
12305
|
// then let's proceed with service updates
|
|
12108
|
-
yield* serializeServiceUpdates(update.
|
|
12306
|
+
yield* serializeServiceUpdates(update.updated, encode, blake2b);
|
|
12109
12307
|
yield* serializePreimages(update.preimages, encode, blake2b);
|
|
12110
12308
|
yield* serializeStorage(update.storage, blake2b);
|
|
12111
|
-
yield* serializeRemovedServices(update.
|
|
12309
|
+
yield* serializeRemovedServices(update.removed);
|
|
12112
12310
|
}
|
|
12113
12311
|
function* serializeRemovedServices(servicesRemoved) {
|
|
12114
|
-
|
|
12312
|
+
if (servicesRemoved === undefined) {
|
|
12313
|
+
return;
|
|
12314
|
+
}
|
|
12315
|
+
for (const serviceId of servicesRemoved) {
|
|
12115
12316
|
// TODO [ToDr] what about all data associated with a service?
|
|
12116
|
-
const codec =
|
|
12317
|
+
const codec = serialize_serialize.serviceData(serviceId);
|
|
12117
12318
|
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12118
12319
|
}
|
|
12119
12320
|
}
|
|
12120
|
-
function* serializeStorage(
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12321
|
+
function* serializeStorage(storageUpdates, blake2b) {
|
|
12322
|
+
if (storageUpdates === undefined) {
|
|
12323
|
+
return;
|
|
12324
|
+
}
|
|
12325
|
+
for (const [serviceId, updates] of storageUpdates.entries()) {
|
|
12326
|
+
for (const { action } of updates) {
|
|
12327
|
+
switch (action.kind) {
|
|
12328
|
+
case UpdateStorageKind.Set: {
|
|
12329
|
+
const key = action.storage.key;
|
|
12330
|
+
const codec = serialize_serialize.serviceStorage(blake2b, serviceId, key);
|
|
12331
|
+
yield [StateEntryUpdateAction.Insert, codec.key, action.storage.value];
|
|
12332
|
+
break;
|
|
12333
|
+
}
|
|
12334
|
+
case UpdateStorageKind.Remove: {
|
|
12335
|
+
const key = action.key;
|
|
12336
|
+
const codec = serialize_serialize.serviceStorage(blake2b, serviceId, key);
|
|
12337
|
+
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12338
|
+
break;
|
|
12339
|
+
}
|
|
12134
12340
|
}
|
|
12135
|
-
default:
|
|
12136
|
-
debug_assertNever(action);
|
|
12137
12341
|
}
|
|
12138
12342
|
}
|
|
12139
12343
|
}
|
|
12140
|
-
function* serializePreimages(
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
const
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12344
|
+
function* serializePreimages(preimagesUpdates, encode, blake2b) {
|
|
12345
|
+
if (preimagesUpdates === undefined) {
|
|
12346
|
+
return;
|
|
12347
|
+
}
|
|
12348
|
+
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
12349
|
+
for (const { action } of updates) {
|
|
12350
|
+
switch (action.kind) {
|
|
12351
|
+
case UpdatePreimageKind.Provide: {
|
|
12352
|
+
const { hash, blob } = action.preimage;
|
|
12353
|
+
const codec = serialize_serialize.servicePreimages(blake2b, serviceId, hash);
|
|
12354
|
+
yield [StateEntryUpdateAction.Insert, codec.key, blob];
|
|
12355
|
+
if (action.slot !== null) {
|
|
12356
|
+
const codec2 = serialize_serialize.serviceLookupHistory(blake2b, serviceId, hash, numbers_tryAsU32(blob.length));
|
|
12357
|
+
yield [
|
|
12358
|
+
StateEntryUpdateAction.Insert,
|
|
12359
|
+
codec2.key,
|
|
12360
|
+
encode(codec2.Codec, tryAsLookupHistorySlots([action.slot])),
|
|
12361
|
+
];
|
|
12362
|
+
}
|
|
12363
|
+
break;
|
|
12364
|
+
}
|
|
12365
|
+
case UpdatePreimageKind.UpdateOrAdd: {
|
|
12366
|
+
const { hash, length, slots } = action.item;
|
|
12367
|
+
const codec = serialize_serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
12368
|
+
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, slots)];
|
|
12369
|
+
break;
|
|
12370
|
+
}
|
|
12371
|
+
case UpdatePreimageKind.Remove: {
|
|
12372
|
+
const { hash, length } = action;
|
|
12373
|
+
const codec = serialize_serialize.servicePreimages(blake2b, serviceId, hash);
|
|
12374
|
+
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12375
|
+
const codec2 = serialize_serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
12376
|
+
yield [StateEntryUpdateAction.Remove, codec2.key, EMPTY_BLOB];
|
|
12377
|
+
break;
|
|
12154
12378
|
}
|
|
12155
|
-
break;
|
|
12156
|
-
}
|
|
12157
|
-
case UpdatePreimageKind.UpdateOrAdd: {
|
|
12158
|
-
const { hash, length, slots } = action.item;
|
|
12159
|
-
const codec = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
12160
|
-
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, slots)];
|
|
12161
|
-
break;
|
|
12162
|
-
}
|
|
12163
|
-
case UpdatePreimageKind.Remove: {
|
|
12164
|
-
const { hash, length } = action;
|
|
12165
|
-
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
12166
|
-
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12167
|
-
const codec2 = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
12168
|
-
yield [StateEntryUpdateAction.Remove, codec2.key, EMPTY_BLOB];
|
|
12169
|
-
break;
|
|
12170
12379
|
}
|
|
12171
|
-
default:
|
|
12172
|
-
debug_assertNever(action);
|
|
12173
12380
|
}
|
|
12174
12381
|
}
|
|
12175
12382
|
}
|
|
12176
12383
|
function* serializeServiceUpdates(servicesUpdates, encode, blake2b) {
|
|
12177
|
-
|
|
12384
|
+
if (servicesUpdates === undefined) {
|
|
12385
|
+
return;
|
|
12386
|
+
}
|
|
12387
|
+
for (const [serviceId, { action }] of servicesUpdates.entries()) {
|
|
12178
12388
|
// new service being created or updated
|
|
12179
|
-
const codec =
|
|
12389
|
+
const codec = serialize_serialize.serviceData(serviceId);
|
|
12180
12390
|
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, action.account)];
|
|
12181
12391
|
// additional lookup history update
|
|
12182
12392
|
if (action.kind === UpdateServiceKind.Create && action.lookupHistory !== null) {
|
|
12183
12393
|
const { lookupHistory } = action;
|
|
12184
|
-
const codec2 =
|
|
12394
|
+
const codec2 = serialize_serialize.serviceLookupHistory(blake2b, serviceId, lookupHistory.hash, lookupHistory.length);
|
|
12185
12395
|
yield [StateEntryUpdateAction.Insert, codec2.key, encode(codec2.Codec, lookupHistory.slots)];
|
|
12186
12396
|
}
|
|
12187
12397
|
}
|
|
@@ -12191,53 +12401,53 @@ function* serializeBasicKeys(spec, update) {
|
|
|
12191
12401
|
return [StateEntryUpdateAction.Insert, codec.key, encoder_Encoder.encodeObject(codec.Codec, val, spec)];
|
|
12192
12402
|
}
|
|
12193
12403
|
if (update.authPools !== undefined) {
|
|
12194
|
-
yield doSerialize(update.authPools,
|
|
12404
|
+
yield doSerialize(update.authPools, serialize_serialize.authPools); // C(1)
|
|
12195
12405
|
}
|
|
12196
12406
|
if (update.authQueues !== undefined) {
|
|
12197
|
-
yield doSerialize(update.authQueues,
|
|
12407
|
+
yield doSerialize(update.authQueues, serialize_serialize.authQueues); // C(2)
|
|
12198
12408
|
}
|
|
12199
12409
|
if (update.recentBlocks !== undefined) {
|
|
12200
|
-
yield doSerialize(update.recentBlocks,
|
|
12410
|
+
yield doSerialize(update.recentBlocks, serialize_serialize.recentBlocks); // C(3)
|
|
12201
12411
|
}
|
|
12202
12412
|
const safroleData = getSafroleData(update.nextValidatorData, update.epochRoot, update.sealingKeySeries, update.ticketsAccumulator);
|
|
12203
12413
|
if (safroleData !== undefined) {
|
|
12204
|
-
yield doSerialize(safroleData,
|
|
12414
|
+
yield doSerialize(safroleData, serialize_serialize.safrole); // C(4)
|
|
12205
12415
|
}
|
|
12206
12416
|
if (update.disputesRecords !== undefined) {
|
|
12207
|
-
yield doSerialize(update.disputesRecords,
|
|
12417
|
+
yield doSerialize(update.disputesRecords, serialize_serialize.disputesRecords); // C(5)
|
|
12208
12418
|
}
|
|
12209
12419
|
if (update.entropy !== undefined) {
|
|
12210
|
-
yield doSerialize(update.entropy,
|
|
12420
|
+
yield doSerialize(update.entropy, serialize_serialize.entropy); // C(6)
|
|
12211
12421
|
}
|
|
12212
12422
|
if (update.designatedValidatorData !== undefined) {
|
|
12213
|
-
yield doSerialize(update.designatedValidatorData,
|
|
12423
|
+
yield doSerialize(update.designatedValidatorData, serialize_serialize.designatedValidators); // C(7)
|
|
12214
12424
|
}
|
|
12215
12425
|
if (update.currentValidatorData !== undefined) {
|
|
12216
|
-
yield doSerialize(update.currentValidatorData,
|
|
12426
|
+
yield doSerialize(update.currentValidatorData, serialize_serialize.currentValidators); // C(8)
|
|
12217
12427
|
}
|
|
12218
12428
|
if (update.previousValidatorData !== undefined) {
|
|
12219
|
-
yield doSerialize(update.previousValidatorData,
|
|
12429
|
+
yield doSerialize(update.previousValidatorData, serialize_serialize.previousValidators); // C(9)
|
|
12220
12430
|
}
|
|
12221
12431
|
if (update.availabilityAssignment !== undefined) {
|
|
12222
|
-
yield doSerialize(update.availabilityAssignment,
|
|
12432
|
+
yield doSerialize(update.availabilityAssignment, serialize_serialize.availabilityAssignment); // C(10)
|
|
12223
12433
|
}
|
|
12224
12434
|
if (update.timeslot !== undefined) {
|
|
12225
|
-
yield doSerialize(update.timeslot,
|
|
12435
|
+
yield doSerialize(update.timeslot, serialize_serialize.timeslot); // C(11)
|
|
12226
12436
|
}
|
|
12227
12437
|
if (update.privilegedServices !== undefined) {
|
|
12228
|
-
yield doSerialize(update.privilegedServices,
|
|
12438
|
+
yield doSerialize(update.privilegedServices, serialize_serialize.privilegedServices); // C(12)
|
|
12229
12439
|
}
|
|
12230
12440
|
if (update.statistics !== undefined) {
|
|
12231
|
-
yield doSerialize(update.statistics,
|
|
12441
|
+
yield doSerialize(update.statistics, serialize_serialize.statistics); // C(13)
|
|
12232
12442
|
}
|
|
12233
12443
|
if (update.accumulationQueue !== undefined) {
|
|
12234
|
-
yield doSerialize(update.accumulationQueue,
|
|
12444
|
+
yield doSerialize(update.accumulationQueue, serialize_serialize.accumulationQueue); // C(14)
|
|
12235
12445
|
}
|
|
12236
12446
|
if (update.recentlyAccumulated !== undefined) {
|
|
12237
|
-
yield doSerialize(update.recentlyAccumulated,
|
|
12447
|
+
yield doSerialize(update.recentlyAccumulated, serialize_serialize.recentlyAccumulated); // C(15)
|
|
12238
12448
|
}
|
|
12239
12449
|
if (update.accumulationOutputLog !== undefined) {
|
|
12240
|
-
yield doSerialize(update.accumulationOutputLog,
|
|
12450
|
+
yield doSerialize(update.accumulationOutputLog, serialize_serialize.accumulationOutputLog); // C(16)
|
|
12241
12451
|
}
|
|
12242
12452
|
}
|
|
12243
12453
|
function getSafroleData(nextValidatorData, epochRoot, sealingKeySeries, ticketsAccumulator) {
|
|
@@ -12350,41 +12560,41 @@ function convertInMemoryStateToDictionary(spec, blake2b, state) {
|
|
|
12350
12560
|
function doSerialize(codec) {
|
|
12351
12561
|
serialized.set(codec.key, encoder_Encoder.encodeObject(codec.Codec, codec.extract(state), spec));
|
|
12352
12562
|
}
|
|
12353
|
-
doSerialize(
|
|
12354
|
-
doSerialize(
|
|
12355
|
-
doSerialize(
|
|
12356
|
-
doSerialize(
|
|
12357
|
-
doSerialize(
|
|
12358
|
-
doSerialize(
|
|
12359
|
-
doSerialize(
|
|
12360
|
-
doSerialize(
|
|
12361
|
-
doSerialize(
|
|
12362
|
-
doSerialize(
|
|
12363
|
-
doSerialize(
|
|
12364
|
-
doSerialize(
|
|
12365
|
-
doSerialize(
|
|
12366
|
-
doSerialize(
|
|
12367
|
-
doSerialize(
|
|
12368
|
-
doSerialize(
|
|
12563
|
+
doSerialize(serialize_serialize.authPools); // C(1)
|
|
12564
|
+
doSerialize(serialize_serialize.authQueues); // C(2)
|
|
12565
|
+
doSerialize(serialize_serialize.recentBlocks); // C(3)
|
|
12566
|
+
doSerialize(serialize_serialize.safrole); // C(4)
|
|
12567
|
+
doSerialize(serialize_serialize.disputesRecords); // C(5)
|
|
12568
|
+
doSerialize(serialize_serialize.entropy); // C(6)
|
|
12569
|
+
doSerialize(serialize_serialize.designatedValidators); // C(7)
|
|
12570
|
+
doSerialize(serialize_serialize.currentValidators); // C(8)
|
|
12571
|
+
doSerialize(serialize_serialize.previousValidators); // C(9)
|
|
12572
|
+
doSerialize(serialize_serialize.availabilityAssignment); // C(10)
|
|
12573
|
+
doSerialize(serialize_serialize.timeslot); // C(11)
|
|
12574
|
+
doSerialize(serialize_serialize.privilegedServices); // C(12)
|
|
12575
|
+
doSerialize(serialize_serialize.statistics); // C(13)
|
|
12576
|
+
doSerialize(serialize_serialize.accumulationQueue); // C(14)
|
|
12577
|
+
doSerialize(serialize_serialize.recentlyAccumulated); // C(15)
|
|
12578
|
+
doSerialize(serialize_serialize.accumulationOutputLog); // C(16)
|
|
12369
12579
|
// services
|
|
12370
12580
|
for (const [serviceId, service] of state.services.entries()) {
|
|
12371
12581
|
// data
|
|
12372
|
-
const { key, Codec } =
|
|
12582
|
+
const { key, Codec } = serialize_serialize.serviceData(serviceId);
|
|
12373
12583
|
serialized.set(key, encoder_Encoder.encodeObject(Codec, service.getInfo()));
|
|
12374
12584
|
// preimages
|
|
12375
12585
|
for (const preimage of service.data.preimages.values()) {
|
|
12376
|
-
const { key, Codec } =
|
|
12586
|
+
const { key, Codec } = serialize_serialize.servicePreimages(blake2b, serviceId, preimage.hash);
|
|
12377
12587
|
serialized.set(key, encoder_Encoder.encodeObject(Codec, preimage.blob));
|
|
12378
12588
|
}
|
|
12379
12589
|
// storage
|
|
12380
12590
|
for (const storage of service.data.storage.values()) {
|
|
12381
|
-
const { key, Codec } =
|
|
12591
|
+
const { key, Codec } = serialize_serialize.serviceStorage(blake2b, serviceId, storage.key);
|
|
12382
12592
|
serialized.set(key, encoder_Encoder.encodeObject(Codec, storage.value));
|
|
12383
12593
|
}
|
|
12384
12594
|
// lookup history
|
|
12385
12595
|
for (const lookupHistoryList of service.data.lookupHistory.values()) {
|
|
12386
12596
|
for (const lookupHistory of lookupHistoryList) {
|
|
12387
|
-
const { key, Codec } =
|
|
12597
|
+
const { key, Codec } = serialize_serialize.serviceLookupHistory(blake2b, serviceId, lookupHistory.hash, lookupHistory.length);
|
|
12388
12598
|
serialized.set(key, encoder_Encoder.encodeObject(Codec, lookupHistory.slots.slice()));
|
|
12389
12599
|
}
|
|
12390
12600
|
}
|
|
@@ -12434,6 +12644,7 @@ function loadState(spec, blake2b, entries) {
|
|
|
12434
12644
|
|
|
12435
12645
|
|
|
12436
12646
|
|
|
12647
|
+
|
|
12437
12648
|
;// CONCATENATED MODULE: ./packages/jam/database/leaf-db.ts
|
|
12438
12649
|
|
|
12439
12650
|
|
|
@@ -12460,13 +12671,13 @@ class LeafDb {
|
|
|
12460
12671
|
*/
|
|
12461
12672
|
static fromLeavesBlob(blob, db) {
|
|
12462
12673
|
if (blob.length % TRIE_NODE_BYTES !== 0) {
|
|
12463
|
-
return result_Result.error(LeafDbError.InvalidLeafData, `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
|
|
12674
|
+
return result_Result.error(LeafDbError.InvalidLeafData, () => `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
|
|
12464
12675
|
}
|
|
12465
12676
|
const leaves = SortedSet.fromArray(leafComparator, []);
|
|
12466
12677
|
for (const nodeData of blob.chunks(TRIE_NODE_BYTES)) {
|
|
12467
12678
|
const node = new TrieNode(nodeData.raw);
|
|
12468
12679
|
if (node.getNodeType() === NodeType.Branch) {
|
|
12469
|
-
return result_Result.error(LeafDbError.InvalidLeafData, `Branch node detected: ${nodeData}`);
|
|
12680
|
+
return result_Result.error(LeafDbError.InvalidLeafData, () => `Branch node detected: ${nodeData}`);
|
|
12470
12681
|
}
|
|
12471
12682
|
leaves.insert(node.asLeafNode());
|
|
12472
12683
|
}
|
|
@@ -12592,7 +12803,7 @@ const codecMap = (value, extractKey, { typicalLength = TYPICAL_DICTIONARY_LENGTH
|
|
|
12592
12803
|
const lookupHistoryItemCodec = descriptors_codec.object({
|
|
12593
12804
|
hash: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
12594
12805
|
length: descriptors_codec.u32,
|
|
12595
|
-
slots:
|
|
12806
|
+
slots: descriptors_readonlyArray(descriptors_codec.sequenceVarLen(descriptors_codec.u32.asOpaque())).convert(seeThrough, tryAsLookupHistorySlots),
|
|
12596
12807
|
}, "LookupHistoryItem", ({ hash, length, slots }) => new LookupHistoryItem(hash, length, slots));
|
|
12597
12808
|
const lookupHistoryEntryCodec = descriptors_codec.object({
|
|
12598
12809
|
key: descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(),
|
|
@@ -12635,7 +12846,11 @@ class ServiceWithCodec extends InMemoryService {
|
|
|
12635
12846
|
return new ServiceWithCodec(serviceId, data);
|
|
12636
12847
|
}
|
|
12637
12848
|
}
|
|
12638
|
-
const in_memory_state_codec_inMemoryStateCodec =
|
|
12849
|
+
const in_memory_state_codec_inMemoryStateCodec = (spec) => codec.Class(class State extends InMemoryState {
|
|
12850
|
+
static create(data) {
|
|
12851
|
+
return InMemoryState.new(spec, data);
|
|
12852
|
+
}
|
|
12853
|
+
}, {
|
|
12639
12854
|
// alpha
|
|
12640
12855
|
authPools: serialize.authPools.Codec,
|
|
12641
12856
|
// phi
|
|
@@ -12645,11 +12860,11 @@ const in_memory_state_codec_inMemoryStateCodec = descriptors_codec.Class(InMemor
|
|
|
12645
12860
|
// gamma_k
|
|
12646
12861
|
nextValidatorData: codecPerValidator(ValidatorData.Codec),
|
|
12647
12862
|
// gamma_z
|
|
12648
|
-
epochRoot:
|
|
12863
|
+
epochRoot: codec.bytes(BANDERSNATCH_RING_ROOT_BYTES).asOpaque(),
|
|
12649
12864
|
// gamma_s
|
|
12650
12865
|
sealingKeySeries: SafroleSealingKeysData.Codec,
|
|
12651
12866
|
// gamma_a
|
|
12652
|
-
ticketsAccumulator: readonlyArray(
|
|
12867
|
+
ticketsAccumulator: readonlyArray(codec.sequenceVarLen(Ticket.Codec)).convert((x) => x, asKnownSize),
|
|
12653
12868
|
// psi
|
|
12654
12869
|
disputesRecords: serialize.disputesRecords.Codec,
|
|
12655
12870
|
// eta
|
|
@@ -12675,7 +12890,7 @@ const in_memory_state_codec_inMemoryStateCodec = descriptors_codec.Class(InMemor
|
|
|
12675
12890
|
// theta
|
|
12676
12891
|
accumulationOutputLog: serialize.accumulationOutputLog.Codec,
|
|
12677
12892
|
// delta
|
|
12678
|
-
services:
|
|
12893
|
+
services: codec.dictionary(codec.u32.asOpaque(), ServiceWithCodec.Codec, {
|
|
12679
12894
|
sortKeys: (a, b) => a - b,
|
|
12680
12895
|
}),
|
|
12681
12896
|
});
|
|
@@ -12722,7 +12937,7 @@ class InMemoryStates {
|
|
|
12722
12937
|
}
|
|
12723
12938
|
/** Insert a full state into the database. */
|
|
12724
12939
|
async insertState(headerHash, state) {
|
|
12725
|
-
const encoded = Encoder.encodeObject(inMemoryStateCodec, state, this.spec);
|
|
12940
|
+
const encoded = Encoder.encodeObject(inMemoryStateCodec(this.spec), state, this.spec);
|
|
12726
12941
|
this.db.set(headerHash, encoded);
|
|
12727
12942
|
return Result.ok(OK);
|
|
12728
12943
|
}
|
|
@@ -12731,7 +12946,7 @@ class InMemoryStates {
|
|
|
12731
12946
|
if (encodedState === undefined) {
|
|
12732
12947
|
return null;
|
|
12733
12948
|
}
|
|
12734
|
-
return Decoder.decodeObject(inMemoryStateCodec, encodedState, this.spec);
|
|
12949
|
+
return Decoder.decodeObject(inMemoryStateCodec(this.spec), encodedState, this.spec);
|
|
12735
12950
|
}
|
|
12736
12951
|
}
|
|
12737
12952
|
|
|
@@ -13181,7 +13396,7 @@ class LmdbStates {
|
|
|
13181
13396
|
}
|
|
13182
13397
|
catch (e) {
|
|
13183
13398
|
logger.error `${e}`;
|
|
13184
|
-
return result_Result.error(StateUpdateError.Commit);
|
|
13399
|
+
return result_Result.error(StateUpdateError.Commit, () => `Failed to commit state update: ${e}`);
|
|
13185
13400
|
}
|
|
13186
13401
|
return result_Result.ok(result_OK);
|
|
13187
13402
|
}
|
|
@@ -13839,21 +14054,21 @@ class TransitionHasher {
|
|
|
13839
14054
|
*/
|
|
13840
14055
|
extrinsic(extrinsicView) {
|
|
13841
14056
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0cfb000cfb00?v=0.6.5
|
|
13842
|
-
const
|
|
14057
|
+
const guaranteesCount = numbers_tryAsU32(extrinsicView.guarantees.view().length);
|
|
14058
|
+
const countEncoded = encoder_Encoder.encodeObject(descriptors_codec.varU32, guaranteesCount);
|
|
14059
|
+
const guaranteesBlobs = extrinsicView.guarantees
|
|
13843
14060
|
.view()
|
|
13844
14061
|
.map((g) => g.view())
|
|
13845
|
-
.
|
|
14062
|
+
.reduce((aggregated, guarantee) => {
|
|
13846
14063
|
const reportHash = this.blake2b.hashBytes(guarantee.report.encoded()).asOpaque();
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
});
|
|
13853
|
-
const guaranteeBlob = encoder_Encoder.encodeObject(descriptors_codec.sequenceVarLen(dumpCodec), guarantees, this.context);
|
|
14064
|
+
aggregated.push(reportHash.raw);
|
|
14065
|
+
aggregated.push(guarantee.slot.encoded().raw);
|
|
14066
|
+
aggregated.push(guarantee.credentials.encoded().raw);
|
|
14067
|
+
return aggregated;
|
|
14068
|
+
}, [countEncoded.raw]);
|
|
13854
14069
|
const et = this.blake2b.hashBytes(extrinsicView.tickets.encoded()).asOpaque();
|
|
13855
14070
|
const ep = this.blake2b.hashBytes(extrinsicView.preimages.encoded()).asOpaque();
|
|
13856
|
-
const eg = this.blake2b.
|
|
14071
|
+
const eg = this.blake2b.hashBlobs(guaranteesBlobs).asOpaque();
|
|
13857
14072
|
const ea = this.blake2b.hashBytes(extrinsicView.assurances.encoded()).asOpaque();
|
|
13858
14073
|
const ed = this.blake2b.hashBytes(extrinsicView.disputes.encoded()).asOpaque();
|
|
13859
14074
|
const encoded = bytes_BytesBlob.blobFromParts([et.raw, ep.raw, eg.raw, ea.raw, ed.raw]);
|
|
@@ -13901,32 +14116,33 @@ class Preimages {
|
|
|
13901
14116
|
}
|
|
13902
14117
|
if (prevPreimage.requester > currPreimage.requester ||
|
|
13903
14118
|
currPreimage.blob.compare(prevPreimage.blob).isLessOrEqual()) {
|
|
13904
|
-
return result_Result.error(PreimagesErrorCode.PreimagesNotSortedUnique);
|
|
14119
|
+
return result_Result.error(PreimagesErrorCode.PreimagesNotSortedUnique, () => `Preimages not sorted/unique at index ${i}`);
|
|
13905
14120
|
}
|
|
13906
14121
|
}
|
|
13907
14122
|
const { preimages, slot } = input;
|
|
13908
|
-
const pendingChanges =
|
|
14123
|
+
const pendingChanges = new Map();
|
|
13909
14124
|
// select preimages for integration
|
|
13910
14125
|
for (const preimage of preimages) {
|
|
13911
14126
|
const { requester, blob } = preimage;
|
|
13912
14127
|
const hash = this.blake2b.hashBytes(blob).asOpaque();
|
|
13913
14128
|
const service = this.state.getService(requester);
|
|
13914
14129
|
if (service === null) {
|
|
13915
|
-
return result_Result.error(PreimagesErrorCode.AccountNotFound);
|
|
14130
|
+
return result_Result.error(PreimagesErrorCode.AccountNotFound, () => `Service not found: ${requester}`);
|
|
13916
14131
|
}
|
|
13917
14132
|
const hasPreimage = service.hasPreimage(hash);
|
|
13918
14133
|
const slots = service.getLookupHistory(hash, numbers_tryAsU32(blob.length));
|
|
13919
14134
|
// https://graypaper.fluffylabs.dev/#/5f542d7/181800181900
|
|
13920
14135
|
// https://graypaper.fluffylabs.dev/#/5f542d7/116f0011a500
|
|
13921
14136
|
if (hasPreimage || slots === null || !LookupHistoryItem.isRequested(slots)) {
|
|
13922
|
-
return result_Result.error(PreimagesErrorCode.PreimageUnneeded);
|
|
14137
|
+
return result_Result.error(PreimagesErrorCode.PreimageUnneeded, () => `Preimage unneeded: requester=${requester}, hash=${hash}, hasPreimage=${hasPreimage}, isRequested=${slots !== null && LookupHistoryItem.isRequested(slots)}`);
|
|
13923
14138
|
}
|
|
13924
14139
|
// https://graypaper.fluffylabs.dev/#/5f542d7/18c00018f300
|
|
13925
|
-
pendingChanges.
|
|
13926
|
-
|
|
14140
|
+
const updates = pendingChanges.get(requester) ?? [];
|
|
14141
|
+
updates.push(UpdatePreimage.provide({
|
|
13927
14142
|
preimage: PreimageItem.create({ hash, blob }),
|
|
13928
14143
|
slot,
|
|
13929
14144
|
}));
|
|
14145
|
+
pendingChanges.set(requester, updates);
|
|
13930
14146
|
}
|
|
13931
14147
|
return result_Result.ok({
|
|
13932
14148
|
preimages: pendingChanges,
|
|
@@ -13964,7 +14180,7 @@ class BlockVerifier {
|
|
|
13964
14180
|
const headerHash = this.hasher.header(headerView);
|
|
13965
14181
|
// check if current block is already imported
|
|
13966
14182
|
if (this.blocks.getHeader(headerHash.hash) !== null) {
|
|
13967
|
-
return result_Result.error(BlockVerifierError.AlreadyImported, `Block ${headerHash.hash} is already imported.`);
|
|
14183
|
+
return result_Result.error(BlockVerifierError.AlreadyImported, () => `Block ${headerHash.hash} is already imported.`);
|
|
13968
14184
|
}
|
|
13969
14185
|
// Check if parent block exists.
|
|
13970
14186
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0c82000c8200?v=0.6.5
|
|
@@ -13974,14 +14190,14 @@ class BlockVerifier {
|
|
|
13974
14190
|
if (!parentHash.isEqualTo(block_verifier_ZERO_HASH)) {
|
|
13975
14191
|
const parentBlock = this.blocks.getHeader(parentHash);
|
|
13976
14192
|
if (parentBlock === null) {
|
|
13977
|
-
return result_Result.error(BlockVerifierError.ParentNotFound, `Parent ${parentHash.toString()} not found`);
|
|
14193
|
+
return result_Result.error(BlockVerifierError.ParentNotFound, () => `Parent ${parentHash.toString()} not found`);
|
|
13978
14194
|
}
|
|
13979
14195
|
// Check if the time slot index is consecutive and not from future.
|
|
13980
14196
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0c02010c0201?v=0.6.5
|
|
13981
14197
|
const timeslot = headerView.timeSlotIndex.materialize();
|
|
13982
14198
|
const parentTimeslot = parentBlock.timeSlotIndex.materialize();
|
|
13983
14199
|
if (timeslot <= parentTimeslot) {
|
|
13984
|
-
return result_Result.error(BlockVerifierError.InvalidTimeSlot, `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
|
|
14200
|
+
return result_Result.error(BlockVerifierError.InvalidTimeSlot, () => `Invalid time slot index: ${timeslot}, expected > ${parentTimeslot}`);
|
|
13985
14201
|
}
|
|
13986
14202
|
}
|
|
13987
14203
|
// Check if extrinsic is valid.
|
|
@@ -13989,17 +14205,17 @@ class BlockVerifier {
|
|
|
13989
14205
|
const extrinsicHash = headerView.extrinsicHash.materialize();
|
|
13990
14206
|
const extrinsicMerkleCommitment = this.hasher.extrinsic(block.extrinsic.view());
|
|
13991
14207
|
if (!extrinsicHash.isEqualTo(extrinsicMerkleCommitment.hash)) {
|
|
13992
|
-
return result_Result.error(BlockVerifierError.InvalidExtrinsic, `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
|
|
14208
|
+
return result_Result.error(BlockVerifierError.InvalidExtrinsic, () => `Invalid extrinsic hash: ${extrinsicHash.toString()}, expected ${extrinsicMerkleCommitment.hash.toString()}`);
|
|
13993
14209
|
}
|
|
13994
14210
|
// Check if the state root is valid.
|
|
13995
14211
|
// https://graypaper.fluffylabs.dev/#/cc517d7/0c18010c1801?v=0.6.5
|
|
13996
14212
|
const stateRoot = headerView.priorStateRoot.materialize();
|
|
13997
14213
|
const posteriorStateRoot = this.blocks.getPostStateRoot(parentHash);
|
|
13998
14214
|
if (posteriorStateRoot === null) {
|
|
13999
|
-
return result_Result.error(BlockVerifierError.StateRootNotFound, `Posterior state root ${parentHash.toString()} not found`);
|
|
14215
|
+
return result_Result.error(BlockVerifierError.StateRootNotFound, () => `Posterior state root ${parentHash.toString()} not found`);
|
|
14000
14216
|
}
|
|
14001
14217
|
if (!stateRoot.isEqualTo(posteriorStateRoot)) {
|
|
14002
|
-
return result_Result.error(BlockVerifierError.InvalidStateRoot, `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
|
|
14218
|
+
return result_Result.error(BlockVerifierError.InvalidStateRoot, () => `Invalid prior state root: ${stateRoot.toString()}, expected ${posteriorStateRoot.toString()} (ours)`);
|
|
14003
14219
|
}
|
|
14004
14220
|
return result_Result.ok(headerHash.hash);
|
|
14005
14221
|
}
|
|
@@ -14124,7 +14340,7 @@ class Disputes {
|
|
|
14124
14340
|
// check if culprits are sorted by key
|
|
14125
14341
|
// https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
|
|
14126
14342
|
if (!isUniqueSortedBy(disputes.culprits, "key")) {
|
|
14127
|
-
return result_Result.error(DisputesErrorCode.CulpritsNotSortedUnique);
|
|
14343
|
+
return result_Result.error(DisputesErrorCode.CulpritsNotSortedUnique, () => "Culprits are not uniquely sorted by key");
|
|
14128
14344
|
}
|
|
14129
14345
|
const culpritsLength = disputes.culprits.length;
|
|
14130
14346
|
for (let i = 0; i < culpritsLength; i++) {
|
|
@@ -14133,24 +14349,24 @@ class Disputes {
|
|
|
14133
14349
|
// https://graypaper.fluffylabs.dev/#/579bd12/125501125501
|
|
14134
14350
|
const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
|
|
14135
14351
|
if (isInPunishSet) {
|
|
14136
|
-
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported);
|
|
14352
|
+
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: culprit ${i}, key=${key}`);
|
|
14137
14353
|
}
|
|
14138
14354
|
// check if the guarantor key is correct
|
|
14139
14355
|
// https://graypaper.fluffylabs.dev/#/85129da/125501125501?v=0.6.3
|
|
14140
14356
|
if (!allValidatorKeys.has(key)) {
|
|
14141
|
-
return result_Result.error(DisputesErrorCode.BadGuarantorKey);
|
|
14357
|
+
return result_Result.error(DisputesErrorCode.BadGuarantorKey, () => `Bad guarantor key: culprit ${i}, key=${key}`);
|
|
14142
14358
|
}
|
|
14143
14359
|
// verify if the culprit will be in new bad set
|
|
14144
14360
|
// https://graypaper.fluffylabs.dev/#/579bd12/124601124601
|
|
14145
14361
|
const isInNewBadSet = newItems.asDictionaries().badSet.has(workReportHash);
|
|
14146
14362
|
if (!isInNewBadSet) {
|
|
14147
|
-
return result_Result.error(DisputesErrorCode.CulpritsVerdictNotBad);
|
|
14363
|
+
return result_Result.error(DisputesErrorCode.CulpritsVerdictNotBad, () => `Culprit verdict not bad: culprit ${i}, work report=${workReportHash}`);
|
|
14148
14364
|
}
|
|
14149
14365
|
// verify culprit signature
|
|
14150
14366
|
// https://graypaper.fluffylabs.dev/#/579bd12/125c01125c01
|
|
14151
14367
|
const result = verificationResult.culprits[i];
|
|
14152
14368
|
if (!result?.isValid) {
|
|
14153
|
-
return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for culprit: ${i}`);
|
|
14369
|
+
return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for culprit: ${i}`);
|
|
14154
14370
|
}
|
|
14155
14371
|
}
|
|
14156
14372
|
return result_Result.ok(null);
|
|
@@ -14159,7 +14375,7 @@ class Disputes {
|
|
|
14159
14375
|
// check if faults are sorted by key
|
|
14160
14376
|
// https://graypaper.fluffylabs.dev/#/579bd12/12c50112c601
|
|
14161
14377
|
if (!isUniqueSortedBy(disputes.faults, "key")) {
|
|
14162
|
-
return result_Result.error(DisputesErrorCode.FaultsNotSortedUnique);
|
|
14378
|
+
return result_Result.error(DisputesErrorCode.FaultsNotSortedUnique, () => "Faults are not uniquely sorted by key");
|
|
14163
14379
|
}
|
|
14164
14380
|
const faultsLength = disputes.faults.length;
|
|
14165
14381
|
for (let i = 0; i < faultsLength; i++) {
|
|
@@ -14168,12 +14384,12 @@ class Disputes {
|
|
|
14168
14384
|
// https://graypaper.fluffylabs.dev/#/579bd12/12a20112a201
|
|
14169
14385
|
const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
|
|
14170
14386
|
if (isInPunishSet) {
|
|
14171
|
-
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported);
|
|
14387
|
+
return result_Result.error(DisputesErrorCode.OffenderAlreadyReported, () => `Offender already reported: fault ${i}, key=${key}`);
|
|
14172
14388
|
}
|
|
14173
14389
|
// check if the auditor key is correct
|
|
14174
14390
|
// https://graypaper.fluffylabs.dev/#/85129da/12a20112a201?v=0.6.3
|
|
14175
14391
|
if (!allValidatorKeys.has(key)) {
|
|
14176
|
-
return result_Result.error(DisputesErrorCode.BadAuditorKey);
|
|
14392
|
+
return result_Result.error(DisputesErrorCode.BadAuditorKey, () => `Bad auditor key: fault ${i}, key=${key}`);
|
|
14177
14393
|
}
|
|
14178
14394
|
// verify if the fault will be included in new good/bad set
|
|
14179
14395
|
// it may be not correct as in GP there is "iff" what means it should be rather
|
|
@@ -14185,14 +14401,14 @@ class Disputes {
|
|
|
14185
14401
|
const isInNewGoodSet = goodSet.has(workReportHash);
|
|
14186
14402
|
const isInNewBadSet = badSet.has(workReportHash);
|
|
14187
14403
|
if (isInNewGoodSet || !isInNewBadSet) {
|
|
14188
|
-
return result_Result.error(DisputesErrorCode.FaultVerdictWrong);
|
|
14404
|
+
return result_Result.error(DisputesErrorCode.FaultVerdictWrong, () => `Fault verdict wrong: fault ${i}, work report=${workReportHash}, inGood=${isInNewGoodSet}, inBad=${isInNewBadSet}`);
|
|
14189
14405
|
}
|
|
14190
14406
|
}
|
|
14191
14407
|
// verify fault signature. Verification was done earlier, here we only check the result.
|
|
14192
14408
|
// https://graypaper.fluffylabs.dev/#/579bd12/12a90112a901
|
|
14193
14409
|
const result = verificationResult.faults[i];
|
|
14194
14410
|
if (!result.isValid) {
|
|
14195
|
-
return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for fault: ${i}`);
|
|
14411
|
+
return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for fault: ${i}`);
|
|
14196
14412
|
}
|
|
14197
14413
|
}
|
|
14198
14414
|
return result_Result.ok(null);
|
|
@@ -14201,32 +14417,32 @@ class Disputes {
|
|
|
14201
14417
|
// check if verdicts are correctly sorted
|
|
14202
14418
|
// https://graypaper.fluffylabs.dev/#/579bd12/12c40112c401
|
|
14203
14419
|
if (!isUniqueSortedBy(disputes.verdicts, "workReportHash")) {
|
|
14204
|
-
return result_Result.error(DisputesErrorCode.VerdictsNotSortedUnique);
|
|
14420
|
+
return result_Result.error(DisputesErrorCode.VerdictsNotSortedUnique, () => "Verdicts are not uniquely sorted by work report hash");
|
|
14205
14421
|
}
|
|
14206
14422
|
// check if judgement are correctly sorted
|
|
14207
14423
|
// https://graypaper.fluffylabs.dev/#/579bd12/123702123802
|
|
14208
14424
|
if (disputes.verdicts.some((verdict) => !isUniqueSortedByIndex(verdict.votes))) {
|
|
14209
|
-
return result_Result.error(DisputesErrorCode.JudgementsNotSortedUnique);
|
|
14425
|
+
return result_Result.error(DisputesErrorCode.JudgementsNotSortedUnique, () => "Judgements are not uniquely sorted by index");
|
|
14210
14426
|
}
|
|
14211
14427
|
const currentEpoch = Math.floor(this.state.timeslot / this.chainSpec.epochLength);
|
|
14212
14428
|
let voteSignatureIndex = 0;
|
|
14213
14429
|
for (const { votesEpoch, votes } of disputes.verdicts) {
|
|
14214
14430
|
// https://graypaper.fluffylabs.dev/#/579bd12/12bb0012bc00
|
|
14215
14431
|
if (votesEpoch !== currentEpoch && votesEpoch + 1 !== currentEpoch) {
|
|
14216
|
-
return result_Result.error(DisputesErrorCode.BadJudgementAge);
|
|
14432
|
+
return result_Result.error(DisputesErrorCode.BadJudgementAge, () => `Bad judgement age: epoch=${votesEpoch}, current=${currentEpoch}`);
|
|
14217
14433
|
}
|
|
14218
14434
|
const k = votesEpoch === currentEpoch ? this.state.currentValidatorData : this.state.previousValidatorData;
|
|
14219
14435
|
for (const { index } of votes) {
|
|
14220
14436
|
const key = k[index]?.ed25519;
|
|
14221
14437
|
// no particular GP fragment but I think we don't believe in ghosts
|
|
14222
14438
|
if (key === undefined) {
|
|
14223
|
-
return result_Result.error(DisputesErrorCode.BadValidatorIndex);
|
|
14439
|
+
return result_Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index: ${index} in epoch ${votesEpoch}`);
|
|
14224
14440
|
}
|
|
14225
14441
|
// verify vote signature. Verification was done earlier, here we only check the result.
|
|
14226
14442
|
// https://graypaper.fluffylabs.dev/#/579bd12/12cd0012cd00
|
|
14227
14443
|
const result = verificationResult.judgements[voteSignatureIndex];
|
|
14228
14444
|
if (!result.isValid) {
|
|
14229
|
-
return result_Result.error(DisputesErrorCode.BadSignature, `Invalid signature for judgement: ${voteSignatureIndex}`);
|
|
14445
|
+
return result_Result.error(DisputesErrorCode.BadSignature, () => `Invalid signature for judgement: ${voteSignatureIndex}`);
|
|
14230
14446
|
}
|
|
14231
14447
|
voteSignatureIndex += 1;
|
|
14232
14448
|
}
|
|
@@ -14242,7 +14458,7 @@ class Disputes {
|
|
|
14242
14458
|
const isInBadSet = badSet.has(verdict.workReportHash);
|
|
14243
14459
|
const isInWonkySet = wonkySet.has(verdict.workReportHash);
|
|
14244
14460
|
if (isInGoodSet || isInBadSet || isInWonkySet) {
|
|
14245
|
-
return result_Result.error(DisputesErrorCode.AlreadyJudged);
|
|
14461
|
+
return result_Result.error(DisputesErrorCode.AlreadyJudged, () => `Work report already judged: ${verdict.workReportHash}`);
|
|
14246
14462
|
}
|
|
14247
14463
|
}
|
|
14248
14464
|
return result_Result.ok(null);
|
|
@@ -14273,7 +14489,7 @@ class Disputes {
|
|
|
14273
14489
|
// https://graypaper.fluffylabs.dev/#/579bd12/12f10212fc02
|
|
14274
14490
|
const f = disputes.faults.find((x) => x.workReportHash.isEqualTo(r));
|
|
14275
14491
|
if (f === undefined) {
|
|
14276
|
-
return result_Result.error(DisputesErrorCode.NotEnoughFaults);
|
|
14492
|
+
return result_Result.error(DisputesErrorCode.NotEnoughFaults, () => `Not enough faults for work report: ${r}`);
|
|
14277
14493
|
}
|
|
14278
14494
|
}
|
|
14279
14495
|
else if (sum === 0) {
|
|
@@ -14282,13 +14498,13 @@ class Disputes {
|
|
|
14282
14498
|
const c1 = disputes.culprits.find((x) => x.workReportHash.isEqualTo(r));
|
|
14283
14499
|
const c2 = disputes.culprits.findLast((x) => x.workReportHash.isEqualTo(r));
|
|
14284
14500
|
if (c1 === c2) {
|
|
14285
|
-
return result_Result.error(DisputesErrorCode.NotEnoughCulprits);
|
|
14501
|
+
return result_Result.error(DisputesErrorCode.NotEnoughCulprits, () => `Not enough culprits for work report: ${r}`);
|
|
14286
14502
|
}
|
|
14287
14503
|
}
|
|
14288
14504
|
else if (sum !== this.chainSpec.thirdOfValidators) {
|
|
14289
14505
|
// positive votes count is not correct
|
|
14290
14506
|
// https://graypaper.fluffylabs.dev/#/579bd12/125002128102
|
|
14291
|
-
return result_Result.error(DisputesErrorCode.BadVoteSplit);
|
|
14507
|
+
return result_Result.error(DisputesErrorCode.BadVoteSplit, () => `Bad vote split: sum=${sum}, expected=${this.chainSpec.thirdOfValidators} for work report ${r}`);
|
|
14292
14508
|
}
|
|
14293
14509
|
}
|
|
14294
14510
|
return result_Result.ok(null);
|
|
@@ -14376,7 +14592,7 @@ class Disputes {
|
|
|
14376
14592
|
const validator = k[j.index];
|
|
14377
14593
|
// no particular GP fragment but I think we don't believe in ghosts
|
|
14378
14594
|
if (validator === undefined) {
|
|
14379
|
-
return result_Result.error(DisputesErrorCode.BadValidatorIndex);
|
|
14595
|
+
return result_Result.error(DisputesErrorCode.BadValidatorIndex, () => `Bad validator index in signature verification: ${j.index}`);
|
|
14380
14596
|
}
|
|
14381
14597
|
const key = validator.ed25519;
|
|
14382
14598
|
// verify vote signature
|
|
@@ -14484,7 +14700,7 @@ const ringCommitmentCache = [];
|
|
|
14484
14700
|
async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUnsealedHeader) {
|
|
14485
14701
|
const sealResult = await bandersnatch.verifySeal(authorKey.raw, signature.raw, payload.raw, encodedUnsealedHeader.raw);
|
|
14486
14702
|
if (sealResult[RESULT_INDEX] === ResultValues.Error) {
|
|
14487
|
-
return result_Result.error(null);
|
|
14703
|
+
return result_Result.error(null, () => "Bandersnatch VRF seal verification failed");
|
|
14488
14704
|
}
|
|
14489
14705
|
return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
|
|
14490
14706
|
}
|
|
@@ -14510,9 +14726,9 @@ function getRingCommitment(bandersnatch, validators) {
|
|
|
14510
14726
|
async function getRingCommitmentNoCache(bandersnatch, keys) {
|
|
14511
14727
|
const commitmentResult = await bandersnatch.getRingCommitment(keys.raw);
|
|
14512
14728
|
if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
|
|
14513
|
-
return result_Result.error(null);
|
|
14729
|
+
return result_Result.error(null, () => "Bandersnatch ring commitment calculation failed");
|
|
14514
14730
|
}
|
|
14515
|
-
return result_Result.ok(bytes_Bytes.fromBlob(commitmentResult.subarray(1),
|
|
14731
|
+
return result_Result.ok(bytes_Bytes.fromBlob(commitmentResult.subarray(1), bandersnatch_BANDERSNATCH_RING_ROOT_BYTES).asOpaque());
|
|
14516
14732
|
}
|
|
14517
14733
|
// One byte for result discriminator (`ResultValues`) and the rest is entropy hash.
|
|
14518
14734
|
const TICKET_RESULT_LENGTH = 1 + hash_HASH_SIZE;
|
|
@@ -14666,7 +14882,7 @@ class Safrole {
|
|
|
14666
14882
|
* https://graypaper.fluffylabs.dev/#/5f542d7/0ea2000ea200
|
|
14667
14883
|
*/
|
|
14668
14884
|
if (isOffender) {
|
|
14669
|
-
return
|
|
14885
|
+
return validator_data_ValidatorData.create({
|
|
14670
14886
|
bandersnatch: bytes_Bytes.zero(BANDERSNATCH_KEY_BYTES).asOpaque(),
|
|
14671
14887
|
ed25519: bytes_Bytes.zero(ED25519_KEY_BYTES).asOpaque(),
|
|
14672
14888
|
bls: bytes_Bytes.zero(BLS_KEY_BYTES).asOpaque(),
|
|
@@ -14685,7 +14901,7 @@ class Safrole {
|
|
|
14685
14901
|
epochRoot: epochRootResult.ok,
|
|
14686
14902
|
});
|
|
14687
14903
|
}
|
|
14688
|
-
return result_Result.error(SafroleErrorCode.IncorrectData);
|
|
14904
|
+
return result_Result.error(SafroleErrorCode.IncorrectData, () => "Safrole: failed to get epoch root for validator keys");
|
|
14689
14905
|
}
|
|
14690
14906
|
/**
|
|
14691
14907
|
* Ticket sequencer that is used in standard mode
|
|
@@ -14744,13 +14960,13 @@ class Safrole {
|
|
|
14744
14960
|
if (this.isNextEpoch(timeslot) &&
|
|
14745
14961
|
m >= this.chainSpec.contestLength &&
|
|
14746
14962
|
this.state.ticketsAccumulator.length === this.chainSpec.epochLength) {
|
|
14747
|
-
return
|
|
14963
|
+
return safrole_data_SafroleSealingKeysData.tickets(this.outsideInSequencer(this.state.ticketsAccumulator).tickets);
|
|
14748
14964
|
}
|
|
14749
14965
|
if (this.isSameEpoch(timeslot)) {
|
|
14750
14966
|
return this.state.sealingKeySeries;
|
|
14751
14967
|
}
|
|
14752
14968
|
// TODO [MaSi]: the result of fallback sequencer should be cached
|
|
14753
|
-
return
|
|
14969
|
+
return safrole_data_SafroleSealingKeysData.keys(this.fallbackKeySequencer(newEntropy, newValidators));
|
|
14754
14970
|
}
|
|
14755
14971
|
/**
|
|
14756
14972
|
* Returns epoch markers if the epoch is changed and null otherwise
|
|
@@ -14776,10 +14992,10 @@ class Safrole {
|
|
|
14776
14992
|
for (let i = 1; i < ticketsLength; i++) {
|
|
14777
14993
|
const order = tickets[i - 1].id.compare(tickets[i].id);
|
|
14778
14994
|
if (order.isEqual()) {
|
|
14779
|
-
return result_Result.error(SafroleErrorCode.DuplicateTicket);
|
|
14995
|
+
return result_Result.error(SafroleErrorCode.DuplicateTicket, () => `Safrole: duplicate ticket found at index ${i}`);
|
|
14780
14996
|
}
|
|
14781
14997
|
if (order.isGreater()) {
|
|
14782
|
-
return result_Result.error(SafroleErrorCode.BadTicketOrder);
|
|
14998
|
+
return result_Result.error(SafroleErrorCode.BadTicketOrder, () => `Safrole: bad ticket order at index ${i}`);
|
|
14783
14999
|
}
|
|
14784
15000
|
}
|
|
14785
15001
|
return result_Result.ok(null);
|
|
@@ -14806,7 +15022,7 @@ class Safrole {
|
|
|
14806
15022
|
attempt: ticket.attempt,
|
|
14807
15023
|
}));
|
|
14808
15024
|
if (!verificationResult.every((x) => x.isValid)) {
|
|
14809
|
-
return result_Result.error(SafroleErrorCode.BadTicketProof);
|
|
15025
|
+
return result_Result.error(SafroleErrorCode.BadTicketProof, () => "Safrole: invalid ticket proof in extrinsic");
|
|
14810
15026
|
}
|
|
14811
15027
|
/**
|
|
14812
15028
|
* Verify if tickets are sorted and unique
|
|
@@ -14815,7 +15031,7 @@ class Safrole {
|
|
|
14815
15031
|
*/
|
|
14816
15032
|
const ticketsVerifcationResult = this.verifyTickets(tickets);
|
|
14817
15033
|
if (ticketsVerifcationResult.isError) {
|
|
14818
|
-
return result_Result.error(ticketsVerifcationResult.error);
|
|
15034
|
+
return result_Result.error(ticketsVerifcationResult.error, ticketsVerifcationResult.details);
|
|
14819
15035
|
}
|
|
14820
15036
|
if (this.isEpochChanged(timeslot)) {
|
|
14821
15037
|
return result_Result.ok(tickets);
|
|
@@ -14824,7 +15040,7 @@ class Safrole {
|
|
|
14824
15040
|
const ticketsFromExtrinsic = SortedSet.fromSortedArray(ticketComparator, tickets);
|
|
14825
15041
|
const mergedTickets = SortedSet.fromTwoSortedCollections(ticketsFromState, ticketsFromExtrinsic);
|
|
14826
15042
|
if (ticketsFromState.length + ticketsFromExtrinsic.length !== mergedTickets.length) {
|
|
14827
|
-
return result_Result.error(SafroleErrorCode.DuplicateTicket);
|
|
15043
|
+
return result_Result.error(SafroleErrorCode.DuplicateTicket, () => "Safrole: duplicate ticket when merging state and extrinsic tickets");
|
|
14828
15044
|
}
|
|
14829
15045
|
/**
|
|
14830
15046
|
* Remove tickets if size of accumulator exceeds E (epoch length).
|
|
@@ -14893,24 +15109,24 @@ class Safrole {
|
|
|
14893
15109
|
}
|
|
14894
15110
|
async transition(input) {
|
|
14895
15111
|
if (this.state.timeslot >= input.slot) {
|
|
14896
|
-
return result_Result.error(SafroleErrorCode.BadSlot);
|
|
15112
|
+
return result_Result.error(SafroleErrorCode.BadSlot, () => `Safrole: bad slot, state timeslot ${this.state.timeslot} >= input slot ${input.slot}`);
|
|
14897
15113
|
}
|
|
14898
15114
|
if (!this.isExtrinsicLengthValid(input.slot, input.extrinsic)) {
|
|
14899
|
-
return result_Result.error(SafroleErrorCode.UnexpectedTicket);
|
|
15115
|
+
return result_Result.error(SafroleErrorCode.UnexpectedTicket, () => `Safrole: unexpected ticket, invalid extrinsic length ${input.extrinsic.length}`);
|
|
14900
15116
|
}
|
|
14901
15117
|
if (!this.areTicketAttemptsValid(input.extrinsic)) {
|
|
14902
|
-
return result_Result.error(SafroleErrorCode.BadTicketAttempt);
|
|
15118
|
+
return result_Result.error(SafroleErrorCode.BadTicketAttempt, () => "Safrole: bad ticket attempt value in extrinsic");
|
|
14903
15119
|
}
|
|
14904
15120
|
const validatorKeysResult = await this.getValidatorKeys(input.slot, input.punishSet);
|
|
14905
15121
|
if (validatorKeysResult.isError) {
|
|
14906
|
-
return result_Result.error(validatorKeysResult.error);
|
|
15122
|
+
return result_Result.error(validatorKeysResult.error, validatorKeysResult.details);
|
|
14907
15123
|
}
|
|
14908
15124
|
const { nextValidatorData, currentValidatorData, previousValidatorData, epochRoot } = validatorKeysResult.ok;
|
|
14909
15125
|
const entropy = this.getEntropy(input.slot, input.entropy);
|
|
14910
15126
|
const sealingKeySeries = this.getSlotKeySequence(input.slot, currentValidatorData, entropy[2]);
|
|
14911
15127
|
const newTicketsAccumulatorResult = await this.getNewTicketAccumulator(input.slot, input.extrinsic, this.state.nextValidatorData, epochRoot, entropy[2]);
|
|
14912
15128
|
if (newTicketsAccumulatorResult.isError) {
|
|
14913
|
-
return result_Result.error(newTicketsAccumulatorResult.error);
|
|
15129
|
+
return result_Result.error(newTicketsAccumulatorResult.error, newTicketsAccumulatorResult.details);
|
|
14914
15130
|
}
|
|
14915
15131
|
const stateUpdate = {
|
|
14916
15132
|
nextValidatorData,
|
|
@@ -14944,14 +15160,14 @@ function compareWithEncoding(chainSpec, error, actual, expected, codec) {
|
|
|
14944
15160
|
if (actual === null || expected === null) {
|
|
14945
15161
|
// if one of them is `null`, both need to be.
|
|
14946
15162
|
if (actual !== expected) {
|
|
14947
|
-
return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
|
|
15163
|
+
return result_Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
|
|
14948
15164
|
}
|
|
14949
15165
|
return result_Result.ok(result_OK);
|
|
14950
15166
|
}
|
|
14951
15167
|
// compare the literal encoding.
|
|
14952
15168
|
const encoded = encoder_Encoder.encodeObject(codec, actual, chainSpec);
|
|
14953
15169
|
if (!encoded.isEqualTo(expected.encoded())) {
|
|
14954
|
-
return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
|
|
15170
|
+
return result_Result.error(error, () => `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
|
|
14955
15171
|
}
|
|
14956
15172
|
return result_Result.ok(result_OK);
|
|
14957
15173
|
}
|
|
@@ -14994,55 +15210,54 @@ class SafroleSeal {
|
|
|
14994
15210
|
const blockAuthorKey = state.currentValidatorData.at(blockAuthorIndex)?.bandersnatch;
|
|
14995
15211
|
const entropySourceResult = await bandersnatch_vrf.verifySeal(await this.bandersnatch, blockAuthorKey ?? BANDERSNATCH_ZERO_KEY, headerView.entropySource.materialize(), payload, bytes_BytesBlob.blobFromNumbers([]));
|
|
14996
15212
|
if (entropySourceResult.isError) {
|
|
14997
|
-
return result_Result.error(SafroleSealError.IncorrectEntropySource);
|
|
15213
|
+
return result_Result.error(SafroleSealError.IncorrectEntropySource, () => "Safrole: incorrect entropy source in header seal");
|
|
14998
15214
|
}
|
|
14999
15215
|
return result_Result.ok(entropySourceResult.ok);
|
|
15000
15216
|
}
|
|
15001
15217
|
async verifySeal(headerView, state) {
|
|
15002
15218
|
// we use transitioned keys already
|
|
15003
|
-
const validators = state.currentValidatorData;
|
|
15004
15219
|
const validatorIndex = headerView.bandersnatchBlockAuthorIndex.materialize();
|
|
15005
|
-
const
|
|
15006
|
-
if (
|
|
15007
|
-
return result_Result.error(SafroleSealError.InvalidValidatorIndex);
|
|
15220
|
+
const authorKeys = state.currentValidatorData.at(validatorIndex);
|
|
15221
|
+
if (authorKeys === undefined) {
|
|
15222
|
+
return result_Result.error(SafroleSealError.InvalidValidatorIndex, () => `Safrole: invalid validator index ${validatorIndex}`);
|
|
15008
15223
|
}
|
|
15009
15224
|
const timeSlot = headerView.timeSlotIndex.materialize();
|
|
15010
15225
|
const sealingKeys = state.sealingKeySeries;
|
|
15011
15226
|
const entropy = state.currentEntropy;
|
|
15012
15227
|
if (sealingKeys.kind === SafroleSealingKeysKind.Tickets) {
|
|
15013
|
-
return await this.verifySealWithTicket(sealingKeys.tickets, timeSlot, entropy,
|
|
15228
|
+
return await this.verifySealWithTicket(sealingKeys.tickets, timeSlot, entropy, authorKeys, headerView);
|
|
15014
15229
|
}
|
|
15015
|
-
return await this.verifySealWithKeys(sealingKeys.keys,
|
|
15230
|
+
return await this.verifySealWithKeys(sealingKeys.keys, timeSlot, entropy, authorKeys, headerView);
|
|
15016
15231
|
}
|
|
15017
15232
|
/** Regular (non-fallback) mode of Safrole. */
|
|
15018
|
-
async verifySealWithTicket(tickets, timeSlot, entropy,
|
|
15233
|
+
async verifySealWithTicket(tickets, timeSlot, entropy, validatorData, headerView) {
|
|
15019
15234
|
const index = timeSlot % tickets.length;
|
|
15020
|
-
const
|
|
15021
|
-
const payload = bytes_BytesBlob.blobFromParts(JAM_TICKET_SEAL, entropy.raw, new Uint8Array([attempt]));
|
|
15235
|
+
const ticket = tickets.at(index);
|
|
15236
|
+
const payload = bytes_BytesBlob.blobFromParts(JAM_TICKET_SEAL, entropy.raw, new Uint8Array([ticket?.attempt ?? 0]));
|
|
15022
15237
|
// verify seal correctness
|
|
15023
|
-
const authorKey =
|
|
15238
|
+
const authorKey = validatorData.bandersnatch;
|
|
15024
15239
|
const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, authorKey ?? BANDERSNATCH_ZERO_KEY, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
|
|
15025
15240
|
if (result.isError) {
|
|
15026
|
-
return result_Result.error(SafroleSealError.IncorrectSeal);
|
|
15241
|
+
return result_Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with ticket");
|
|
15027
15242
|
}
|
|
15028
|
-
if (!id.isEqualTo(result.ok)) {
|
|
15029
|
-
return result_Result.error(SafroleSealError.InvalidTicket);
|
|
15243
|
+
if (ticket === undefined || !ticket.id.isEqualTo(result.ok)) {
|
|
15244
|
+
return result_Result.error(SafroleSealError.InvalidTicket, () => `Safrole: invalid ticket, expected ${ticket?.id} got ${result.ok}`);
|
|
15030
15245
|
}
|
|
15031
15246
|
return result_Result.ok(result.ok);
|
|
15032
15247
|
}
|
|
15033
15248
|
/** Fallback mode of Safrole. */
|
|
15034
|
-
async verifySealWithKeys(keys,
|
|
15249
|
+
async verifySealWithKeys(keys, timeSlot, entropy, authorKey, headerView) {
|
|
15035
15250
|
const index = timeSlot % keys.length;
|
|
15036
|
-
const sealingKey = keys
|
|
15037
|
-
|
|
15038
|
-
|
|
15251
|
+
const sealingKey = keys.at(index);
|
|
15252
|
+
const authorBandersnatchKey = authorKey.bandersnatch;
|
|
15253
|
+
if (sealingKey === undefined || !sealingKey.isEqualTo(authorBandersnatchKey)) {
|
|
15254
|
+
return result_Result.error(SafroleSealError.InvalidValidator, () => `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
|
|
15039
15255
|
}
|
|
15040
15256
|
// verify seal correctness
|
|
15041
15257
|
const payload = bytes_BytesBlob.blobFromParts(JAM_FALLBACK_SEAL, entropy.raw);
|
|
15042
|
-
const
|
|
15043
|
-
const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, blockAuthorKey ?? BANDERSNATCH_ZERO_KEY, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
|
|
15258
|
+
const result = await bandersnatch_vrf.verifySeal(await this.bandersnatch, authorBandersnatchKey, headerView.seal.materialize(), payload, encodeUnsealedHeader(headerView));
|
|
15044
15259
|
if (result.isError) {
|
|
15045
|
-
return result_Result.error(SafroleSealError.IncorrectSeal);
|
|
15260
|
+
return result_Result.error(SafroleSealError.IncorrectSeal, () => "Safrole: incorrect seal with keys");
|
|
15046
15261
|
}
|
|
15047
15262
|
return result_Result.ok(result.ok);
|
|
15048
15263
|
}
|
|
@@ -15085,6 +15300,14 @@ async function getRootHash(yieldedRoots) {
|
|
|
15085
15300
|
|
|
15086
15301
|
|
|
15087
15302
|
const InsufficientFundsError = "insufficient funds";
|
|
15303
|
+
/** Deep clone of a map with array. */
|
|
15304
|
+
function deepCloneMapWithArray(map) {
|
|
15305
|
+
const cloned = [];
|
|
15306
|
+
for (const [k, v] of map.entries()) {
|
|
15307
|
+
cloned.push([k, v.slice()]);
|
|
15308
|
+
}
|
|
15309
|
+
return new Map(cloned);
|
|
15310
|
+
}
|
|
15088
15311
|
/**
|
|
15089
15312
|
* State updates that currently accumulating service produced.
|
|
15090
15313
|
*
|
|
@@ -15114,10 +15337,11 @@ class AccumulationStateUpdate {
|
|
|
15114
15337
|
/** Create new empty state update. */
|
|
15115
15338
|
static empty() {
|
|
15116
15339
|
return new AccumulationStateUpdate({
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15340
|
+
created: [],
|
|
15341
|
+
updated: new Map(),
|
|
15342
|
+
removed: [],
|
|
15343
|
+
preimages: new Map(),
|
|
15344
|
+
storage: new Map(),
|
|
15121
15345
|
}, []);
|
|
15122
15346
|
}
|
|
15123
15347
|
/** Create a state update with some existing, yet uncommited services updates. */
|
|
@@ -15129,10 +15353,13 @@ class AccumulationStateUpdate {
|
|
|
15129
15353
|
/** Create a copy of another `StateUpdate`. Used by checkpoints. */
|
|
15130
15354
|
static copyFrom(from) {
|
|
15131
15355
|
const serviceUpdates = {
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15356
|
+
// shallow copy
|
|
15357
|
+
created: [...from.services.created],
|
|
15358
|
+
updated: new Map(from.services.updated),
|
|
15359
|
+
removed: [...from.services.removed],
|
|
15360
|
+
// deep copy
|
|
15361
|
+
preimages: deepCloneMapWithArray(from.services.preimages),
|
|
15362
|
+
storage: deepCloneMapWithArray(from.services.storage),
|
|
15136
15363
|
};
|
|
15137
15364
|
const transfers = [...from.transfers];
|
|
15138
15365
|
const update = new AccumulationStateUpdate(serviceUpdates, transfers, new Map(from.yieldedRoots));
|
|
@@ -15151,6 +15378,12 @@ class AccumulationStateUpdate {
|
|
|
15151
15378
|
}
|
|
15152
15379
|
return update;
|
|
15153
15380
|
}
|
|
15381
|
+
/** Retrieve and clear pending transfers. */
|
|
15382
|
+
takeTransfers() {
|
|
15383
|
+
const transfers = this.transfers;
|
|
15384
|
+
this.transfers = [];
|
|
15385
|
+
return transfers;
|
|
15386
|
+
}
|
|
15154
15387
|
}
|
|
15155
15388
|
class PartiallyUpdatedState {
|
|
15156
15389
|
state;
|
|
@@ -15174,9 +15407,9 @@ class PartiallyUpdatedState {
|
|
|
15174
15407
|
if (destination === null) {
|
|
15175
15408
|
return null;
|
|
15176
15409
|
}
|
|
15177
|
-
const
|
|
15178
|
-
if (
|
|
15179
|
-
return
|
|
15410
|
+
const maybeUpdatedServiceInfo = this.stateUpdate.services.updated.get(destination);
|
|
15411
|
+
if (maybeUpdatedServiceInfo !== undefined) {
|
|
15412
|
+
return maybeUpdatedServiceInfo.action.account;
|
|
15180
15413
|
}
|
|
15181
15414
|
const maybeService = this.state.getService(destination);
|
|
15182
15415
|
if (maybeService === null) {
|
|
@@ -15185,7 +15418,8 @@ class PartiallyUpdatedState {
|
|
|
15185
15418
|
return maybeService.getInfo();
|
|
15186
15419
|
}
|
|
15187
15420
|
getStorage(serviceId, rawKey) {
|
|
15188
|
-
const
|
|
15421
|
+
const storages = this.stateUpdate.services.storage.get(serviceId) ?? [];
|
|
15422
|
+
const item = storages.find((x) => x.key.isEqualTo(rawKey));
|
|
15189
15423
|
if (item !== undefined) {
|
|
15190
15424
|
return item.value;
|
|
15191
15425
|
}
|
|
@@ -15200,10 +15434,11 @@ class PartiallyUpdatedState {
|
|
|
15200
15434
|
* the existence in `preimages` map.
|
|
15201
15435
|
*/
|
|
15202
15436
|
hasPreimage(serviceId, hash) {
|
|
15203
|
-
const
|
|
15437
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
15438
|
+
const providedPreimage = preimages.find(
|
|
15204
15439
|
// we ignore the action here, since if there is <any> update on that
|
|
15205
15440
|
// hash it means it has to exist, right?
|
|
15206
|
-
(p) => p.
|
|
15441
|
+
(p) => p.hash.isEqualTo(hash));
|
|
15207
15442
|
if (providedPreimage !== undefined) {
|
|
15208
15443
|
return true;
|
|
15209
15444
|
}
|
|
@@ -15216,7 +15451,8 @@ class PartiallyUpdatedState {
|
|
|
15216
15451
|
}
|
|
15217
15452
|
getPreimage(serviceId, hash) {
|
|
15218
15453
|
// TODO [ToDr] Should we verify availability here?
|
|
15219
|
-
const
|
|
15454
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
15455
|
+
const freshlyProvided = preimages.find((x) => x.hash.isEqualTo(hash));
|
|
15220
15456
|
if (freshlyProvided !== undefined && freshlyProvided.action.kind === UpdatePreimageKind.Provide) {
|
|
15221
15457
|
return freshlyProvided.action.preimage.blob;
|
|
15222
15458
|
}
|
|
@@ -15225,10 +15461,11 @@ class PartiallyUpdatedState {
|
|
|
15225
15461
|
}
|
|
15226
15462
|
/** Get status of a preimage of current service taking into account any updates. */
|
|
15227
15463
|
getLookupHistory(currentTimeslot, serviceId, hash, length) {
|
|
15464
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
15228
15465
|
// TODO [ToDr] This is most likely wrong. We may have `provide` and `remove` within
|
|
15229
15466
|
// the same state update. We should however switch to proper "updated state"
|
|
15230
15467
|
// representation soon.
|
|
15231
|
-
const updatedPreimage =
|
|
15468
|
+
const updatedPreimage = preimages.findLast((update) => update.hash.isEqualTo(hash) && BigInt(update.length) === length);
|
|
15232
15469
|
const stateFallback = () => {
|
|
15233
15470
|
// fallback to state lookup
|
|
15234
15471
|
const service = this.state.getService(serviceId);
|
|
@@ -15265,14 +15502,15 @@ class PartiallyUpdatedState {
|
|
|
15265
15502
|
/* State update functions. */
|
|
15266
15503
|
updateStorage(serviceId, key, value) {
|
|
15267
15504
|
const update = value === null
|
|
15268
|
-
? UpdateStorage.remove({
|
|
15505
|
+
? UpdateStorage.remove({ key })
|
|
15269
15506
|
: UpdateStorage.set({
|
|
15270
|
-
serviceId,
|
|
15271
15507
|
storage: StorageItem.create({ key, value }),
|
|
15272
15508
|
});
|
|
15273
|
-
const
|
|
15509
|
+
const storages = this.stateUpdate.services.storage.get(serviceId) ?? [];
|
|
15510
|
+
const index = storages.findIndex((x) => x.key.isEqualTo(key));
|
|
15274
15511
|
const count = index === -1 ? 0 : 1;
|
|
15275
|
-
|
|
15512
|
+
storages.splice(index, count, update);
|
|
15513
|
+
this.stateUpdate.services.storage.set(serviceId, storages);
|
|
15276
15514
|
}
|
|
15277
15515
|
/**
|
|
15278
15516
|
* Update a preimage.
|
|
@@ -15280,8 +15518,10 @@ class PartiallyUpdatedState {
|
|
|
15280
15518
|
* Note we store all previous entries as well, since there might be a sequence of:
|
|
15281
15519
|
* `provide` -> `remove` and both should update the end state somehow.
|
|
15282
15520
|
*/
|
|
15283
|
-
updatePreimage(newUpdate) {
|
|
15284
|
-
this.stateUpdate.services.preimages.
|
|
15521
|
+
updatePreimage(serviceId, newUpdate) {
|
|
15522
|
+
const updatePreimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
15523
|
+
updatePreimages.push(newUpdate);
|
|
15524
|
+
this.stateUpdate.services.preimages.set(serviceId, updatePreimages);
|
|
15285
15525
|
}
|
|
15286
15526
|
updateServiceStorageUtilisation(serviceId, items, bytes, serviceInfo) {
|
|
15287
15527
|
debug_check `${items >= 0} storageUtilisationCount has to be a positive number, got: ${items}`;
|
|
@@ -15290,11 +15530,11 @@ class PartiallyUpdatedState {
|
|
|
15290
15530
|
const overflowBytes = !isU64(bytes);
|
|
15291
15531
|
// TODO [ToDr] this is not specified in GP, but it seems sensible.
|
|
15292
15532
|
if (overflowItems || overflowBytes) {
|
|
15293
|
-
return result_Result.error(InsufficientFundsError);
|
|
15533
|
+
return result_Result.error(InsufficientFundsError, () => `Storage utilisation overflow: items=${overflowItems}, bytes=${overflowBytes}`);
|
|
15294
15534
|
}
|
|
15295
15535
|
const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(items, bytes, serviceInfo.gratisStorage);
|
|
15296
15536
|
if (serviceInfo.balance < thresholdBalance) {
|
|
15297
|
-
return result_Result.error(InsufficientFundsError);
|
|
15537
|
+
return result_Result.error(InsufficientFundsError, () => `Service balance (${serviceInfo.balance}) below threshold (${thresholdBalance})`);
|
|
15298
15538
|
}
|
|
15299
15539
|
// Update service info with new details.
|
|
15300
15540
|
this.updateServiceInfo(serviceId, ServiceAccountInfo.create({
|
|
@@ -15305,20 +15545,23 @@ class PartiallyUpdatedState {
|
|
|
15305
15545
|
return result_Result.ok(result_OK);
|
|
15306
15546
|
}
|
|
15307
15547
|
updateServiceInfo(serviceId, newInfo) {
|
|
15308
|
-
const
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
if (existingItem?.action.kind === UpdateServiceKind.Create) {
|
|
15312
|
-
this.stateUpdate.services.servicesUpdates.splice(idx, toRemove, UpdateService.create({
|
|
15313
|
-
serviceId,
|
|
15548
|
+
const existingUpdate = this.stateUpdate.services.updated.get(serviceId);
|
|
15549
|
+
if (existingUpdate?.action.kind === UpdateServiceKind.Create) {
|
|
15550
|
+
this.stateUpdate.services.updated.set(serviceId, UpdateService.create({
|
|
15314
15551
|
serviceInfo: newInfo,
|
|
15315
|
-
lookupHistory:
|
|
15552
|
+
lookupHistory: existingUpdate.action.lookupHistory,
|
|
15316
15553
|
}));
|
|
15317
15554
|
return;
|
|
15318
15555
|
}
|
|
15319
|
-
this.stateUpdate.services.
|
|
15320
|
-
|
|
15556
|
+
this.stateUpdate.services.updated.set(serviceId, UpdateService.update({
|
|
15557
|
+
serviceInfo: newInfo,
|
|
15558
|
+
}));
|
|
15559
|
+
}
|
|
15560
|
+
createService(serviceId, newInfo, newLookupHistory) {
|
|
15561
|
+
this.stateUpdate.services.created.push(serviceId);
|
|
15562
|
+
this.stateUpdate.services.updated.set(serviceId, UpdateService.create({
|
|
15321
15563
|
serviceInfo: newInfo,
|
|
15564
|
+
lookupHistory: newLookupHistory,
|
|
15322
15565
|
}));
|
|
15323
15566
|
}
|
|
15324
15567
|
getPrivilegedServices() {
|
|
@@ -16794,7 +17037,7 @@ class ReadablePage extends MemoryPage {
|
|
|
16794
17037
|
loadInto(result, startIndex, length) {
|
|
16795
17038
|
const endIndex = startIndex + length;
|
|
16796
17039
|
if (endIndex > PAGE_SIZE) {
|
|
16797
|
-
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE));
|
|
17040
|
+
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE}`);
|
|
16798
17041
|
}
|
|
16799
17042
|
const bytes = this.data.subarray(startIndex, endIndex);
|
|
16800
17043
|
// we zero the bytes, since data might not yet be initialized at `endIndex`.
|
|
@@ -16803,7 +17046,7 @@ class ReadablePage extends MemoryPage {
|
|
|
16803
17046
|
return result_Result.ok(result_OK);
|
|
16804
17047
|
}
|
|
16805
17048
|
storeFrom(_address, _data) {
|
|
16806
|
-
return result_Result.error(PageFault.fromMemoryIndex(this.start, true));
|
|
17049
|
+
return result_Result.error(PageFault.fromMemoryIndex(this.start, true), () => `Page fault: attempted to write to read-only page at ${this.start}`);
|
|
16807
17050
|
}
|
|
16808
17051
|
setData(pageIndex, data) {
|
|
16809
17052
|
this.data.set(data, pageIndex);
|
|
@@ -16837,7 +17080,7 @@ class WriteablePage extends MemoryPage {
|
|
|
16837
17080
|
loadInto(result, startIndex, length) {
|
|
16838
17081
|
const endIndex = startIndex + length;
|
|
16839
17082
|
if (endIndex > PAGE_SIZE) {
|
|
16840
|
-
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE));
|
|
17083
|
+
return result_Result.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE}`);
|
|
16841
17084
|
}
|
|
16842
17085
|
const bytes = this.view.subarray(startIndex, endIndex);
|
|
16843
17086
|
// we zero the bytes, since the view might not yet be initialized at `endIndex`.
|
|
@@ -16923,7 +17166,7 @@ class Memory {
|
|
|
16923
17166
|
memory_logger.insane `MEM[${address}] <- ${bytes_BytesBlob.blobFrom(bytes)}`;
|
|
16924
17167
|
const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
|
|
16925
17168
|
if (pagesResult.isError) {
|
|
16926
|
-
return result_Result.error(pagesResult.error);
|
|
17169
|
+
return result_Result.error(pagesResult.error, pagesResult.details);
|
|
16927
17170
|
}
|
|
16928
17171
|
const pages = pagesResult.ok;
|
|
16929
17172
|
let currentPosition = address;
|
|
@@ -16948,14 +17191,14 @@ class Memory {
|
|
|
16948
17191
|
const pages = [];
|
|
16949
17192
|
for (const pageNumber of pageRange) {
|
|
16950
17193
|
if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
|
|
16951
|
-
return result_Result.error(PageFault.fromPageNumber(pageNumber, true));
|
|
17194
|
+
return result_Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
|
|
16952
17195
|
}
|
|
16953
17196
|
const page = this.memory.get(pageNumber);
|
|
16954
17197
|
if (page === undefined) {
|
|
16955
|
-
return result_Result.error(PageFault.fromPageNumber(pageNumber));
|
|
17198
|
+
return result_Result.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
|
|
16956
17199
|
}
|
|
16957
17200
|
if (accessType === AccessType.WRITE && !page.isWriteable()) {
|
|
16958
|
-
return result_Result.error(PageFault.fromPageNumber(pageNumber, true));
|
|
17201
|
+
return result_Result.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
|
|
16959
17202
|
}
|
|
16960
17203
|
pages.push(page);
|
|
16961
17204
|
}
|
|
@@ -16973,7 +17216,7 @@ class Memory {
|
|
|
16973
17216
|
}
|
|
16974
17217
|
const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
|
|
16975
17218
|
if (pagesResult.isError) {
|
|
16976
|
-
return result_Result.error(pagesResult.error);
|
|
17219
|
+
return result_Result.error(pagesResult.error, pagesResult.details);
|
|
16977
17220
|
}
|
|
16978
17221
|
const pages = pagesResult.ok;
|
|
16979
17222
|
let currentPosition = startAddress;
|
|
@@ -18912,7 +19155,7 @@ class ProgramDecoder {
|
|
|
18912
19155
|
}
|
|
18913
19156
|
catch (e) {
|
|
18914
19157
|
program_decoder_logger.error `Invalid program: ${e}`;
|
|
18915
|
-
return result_Result.error(ProgramDecoderError.InvalidProgramError);
|
|
19158
|
+
return result_Result.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
|
|
18916
19159
|
}
|
|
18917
19160
|
}
|
|
18918
19161
|
}
|
|
@@ -19190,6 +19433,24 @@ class Interpreter {
|
|
|
19190
19433
|
getMemoryPage(pageNumber) {
|
|
19191
19434
|
return this.memory.getPageDump(tryAsPageNumber(pageNumber));
|
|
19192
19435
|
}
|
|
19436
|
+
calculateBlockGasCost() {
|
|
19437
|
+
const codeLength = this.code.length;
|
|
19438
|
+
const blocks = new Map();
|
|
19439
|
+
let currentBlock = "0";
|
|
19440
|
+
let gasCost = 0;
|
|
19441
|
+
const getNextIstructionIndex = (index) => index + 1 + this.mask.getNoOfBytesToNextInstruction(index + 1);
|
|
19442
|
+
for (let index = 0; index < codeLength; index = getNextIstructionIndex(index)) {
|
|
19443
|
+
const instruction = this.code[index];
|
|
19444
|
+
if (this.basicBlocks.isBeginningOfBasicBlock(index)) {
|
|
19445
|
+
blocks.set(currentBlock, gasCost);
|
|
19446
|
+
currentBlock = index.toString();
|
|
19447
|
+
gasCost = 0;
|
|
19448
|
+
}
|
|
19449
|
+
gasCost += instructionGasMap[instruction];
|
|
19450
|
+
}
|
|
19451
|
+
blocks.set(currentBlock, gasCost);
|
|
19452
|
+
return blocks;
|
|
19453
|
+
}
|
|
19193
19454
|
}
|
|
19194
19455
|
|
|
19195
19456
|
;// CONCATENATED MODULE: ./packages/core/pvm-interpreter/index.ts
|
|
@@ -19637,10 +19898,10 @@ class AccumulateExternalities {
|
|
|
19637
19898
|
const len = existingPreimage.slots.length;
|
|
19638
19899
|
// https://graypaper.fluffylabs.dev/#/9a08063/380901380901?v=0.6.6
|
|
19639
19900
|
if (len === PreimageStatusKind.Requested) {
|
|
19640
|
-
return result_Result.error(RequestPreimageError.AlreadyRequested);
|
|
19901
|
+
return result_Result.error(RequestPreimageError.AlreadyRequested, () => `Preimage already requested: hash=${hash}`);
|
|
19641
19902
|
}
|
|
19642
19903
|
if (len === PreimageStatusKind.Available || len === PreimageStatusKind.Reavailable) {
|
|
19643
|
-
return result_Result.error(RequestPreimageError.AlreadyAvailable);
|
|
19904
|
+
return result_Result.error(RequestPreimageError.AlreadyAvailable, () => `Preimage already available: hash=${hash}`);
|
|
19644
19905
|
}
|
|
19645
19906
|
// TODO [ToDr] Not sure if we should update the service info in that case,
|
|
19646
19907
|
// but for now we let that case fall-through.
|
|
@@ -19665,15 +19926,13 @@ class AccumulateExternalities {
|
|
|
19665
19926
|
const clampedLength = clampU64ToU32(length);
|
|
19666
19927
|
if (existingPreimage === null) {
|
|
19667
19928
|
// https://graypaper.fluffylabs.dev/#/9a08063/38a60038a600?v=0.6.6
|
|
19668
|
-
this.updatedState.updatePreimage(UpdatePreimage.updateOrAdd({
|
|
19669
|
-
serviceId: this.currentServiceId,
|
|
19929
|
+
this.updatedState.updatePreimage(this.currentServiceId, UpdatePreimage.updateOrAdd({
|
|
19670
19930
|
lookupHistory: new LookupHistoryItem(hash, clampedLength, tryAsLookupHistorySlots([])),
|
|
19671
19931
|
}));
|
|
19672
19932
|
}
|
|
19673
19933
|
else {
|
|
19674
19934
|
/** https://graypaper.fluffylabs.dev/#/9a08063/38ca0038ca00?v=0.6.6 */
|
|
19675
|
-
this.updatedState.updatePreimage(UpdatePreimage.updateOrAdd({
|
|
19676
|
-
serviceId: this.currentServiceId,
|
|
19935
|
+
this.updatedState.updatePreimage(this.currentServiceId, UpdatePreimage.updateOrAdd({
|
|
19677
19936
|
lookupHistory: new LookupHistoryItem(hash, clampedLength, tryAsLookupHistorySlots([...existingPreimage.slots, this.currentTimeslot])),
|
|
19678
19937
|
}));
|
|
19679
19938
|
}
|
|
@@ -19683,7 +19942,7 @@ class AccumulateExternalities {
|
|
|
19683
19942
|
const serviceId = this.currentServiceId;
|
|
19684
19943
|
const status = this.updatedState.getLookupHistory(this.currentTimeslot, this.currentServiceId, hash, length);
|
|
19685
19944
|
if (status === null) {
|
|
19686
|
-
return result_Result.error(ForgetPreimageError.NotFound);
|
|
19945
|
+
return result_Result.error(ForgetPreimageError.NotFound, () => `Preimage not found: hash=${hash}, length=${length}`);
|
|
19687
19946
|
}
|
|
19688
19947
|
const s = slotsToPreimageStatus(status.slots);
|
|
19689
19948
|
const updateStorageUtilisation = () => {
|
|
@@ -19696,10 +19955,9 @@ class AccumulateExternalities {
|
|
|
19696
19955
|
if (s.status === PreimageStatusKind.Requested) {
|
|
19697
19956
|
const res = updateStorageUtilisation();
|
|
19698
19957
|
if (res.isError) {
|
|
19699
|
-
return result_Result.error(ForgetPreimageError.StorageUtilisationError);
|
|
19958
|
+
return result_Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
|
|
19700
19959
|
}
|
|
19701
|
-
this.updatedState.updatePreimage(UpdatePreimage.remove({
|
|
19702
|
-
serviceId,
|
|
19960
|
+
this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
|
|
19703
19961
|
hash: status.hash,
|
|
19704
19962
|
length: status.length,
|
|
19705
19963
|
}));
|
|
@@ -19712,21 +19970,19 @@ class AccumulateExternalities {
|
|
|
19712
19970
|
if (y < t - this.chainSpec.preimageExpungePeriod) {
|
|
19713
19971
|
const res = updateStorageUtilisation();
|
|
19714
19972
|
if (res.isError) {
|
|
19715
|
-
return result_Result.error(ForgetPreimageError.StorageUtilisationError);
|
|
19973
|
+
return result_Result.error(ForgetPreimageError.StorageUtilisationError, res.details);
|
|
19716
19974
|
}
|
|
19717
|
-
this.updatedState.updatePreimage(UpdatePreimage.remove({
|
|
19718
|
-
serviceId,
|
|
19975
|
+
this.updatedState.updatePreimage(serviceId, UpdatePreimage.remove({
|
|
19719
19976
|
hash: status.hash,
|
|
19720
19977
|
length: status.length,
|
|
19721
19978
|
}));
|
|
19722
19979
|
return result_Result.ok(result_OK);
|
|
19723
19980
|
}
|
|
19724
|
-
return result_Result.error(ForgetPreimageError.NotExpired);
|
|
19981
|
+
return result_Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
|
|
19725
19982
|
}
|
|
19726
19983
|
// https://graypaper.fluffylabs.dev/#/9a08063/38c80138c801?v=0.6.6
|
|
19727
19984
|
if (s.status === PreimageStatusKind.Available) {
|
|
19728
|
-
this.updatedState.updatePreimage(UpdatePreimage.updateOrAdd({
|
|
19729
|
-
serviceId,
|
|
19985
|
+
this.updatedState.updatePreimage(serviceId, UpdatePreimage.updateOrAdd({
|
|
19730
19986
|
lookupHistory: new LookupHistoryItem(status.hash, status.length, tryAsLookupHistorySlots([s.data[0], t])),
|
|
19731
19987
|
}));
|
|
19732
19988
|
return result_Result.ok(result_OK);
|
|
@@ -19735,13 +19991,12 @@ class AccumulateExternalities {
|
|
|
19735
19991
|
if (s.status === PreimageStatusKind.Reavailable) {
|
|
19736
19992
|
const y = s.data[1];
|
|
19737
19993
|
if (y < t - this.chainSpec.preimageExpungePeriod) {
|
|
19738
|
-
this.updatedState.updatePreimage(UpdatePreimage.updateOrAdd({
|
|
19739
|
-
serviceId,
|
|
19994
|
+
this.updatedState.updatePreimage(serviceId, UpdatePreimage.updateOrAdd({
|
|
19740
19995
|
lookupHistory: new LookupHistoryItem(status.hash, status.length, tryAsLookupHistorySlots([s.data[2], t])),
|
|
19741
19996
|
}));
|
|
19742
19997
|
return result_Result.ok(result_OK);
|
|
19743
19998
|
}
|
|
19744
|
-
return result_Result.error(ForgetPreimageError.NotExpired);
|
|
19999
|
+
return result_Result.error(ForgetPreimageError.NotExpired, () => `Preimage not expired: y=${y}, timeslot=${t}, period=${this.chainSpec.preimageExpungePeriod}`);
|
|
19745
20000
|
}
|
|
19746
20001
|
debug_assertNever(s);
|
|
19747
20002
|
}
|
|
@@ -19750,17 +20005,17 @@ class AccumulateExternalities {
|
|
|
19750
20005
|
const destination = this.getServiceInfo(destinationId);
|
|
19751
20006
|
/** https://graypaper.fluffylabs.dev/#/9a08063/370401370401?v=0.6.6 */
|
|
19752
20007
|
if (destination === null || destinationId === null) {
|
|
19753
|
-
return result_Result.error(TransferError.DestinationNotFound);
|
|
20008
|
+
return result_Result.error(TransferError.DestinationNotFound, () => `Destination service not found: ${destinationId}`);
|
|
19754
20009
|
}
|
|
19755
20010
|
/** https://graypaper.fluffylabs.dev/#/9a08063/371301371301?v=0.6.6 */
|
|
19756
20011
|
if (gas < destination.onTransferMinGas) {
|
|
19757
|
-
return result_Result.error(TransferError.GasTooLow);
|
|
20012
|
+
return result_Result.error(TransferError.GasTooLow, () => `Gas ${gas} below minimum ${destination.onTransferMinGas}`);
|
|
19758
20013
|
}
|
|
19759
20014
|
/** https://graypaper.fluffylabs.dev/#/9a08063/371b01371b01?v=0.6.6 */
|
|
19760
20015
|
const newBalance = source.balance - amount;
|
|
19761
20016
|
const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(source.storageUtilisationCount, source.storageUtilisationBytes, source.gratisStorage);
|
|
19762
20017
|
if (newBalance < thresholdBalance) {
|
|
19763
|
-
return result_Result.error(TransferError.BalanceBelowThreshold);
|
|
20018
|
+
return result_Result.error(TransferError.BalanceBelowThreshold, () => `Balance ${newBalance} below threshold ${thresholdBalance}`);
|
|
19764
20019
|
}
|
|
19765
20020
|
// outgoing transfer
|
|
19766
20021
|
this.updatedState.stateUpdate.transfers.push(PendingTransfer.create({
|
|
@@ -19787,7 +20042,7 @@ class AccumulateExternalities {
|
|
|
19787
20042
|
// check if we are priviledged to set gratis storage
|
|
19788
20043
|
// https://graypaper.fluffylabs.dev/#/7e6ff6a/369203369603?v=0.6.7
|
|
19789
20044
|
if (gratisStorage !== numbers_tryAsU64(0) && this.currentServiceId !== this.updatedState.getPrivilegedServices().manager) {
|
|
19790
|
-
return result_Result.error(NewServiceError.UnprivilegedService);
|
|
20045
|
+
return result_Result.error(NewServiceError.UnprivilegedService, () => `Service ${this.currentServiceId} not privileged to set gratis storage`);
|
|
19791
20046
|
}
|
|
19792
20047
|
// check if we have enough balance
|
|
19793
20048
|
// https://graypaper.fluffylabs.dev/#/7e6ff6a/369e0336a303?v=0.6.7
|
|
@@ -19796,7 +20051,7 @@ class AccumulateExternalities {
|
|
|
19796
20051
|
const thresholdForCurrent = ServiceAccountInfo.calculateThresholdBalance(currentService.storageUtilisationCount, currentService.storageUtilisationBytes, currentService.gratisStorage);
|
|
19797
20052
|
const balanceLeftForCurrent = currentService.balance - thresholdForNew;
|
|
19798
20053
|
if (balanceLeftForCurrent < thresholdForCurrent || bytes.overflow) {
|
|
19799
|
-
return result_Result.error(NewServiceError.InsufficientFunds);
|
|
20054
|
+
return result_Result.error(NewServiceError.InsufficientFunds, () => `Insufficient funds: balance=${currentService.balance}, required=${thresholdForNew}, overflow=${bytes.overflow}`);
|
|
19800
20055
|
}
|
|
19801
20056
|
// `a`: https://graypaper.fluffylabs.dev/#/ab2cdbd/366b02366d02?v=0.7.2
|
|
19802
20057
|
const newAccount = ServiceAccountInfo.create({
|
|
@@ -19823,15 +20078,11 @@ class AccumulateExternalities {
|
|
|
19823
20078
|
// NOTE: It's safe to cast to `Number` here, bcs here service ID cannot be bigger than 2**16
|
|
19824
20079
|
const newServiceId = tryAsServiceId(Number(wantedServiceId));
|
|
19825
20080
|
if (this.getServiceInfo(newServiceId) !== null) {
|
|
19826
|
-
return result_Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken);
|
|
20081
|
+
return result_Result.error(NewServiceError.RegistrarServiceIdAlreadyTaken, () => `Service ID ${newServiceId} already taken`);
|
|
19827
20082
|
}
|
|
19828
20083
|
// add the new service with selected ID
|
|
19829
20084
|
// https://graypaper.fluffylabs.dev/#/ab2cdbd/36be0336c003?v=0.7.2
|
|
19830
|
-
this.updatedState.
|
|
19831
|
-
serviceId: newServiceId,
|
|
19832
|
-
serviceInfo: newAccount,
|
|
19833
|
-
lookupHistory: newLookupItem,
|
|
19834
|
-
}));
|
|
20085
|
+
this.updatedState.createService(newServiceId, newAccount, newLookupItem);
|
|
19835
20086
|
// update the balance of current service
|
|
19836
20087
|
// https://graypaper.fluffylabs.dev/#/ab2cdbd/36c20336c403?v=0.7.2
|
|
19837
20088
|
this.updatedState.updateServiceInfo(this.currentServiceId, updatedCurrentAccount);
|
|
@@ -19842,12 +20093,8 @@ class AccumulateExternalities {
|
|
|
19842
20093
|
}
|
|
19843
20094
|
const newServiceId = this.nextNewServiceId;
|
|
19844
20095
|
// add the new service
|
|
19845
|
-
// https://graypaper.fluffylabs.dev/#/
|
|
19846
|
-
this.updatedState.
|
|
19847
|
-
serviceId: newServiceId,
|
|
19848
|
-
serviceInfo: newAccount,
|
|
19849
|
-
lookupHistory: newLookupItem,
|
|
19850
|
-
}));
|
|
20096
|
+
// https://graypaper.fluffylabs.dev/#/7e6ff6a/36cb0236cb02?v=0.6.7
|
|
20097
|
+
this.updatedState.createService(newServiceId, newAccount, newLookupItem);
|
|
19851
20098
|
// update the balance of current service
|
|
19852
20099
|
// https://graypaper.fluffylabs.dev/#/ab2cdbd/36ec0336ee03?v=0.7.2
|
|
19853
20100
|
this.updatedState.updateServiceInfo(this.currentServiceId, updatedCurrentAccount);
|
|
@@ -19871,7 +20118,7 @@ class AccumulateExternalities {
|
|
|
19871
20118
|
const currentDelegator = this.updatedState.getPrivilegedServices().delegator;
|
|
19872
20119
|
if (currentDelegator !== this.currentServiceId) {
|
|
19873
20120
|
accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not a validators manager. (expected: ${currentDelegator}) and cannot update validators data. Ignoring`;
|
|
19874
|
-
return result_Result.error(UnprivilegedError);
|
|
20121
|
+
return result_Result.error(UnprivilegedError, () => `Service ${this.currentServiceId} is not delegator (expected: ${currentDelegator})`);
|
|
19875
20122
|
}
|
|
19876
20123
|
this.updatedState.stateUpdate.validatorsData = validatorsData;
|
|
19877
20124
|
return result_Result.ok(result_OK);
|
|
@@ -19886,33 +20133,87 @@ class AccumulateExternalities {
|
|
|
19886
20133
|
const currentAssigners = this.updatedState.getPrivilegedServices().assigners[coreIndex];
|
|
19887
20134
|
if (currentAssigners !== this.currentServiceId) {
|
|
19888
20135
|
accumulate_externalities_logger.trace `Current service id (${this.currentServiceId}) is not an auth manager of core ${coreIndex} (expected: ${currentAssigners}) and cannot update authorization queue.`;
|
|
19889
|
-
return result_Result.error(UpdatePrivilegesError.UnprivilegedService);
|
|
20136
|
+
return result_Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} not assigner for core ${coreIndex} (expected: ${currentAssigners})`);
|
|
19890
20137
|
}
|
|
19891
20138
|
if (assigners === null && Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)) {
|
|
19892
20139
|
accumulate_externalities_logger.trace `The new auth manager is not a valid service id.`;
|
|
19893
|
-
return result_Result.error(UpdatePrivilegesError.InvalidServiceId);
|
|
20140
|
+
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => `New auth manager is null for core ${coreIndex}`);
|
|
19894
20141
|
}
|
|
19895
20142
|
this.updatedState.stateUpdate.authorizationQueues.set(coreIndex, authQueue);
|
|
19896
20143
|
return result_Result.ok(result_OK);
|
|
19897
20144
|
}
|
|
20145
|
+
updatePrivilegedServiceId(
|
|
20146
|
+
// The id that privileged service wants to be updated to
|
|
20147
|
+
newId,
|
|
20148
|
+
// Current id of privileged service (updated state)
|
|
20149
|
+
currentId, {
|
|
20150
|
+
// is current service id a manager (can update anything)
|
|
20151
|
+
isManager,
|
|
20152
|
+
// is current service attempting to update itself (privileged are owned)
|
|
20153
|
+
isSelf,
|
|
20154
|
+
// is the service id already changed in this block
|
|
20155
|
+
isAlreadyChanged, }) {
|
|
20156
|
+
if (isManager) {
|
|
20157
|
+
return newId;
|
|
20158
|
+
}
|
|
20159
|
+
// current service can update itself, only if it was a privileged
|
|
20160
|
+
// service at the start of the block. I.e. owned privileges cannot
|
|
20161
|
+
// be transfered multiple times in a block.
|
|
20162
|
+
if (isSelf && !isAlreadyChanged) {
|
|
20163
|
+
return newId;
|
|
20164
|
+
}
|
|
20165
|
+
return currentId;
|
|
20166
|
+
}
|
|
19898
20167
|
updatePrivilegedServices(manager, authorizers, delegator, registrar, autoAccumulate) {
|
|
19899
20168
|
/** https://graypaper.fluffylabs.dev/#/7e6ff6a/36d90036de00?v=0.6.7 */
|
|
19900
|
-
const
|
|
19901
|
-
|
|
19902
|
-
|
|
19903
|
-
|
|
19904
|
-
|
|
19905
|
-
|
|
20169
|
+
const current = this.updatedState.getPrivilegedServices();
|
|
20170
|
+
const isManager = current.manager === this.currentServiceId;
|
|
20171
|
+
if (Compatibility.isLessThan(GpVersion.V0_7_1)) {
|
|
20172
|
+
if (!isManager) {
|
|
20173
|
+
return result_Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} is not manager`);
|
|
20174
|
+
}
|
|
20175
|
+
if (manager === null || delegator === null) {
|
|
20176
|
+
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator is not a valid service id.");
|
|
20177
|
+
}
|
|
20178
|
+
this.updatedState.stateUpdate.privilegedServices = PrivilegedServices.create({
|
|
20179
|
+
manager,
|
|
20180
|
+
assigners: authorizers,
|
|
20181
|
+
delegator: delegator,
|
|
20182
|
+
registrar: registrar ?? tryAsServiceId(0),
|
|
20183
|
+
autoAccumulateServices: autoAccumulate.map(([service, gasLimit]) => AutoAccumulate.create({ service, gasLimit })),
|
|
20184
|
+
});
|
|
20185
|
+
return result_Result.ok(result_OK);
|
|
19906
20186
|
}
|
|
19907
|
-
|
|
19908
|
-
|
|
20187
|
+
const original = this.updatedState.state.privilegedServices;
|
|
20188
|
+
if (manager === null || delegator === null || registrar === null) {
|
|
20189
|
+
return result_Result.error(UpdatePrivilegesError.InvalidServiceId, () => "Either manager or delegator or registrar is not a valid service id.");
|
|
19909
20190
|
}
|
|
20191
|
+
const newDelegator = this.updatePrivilegedServiceId(delegator, current.delegator, {
|
|
20192
|
+
isManager,
|
|
20193
|
+
isSelf: this.currentServiceId === current.delegator,
|
|
20194
|
+
isAlreadyChanged: current.delegator !== original.delegator,
|
|
20195
|
+
});
|
|
20196
|
+
const newRegistrar = this.updatePrivilegedServiceId(registrar, current.registrar, {
|
|
20197
|
+
isManager,
|
|
20198
|
+
isSelf: this.currentServiceId === current.registrar,
|
|
20199
|
+
isAlreadyChanged: current.registrar !== original.registrar,
|
|
20200
|
+
});
|
|
20201
|
+
const newAssigners = current.assigners.map((currentAssigner, index) => this.updatePrivilegedServiceId(authorizers[index], currentAssigner, {
|
|
20202
|
+
isManager,
|
|
20203
|
+
isSelf: this.currentServiceId === currentAssigner,
|
|
20204
|
+
isAlreadyChanged: currentAssigner !== original.assigners[index],
|
|
20205
|
+
}));
|
|
20206
|
+
const newManager = isManager ? manager : current.manager;
|
|
20207
|
+
const newAutoAccumulateServices = isManager
|
|
20208
|
+
? autoAccumulate.map(([service, gasLimit]) => AutoAccumulate.create({ service, gasLimit }))
|
|
20209
|
+
: current.autoAccumulateServices;
|
|
20210
|
+
// finally update the privileges
|
|
19910
20211
|
this.updatedState.stateUpdate.privilegedServices = PrivilegedServices.create({
|
|
19911
|
-
manager,
|
|
19912
|
-
assigners:
|
|
19913
|
-
delegator,
|
|
19914
|
-
registrar:
|
|
19915
|
-
autoAccumulateServices:
|
|
20212
|
+
manager: newManager,
|
|
20213
|
+
assigners: tryAsPerCore(newAssigners, this.chainSpec),
|
|
20214
|
+
delegator: newDelegator,
|
|
20215
|
+
registrar: newRegistrar,
|
|
20216
|
+
autoAccumulateServices: newAutoAccumulateServices,
|
|
19916
20217
|
});
|
|
19917
20218
|
return result_Result.ok(result_OK);
|
|
19918
20219
|
}
|
|
@@ -19925,23 +20226,22 @@ class AccumulateExternalities {
|
|
|
19925
20226
|
// TODO [ToDr] what about newly created services?
|
|
19926
20227
|
const service = serviceId === null ? null : this.updatedState.state.getService(serviceId);
|
|
19927
20228
|
if (service === null || serviceId === null) {
|
|
19928
|
-
return result_Result.error(ProvidePreimageError.ServiceNotFound);
|
|
20229
|
+
return result_Result.error(ProvidePreimageError.ServiceNotFound, () => `Service not found: ${serviceId}`);
|
|
19929
20230
|
}
|
|
19930
20231
|
// calculating the hash
|
|
19931
20232
|
const preimageHash = this.blake2b.hashBytes(preimage).asOpaque();
|
|
19932
20233
|
// checking service internal lookup
|
|
19933
20234
|
const stateLookup = this.updatedState.getLookupHistory(this.currentTimeslot, serviceId, preimageHash, numbers_tryAsU64(preimage.length));
|
|
19934
20235
|
if (stateLookup === null || !LookupHistoryItem.isRequested(stateLookup)) {
|
|
19935
|
-
return result_Result.error(ProvidePreimageError.WasNotRequested);
|
|
20236
|
+
return result_Result.error(ProvidePreimageError.WasNotRequested, () => `Preimage was not requested: hash=${preimageHash}, service=${serviceId}`);
|
|
19936
20237
|
}
|
|
19937
20238
|
// checking already provided preimages
|
|
19938
20239
|
const hasPreimage = this.updatedState.hasPreimage(serviceId, preimageHash);
|
|
19939
20240
|
if (hasPreimage) {
|
|
19940
|
-
return result_Result.error(ProvidePreimageError.AlreadyProvided);
|
|
20241
|
+
return result_Result.error(ProvidePreimageError.AlreadyProvided, () => `Preimage already provided: hash=${preimageHash}, service=${serviceId}`);
|
|
19941
20242
|
}
|
|
19942
20243
|
// setting up the new preimage
|
|
19943
|
-
this.updatedState.updatePreimage(UpdatePreimage.provide({
|
|
19944
|
-
serviceId,
|
|
20244
|
+
this.updatedState.updatePreimage(serviceId, UpdatePreimage.provide({
|
|
19945
20245
|
preimage: PreimageItem.create({
|
|
19946
20246
|
hash: preimageHash,
|
|
19947
20247
|
blob: preimage,
|
|
@@ -19953,31 +20253,31 @@ class AccumulateExternalities {
|
|
|
19953
20253
|
eject(destination, previousCodeHash) {
|
|
19954
20254
|
const service = this.getServiceInfo(destination);
|
|
19955
20255
|
if (service === null || destination === null) {
|
|
19956
|
-
return result_Result.error(EjectError.InvalidService, "Service missing");
|
|
20256
|
+
return result_Result.error(EjectError.InvalidService, () => "Service missing");
|
|
19957
20257
|
}
|
|
19958
20258
|
const currentService = this.getCurrentServiceInfo();
|
|
19959
20259
|
// check if the service expects to be ejected by us:
|
|
19960
20260
|
const expectedCodeHash = bytes_Bytes.zero(hash_HASH_SIZE).asOpaque();
|
|
19961
20261
|
writeServiceIdAsLeBytes(this.currentServiceId, expectedCodeHash.raw);
|
|
19962
20262
|
if (!service.codeHash.isEqualTo(expectedCodeHash)) {
|
|
19963
|
-
return result_Result.error(EjectError.InvalidService, "Invalid code hash");
|
|
20263
|
+
return result_Result.error(EjectError.InvalidService, () => "Invalid code hash");
|
|
19964
20264
|
}
|
|
19965
20265
|
// make sure the service only has required number of storage items?
|
|
19966
20266
|
if (service.storageUtilisationCount !== REQUIRED_NUMBER_OF_STORAGE_ITEMS_FOR_EJECT) {
|
|
19967
|
-
return result_Result.error(EjectError.InvalidPreimage, "Too many storage items");
|
|
20267
|
+
return result_Result.error(EjectError.InvalidPreimage, () => "Too many storage items");
|
|
19968
20268
|
}
|
|
19969
20269
|
// storage items length
|
|
19970
20270
|
const l = numbers_tryAsU64(maxU64(service.storageUtilisationBytes, LOOKUP_HISTORY_ENTRY_BYTES) - LOOKUP_HISTORY_ENTRY_BYTES);
|
|
19971
20271
|
// check if we have a preimage with the entire storage.
|
|
19972
20272
|
const [isPreviousCodeExpired, errorReason] = this.isPreviousCodeExpired(destination, previousCodeHash, l);
|
|
19973
20273
|
if (!isPreviousCodeExpired) {
|
|
19974
|
-
return result_Result.error(EjectError.InvalidPreimage, `Previous code available: ${errorReason}`);
|
|
20274
|
+
return result_Result.error(EjectError.InvalidPreimage, () => `Previous code available: ${errorReason}`);
|
|
19975
20275
|
}
|
|
19976
20276
|
// compute new balance of the service.
|
|
19977
20277
|
const newBalance = sumU64(currentService.balance, service.balance);
|
|
19978
20278
|
// TODO [ToDr] what to do in case of overflow?
|
|
19979
20279
|
if (newBalance.overflow) {
|
|
19980
|
-
return result_Result.error(EjectError.InvalidService, "Balance overflow");
|
|
20280
|
+
return result_Result.error(EjectError.InvalidService, () => "Balance overflow");
|
|
19981
20281
|
}
|
|
19982
20282
|
// update current service.
|
|
19983
20283
|
this.updatedState.updateServiceInfo(this.currentServiceId, ServiceAccountInfo.create({
|
|
@@ -19985,11 +20285,13 @@ class AccumulateExternalities {
|
|
|
19985
20285
|
balance: newBalance.value,
|
|
19986
20286
|
}));
|
|
19987
20287
|
// and finally add an ejected service.
|
|
19988
|
-
this.updatedState.stateUpdate.services.
|
|
20288
|
+
this.updatedState.stateUpdate.services.removed.push(destination);
|
|
19989
20289
|
// take care of the code preimage and its lookup history
|
|
19990
20290
|
// Safe, because we know the preimage is valid, and it's the code of the service, which is bounded by maximal service code size anyway (much smaller than 2**32 bytes).
|
|
19991
20291
|
const preimageLength = numbers_tryAsU32(Number(l));
|
|
19992
|
-
this.updatedState.stateUpdate.services.preimages.
|
|
20292
|
+
const preimages = this.updatedState.stateUpdate.services.preimages.get(destination) ?? [];
|
|
20293
|
+
preimages.push(UpdatePreimage.remove({ hash: previousCodeHash, length: preimageLength }));
|
|
20294
|
+
this.updatedState.stateUpdate.services.preimages.set(destination, preimages);
|
|
19993
20295
|
return result_Result.ok(result_OK);
|
|
19994
20296
|
}
|
|
19995
20297
|
read(serviceId, rawKey) {
|
|
@@ -20170,10 +20472,10 @@ class Assurances {
|
|
|
20170
20472
|
for (const assurance of assurances) {
|
|
20171
20473
|
const { anchor, validatorIndex, bitfield } = assurance;
|
|
20172
20474
|
if (!anchor.isEqualTo(input.parentHash)) {
|
|
20173
|
-
return result_Result.error(AssurancesError.InvalidAnchor, `anchor: expected: ${input.parentHash}, got ${anchor}`);
|
|
20475
|
+
return result_Result.error(AssurancesError.InvalidAnchor, () => `anchor: expected: ${input.parentHash}, got ${anchor}`);
|
|
20174
20476
|
}
|
|
20175
20477
|
if (prevValidatorIndex >= validatorIndex) {
|
|
20176
|
-
return result_Result.error(AssurancesError.InvalidOrder, `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
|
|
20478
|
+
return result_Result.error(AssurancesError.InvalidOrder, () => `order: expected: ${prevValidatorIndex + 1}, got: ${validatorIndex}`);
|
|
20177
20479
|
}
|
|
20178
20480
|
prevValidatorIndex = assurance.validatorIndex;
|
|
20179
20481
|
debug_check `${bitfield.bitLength === coresCount} Invalid bitfield length of ${bitfield.bitLength}`;
|
|
@@ -20196,7 +20498,7 @@ class Assurances {
|
|
|
20196
20498
|
* https://graypaper.fluffylabs.dev/#/579bd12/14e90014ea00
|
|
20197
20499
|
*/
|
|
20198
20500
|
if (noOfAssurances > 0 && !isReportPending) {
|
|
20199
|
-
return result_Result.error(AssurancesError.NoReportPending, `no report pending for core ${c} yet we got an assurance`);
|
|
20501
|
+
return result_Result.error(AssurancesError.NoReportPending, () => `no report pending for core ${c} yet we got an assurance`);
|
|
20200
20502
|
}
|
|
20201
20503
|
/**
|
|
20202
20504
|
* Remove work report if it's became available or timed out.
|
|
@@ -20242,7 +20544,7 @@ class Assurances {
|
|
|
20242
20544
|
const v = assurance.view();
|
|
20243
20545
|
const key = validatorData[v.validatorIndex.materialize()];
|
|
20244
20546
|
if (key === undefined) {
|
|
20245
|
-
return result_Result.error(AssurancesError.InvalidValidatorIndex);
|
|
20547
|
+
return result_Result.error(AssurancesError.InvalidValidatorIndex, () => `Invalid validator index: ${v.validatorIndex.materialize()}`);
|
|
20246
20548
|
}
|
|
20247
20549
|
signatures.push({
|
|
20248
20550
|
signature: v.signature.materialize(),
|
|
@@ -20254,7 +20556,7 @@ class Assurances {
|
|
|
20254
20556
|
const isAllSignaturesValid = signaturesValid.every((x) => x);
|
|
20255
20557
|
if (!isAllSignaturesValid) {
|
|
20256
20558
|
const invalidIndices = signaturesValid.reduce((acc, isValid, idx) => (isValid ? acc : acc.concat(idx)), []);
|
|
20257
|
-
return result_Result.error(AssurancesError.InvalidSignature, `invalid signatures at ${invalidIndices.join(", ")}`);
|
|
20559
|
+
return result_Result.error(AssurancesError.InvalidSignature, () => `invalid signatures at ${invalidIndices.join(", ")}`);
|
|
20258
20560
|
}
|
|
20259
20561
|
return result_Result.ok(result_OK);
|
|
20260
20562
|
}
|
|
@@ -20865,7 +21167,7 @@ class HostCallMemory {
|
|
|
20865
21167
|
return result_Result.ok(result_OK);
|
|
20866
21168
|
}
|
|
20867
21169
|
if (address + numbers_tryAsU64(bytes.length) > MEMORY_SIZE) {
|
|
20868
|
-
return result_Result.error(new OutOfBounds());
|
|
21170
|
+
return result_Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`);
|
|
20869
21171
|
}
|
|
20870
21172
|
return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
|
|
20871
21173
|
}
|
|
@@ -20874,13 +21176,10 @@ class HostCallMemory {
|
|
|
20874
21176
|
return result_Result.ok(result_OK);
|
|
20875
21177
|
}
|
|
20876
21178
|
if (startAddress + numbers_tryAsU64(result.length) > MEMORY_SIZE) {
|
|
20877
|
-
return result_Result.error(new OutOfBounds());
|
|
21179
|
+
return result_Result.error(new OutOfBounds(), () => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`);
|
|
20878
21180
|
}
|
|
20879
21181
|
return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
|
|
20880
21182
|
}
|
|
20881
|
-
getMemory() {
|
|
20882
|
-
return this.memory;
|
|
20883
|
-
}
|
|
20884
21183
|
}
|
|
20885
21184
|
|
|
20886
21185
|
;// CONCATENATED MODULE: ./packages/core/pvm-host-calls/host-call-registers.ts
|
|
@@ -21159,7 +21458,7 @@ class Assign {
|
|
|
21159
21458
|
// NOTE: Here we know the core index is valid
|
|
21160
21459
|
const coreIndex = tryAsCoreIndex(Number(maybeCoreIndex));
|
|
21161
21460
|
const decoder = decoder_Decoder.fromBlob(res);
|
|
21162
|
-
const authQueue = decoder.sequenceFixLen(descriptors_codec.bytes(hash_HASH_SIZE), AUTHORIZATION_QUEUE_SIZE);
|
|
21461
|
+
const authQueue = decoder.sequenceFixLen(descriptors_codec.bytes(hash_HASH_SIZE).asOpaque(), AUTHORIZATION_QUEUE_SIZE);
|
|
21163
21462
|
const fixedSizeAuthQueue = FixedSizeArray.new(authQueue, AUTHORIZATION_QUEUE_SIZE);
|
|
21164
21463
|
const result = this.partialState.updateAuthorizationQueue(coreIndex, fixedSizeAuthQueue, assigners);
|
|
21165
21464
|
if (result.isOk) {
|
|
@@ -21271,6 +21570,7 @@ class Bless {
|
|
|
21271
21570
|
return;
|
|
21272
21571
|
}
|
|
21273
21572
|
const e = updateResult.error;
|
|
21573
|
+
// NOTE: `UpdatePrivilegesError.UnprivilegedService` won't happen in 0.7.1+
|
|
21274
21574
|
if (e === UpdatePrivilegesError.UnprivilegedService) {
|
|
21275
21575
|
logger_logger.trace `BLESS(${manager}, ${authorizers}, ${delegator}, ${registrar}, ${autoAccumulateEntries}) <- HUH`;
|
|
21276
21576
|
regs.set(bless_IN_OUT_REG, HostCallResult.HUH);
|
|
@@ -21354,7 +21654,7 @@ class Checkpoint {
|
|
|
21354
21654
|
|
|
21355
21655
|
|
|
21356
21656
|
const designate_IN_OUT_REG = 7;
|
|
21357
|
-
const VALIDATOR_DATA_BYTES = tryAsExactBytes(
|
|
21657
|
+
const VALIDATOR_DATA_BYTES = tryAsExactBytes(validator_data_ValidatorData.Codec.sizeHint);
|
|
21358
21658
|
/**
|
|
21359
21659
|
* Designate a new set of validator keys.
|
|
21360
21660
|
*
|
|
@@ -21383,7 +21683,7 @@ class Designate {
|
|
|
21383
21683
|
return PvmExecution.Panic;
|
|
21384
21684
|
}
|
|
21385
21685
|
const decoder = decoder_Decoder.fromBlob(res);
|
|
21386
|
-
const validatorsData = decoder.sequenceFixLen(
|
|
21686
|
+
const validatorsData = decoder.sequenceFixLen(validator_data_ValidatorData.Codec, this.chainSpec.validatorsCount);
|
|
21387
21687
|
const result = this.partialState.updateValidatorsData(tryAsPerValidator(validatorsData, this.chainSpec));
|
|
21388
21688
|
if (result.isError) {
|
|
21389
21689
|
logger_logger.trace `DESIGNATE([${validatorsData[0]}, ${validatorsData[1]}, ...]) <- HUH`;
|
|
@@ -22265,7 +22565,7 @@ class Lookup {
|
|
|
22265
22565
|
}
|
|
22266
22566
|
// v
|
|
22267
22567
|
const preImage = this.account.lookup(serviceId, preImageHash);
|
|
22268
|
-
logger_logger.trace `LOOKUP(${serviceId}, ${preImageHash}) <- ${preImage?.toStringTruncated()}...`;
|
|
22568
|
+
logger_logger.trace `LOOKUP(${serviceId}, ${preImageHash}) <- ${preImage?.toStringTruncated() ?? "<missing>"}...`;
|
|
22269
22569
|
const preImageLength = preImage === null ? numbers_tryAsU64(0) : numbers_tryAsU64(preImage.raw.length);
|
|
22270
22570
|
const preimageBlobOffset = regs.get(10);
|
|
22271
22571
|
const lengthToWrite = regs.get(11);
|
|
@@ -22815,25 +23115,25 @@ class Accumulate {
|
|
|
22815
23115
|
*
|
|
22816
23116
|
* https://graypaper.fluffylabs.dev/#/7e6ff6a/2fdb012fdb01?v=0.6.7
|
|
22817
23117
|
*/
|
|
22818
|
-
async pvmAccumulateInvocation(slot, serviceId, transfers, operands, gas, entropy,
|
|
22819
|
-
const
|
|
22820
|
-
if (
|
|
23118
|
+
async pvmAccumulateInvocation(slot, serviceId, transfers, operands, gas, entropy, updatedState) {
|
|
23119
|
+
const serviceInfo = updatedState.getServiceInfo(serviceId);
|
|
23120
|
+
if (serviceInfo === null) {
|
|
22821
23121
|
accumulate_logger.log `Service with id ${serviceId} not found.`;
|
|
22822
|
-
return result_Result.error(PvmInvocationError.NoService);
|
|
23122
|
+
return result_Result.error(PvmInvocationError.NoService, () => `Accumulate: service ${serviceId} not found`);
|
|
22823
23123
|
}
|
|
22824
|
-
const codeHash =
|
|
23124
|
+
const codeHash = serviceInfo.codeHash;
|
|
22825
23125
|
// TODO [ToDr] Should we check that the preimage is still available?
|
|
22826
|
-
const code =
|
|
23126
|
+
const code = updatedState.getPreimage(serviceId, codeHash.asOpaque());
|
|
22827
23127
|
if (code === null) {
|
|
22828
23128
|
accumulate_logger.log `Code with hash ${codeHash} not found for service ${serviceId}.`;
|
|
22829
|
-
return result_Result.error(PvmInvocationError.NoPreimage);
|
|
23129
|
+
return result_Result.error(PvmInvocationError.NoPreimage, () => `Accumulate: code with hash ${codeHash} not found for service ${serviceId}`);
|
|
22830
23130
|
}
|
|
22831
23131
|
if (code.length > W_C) {
|
|
22832
23132
|
accumulate_logger.log `Code with hash ${codeHash} is too long for service ${serviceId}.`;
|
|
22833
|
-
return result_Result.error(PvmInvocationError.PreimageTooLong);
|
|
23133
|
+
return result_Result.error(PvmInvocationError.PreimageTooLong, () => `Accumulate: code length ${code.length} exceeds max ${W_C} for service ${serviceId}`);
|
|
22834
23134
|
}
|
|
22835
23135
|
const nextServiceId = generateNextServiceId({ serviceId, entropy, timeslot: slot }, this.chainSpec, this.blake2b);
|
|
22836
|
-
const partialState = new AccumulateExternalities(this.chainSpec, this.blake2b,
|
|
23136
|
+
const partialState = new AccumulateExternalities(this.chainSpec, this.blake2b, updatedState, serviceId, nextServiceId, slot);
|
|
22837
23137
|
const fetchExternalities = Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)
|
|
22838
23138
|
? FetchExternalities.createForAccumulate({ entropy, transfers, operands }, this.chainSpec)
|
|
22839
23139
|
: FetchExternalities.createForPre071Accumulate({ entropy, operands }, this.chainSpec);
|
|
@@ -22887,11 +23187,28 @@ class Accumulate {
|
|
|
22887
23187
|
*/
|
|
22888
23188
|
async accumulateSingleService(serviceId, transfers, operands, gasCost, slot, entropy, inputStateUpdate) {
|
|
22889
23189
|
accumulate_logger.log `Accumulating service ${serviceId}, transfers: ${transfers.length} operands: ${operands.length} at slot: ${slot}.`;
|
|
22890
|
-
const
|
|
23190
|
+
const updatedState = new PartiallyUpdatedState(this.state, inputStateUpdate);
|
|
23191
|
+
// update service balance from incoming transfers
|
|
23192
|
+
if (Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)) {
|
|
23193
|
+
const serviceInfo = updatedState.getServiceInfo(serviceId);
|
|
23194
|
+
if (serviceInfo !== null) {
|
|
23195
|
+
// update the balance from incoming tranfsers
|
|
23196
|
+
const newBalance = sumU64(serviceInfo.balance, ...transfers.map((item) => item.amount));
|
|
23197
|
+
if (newBalance.overflow) {
|
|
23198
|
+
accumulate_logger.log `Accumulation failed because of overflowing balance ${serviceId}.`;
|
|
23199
|
+
return { stateUpdate: null, consumedGas: 0n };
|
|
23200
|
+
}
|
|
23201
|
+
const newInfo = ServiceAccountInfo.create({ ...serviceInfo, balance: newBalance.value });
|
|
23202
|
+
updatedState.updateServiceInfo(serviceId, newInfo);
|
|
23203
|
+
}
|
|
23204
|
+
}
|
|
23205
|
+
const result = await this.pvmAccumulateInvocation(slot, serviceId, transfers, operands, gasCost, entropy, updatedState);
|
|
22891
23206
|
if (result.isError) {
|
|
22892
|
-
// https://graypaper.fluffylabs.dev/#/
|
|
23207
|
+
// https://graypaper.fluffylabs.dev/#/ab2cdbd/2fc9032fc903?v=0.7.2
|
|
22893
23208
|
accumulate_logger.log `Accumulation failed for ${serviceId}.`;
|
|
22894
|
-
|
|
23209
|
+
// even though accumulation failed, we still need to make sure that
|
|
23210
|
+
// incoming transfers updated the balance, hence we pass state update here
|
|
23211
|
+
return { stateUpdate: updatedState.stateUpdate, consumedGas: 0n };
|
|
22895
23212
|
}
|
|
22896
23213
|
accumulate_logger.log `Accumulation successful for ${serviceId}. Consumed: ${result.ok.consumedGas}`;
|
|
22897
23214
|
return result.ok;
|
|
@@ -22949,7 +23266,7 @@ class Accumulate {
|
|
|
22949
23266
|
const accumulateData = new AccumulateData(reportsToAccumulateInParallel, transfers, autoAccumulateServices);
|
|
22950
23267
|
const reportsToAccumulateSequentially = reports.subview(i);
|
|
22951
23268
|
const { gasCost, state: stateAfterParallelAcc, ...rest } = await this.accumulateInParallel(accumulateData, slot, entropy, statistics, stateUpdate);
|
|
22952
|
-
const newTransfers = stateAfterParallelAcc.
|
|
23269
|
+
const newTransfers = stateAfterParallelAcc.takeTransfers();
|
|
22953
23270
|
assertEmpty(rest);
|
|
22954
23271
|
// NOTE [ToDr] recursive invocation
|
|
22955
23272
|
const { accumulatedReports, gasCost: seqGasCost, state, ...seqRest } = await this.accumulateSequentially(tryAsServiceGas(gasLimit - gasCost), reportsToAccumulateSequentially, newTransfers, slot, entropy, statistics, stateAfterParallelAcc, []);
|
|
@@ -22977,12 +23294,19 @@ class Accumulate {
|
|
|
22977
23294
|
const currentManager = (inputStateUpdate.privilegedServices ?? this.state.privilegedServices).manager;
|
|
22978
23295
|
for (const serviceId of serviceIds) {
|
|
22979
23296
|
const checkpoint = AccumulationStateUpdate.copyFrom(currentState);
|
|
22980
|
-
const
|
|
23297
|
+
const operands = accumulateData.getOperands(serviceId);
|
|
23298
|
+
const { consumedGas, stateUpdate } = await this.accumulateSingleService(serviceId, accumulateData.getTransfers(serviceId), operands, accumulateData.getGasCost(serviceId), slot, entropy, currentState);
|
|
22981
23299
|
gasCost = tryAsServiceGas(gasCost + consumedGas);
|
|
23300
|
+
// https://graypaper.fluffylabs.dev/#/ab2cdbd/193b05193b05?v=0.7.2
|
|
22982
23301
|
const serviceStatistics = statistics.get(serviceId) ?? { count: numbers_tryAsU32(0), gasUsed: tryAsServiceGas(0) };
|
|
22983
|
-
|
|
22984
|
-
|
|
22985
|
-
|
|
23302
|
+
const count = accumulateData.getReportsLength(serviceId);
|
|
23303
|
+
// [0.7.1]: do not update statistics, if the service only had incoming transfers
|
|
23304
|
+
if ((Compatibility.isLessThan(GpVersion.V0_7_2) && count > 0) ||
|
|
23305
|
+
(Compatibility.isGreaterOrEqual(GpVersion.V0_7_2) && (count > 0 || consumedGas > 0n))) {
|
|
23306
|
+
serviceStatistics.count = numbers_tryAsU32(serviceStatistics.count + count);
|
|
23307
|
+
serviceStatistics.gasUsed = tryAsServiceGas(serviceStatistics.gasUsed + consumedGas);
|
|
23308
|
+
statistics.set(serviceId, serviceStatistics);
|
|
23309
|
+
}
|
|
22986
23310
|
currentState = stateUpdate === null ? checkpoint : stateUpdate;
|
|
22987
23311
|
if (Compatibility.is(GpVersion.V0_7_0) && serviceId === currentManager) {
|
|
22988
23312
|
const newV = currentState.privilegedServices?.delegator;
|
|
@@ -23017,9 +23341,10 @@ class Accumulate {
|
|
|
23017
23341
|
const recentlyAccumulated = tryAsPerEpochBlock(newRecentlyAccumulated, this.chainSpec);
|
|
23018
23342
|
const accumulationQueue = this.state.accumulationQueue.slice();
|
|
23019
23343
|
accumulationQueue[phaseIndex] = pruneQueue(toAccumulateLater, accumulatedSet);
|
|
23344
|
+
const timeslot = this.state.timeslot;
|
|
23020
23345
|
for (let i = 1; i < epochLength; i++) {
|
|
23021
23346
|
const queueIndex = (phaseIndex + epochLength - i) % epochLength;
|
|
23022
|
-
if (i < slot -
|
|
23347
|
+
if (i < slot - timeslot) {
|
|
23023
23348
|
accumulationQueue[queueIndex] = [];
|
|
23024
23349
|
}
|
|
23025
23350
|
else {
|
|
@@ -23034,6 +23359,7 @@ class Accumulate {
|
|
|
23034
23359
|
const info = partialStateUpdate.getServiceInfo(serviceId);
|
|
23035
23360
|
if (info === null) {
|
|
23036
23361
|
// NOTE If there is no service, we dont update it.
|
|
23362
|
+
accumulate_logger.log `Skipping update of ${serviceId}, because we have no service info.`;
|
|
23037
23363
|
continue;
|
|
23038
23364
|
}
|
|
23039
23365
|
// δ‡
|
|
@@ -23059,19 +23385,16 @@ class Accumulate {
|
|
|
23059
23385
|
const gasLimit = tryAsServiceGas(this.chainSpec.maxBlockGas > calculatedGasLimit ? this.chainSpec.maxBlockGas : calculatedGasLimit);
|
|
23060
23386
|
return tryAsServiceGas(gasLimit);
|
|
23061
23387
|
}
|
|
23062
|
-
|
|
23063
|
-
|
|
23064
|
-
|
|
23065
|
-
|
|
23066
|
-
|
|
23067
|
-
|
|
23068
|
-
|
|
23069
|
-
|
|
23070
|
-
|
|
23071
|
-
|
|
23072
|
-
}
|
|
23073
|
-
}
|
|
23074
|
-
return false;
|
|
23388
|
+
/**
|
|
23389
|
+
* Detects the very unlikely situation where multiple services are created with the same ID.
|
|
23390
|
+
*
|
|
23391
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/30f20330f403?v=0.7.2
|
|
23392
|
+
*
|
|
23393
|
+
* NOTE: This is public only for testing purposes and should not be used outside of accumulation.
|
|
23394
|
+
*/
|
|
23395
|
+
hasDuplicatedServiceIdCreated(createdIds) {
|
|
23396
|
+
const uniqueIds = new Set(createdIds);
|
|
23397
|
+
return uniqueIds.size !== createdIds.length;
|
|
23075
23398
|
}
|
|
23076
23399
|
async transition({ reports, slot, entropy }) {
|
|
23077
23400
|
const statistics = new Map();
|
|
@@ -23093,8 +23416,9 @@ class Accumulate {
|
|
|
23093
23416
|
const accumulated = accumulatableReports.subview(0, accumulatedReports);
|
|
23094
23417
|
const { services, yieldedRoots, transfers, validatorsData, privilegedServices, authorizationQueues, ...stateUpdateRest } = state;
|
|
23095
23418
|
assertEmpty(stateUpdateRest);
|
|
23096
|
-
if (this.
|
|
23097
|
-
|
|
23419
|
+
if (this.hasDuplicatedServiceIdCreated(services.created)) {
|
|
23420
|
+
accumulate_logger.trace `Duplicated Service creation detected. Block is invalid.`;
|
|
23421
|
+
return result_Result.error(ACCUMULATION_ERROR, () => "Accumulate: duplicate service created");
|
|
23098
23422
|
}
|
|
23099
23423
|
const accStateUpdate = this.getAccumulationStateUpdate(accumulated.toArray(), toAccumulateLater, slot, Array.from(statistics.keys()), services);
|
|
23100
23424
|
const accumulationOutputUnsorted = Array.from(yieldedRoots.entries()).map(([serviceId, root]) => {
|
|
@@ -23175,13 +23499,13 @@ class DeferredTransfers {
|
|
|
23175
23499
|
.toSorted((a, b) => a.source - b.source);
|
|
23176
23500
|
const info = partiallyUpdatedState.getServiceInfo(serviceId);
|
|
23177
23501
|
if (info === null) {
|
|
23178
|
-
return result_Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist);
|
|
23502
|
+
return result_Result.error(DeferredTransfersErrorCode.ServiceInfoNotExist, () => `Deferred transfers: service info not found for ${serviceId}`);
|
|
23179
23503
|
}
|
|
23180
23504
|
const codeHash = info.codeHash;
|
|
23181
23505
|
const code = partiallyUpdatedState.getPreimage(serviceId, codeHash.asOpaque());
|
|
23182
23506
|
const newBalance = sumU64(info.balance, ...transfers.map((item) => item.amount));
|
|
23183
23507
|
if (newBalance.overflow) {
|
|
23184
|
-
return result_Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow);
|
|
23508
|
+
return result_Result.error(DeferredTransfersErrorCode.ServiceBalanceOverflow, () => `Deferred transfers: balance overflow for service ${serviceId}`);
|
|
23185
23509
|
}
|
|
23186
23510
|
const newInfo = ServiceAccountInfo.create({ ...info, balance: newBalance.value });
|
|
23187
23511
|
partiallyUpdatedState.updateServiceInfo(serviceId, newInfo);
|
|
@@ -23230,7 +23554,6 @@ class DeferredTransfers {
|
|
|
23230
23554
|
|
|
23231
23555
|
|
|
23232
23556
|
|
|
23233
|
-
|
|
23234
23557
|
/**
|
|
23235
23558
|
* Maintain a list of available authorizations per core.
|
|
23236
23559
|
*
|
|
@@ -23259,11 +23582,12 @@ class Authorization {
|
|
|
23259
23582
|
*/
|
|
23260
23583
|
transition(input) {
|
|
23261
23584
|
const authPoolsUpdate = this.state.authPools.slice();
|
|
23585
|
+
const authQueues = this.state.authQueues;
|
|
23262
23586
|
// we transition authorizations for each core.
|
|
23263
23587
|
for (let coreIndex = tryAsCoreIndex(0); coreIndex < this.chainSpec.coresCount; coreIndex++) {
|
|
23264
23588
|
let pool = authPoolsUpdate[coreIndex].slice();
|
|
23265
23589
|
// the queue is only read (we should most likely use `ArrayView` here).
|
|
23266
|
-
const queue =
|
|
23590
|
+
const queue = authQueues[coreIndex];
|
|
23267
23591
|
// if there were any used hashes - remove them
|
|
23268
23592
|
const usedHashes = input.used.get(coreIndex);
|
|
23269
23593
|
if (usedHashes !== undefined) {
|
|
@@ -23437,14 +23761,18 @@ class RecentHistory {
|
|
|
23437
23761
|
* https://graypaper.fluffylabs.dev/#/1c979cb/0f55020f5502?v=0.7.1
|
|
23438
23762
|
*/
|
|
23439
23763
|
partialTransition(input) {
|
|
23440
|
-
const
|
|
23764
|
+
const stateBlocks = this.state.recentBlocks;
|
|
23765
|
+
const recentBlocks = stateBlocks.blocks.slice();
|
|
23441
23766
|
const lastState = recentBlocks.length > 0 ? recentBlocks[recentBlocks.length - 1] : null;
|
|
23442
23767
|
// update the posterior root of previous state.
|
|
23443
23768
|
if (lastState !== null) {
|
|
23444
23769
|
lastState.postStateRoot = input.priorStateRoot;
|
|
23445
23770
|
}
|
|
23446
23771
|
return {
|
|
23447
|
-
recentBlocks:
|
|
23772
|
+
recentBlocks: RecentBlocks.create({
|
|
23773
|
+
blocks: sized_array_asKnownSize(recentBlocks),
|
|
23774
|
+
accumulationLog: stateBlocks.accumulationLog,
|
|
23775
|
+
}), // β_H†
|
|
23448
23776
|
};
|
|
23449
23777
|
}
|
|
23450
23778
|
/**
|
|
@@ -23456,8 +23784,8 @@ class RecentHistory {
|
|
|
23456
23784
|
transition(input) {
|
|
23457
23785
|
const recentBlocks = input.partial.recentBlocks.blocks.slice();
|
|
23458
23786
|
// `β′_B`
|
|
23459
|
-
const mmr = this.state.recentBlocks.
|
|
23460
|
-
? MerkleMountainRange.fromPeaks(this.hasher, this.state.recentBlocks.
|
|
23787
|
+
const mmr = this.state.recentBlocks.accumulationLog !== null
|
|
23788
|
+
? MerkleMountainRange.fromPeaks(this.hasher, this.state.recentBlocks.accumulationLog)
|
|
23461
23789
|
: MerkleMountainRange.empty(this.hasher);
|
|
23462
23790
|
// append the accumulation root
|
|
23463
23791
|
mmr.append(input.accumulateRoot);
|
|
@@ -23475,7 +23803,7 @@ class RecentHistory {
|
|
|
23475
23803
|
}
|
|
23476
23804
|
// write back to the state.
|
|
23477
23805
|
return {
|
|
23478
|
-
recentBlocks:
|
|
23806
|
+
recentBlocks: RecentBlocks.create(RecentBlocks.create({
|
|
23479
23807
|
blocks: sized_array_asKnownSize(recentBlocks),
|
|
23480
23808
|
accumulationLog: peaks,
|
|
23481
23809
|
})),
|
|
@@ -23655,7 +23983,7 @@ function verifyReportsBasic(input) {
|
|
|
23655
23983
|
const noOfPrerequisites = reportView.context.view().prerequisites.view().length;
|
|
23656
23984
|
const noOfSegmentRootLookups = reportView.segmentRootLookup.view().length;
|
|
23657
23985
|
if (noOfPrerequisites + noOfSegmentRootLookups > MAX_REPORT_DEPENDENCIES) {
|
|
23658
|
-
return result_Result.error(ReportsError.TooManyDependencies, `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
|
|
23986
|
+
return result_Result.error(ReportsError.TooManyDependencies, () => `Report at ${reportView.coreIndex.materialize()} has too many dependencies. Got ${noOfPrerequisites} + ${noOfSegmentRootLookups}, max: ${MAX_REPORT_DEPENDENCIES}`);
|
|
23659
23987
|
}
|
|
23660
23988
|
/**
|
|
23661
23989
|
* In order to ensure fair use of a block’s extrinsic space,
|
|
@@ -23674,7 +24002,7 @@ function verifyReportsBasic(input) {
|
|
|
23674
24002
|
totalOutputsSize += item.view().result.view().okBlob?.raw.length ?? 0;
|
|
23675
24003
|
}
|
|
23676
24004
|
if (authOutputSize + totalOutputsSize > MAX_WORK_REPORT_SIZE_BYTES) {
|
|
23677
|
-
return result_Result.error(ReportsError.WorkReportTooBig, `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
|
|
24005
|
+
return result_Result.error(ReportsError.WorkReportTooBig, () => `Work report at ${reportView.coreIndex.materialize()} too big. Got ${authOutputSize} + ${totalOutputsSize}, max: ${MAX_WORK_REPORT_SIZE_BYTES}`);
|
|
23678
24006
|
}
|
|
23679
24007
|
}
|
|
23680
24008
|
return result_Result.ok(result_OK);
|
|
@@ -23687,7 +24015,6 @@ function verifyReportsBasic(input) {
|
|
|
23687
24015
|
|
|
23688
24016
|
|
|
23689
24017
|
|
|
23690
|
-
|
|
23691
24018
|
const verify_contextual_logger = Logger.new(import.meta.filename, "stf:reports");
|
|
23692
24019
|
/** https://graypaper.fluffylabs.dev/#/7e6ff6a/15eb0115eb01?v=0.6.7 */
|
|
23693
24020
|
function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge) {
|
|
@@ -23709,12 +24036,12 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
|
|
|
23709
24036
|
for (const result of guarantee.report.results) {
|
|
23710
24037
|
const service = state.getService(result.serviceId);
|
|
23711
24038
|
if (service === null) {
|
|
23712
|
-
return result_Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
|
|
24039
|
+
return result_Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
|
|
23713
24040
|
}
|
|
23714
24041
|
// check service code hash
|
|
23715
24042
|
// https://graypaper.fluffylabs.dev/#/5f542d7/154b02154b02
|
|
23716
24043
|
if (!result.codeHash.isEqualTo(service.getInfo().codeHash)) {
|
|
23717
|
-
return result_Result.error(ReportsError.BadCodeHash, `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
|
|
24044
|
+
return result_Result.error(ReportsError.BadCodeHash, () => `Service (${result.serviceId}) code hash mismatch. Got: ${result.codeHash}, expected: ${service.getInfo().codeHash}`);
|
|
23718
24045
|
}
|
|
23719
24046
|
}
|
|
23720
24047
|
}
|
|
@@ -23725,7 +24052,7 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
|
|
|
23725
24052
|
* https://graypaper.fluffylabs.dev/#/5f542d7/151f01152101
|
|
23726
24053
|
*/
|
|
23727
24054
|
if (currentWorkPackages.size !== input.guarantees.length) {
|
|
23728
|
-
return result_Result.error(ReportsError.DuplicatePackage, "Duplicate work package detected.");
|
|
24055
|
+
return result_Result.error(ReportsError.DuplicatePackage, () => "Duplicate work package detected.");
|
|
23729
24056
|
}
|
|
23730
24057
|
const minLookupSlot = Math.max(0, input.slot - maxLookupAnchorAge);
|
|
23731
24058
|
const contextResult = verifyRefineContexts(minLookupSlot, contexts, input.recentBlocksPartialUpdate, headerChain);
|
|
@@ -23770,7 +24097,7 @@ function verifyContextualValidity(input, state, headerChain, maxLookupAnchorAge)
|
|
|
23770
24097
|
: undefined;
|
|
23771
24098
|
}
|
|
23772
24099
|
if (root === undefined || !root.segmentTreeRoot.isEqualTo(lookup.segmentTreeRoot)) {
|
|
23773
|
-
return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
|
|
24100
|
+
return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Mismatching segment tree root for package ${lookup.workPackageHash}. Got: ${lookup.segmentTreeRoot}, expected: ${root?.segmentTreeRoot}`);
|
|
23774
24101
|
}
|
|
23775
24102
|
}
|
|
23776
24103
|
}
|
|
@@ -23793,16 +24120,16 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
|
|
|
23793
24120
|
*/
|
|
23794
24121
|
const recentBlock = recentBlocks.get(context.anchor);
|
|
23795
24122
|
if (recentBlock === undefined) {
|
|
23796
|
-
return result_Result.error(ReportsError.AnchorNotRecent, `Anchor block ${context.anchor} not found in recent blocks.`);
|
|
24123
|
+
return result_Result.error(ReportsError.AnchorNotRecent, () => `Anchor block ${context.anchor} not found in recent blocks.`);
|
|
23797
24124
|
}
|
|
23798
24125
|
// check state root
|
|
23799
24126
|
if (!recentBlock.postStateRoot.isEqualTo(context.stateRoot)) {
|
|
23800
|
-
return result_Result.error(ReportsError.BadStateRoot, `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
|
|
24127
|
+
return result_Result.error(ReportsError.BadStateRoot, () => `Anchor state root mismatch. Got: ${context.stateRoot}, expected: ${recentBlock.postStateRoot}.`);
|
|
23801
24128
|
}
|
|
23802
24129
|
// check beefy root
|
|
23803
|
-
const beefyRoot =
|
|
24130
|
+
const beefyRoot = recentBlock.accumulationResult;
|
|
23804
24131
|
if (!beefyRoot.isEqualTo(context.beefyRoot)) {
|
|
23805
|
-
return result_Result.error(ReportsError.BadBeefyMmrRoot, `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
|
|
24132
|
+
return result_Result.error(ReportsError.BadBeefyMmrRoot, () => `Invalid BEEFY super peak hash. Got: ${context.beefyRoot}, expected: ${beefyRoot}. Anchor: ${recentBlock.headerHash}`);
|
|
23806
24133
|
}
|
|
23807
24134
|
/**
|
|
23808
24135
|
* We require that each lookup-anchor block be within the
|
|
@@ -23811,7 +24138,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
|
|
|
23811
24138
|
* https://graypaper.fluffylabs.dev/#/5f542d7/154601154701
|
|
23812
24139
|
*/
|
|
23813
24140
|
if (context.lookupAnchorSlot < minLookupSlot) {
|
|
23814
|
-
return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
|
|
24141
|
+
return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor slot's too old. Got: ${context.lookupAnchorSlot}, minimal: ${minLookupSlot}`);
|
|
23815
24142
|
}
|
|
23816
24143
|
/**
|
|
23817
24144
|
* We also require that we have a record of it; this is one of
|
|
@@ -23828,7 +24155,7 @@ function verifyRefineContexts(minLookupSlot, contexts, recentBlocksPartialUpdate
|
|
|
23828
24155
|
verify_contextual_logger.warn `Lookup anchor check for ${context.lookupAnchor} would fail, but override is active.`;
|
|
23829
24156
|
}
|
|
23830
24157
|
else {
|
|
23831
|
-
return result_Result.error(ReportsError.SegmentRootLookupInvalid, `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
|
|
24158
|
+
return result_Result.error(ReportsError.SegmentRootLookupInvalid, () => `Lookup anchor is not found in chain. Hash: ${context.lookupAnchor} (slot: ${context.lookupAnchorSlot})`);
|
|
23832
24159
|
}
|
|
23833
24160
|
}
|
|
23834
24161
|
}
|
|
@@ -23851,7 +24178,7 @@ function verifyDependencies({ currentWorkPackages, recentlyReported, prerequisit
|
|
|
23851
24178
|
if (recentlyReported.has(preReqHash)) {
|
|
23852
24179
|
continue;
|
|
23853
24180
|
}
|
|
23854
|
-
return result_Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, `Missing work package ${preReqHash} in current extrinsic or recent history.`);
|
|
24181
|
+
return result_Result.error(isSegmentRoot ? ReportsError.SegmentRootLookupInvalid : ReportsError.DependencyMissing, () => `Missing work package ${preReqHash} in current extrinsic or recent history.`);
|
|
23855
24182
|
}
|
|
23856
24183
|
return result_Result.ok(result_OK);
|
|
23857
24184
|
};
|
|
@@ -23899,7 +24226,7 @@ function verifyWorkPackagesUniqueness(workPackageHashes, state) {
|
|
|
23899
24226
|
// let's check if any of our packages is in the pipeline
|
|
23900
24227
|
const intersection = packagesInPipeline.intersection(workPackageHashes);
|
|
23901
24228
|
for (const packageHash of intersection) {
|
|
23902
|
-
return result_Result.error(ReportsError.DuplicatePackage, `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
|
|
24229
|
+
return result_Result.error(ReportsError.DuplicatePackage, () => `The same work package hash found in the pipeline (workPackageHash: ${packageHash})`);
|
|
23903
24230
|
}
|
|
23904
24231
|
return result_Result.ok(result_OK);
|
|
23905
24232
|
}
|
|
@@ -23938,7 +24265,7 @@ workReportHashes, slot, getGuarantorAssignment) {
|
|
|
23938
24265
|
const credentialsView = guaranteeView.credentials.view();
|
|
23939
24266
|
if (credentialsView.length < REQUIRED_CREDENTIALS_RANGE[0] ||
|
|
23940
24267
|
credentialsView.length > REQUIRED_CREDENTIALS_RANGE[1]) {
|
|
23941
|
-
return result_Result.error(ReportsError.InsufficientGuarantees, `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
|
|
24268
|
+
return result_Result.error(ReportsError.InsufficientGuarantees, () => `Invalid number of credentials. Expected ${REQUIRED_CREDENTIALS_RANGE}, got ${credentialsView.length}`);
|
|
23942
24269
|
}
|
|
23943
24270
|
/** Retrieve current core assignment. */
|
|
23944
24271
|
const timeSlot = guaranteeView.slot.materialize();
|
|
@@ -23953,20 +24280,20 @@ workReportHashes, slot, getGuarantorAssignment) {
|
|
|
23953
24280
|
const credentialView = credential.view();
|
|
23954
24281
|
const validatorIndex = credentialView.validatorIndex.materialize();
|
|
23955
24282
|
if (lastValidatorIndex >= validatorIndex) {
|
|
23956
|
-
return result_Result.error(ReportsError.NotSortedOrUniqueGuarantors, `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
|
|
24283
|
+
return result_Result.error(ReportsError.NotSortedOrUniqueGuarantors, () => `Credentials must be sorted by validator index. Got ${validatorIndex}, expected at least ${lastValidatorIndex + 1}`);
|
|
23957
24284
|
}
|
|
23958
24285
|
lastValidatorIndex = validatorIndex;
|
|
23959
24286
|
const signature = credentialView.signature.materialize();
|
|
23960
24287
|
const guarantorData = guarantorAssignments[validatorIndex];
|
|
23961
24288
|
if (guarantorData === undefined) {
|
|
23962
|
-
return result_Result.error(ReportsError.BadValidatorIndex, `Invalid validator index: ${validatorIndex}`);
|
|
24289
|
+
return result_Result.error(ReportsError.BadValidatorIndex, () => `Invalid validator index: ${validatorIndex}`);
|
|
23963
24290
|
}
|
|
23964
24291
|
/**
|
|
23965
24292
|
* Verify core assignment.
|
|
23966
24293
|
* https://graypaper.fluffylabs.dev/#/5f542d7/14e40214e602
|
|
23967
24294
|
*/
|
|
23968
24295
|
if (guarantorData.core !== coreIndex) {
|
|
23969
|
-
return result_Result.error(ReportsError.WrongAssignment, `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
|
|
24296
|
+
return result_Result.error(ReportsError.WrongAssignment, () => `Invalid core assignment for validator ${validatorIndex}. Expected: ${guarantorData.core}, got: ${coreIndex}`);
|
|
23970
24297
|
}
|
|
23971
24298
|
signaturesToVerify.push({
|
|
23972
24299
|
signature,
|
|
@@ -24004,10 +24331,10 @@ function verifyReportsOrder(input, chainSpec) {
|
|
|
24004
24331
|
const reportView = guarantee.view().report.view();
|
|
24005
24332
|
const coreIndex = reportView.coreIndex.materialize();
|
|
24006
24333
|
if (lastCoreIndex >= coreIndex) {
|
|
24007
|
-
return result_Result.error(ReportsError.OutOfOrderGuarantee, `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
|
|
24334
|
+
return result_Result.error(ReportsError.OutOfOrderGuarantee, () => `Core indices of work reports are not unique or in order. Got: ${coreIndex}, expected at least: ${lastCoreIndex + 1}`);
|
|
24008
24335
|
}
|
|
24009
24336
|
if (coreIndex >= noOfCores) {
|
|
24010
|
-
return result_Result.error(ReportsError.BadCoreIndex, `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
|
|
24337
|
+
return result_Result.error(ReportsError.BadCoreIndex, () => `Invalid core index. Got: ${coreIndex}, max: ${noOfCores}`);
|
|
24011
24338
|
}
|
|
24012
24339
|
lastCoreIndex = coreIndex;
|
|
24013
24340
|
}
|
|
@@ -24032,7 +24359,7 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
|
|
|
24032
24359
|
* https://graypaper.fluffylabs.dev/#/5f542d7/15ea0015ea00
|
|
24033
24360
|
*/
|
|
24034
24361
|
if (availabilityAssignment[coreIndex] !== null) {
|
|
24035
|
-
return result_Result.error(ReportsError.CoreEngaged, `Report pending availability at core: ${coreIndex}`);
|
|
24362
|
+
return result_Result.error(ReportsError.CoreEngaged, () => `Report pending availability at core: ${coreIndex}`);
|
|
24036
24363
|
}
|
|
24037
24364
|
/**
|
|
24038
24365
|
* A report is valid only if the authorizer hash is present
|
|
@@ -24042,9 +24369,10 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
|
|
|
24042
24369
|
* https://graypaper.fluffylabs.dev/#/5f542d7/15eb0015ed00
|
|
24043
24370
|
*/
|
|
24044
24371
|
const authorizerHash = report.authorizerHash;
|
|
24045
|
-
const authorizerPool = authPools
|
|
24046
|
-
|
|
24047
|
-
|
|
24372
|
+
const authorizerPool = authPools.get(coreIndex);
|
|
24373
|
+
const pool = authorizerPool?.materialize() ?? [];
|
|
24374
|
+
if (pool.find((hash) => hash.isEqualTo(authorizerHash)) === undefined) {
|
|
24375
|
+
return result_Result.error(ReportsError.CoreUnauthorized, () => `Authorizer hash not found in the pool of core ${coreIndex}: ${authorizerHash}`);
|
|
24048
24376
|
}
|
|
24049
24377
|
/**
|
|
24050
24378
|
* We require that the gas allotted for accumulation of each
|
|
@@ -24056,17 +24384,17 @@ function verifyPostSignatureChecks(input, availabilityAssignment, authPools, ser
|
|
|
24056
24384
|
for (const result of report.results) {
|
|
24057
24385
|
const service = services(result.serviceId);
|
|
24058
24386
|
if (service === null) {
|
|
24059
|
-
return result_Result.error(ReportsError.BadServiceId, `No service with id: ${result.serviceId}`);
|
|
24387
|
+
return result_Result.error(ReportsError.BadServiceId, () => `No service with id: ${result.serviceId}`);
|
|
24060
24388
|
}
|
|
24061
24389
|
const info = service.getInfo();
|
|
24062
24390
|
// check minimal accumulation gas
|
|
24063
24391
|
if (result.gas < info.accumulateMinGas) {
|
|
24064
|
-
return result_Result.error(ReportsError.ServiceItemGasTooLow, `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
|
|
24392
|
+
return result_Result.error(ReportsError.ServiceItemGasTooLow, () => `Service (${result.serviceId}) gas is less than minimal. Got: ${result.gas}, expected at least: ${info.accumulateMinGas}`);
|
|
24065
24393
|
}
|
|
24066
24394
|
}
|
|
24067
24395
|
const totalGas = sumU64(...report.results.map((x) => x.gas));
|
|
24068
24396
|
if (totalGas.overflow || totalGas.value > G_A) {
|
|
24069
|
-
return result_Result.error(ReportsError.WorkReportGasTooHigh, `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
|
|
24397
|
+
return result_Result.error(ReportsError.WorkReportGasTooHigh, () => `Total gas too high. Got: ${totalGas.value} (ovfl: ${totalGas.overflow}), maximal: ${G_A}`);
|
|
24070
24398
|
}
|
|
24071
24399
|
}
|
|
24072
24400
|
return result_Result.ok(result_OK);
|
|
@@ -24152,7 +24480,7 @@ class Reports {
|
|
|
24152
24480
|
}
|
|
24153
24481
|
const reporters = SortedSet.fromArray(bytesBlobComparator, signaturesToVerify.ok.map((x) => x.key)).slice();
|
|
24154
24482
|
if (hasAnyOffenders(reporters, input.offenders)) {
|
|
24155
|
-
return result_Result.error(ReportsError.BannedValidator);
|
|
24483
|
+
return result_Result.error(ReportsError.BannedValidator, () => "One or more reporters are banned validators");
|
|
24156
24484
|
}
|
|
24157
24485
|
return result_Result.ok({
|
|
24158
24486
|
stateUpdate: {
|
|
@@ -24173,7 +24501,8 @@ class Reports {
|
|
|
24173
24501
|
return verifyCredentials(input.guarantees, workReportHashes, input.slot, (headerTimeSlot, guaranteeTimeSlot) => this.getGuarantorAssignment(headerTimeSlot, guaranteeTimeSlot, input.newEntropy));
|
|
24174
24502
|
}
|
|
24175
24503
|
verifyPostSignatureChecks(input, assurancesAvailAssignment) {
|
|
24176
|
-
|
|
24504
|
+
const authPoolsView = this.state.view().authPoolsView();
|
|
24505
|
+
return verifyPostSignatureChecks(input, assurancesAvailAssignment, authPoolsView, (id) => this.state.getService(id));
|
|
24177
24506
|
}
|
|
24178
24507
|
verifyContextualValidity(input) {
|
|
24179
24508
|
return verifyContextualValidity(input, this.state, this.headerChain, this.chainSpec.maxLookupAnchorAge);
|
|
@@ -24191,7 +24520,7 @@ class Reports {
|
|
|
24191
24520
|
return signaturesToVerify[idx].key;
|
|
24192
24521
|
})
|
|
24193
24522
|
.filter((x) => x !== null);
|
|
24194
|
-
return result_Result.error(ReportsError.BadSignature, `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
|
|
24523
|
+
return result_Result.error(ReportsError.BadSignature, () => `Invalid signatures for validators with keys: ${invalidKeys.join(", ")}`);
|
|
24195
24524
|
}
|
|
24196
24525
|
/**
|
|
24197
24526
|
* Get the guarantor assignment (both core and validator data)
|
|
@@ -24207,10 +24536,10 @@ class Reports {
|
|
|
24207
24536
|
const minTimeSlot = Math.max(0, headerRotation - 1) * rotationPeriod;
|
|
24208
24537
|
// https://graypaper.fluffylabs.dev/#/5f542d7/155e00156900
|
|
24209
24538
|
if (guaranteeTimeSlot > headerTimeSlot) {
|
|
24210
|
-
return result_Result.error(ReportsError.FutureReportSlot, `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24539
|
+
return result_Result.error(ReportsError.FutureReportSlot, () => `Report slot is in future. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24211
24540
|
}
|
|
24212
24541
|
if (guaranteeTimeSlot < minTimeSlot) {
|
|
24213
|
-
return result_Result.error(ReportsError.ReportEpochBeforeLast, `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24542
|
+
return result_Result.error(ReportsError.ReportEpochBeforeLast, () => `Report slot is too old. Block ${headerTimeSlot}, Report: ${guaranteeTimeSlot}`);
|
|
24214
24543
|
}
|
|
24215
24544
|
// TODO [ToDr] [opti] below code needs cache.
|
|
24216
24545
|
// The `G` and `G*` sets should only be computed once per rotation.
|
|
@@ -24746,6 +25075,9 @@ class OnChain {
|
|
|
24746
25075
|
servicesUpdate = servicesUpdateFromDeferredTransfers;
|
|
24747
25076
|
assertEmpty(deferredTransfersRest);
|
|
24748
25077
|
}
|
|
25078
|
+
else {
|
|
25079
|
+
debug_check `${pendingTransfers.length === 0} All transfers should be already accumulated.`;
|
|
25080
|
+
}
|
|
24749
25081
|
const accumulateRoot = await this.accumulateOutput.transition({ accumulationOutputLog });
|
|
24750
25082
|
// recent history
|
|
24751
25083
|
const recentHistoryUpdate = this.recentHistory.transition({
|
|
@@ -24775,6 +25107,16 @@ class OnChain {
|
|
|
24775
25107
|
});
|
|
24776
25108
|
const { statistics, ...statisticsRest } = statisticsUpdate;
|
|
24777
25109
|
assertEmpty(statisticsRest);
|
|
25110
|
+
// Concat accumulatePreimages updates with preimages
|
|
25111
|
+
for (const [serviceId, accPreimageUpdates] of accumulatePreimages.entries()) {
|
|
25112
|
+
const preimagesUpdates = preimages.get(serviceId);
|
|
25113
|
+
if (preimagesUpdates === undefined) {
|
|
25114
|
+
preimages.set(serviceId, accPreimageUpdates);
|
|
25115
|
+
}
|
|
25116
|
+
else {
|
|
25117
|
+
preimages.set(serviceId, preimagesUpdates.concat(accPreimageUpdates));
|
|
25118
|
+
}
|
|
25119
|
+
}
|
|
24778
25120
|
return result_Result.ok({
|
|
24779
25121
|
...(maybeAuthorizationQueues !== undefined ? { authQueues: maybeAuthorizationQueues } : {}),
|
|
24780
25122
|
...(maybeDesignatedValidatorData !== undefined ? { designatedValidatorData: maybeDesignatedValidatorData } : {}),
|
|
@@ -24796,7 +25138,7 @@ class OnChain {
|
|
|
24796
25138
|
recentlyAccumulated,
|
|
24797
25139
|
accumulationOutputLog,
|
|
24798
25140
|
...servicesUpdate,
|
|
24799
|
-
preimages
|
|
25141
|
+
preimages,
|
|
24800
25142
|
});
|
|
24801
25143
|
}
|
|
24802
25144
|
getUsedAuthorizerHashes(guarantees) {
|
|
@@ -24813,11 +25155,11 @@ class OnChain {
|
|
|
24813
25155
|
}
|
|
24814
25156
|
function checkOffendersMatch(offendersMark, headerOffendersMark) {
|
|
24815
25157
|
if (offendersMark.size !== headerOffendersMark.length) {
|
|
24816
|
-
return result_Result.error(OFFENDERS_ERROR, `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
|
|
25158
|
+
return result_Result.error(OFFENDERS_ERROR, () => `Length mismatch: ${offendersMark.size} vs ${headerOffendersMark.length}`);
|
|
24817
25159
|
}
|
|
24818
25160
|
for (const key of headerOffendersMark) {
|
|
24819
25161
|
if (!offendersMark.has(key)) {
|
|
24820
|
-
return result_Result.error(OFFENDERS_ERROR, `Missing key: ${key}`);
|
|
25162
|
+
return result_Result.error(OFFENDERS_ERROR, () => `Missing key: ${key}`);
|
|
24821
25163
|
}
|
|
24822
25164
|
}
|
|
24823
25165
|
return result_Result.ok(result_OK);
|
|
@@ -24899,7 +25241,7 @@ class Importer {
|
|
|
24899
25241
|
if (!this.currentHash.isEqualTo(parentHash)) {
|
|
24900
25242
|
const state = this.states.getState(parentHash);
|
|
24901
25243
|
if (state === null) {
|
|
24902
|
-
const e = result_Result.error(BlockVerifierError.StateRootNotFound);
|
|
25244
|
+
const e = result_Result.error(BlockVerifierError.StateRootNotFound, () => `State not found for parent block ${parentHash}`);
|
|
24903
25245
|
if (!e.isError) {
|
|
24904
25246
|
throw new Error("unreachable, just adding to make compiler happy");
|
|
24905
25247
|
}
|
|
@@ -25095,7 +25437,7 @@ const importBlockResultCodec = descriptors_codec.custom({
|
|
|
25095
25437
|
}
|
|
25096
25438
|
if (kind === 1) {
|
|
25097
25439
|
const error = d.bytesBlob();
|
|
25098
|
-
return result_Result.error(error.asText());
|
|
25440
|
+
return result_Result.error(error.asText(), () => error.asText());
|
|
25099
25441
|
}
|
|
25100
25442
|
throw new Error(`Invalid Result: ${kind}`);
|
|
25101
25443
|
}, (s) => {
|
|
@@ -25146,7 +25488,7 @@ class MainReady extends State {
|
|
|
25146
25488
|
if (res instanceof Uint8Array) {
|
|
25147
25489
|
return decoder_Decoder.decodeObject(importBlockResultCodec, res);
|
|
25148
25490
|
}
|
|
25149
|
-
return result_Result.error("Invalid worker response.");
|
|
25491
|
+
return result_Result.error("Invalid worker response.", () => "Invalid worker response: expected Uint8Array");
|
|
25150
25492
|
}
|
|
25151
25493
|
async getStateEntries(port, hash) {
|
|
25152
25494
|
const res = await port.sendRequest("getStateEntries", hash, [hash.buffer]);
|
|
@@ -25258,13 +25600,13 @@ class ImporterReady extends State {
|
|
|
25258
25600
|
response = result_Result.ok(this.importer.getBestStateRootHash() ?? ZERO_HASH.asOpaque());
|
|
25259
25601
|
}
|
|
25260
25602
|
else {
|
|
25261
|
-
response = result_Result.error(resultToString(res));
|
|
25603
|
+
response = result_Result.error(resultToString(res), () => resultToString(res));
|
|
25262
25604
|
}
|
|
25263
25605
|
}
|
|
25264
25606
|
catch (e) {
|
|
25265
25607
|
state_machine_logger.error `Failed to import block: ${e}`;
|
|
25266
25608
|
state_machine_logger.error `${e instanceof Error ? e.stack : ""}`;
|
|
25267
|
-
response = result_Result.error(`${e}`);
|
|
25609
|
+
response = result_Result.error(`${e}`, () => `${e}`);
|
|
25268
25610
|
}
|
|
25269
25611
|
const encoded = encoder_Encoder.encodeObject(importBlockResultCodec, response);
|
|
25270
25612
|
return {
|