@typeberry/lib 0.2.0-e767e74 → 0.2.0-ef1ea0e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +362 -386
- package/index.d.ts +1218 -1013
- package/index.js +362 -386
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -304,7 +304,7 @@ function resultToString(res) {
|
|
|
304
304
|
if (res.isOk) {
|
|
305
305
|
return `OK: ${typeof res.ok === "symbol" ? res.ok.toString() : res.ok}`;
|
|
306
306
|
}
|
|
307
|
-
return `${res.details}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
307
|
+
return `${res.details()}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
308
308
|
}
|
|
309
309
|
/** An indication of two possible outcomes returned from a function. */
|
|
310
310
|
const Result$1 = {
|
|
@@ -318,7 +318,7 @@ const Result$1 = {
|
|
|
318
318
|
};
|
|
319
319
|
},
|
|
320
320
|
/** Create new [`Result`] with `Error` status. */
|
|
321
|
-
error: (error, details
|
|
321
|
+
error: (error, details) => {
|
|
322
322
|
check `${error !== undefined} 'Error' type cannot be undefined.`;
|
|
323
323
|
return {
|
|
324
324
|
isOk: false,
|
|
@@ -431,7 +431,7 @@ function deepEqual(actual, expected, { context = [], errorsCollector, ignore = [
|
|
|
431
431
|
}
|
|
432
432
|
if (actual.isError && expected.isError) {
|
|
433
433
|
deepEqual(actual.error, expected.error, { context: ctx.concat(["error"]), errorsCollector: errors, ignore });
|
|
434
|
-
deepEqual(actual.details, expected.details, {
|
|
434
|
+
deepEqual(actual.details(), expected.details(), {
|
|
435
435
|
context: ctx.concat(["details"]),
|
|
436
436
|
errorsCollector: errors,
|
|
437
437
|
// display details when error does not match
|
|
@@ -1122,8 +1122,8 @@ class Decoder {
|
|
|
1122
1122
|
/**
|
|
1123
1123
|
* Create a new [`Decoder`] instance given a raw array of bytes as a source.
|
|
1124
1124
|
*/
|
|
1125
|
-
static fromBlob(source) {
|
|
1126
|
-
return new Decoder(source);
|
|
1125
|
+
static fromBlob(source, context) {
|
|
1126
|
+
return new Decoder(source, undefined, context);
|
|
1127
1127
|
}
|
|
1128
1128
|
/**
|
|
1129
1129
|
* Decode a single object from all of the source bytes.
|
|
@@ -1418,7 +1418,7 @@ class Decoder {
|
|
|
1418
1418
|
ensureHasBytes(bytes) {
|
|
1419
1419
|
check `${bytes >= 0} Negative number of bytes given.`;
|
|
1420
1420
|
if (this.offset + bytes > this.source.length) {
|
|
1421
|
-
throw new
|
|
1421
|
+
throw new EndOfDataError(`Attempting to decode more data than there is left. Need ${bytes}, left: ${this.source.length - this.offset}.`);
|
|
1422
1422
|
}
|
|
1423
1423
|
}
|
|
1424
1424
|
}
|
|
@@ -1432,6 +1432,8 @@ function decodeVariableLengthExtraBytes(firstByte) {
|
|
|
1432
1432
|
}
|
|
1433
1433
|
return 0;
|
|
1434
1434
|
}
|
|
1435
|
+
class EndOfDataError extends Error {
|
|
1436
|
+
}
|
|
1435
1437
|
|
|
1436
1438
|
/** Wrapper for `Decoder` that can skip bytes of fields in the data buffer instead of decoding them. */
|
|
1437
1439
|
class Skipper {
|
|
@@ -2249,6 +2251,8 @@ var codec$1;
|
|
|
2249
2251
|
return ret;
|
|
2250
2252
|
};
|
|
2251
2253
|
})();
|
|
2254
|
+
/** Zero-size `void` value. */
|
|
2255
|
+
codec.nothing = Descriptor.new("void", { bytes: 0, isExact: true }, (_e, _v) => { }, (_d) => { }, (_s) => { });
|
|
2252
2256
|
/** Variable-length U32. */
|
|
2253
2257
|
codec.varU32 = Descriptor.new("var_u32", { bytes: 4, isExact: false }, (e, v) => e.varU32(v), (d) => d.varU32(), (d) => d.varU32());
|
|
2254
2258
|
/** Variable-length U64. */
|
|
@@ -2448,6 +2452,9 @@ function forEachDescriptor(descriptors, f) {
|
|
|
2448
2452
|
f(k, descriptors[k]);
|
|
2449
2453
|
}
|
|
2450
2454
|
catch (e) {
|
|
2455
|
+
if (e instanceof EndOfDataError) {
|
|
2456
|
+
throw new EndOfDataError(`${key}: ${e}`);
|
|
2457
|
+
}
|
|
2451
2458
|
throw new Error(`${key}: ${e}`);
|
|
2452
2459
|
}
|
|
2453
2460
|
}
|
|
@@ -2525,6 +2532,7 @@ var index$q = /*#__PURE__*/Object.freeze({
|
|
|
2525
2532
|
Decoder: Decoder,
|
|
2526
2533
|
Descriptor: Descriptor,
|
|
2527
2534
|
Encoder: Encoder,
|
|
2535
|
+
EndOfDataError: EndOfDataError,
|
|
2528
2536
|
ObjectView: ObjectView,
|
|
2529
2537
|
SequenceView: SequenceView,
|
|
2530
2538
|
TYPICAL_DICTIONARY_LENGTH: TYPICAL_DICTIONARY_LENGTH,
|
|
@@ -4785,7 +4793,7 @@ class SortedArray {
|
|
|
4785
4793
|
isEqual: false,
|
|
4786
4794
|
};
|
|
4787
4795
|
}
|
|
4788
|
-
/** Create a new
|
|
4796
|
+
/** Create a new SortedArray from two sorted collections. */
|
|
4789
4797
|
static fromTwoSortedCollections(first, second) {
|
|
4790
4798
|
check `${first.comparator === second.comparator} Cannot merge arrays if they do not use the same comparator`;
|
|
4791
4799
|
const comparator = first.comparator;
|
|
@@ -5142,31 +5150,6 @@ const fullChainSpec = new ChainSpec({
|
|
|
5142
5150
|
maxLookupAnchorAge: tryAsU32(14_400),
|
|
5143
5151
|
});
|
|
5144
5152
|
|
|
5145
|
-
/**
|
|
5146
|
-
* Configuration object for typeberry workers.
|
|
5147
|
-
*/
|
|
5148
|
-
class WorkerConfig {
|
|
5149
|
-
chainSpec;
|
|
5150
|
-
dbPath;
|
|
5151
|
-
omitSealVerification;
|
|
5152
|
-
/**
|
|
5153
|
-
* Since we loose prototypes when transferring the context,
|
|
5154
|
-
* this function is re-initializing proper types.
|
|
5155
|
-
*
|
|
5156
|
-
* TODO [ToDr] instead of doing this hack, we might prefer to pass data
|
|
5157
|
-
* between workers using JAM codec maybe?
|
|
5158
|
-
*/
|
|
5159
|
-
static reInit(config) {
|
|
5160
|
-
const { chainSpec, dbPath, omitSealVerification } = config;
|
|
5161
|
-
return new WorkerConfig(new ChainSpec(chainSpec), dbPath, omitSealVerification);
|
|
5162
|
-
}
|
|
5163
|
-
constructor(chainSpec, dbPath, omitSealVerification = false) {
|
|
5164
|
-
this.chainSpec = chainSpec;
|
|
5165
|
-
this.dbPath = dbPath;
|
|
5166
|
-
this.omitSealVerification = omitSealVerification;
|
|
5167
|
-
}
|
|
5168
|
-
}
|
|
5169
|
-
|
|
5170
5153
|
/** Bootnode class represents a single contact point in the network */
|
|
5171
5154
|
class Bootnode {
|
|
5172
5155
|
id;
|
|
@@ -5200,7 +5183,6 @@ var index$m = /*#__PURE__*/Object.freeze({
|
|
|
5200
5183
|
EST_EPOCH_LENGTH: EST_EPOCH_LENGTH,
|
|
5201
5184
|
EST_VALIDATORS: EST_VALIDATORS,
|
|
5202
5185
|
EST_VALIDATORS_SUPER_MAJORITY: EST_VALIDATORS_SUPER_MAJORITY,
|
|
5203
|
-
WorkerConfig: WorkerConfig,
|
|
5204
5186
|
fullChainSpec: fullChainSpec,
|
|
5205
5187
|
tinyChainSpec: tinyChainSpec
|
|
5206
5188
|
});
|
|
@@ -7311,9 +7293,7 @@ var chain_spec$1 = {
|
|
|
7311
7293
|
id: "typeberry-default",
|
|
7312
7294
|
bootnodes: [
|
|
7313
7295
|
"e3r2oc62zwfj3crnuifuvsxvbtlzetk4o5qyhetkhagsc2fgl2oka@127.0.0.1:40000",
|
|
7314
|
-
"
|
|
7315
|
-
"en5ejs5b2tybkfh4ym5vpfh7nynby73xhtfzmazumtvcijpcsz6ma@127.0.0.1:12346",
|
|
7316
|
-
"ekwmt37xecoq6a7otkm4ux5gfmm4uwbat4bg5m223shckhaaxdpqa@127.0.0.1:12347"
|
|
7296
|
+
"eyonydqt7gj7bjdek62lwdeuxdzr5q7nmxa2p5zwwtoijgamdnkka@127.0.0.1:12345"
|
|
7317
7297
|
],
|
|
7318
7298
|
genesis_header: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aaff71c6c03ff88adb5ed52c9681de1629a54e702fc14729f6b50d2f0a76f185b34418fb8c85bb3985394a8c2756d3643457ce614546202a2f50b093d762499acedee6d555b82024f1ccf8a1e37e60fa60fd40b1958c4bb3006af78647950e1b91ad93247bd01307550ec7acd757ce6fb805fcf73db364063265b30a949e90d9339326edb21e5541717fde24ec085000b28709847b8aab1ac51f84e94b37ca1b66cab2b9ff25c2410fbe9b8a717abb298c716a03983c98ceb4def2087500b8e3410746846d17469fb2f95ef365efcab9f4e22fa1feb53111c995376be8019981ccf30aa5444688b3cab47697b37d5cac5707bb3289e986b19b17db437206931a8d151e5c8fe2b9d8a606966a79edd2f9e5db47e83947ce368ccba53bf6ba20a40b8b8c5d436f92ecf605421e873a99ec528761eb52a88a2f9a057b3b3003e6f32a2105650944fcd101621fd5bb3124c9fd191d114b7ad936c1d79d734f9f21392eab0084d01534b31c1dd87c81645fd762482a90027754041ca1b56133d0466c0600ffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
7319
7299
|
genesis_state: {
|
|
@@ -7359,9 +7339,7 @@ var authorship = {
|
|
|
7359
7339
|
var chain_spec = {
|
|
7360
7340
|
id: "typeberry-dev",
|
|
7361
7341
|
bootnodes: [
|
|
7362
|
-
"
|
|
7363
|
-
"en5ejs5b2tybkfh4ym5vpfh7nynby73xhtfzmazumtvcijpcsz6ma@127.0.0.1:12346",
|
|
7364
|
-
"ekwmt37xecoq6a7otkm4ux5gfmm4uwbat4bg5m223shckhaaxdpqa@127.0.0.1:12347"
|
|
7342
|
+
"eyonydqt7gj7bjdek62lwdeuxdzr5q7nmxa2p5zwwtoijgamdnkka@127.0.0.1:12345"
|
|
7365
7343
|
],
|
|
7366
7344
|
genesis_header: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aaff71c6c03ff88adb5ed52c9681de1629a54e702fc14729f6b50d2f0a76f185b34418fb8c85bb3985394a8c2756d3643457ce614546202a2f50b093d762499acedee6d555b82024f1ccf8a1e37e60fa60fd40b1958c4bb3006af78647950e1b91ad93247bd01307550ec7acd757ce6fb805fcf73db364063265b30a949e90d9339326edb21e5541717fde24ec085000b28709847b8aab1ac51f84e94b37ca1b66cab2b9ff25c2410fbe9b8a717abb298c716a03983c98ceb4def2087500b8e3410746846d17469fb2f95ef365efcab9f4e22fa1feb53111c995376be8019981ccf30aa5444688b3cab47697b37d5cac5707bb3289e986b19b17db437206931a8d151e5c8fe2b9d8a606966a79edd2f9e5db47e83947ce368ccba53bf6ba20a40b8b8c5d436f92ecf605421e873a99ec528761eb52a88a2f9a057b3b3003e6f32a2105650944fcd101621fd5bb3124c9fd191d114b7ad936c1d79d734f9f21392eab0084d01534b31c1dd87c81645fd762482a90027754041ca1b56133d0466c0600ffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
7367
7345
|
genesis_state: {
|
|
@@ -7784,16 +7762,18 @@ class NodeConfiguration {
|
|
|
7784
7762
|
version: "number",
|
|
7785
7763
|
flavor: knownChainSpecFromJson,
|
|
7786
7764
|
chain_spec: JipChainSpec.fromJson,
|
|
7787
|
-
database_base_path: "string",
|
|
7765
|
+
database_base_path: json.optional("string"),
|
|
7788
7766
|
authorship: AuthorshipOptions.fromJson,
|
|
7789
7767
|
}, NodeConfiguration.new);
|
|
7790
7768
|
static new({ $schema, version, flavor, chain_spec, database_base_path, authorship }) {
|
|
7791
7769
|
if (version !== 1) {
|
|
7792
7770
|
throw new Error("Only version=1 config is supported.");
|
|
7793
7771
|
}
|
|
7794
|
-
return new NodeConfiguration($schema, version, flavor, chain_spec, database_base_path, authorship);
|
|
7772
|
+
return new NodeConfiguration($schema, version, flavor, chain_spec, database_base_path ?? undefined, authorship);
|
|
7795
7773
|
}
|
|
7796
|
-
constructor($schema, version, flavor, chainSpec,
|
|
7774
|
+
constructor($schema, version, flavor, chainSpec,
|
|
7775
|
+
/** If database path is not provided, we load an in-memory db. */
|
|
7776
|
+
databaseBasePath, authorship) {
|
|
7797
7777
|
this.$schema = $schema;
|
|
7798
7778
|
this.version = version;
|
|
7799
7779
|
this.flavor = flavor;
|
|
@@ -7879,6 +7859,7 @@ class InMemoryBlocks {
|
|
|
7879
7859
|
getExtrinsic(hash) {
|
|
7880
7860
|
return this.extrinsicsByHeaderHash.get(hash) ?? null;
|
|
7881
7861
|
}
|
|
7862
|
+
async close() { }
|
|
7882
7863
|
}
|
|
7883
7864
|
|
|
7884
7865
|
/**
|
|
@@ -8072,6 +8053,8 @@ function accumulationOutputComparator(a, b) {
|
|
|
8072
8053
|
const O = 8;
|
|
8073
8054
|
/** `Q`: The number of items in the authorizations queue. */
|
|
8074
8055
|
const Q = 80;
|
|
8056
|
+
/** `W_B`: The maximum size of the concatenated variable-size blobs, extrinsics and imported segments of a work-package, in octets */
|
|
8057
|
+
Compatibility.isGreaterOrEqual(GpVersion.V0_7_2) ? 13_791_360 : 13_794_305;
|
|
8075
8058
|
/** `W_T`: The size of a transfer memo in octets. */
|
|
8076
8059
|
const W_T = 128;
|
|
8077
8060
|
/**
|
|
@@ -9062,31 +9045,29 @@ var UpdatePreimageKind;
|
|
|
9062
9045
|
* 3. Update `LookupHistory` with given value.
|
|
9063
9046
|
*/
|
|
9064
9047
|
class UpdatePreimage {
|
|
9065
|
-
serviceId;
|
|
9066
9048
|
action;
|
|
9067
|
-
constructor(
|
|
9068
|
-
this.serviceId = serviceId;
|
|
9049
|
+
constructor(action) {
|
|
9069
9050
|
this.action = action;
|
|
9070
9051
|
}
|
|
9071
9052
|
/** A preimage is provided. We should update the lookuphistory and add the preimage to db. */
|
|
9072
|
-
static provide({
|
|
9073
|
-
return new UpdatePreimage(
|
|
9053
|
+
static provide({ preimage, slot }) {
|
|
9054
|
+
return new UpdatePreimage({
|
|
9074
9055
|
kind: UpdatePreimageKind.Provide,
|
|
9075
9056
|
preimage,
|
|
9076
9057
|
slot,
|
|
9077
9058
|
});
|
|
9078
9059
|
}
|
|
9079
9060
|
/** The preimage should be removed completely from the database. */
|
|
9080
|
-
static remove({
|
|
9081
|
-
return new UpdatePreimage(
|
|
9061
|
+
static remove({ hash, length }) {
|
|
9062
|
+
return new UpdatePreimage({
|
|
9082
9063
|
kind: UpdatePreimageKind.Remove,
|
|
9083
9064
|
hash,
|
|
9084
9065
|
length,
|
|
9085
9066
|
});
|
|
9086
9067
|
}
|
|
9087
9068
|
/** Update the lookup history of some preimage or add a new one (request). */
|
|
9088
|
-
static updateOrAdd({
|
|
9089
|
-
return new UpdatePreimage(
|
|
9069
|
+
static updateOrAdd({ lookupHistory }) {
|
|
9070
|
+
return new UpdatePreimage({
|
|
9090
9071
|
kind: UpdatePreimageKind.UpdateOrAdd,
|
|
9091
9072
|
item: lookupHistory,
|
|
9092
9073
|
});
|
|
@@ -9123,23 +9104,21 @@ var UpdateServiceKind;
|
|
|
9123
9104
|
UpdateServiceKind[UpdateServiceKind["Create"] = 1] = "Create";
|
|
9124
9105
|
})(UpdateServiceKind || (UpdateServiceKind = {}));
|
|
9125
9106
|
/**
|
|
9126
|
-
* Update service info
|
|
9107
|
+
* Update service info or create a new one.
|
|
9127
9108
|
*/
|
|
9128
9109
|
class UpdateService {
|
|
9129
|
-
serviceId;
|
|
9130
9110
|
action;
|
|
9131
|
-
constructor(
|
|
9132
|
-
this.serviceId = serviceId;
|
|
9111
|
+
constructor(action) {
|
|
9133
9112
|
this.action = action;
|
|
9134
9113
|
}
|
|
9135
|
-
static update({
|
|
9136
|
-
return new UpdateService(
|
|
9114
|
+
static update({ serviceInfo }) {
|
|
9115
|
+
return new UpdateService({
|
|
9137
9116
|
kind: UpdateServiceKind.Update,
|
|
9138
9117
|
account: serviceInfo,
|
|
9139
9118
|
});
|
|
9140
9119
|
}
|
|
9141
|
-
static create({
|
|
9142
|
-
return new UpdateService(
|
|
9120
|
+
static create({ serviceInfo, lookupHistory, }) {
|
|
9121
|
+
return new UpdateService({
|
|
9143
9122
|
kind: UpdateServiceKind.Create,
|
|
9144
9123
|
account: serviceInfo,
|
|
9145
9124
|
lookupHistory,
|
|
@@ -9160,17 +9139,15 @@ var UpdateStorageKind;
|
|
|
9160
9139
|
* Can either create/modify an entry or remove it.
|
|
9161
9140
|
*/
|
|
9162
9141
|
class UpdateStorage {
|
|
9163
|
-
serviceId;
|
|
9164
9142
|
action;
|
|
9165
|
-
constructor(
|
|
9166
|
-
this.serviceId = serviceId;
|
|
9143
|
+
constructor(action) {
|
|
9167
9144
|
this.action = action;
|
|
9168
9145
|
}
|
|
9169
|
-
static set({
|
|
9170
|
-
return new UpdateStorage(
|
|
9146
|
+
static set({ storage }) {
|
|
9147
|
+
return new UpdateStorage({ kind: UpdateStorageKind.Set, storage });
|
|
9171
9148
|
}
|
|
9172
|
-
static remove({
|
|
9173
|
-
return new UpdateStorage(
|
|
9149
|
+
static remove({ key }) {
|
|
9150
|
+
return new UpdateStorage({ kind: UpdateStorageKind.Remove, key });
|
|
9174
9151
|
}
|
|
9175
9152
|
get key() {
|
|
9176
9153
|
if (this.action.kind === UpdateStorageKind.Remove) {
|
|
@@ -9355,12 +9332,12 @@ class InMemoryState extends WithDebug {
|
|
|
9355
9332
|
* Modify the state and apply a single state update.
|
|
9356
9333
|
*/
|
|
9357
9334
|
applyUpdate(update) {
|
|
9358
|
-
const {
|
|
9335
|
+
const { removed, created: _, updated, preimages, storage, ...rest } = update;
|
|
9359
9336
|
// just assign all other variables
|
|
9360
9337
|
Object.assign(this, rest);
|
|
9361
9338
|
// and update the services state
|
|
9362
9339
|
let result;
|
|
9363
|
-
result = this.updateServices(
|
|
9340
|
+
result = this.updateServices(updated);
|
|
9364
9341
|
if (result.isError) {
|
|
9365
9342
|
return result;
|
|
9366
9343
|
}
|
|
@@ -9372,7 +9349,7 @@ class InMemoryState extends WithDebug {
|
|
|
9372
9349
|
if (result.isError) {
|
|
9373
9350
|
return result;
|
|
9374
9351
|
}
|
|
9375
|
-
this.removeServices(
|
|
9352
|
+
this.removeServices(removed);
|
|
9376
9353
|
return Result$1.ok(OK);
|
|
9377
9354
|
}
|
|
9378
9355
|
removeServices(servicesRemoved) {
|
|
@@ -9381,89 +9358,102 @@ class InMemoryState extends WithDebug {
|
|
|
9381
9358
|
this.services.delete(serviceId);
|
|
9382
9359
|
}
|
|
9383
9360
|
}
|
|
9384
|
-
updateStorage(
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9361
|
+
updateStorage(storageUpdates) {
|
|
9362
|
+
if (storageUpdates === undefined) {
|
|
9363
|
+
return Result$1.ok(OK);
|
|
9364
|
+
}
|
|
9365
|
+
for (const [serviceId, updates] of storageUpdates.entries()) {
|
|
9366
|
+
for (const update of updates) {
|
|
9367
|
+
const { kind } = update.action;
|
|
9368
|
+
const service = this.services.get(serviceId);
|
|
9369
|
+
if (service === undefined) {
|
|
9370
|
+
return Result$1.error(UpdateError.NoService, () => `Attempting to update storage of non-existing service: ${serviceId}`);
|
|
9371
|
+
}
|
|
9372
|
+
if (kind === UpdateStorageKind.Set) {
|
|
9373
|
+
const { key, value } = update.action.storage;
|
|
9374
|
+
service.data.storage.set(key.toString(), StorageItem.create({ key, value }));
|
|
9375
|
+
}
|
|
9376
|
+
else if (kind === UpdateStorageKind.Remove) {
|
|
9377
|
+
const { key } = update.action;
|
|
9378
|
+
check `
|
|
9398
9379
|
${service.data.storage.has(key.toString())}
|
|
9399
|
-
Attempting to remove non-existing storage item at ${serviceId}: ${action.key}
|
|
9380
|
+
Attempting to remove non-existing storage item at ${serviceId}: ${update.action.key}
|
|
9400
9381
|
`;
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9382
|
+
service.data.storage.delete(key.toString());
|
|
9383
|
+
}
|
|
9384
|
+
else {
|
|
9385
|
+
assertNever(kind);
|
|
9386
|
+
}
|
|
9405
9387
|
}
|
|
9406
9388
|
}
|
|
9407
9389
|
return Result$1.ok(OK);
|
|
9408
9390
|
}
|
|
9409
|
-
updatePreimages(
|
|
9410
|
-
|
|
9391
|
+
updatePreimages(preimagesUpdates) {
|
|
9392
|
+
if (preimagesUpdates === undefined) {
|
|
9393
|
+
return Result$1.ok(OK);
|
|
9394
|
+
}
|
|
9395
|
+
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
9411
9396
|
const service = this.services.get(serviceId);
|
|
9412
9397
|
if (service === undefined) {
|
|
9413
|
-
return Result$1.error(UpdateError.NoService, `Attempting to update preimage of non-existing service: ${serviceId}`);
|
|
9398
|
+
return Result$1.error(UpdateError.NoService, () => `Attempting to update preimage of non-existing service: ${serviceId}`);
|
|
9414
9399
|
}
|
|
9415
|
-
const
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9400
|
+
for (const update of updates) {
|
|
9401
|
+
const { kind } = update.action;
|
|
9402
|
+
if (kind === UpdatePreimageKind.Provide) {
|
|
9403
|
+
const { preimage, slot } = update.action;
|
|
9404
|
+
if (service.data.preimages.has(preimage.hash)) {
|
|
9405
|
+
return Result$1.error(UpdateError.PreimageExists, () => `Overwriting existing preimage at ${serviceId}: ${preimage}`);
|
|
9406
|
+
}
|
|
9407
|
+
service.data.preimages.set(preimage.hash, preimage);
|
|
9408
|
+
if (slot !== null) {
|
|
9409
|
+
const lookupHistory = service.data.lookupHistory.get(preimage.hash);
|
|
9410
|
+
const length = tryAsU32(preimage.blob.length);
|
|
9411
|
+
const lookup = new LookupHistoryItem(preimage.hash, length, tryAsLookupHistorySlots([slot]));
|
|
9412
|
+
if (lookupHistory === undefined) {
|
|
9413
|
+
// no lookup history for that preimage at all (edge case, should be requested)
|
|
9414
|
+
service.data.lookupHistory.set(preimage.hash, [lookup]);
|
|
9415
|
+
}
|
|
9416
|
+
else {
|
|
9417
|
+
// insert or replace exiting entry
|
|
9418
|
+
const index = lookupHistory.map((x) => x.length).indexOf(length);
|
|
9419
|
+
lookupHistory.splice(index, index === -1 ? 0 : 1, lookup);
|
|
9420
|
+
}
|
|
9429
9421
|
}
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9422
|
+
}
|
|
9423
|
+
else if (kind === UpdatePreimageKind.Remove) {
|
|
9424
|
+
const { hash, length } = update.action;
|
|
9425
|
+
service.data.preimages.delete(hash);
|
|
9426
|
+
const history = service.data.lookupHistory.get(hash) ?? [];
|
|
9427
|
+
const idx = history.map((x) => x.length).indexOf(length);
|
|
9428
|
+
if (idx !== -1) {
|
|
9429
|
+
history.splice(idx, 1);
|
|
9434
9430
|
}
|
|
9435
9431
|
}
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9432
|
+
else if (kind === UpdatePreimageKind.UpdateOrAdd) {
|
|
9433
|
+
const { item } = update.action;
|
|
9434
|
+
const history = service.data.lookupHistory.get(item.hash) ?? [];
|
|
9435
|
+
const existingIdx = history.map((x) => x.length).indexOf(item.length);
|
|
9436
|
+
const removeCount = existingIdx === -1 ? 0 : 1;
|
|
9437
|
+
history.splice(existingIdx, removeCount, item);
|
|
9438
|
+
service.data.lookupHistory.set(item.hash, history);
|
|
9439
|
+
}
|
|
9440
|
+
else {
|
|
9441
|
+
assertNever(kind);
|
|
9444
9442
|
}
|
|
9445
|
-
}
|
|
9446
|
-
else if (kind === UpdatePreimageKind.UpdateOrAdd) {
|
|
9447
|
-
const { item } = action;
|
|
9448
|
-
const history = service.data.lookupHistory.get(item.hash) ?? [];
|
|
9449
|
-
const existingIdx = history.map((x) => x.length).indexOf(item.length);
|
|
9450
|
-
const removeCount = existingIdx === -1 ? 0 : 1;
|
|
9451
|
-
history.splice(existingIdx, removeCount, item);
|
|
9452
|
-
service.data.lookupHistory.set(item.hash, history);
|
|
9453
|
-
}
|
|
9454
|
-
else {
|
|
9455
|
-
assertNever(kind);
|
|
9456
9443
|
}
|
|
9457
9444
|
}
|
|
9458
9445
|
return Result$1.ok(OK);
|
|
9459
9446
|
}
|
|
9460
9447
|
updateServices(servicesUpdates) {
|
|
9461
|
-
|
|
9462
|
-
|
|
9448
|
+
if (servicesUpdates === undefined) {
|
|
9449
|
+
return Result$1.ok(OK);
|
|
9450
|
+
}
|
|
9451
|
+
for (const [serviceId, update] of servicesUpdates.entries()) {
|
|
9452
|
+
const { kind, account } = update.action;
|
|
9463
9453
|
if (kind === UpdateServiceKind.Create) {
|
|
9464
|
-
const { lookupHistory } = action;
|
|
9454
|
+
const { lookupHistory } = update.action;
|
|
9465
9455
|
if (this.services.has(serviceId)) {
|
|
9466
|
-
return Result$1.error(UpdateError.DuplicateService, `${serviceId} already exists!`);
|
|
9456
|
+
return Result$1.error(UpdateError.DuplicateService, () => `${serviceId} already exists!`);
|
|
9467
9457
|
}
|
|
9468
9458
|
this.services.set(serviceId, new InMemoryService(serviceId, {
|
|
9469
9459
|
info: account,
|
|
@@ -9475,7 +9465,7 @@ class InMemoryState extends WithDebug {
|
|
|
9475
9465
|
else if (kind === UpdateServiceKind.Update) {
|
|
9476
9466
|
const existingService = this.services.get(serviceId);
|
|
9477
9467
|
if (existingService === undefined) {
|
|
9478
|
-
return Result$1.error(UpdateError.NoService, `Cannot update ${serviceId} because it does not exist.`);
|
|
9468
|
+
return Result$1.error(UpdateError.NoService, () => `Cannot update ${serviceId} because it does not exist.`);
|
|
9479
9469
|
}
|
|
9480
9470
|
existingService.data.info = account;
|
|
9481
9471
|
}
|
|
@@ -10729,76 +10719,88 @@ function* serializeStateUpdate(spec, blake2b, update) {
|
|
|
10729
10719
|
yield* serializeBasicKeys(spec, update);
|
|
10730
10720
|
const encode = (codec, val) => Encoder.encodeObject(codec, val, spec);
|
|
10731
10721
|
// then let's proceed with service updates
|
|
10732
|
-
yield* serializeServiceUpdates(update.
|
|
10722
|
+
yield* serializeServiceUpdates(update.updated, encode, blake2b);
|
|
10733
10723
|
yield* serializePreimages(update.preimages, encode, blake2b);
|
|
10734
10724
|
yield* serializeStorage(update.storage, blake2b);
|
|
10735
|
-
yield* serializeRemovedServices(update.
|
|
10725
|
+
yield* serializeRemovedServices(update.removed);
|
|
10736
10726
|
}
|
|
10737
10727
|
function* serializeRemovedServices(servicesRemoved) {
|
|
10738
|
-
|
|
10728
|
+
if (servicesRemoved === undefined) {
|
|
10729
|
+
return;
|
|
10730
|
+
}
|
|
10731
|
+
for (const serviceId of servicesRemoved) {
|
|
10739
10732
|
// TODO [ToDr] what about all data associated with a service?
|
|
10740
10733
|
const codec = serialize.serviceData(serviceId);
|
|
10741
10734
|
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
10742
10735
|
}
|
|
10743
10736
|
}
|
|
10744
|
-
function* serializeStorage(
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
10737
|
+
function* serializeStorage(storageUpdates, blake2b) {
|
|
10738
|
+
if (storageUpdates === undefined) {
|
|
10739
|
+
return;
|
|
10740
|
+
}
|
|
10741
|
+
for (const [serviceId, updates] of storageUpdates.entries()) {
|
|
10742
|
+
for (const { action } of updates) {
|
|
10743
|
+
switch (action.kind) {
|
|
10744
|
+
case UpdateStorageKind.Set: {
|
|
10745
|
+
const key = action.storage.key;
|
|
10746
|
+
const codec = serialize.serviceStorage(blake2b, serviceId, key);
|
|
10747
|
+
yield [StateEntryUpdateAction.Insert, codec.key, action.storage.value];
|
|
10748
|
+
break;
|
|
10749
|
+
}
|
|
10750
|
+
case UpdateStorageKind.Remove: {
|
|
10751
|
+
const key = action.key;
|
|
10752
|
+
const codec = serialize.serviceStorage(blake2b, serviceId, key);
|
|
10753
|
+
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
10754
|
+
break;
|
|
10755
|
+
}
|
|
10758
10756
|
}
|
|
10759
|
-
default:
|
|
10760
|
-
assertNever(action);
|
|
10761
10757
|
}
|
|
10762
10758
|
}
|
|
10763
10759
|
}
|
|
10764
|
-
function* serializePreimages(
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
const
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10760
|
+
function* serializePreimages(preimagesUpdates, encode, blake2b) {
|
|
10761
|
+
if (preimagesUpdates === undefined) {
|
|
10762
|
+
return;
|
|
10763
|
+
}
|
|
10764
|
+
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
10765
|
+
for (const { action } of updates) {
|
|
10766
|
+
switch (action.kind) {
|
|
10767
|
+
case UpdatePreimageKind.Provide: {
|
|
10768
|
+
const { hash, blob } = action.preimage;
|
|
10769
|
+
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
10770
|
+
yield [StateEntryUpdateAction.Insert, codec.key, blob];
|
|
10771
|
+
if (action.slot !== null) {
|
|
10772
|
+
const codec2 = serialize.serviceLookupHistory(blake2b, serviceId, hash, tryAsU32(blob.length));
|
|
10773
|
+
yield [
|
|
10774
|
+
StateEntryUpdateAction.Insert,
|
|
10775
|
+
codec2.key,
|
|
10776
|
+
encode(codec2.Codec, tryAsLookupHistorySlots([action.slot])),
|
|
10777
|
+
];
|
|
10778
|
+
}
|
|
10779
|
+
break;
|
|
10780
|
+
}
|
|
10781
|
+
case UpdatePreimageKind.UpdateOrAdd: {
|
|
10782
|
+
const { hash, length, slots } = action.item;
|
|
10783
|
+
const codec = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
10784
|
+
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, slots)];
|
|
10785
|
+
break;
|
|
10786
|
+
}
|
|
10787
|
+
case UpdatePreimageKind.Remove: {
|
|
10788
|
+
const { hash, length } = action;
|
|
10789
|
+
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
10790
|
+
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
10791
|
+
const codec2 = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
10792
|
+
yield [StateEntryUpdateAction.Remove, codec2.key, EMPTY_BLOB];
|
|
10793
|
+
break;
|
|
10778
10794
|
}
|
|
10779
|
-
break;
|
|
10780
|
-
}
|
|
10781
|
-
case UpdatePreimageKind.UpdateOrAdd: {
|
|
10782
|
-
const { hash, length, slots } = action.item;
|
|
10783
|
-
const codec = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
10784
|
-
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, slots)];
|
|
10785
|
-
break;
|
|
10786
|
-
}
|
|
10787
|
-
case UpdatePreimageKind.Remove: {
|
|
10788
|
-
const { hash, length } = action;
|
|
10789
|
-
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
10790
|
-
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
10791
|
-
const codec2 = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
10792
|
-
yield [StateEntryUpdateAction.Remove, codec2.key, EMPTY_BLOB];
|
|
10793
|
-
break;
|
|
10794
10795
|
}
|
|
10795
|
-
default:
|
|
10796
|
-
assertNever(action);
|
|
10797
10796
|
}
|
|
10798
10797
|
}
|
|
10799
10798
|
}
|
|
10800
10799
|
function* serializeServiceUpdates(servicesUpdates, encode, blake2b) {
|
|
10801
|
-
|
|
10800
|
+
if (servicesUpdates === undefined) {
|
|
10801
|
+
return;
|
|
10802
|
+
}
|
|
10803
|
+
for (const [serviceId, { action }] of servicesUpdates.entries()) {
|
|
10802
10804
|
// new service being created or updated
|
|
10803
10805
|
const codec = serialize.serviceData(serviceId);
|
|
10804
10806
|
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, action.account)];
|
|
@@ -11067,31 +11069,35 @@ var LeafDbError;
|
|
|
11067
11069
|
* Note that reading the actual values may require accessing the original database.
|
|
11068
11070
|
*/
|
|
11069
11071
|
class LeafDb {
|
|
11070
|
-
|
|
11072
|
+
leafs;
|
|
11071
11073
|
db;
|
|
11072
11074
|
/**
|
|
11073
11075
|
* Parse given blob containing concatenated leaf nodes into leaf db.
|
|
11074
11076
|
*/
|
|
11075
11077
|
static fromLeavesBlob(blob, db) {
|
|
11076
11078
|
if (blob.length % TRIE_NODE_BYTES !== 0) {
|
|
11077
|
-
return Result$1.error(LeafDbError.InvalidLeafData, `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
|
|
11079
|
+
return Result$1.error(LeafDbError.InvalidLeafData, () => `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`);
|
|
11078
11080
|
}
|
|
11079
11081
|
const leaves = SortedSet.fromArray(leafComparator, []);
|
|
11080
11082
|
for (const nodeData of blob.chunks(TRIE_NODE_BYTES)) {
|
|
11081
11083
|
const node = new TrieNode(nodeData.raw);
|
|
11082
11084
|
if (node.getNodeType() === NodeType.Branch) {
|
|
11083
|
-
return Result$1.error(LeafDbError.InvalidLeafData, `Branch node detected: ${nodeData}`);
|
|
11085
|
+
return Result$1.error(LeafDbError.InvalidLeafData, () => `Branch node detected: ${nodeData}`);
|
|
11084
11086
|
}
|
|
11085
11087
|
leaves.insert(node.asLeafNode());
|
|
11086
11088
|
}
|
|
11087
11089
|
return Result$1.ok(new LeafDb(leaves, db));
|
|
11088
11090
|
}
|
|
11091
|
+
/** Create leaf db from sorted set of leaves. */
|
|
11092
|
+
static fromLeaves(leaves, db) {
|
|
11093
|
+
return new LeafDb(leaves, db);
|
|
11094
|
+
}
|
|
11089
11095
|
/** A mapping between an embedded value or db lookup key. */
|
|
11090
11096
|
lookup;
|
|
11091
|
-
constructor(
|
|
11092
|
-
this.
|
|
11097
|
+
constructor(leafs, db) {
|
|
11098
|
+
this.leafs = leafs;
|
|
11093
11099
|
this.db = db;
|
|
11094
|
-
this.lookup = TruncatedHashDictionary.fromEntries(
|
|
11100
|
+
this.lookup = TruncatedHashDictionary.fromEntries(leafs.array.map((leaf) => {
|
|
11095
11101
|
const key = leaf.getKey().asOpaque();
|
|
11096
11102
|
const value = leaf.hasEmbeddedValue()
|
|
11097
11103
|
? {
|
|
@@ -11100,7 +11106,7 @@ class LeafDb {
|
|
|
11100
11106
|
}
|
|
11101
11107
|
: {
|
|
11102
11108
|
kind: LookupKind.DbKey,
|
|
11103
|
-
key: leaf.getValueHash()
|
|
11109
|
+
key: leaf.getValueHash(),
|
|
11104
11110
|
};
|
|
11105
11111
|
return [key, value];
|
|
11106
11112
|
}));
|
|
@@ -11120,7 +11126,7 @@ class LeafDb {
|
|
|
11120
11126
|
}
|
|
11121
11127
|
getStateRoot(blake2b) {
|
|
11122
11128
|
const blake2bTrieHasher = getBlake2bTrieHasher(blake2b);
|
|
11123
|
-
return InMemoryTrie.computeStateRoot(blake2bTrieHasher, this.
|
|
11129
|
+
return InMemoryTrie.computeStateRoot(blake2bTrieHasher, this.leafs).asOpaque();
|
|
11124
11130
|
}
|
|
11125
11131
|
intoStateEntries() {
|
|
11126
11132
|
const entries = [];
|
|
@@ -11145,144 +11151,89 @@ var LookupKind;
|
|
|
11145
11151
|
LookupKind[LookupKind["DbKey"] = 1] = "DbKey";
|
|
11146
11152
|
})(LookupKind || (LookupKind = {}));
|
|
11147
11153
|
|
|
11148
|
-
|
|
11149
|
-
const
|
|
11150
|
-
|
|
11151
|
-
const
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
+
function updateLeafs(leafs, blake2b, data) {
|
|
11155
|
+
const blake2bTrieHasher = getBlake2bTrieHasher(blake2b);
|
|
11156
|
+
// We will collect all values that don't fit directly into leaf nodes.
|
|
11157
|
+
const values = [];
|
|
11158
|
+
for (const [action, key, value] of data) {
|
|
11159
|
+
if (action === StateEntryUpdateAction.Insert) {
|
|
11160
|
+
const leafNode = InMemoryTrie.constructLeaf(blake2bTrieHasher, key.asOpaque(), value);
|
|
11161
|
+
leafs.replace(leafNode);
|
|
11162
|
+
if (!leafNode.hasEmbeddedValue()) {
|
|
11163
|
+
values.push([leafNode.getValueHash(), value]);
|
|
11164
|
+
}
|
|
11165
|
+
}
|
|
11166
|
+
else if (action === StateEntryUpdateAction.Remove) {
|
|
11167
|
+
const leafNode = InMemoryTrie.constructLeaf(blake2bTrieHasher, key.asOpaque(), BytesBlob.empty());
|
|
11168
|
+
leafs.removeOne(leafNode);
|
|
11169
|
+
// TODO [ToDr] Handle ref-counting values or updating some header-hash-based references.
|
|
11170
|
+
}
|
|
11171
|
+
else {
|
|
11172
|
+
assertNever(action);
|
|
11173
|
+
}
|
|
11154
11174
|
}
|
|
11155
|
-
|
|
11156
|
-
|
|
11175
|
+
return {
|
|
11176
|
+
values,
|
|
11177
|
+
leafs,
|
|
11178
|
+
};
|
|
11179
|
+
}
|
|
11180
|
+
|
|
11181
|
+
/** In-memory serialized-states db. */
|
|
11182
|
+
class InMemorySerializedStates {
|
|
11183
|
+
spec;
|
|
11184
|
+
blake2b;
|
|
11185
|
+
db = HashDictionary.new();
|
|
11186
|
+
valuesDb = HashDictionary.new();
|
|
11187
|
+
constructor(spec, blake2b) {
|
|
11188
|
+
this.spec = spec;
|
|
11189
|
+
this.blake2b = blake2b;
|
|
11157
11190
|
}
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
const data = Array.from(v.values());
|
|
11165
|
-
data.sort((a, b) => compare(a, b).value);
|
|
11166
|
-
e.varU32(tryAsU32(data.length));
|
|
11167
|
-
for (const v of data) {
|
|
11168
|
-
value.encode(e, v);
|
|
11191
|
+
async insertInitialState(headerHash, entries) {
|
|
11192
|
+
// convert state entries into leafdb
|
|
11193
|
+
const { values, leafs } = updateLeafs(SortedSet.fromArray(leafComparator, []), this.blake2b, Array.from(entries, (x) => [StateEntryUpdateAction.Insert, x[0], x[1]]));
|
|
11194
|
+
// insert values to the db.
|
|
11195
|
+
for (const val of values) {
|
|
11196
|
+
this.valuesDb.set(val[0], val[1]);
|
|
11169
11197
|
}
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11198
|
+
this.db.set(headerHash, leafs);
|
|
11199
|
+
return Result$1.ok(OK);
|
|
11200
|
+
}
|
|
11201
|
+
async getStateRoot(state) {
|
|
11202
|
+
return state.backend.getStateRoot(this.blake2b);
|
|
11203
|
+
}
|
|
11204
|
+
async updateAndSetState(header, state, update) {
|
|
11205
|
+
const blake2b = this.blake2b;
|
|
11206
|
+
const updatedValues = serializeStateUpdate(this.spec, blake2b, update);
|
|
11207
|
+
const { values, leafs } = updateLeafs(state.backend.leafs, blake2b, updatedValues);
|
|
11208
|
+
// insert values to the db
|
|
11209
|
+
// valuesdb can be shared between all states because it's just
|
|
11210
|
+
// <valuehash> -> <value> mapping and existence is managed by trie leafs.
|
|
11211
|
+
for (const val of values) {
|
|
11212
|
+
this.valuesDb.set(val[0], val[1]);
|
|
11213
|
+
}
|
|
11214
|
+
// make sure to clone the leafs before writing, since the collection is re-used.
|
|
11215
|
+
this.db.set(header, SortedSet.fromSortedArray(leafComparator, leafs.slice()));
|
|
11216
|
+
return Result$1.ok(OK);
|
|
11217
|
+
}
|
|
11218
|
+
getState(header) {
|
|
11219
|
+
const leafs = this.db.get(header);
|
|
11220
|
+
if (leafs === undefined) {
|
|
11221
|
+
return null;
|
|
11185
11222
|
}
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
};
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
slots: readonlyArray(codec$1.sequenceVarLen(codec$1.u32.asOpaque())).convert(seeThrough, tryAsLookupHistorySlots),
|
|
11196
|
-
}, "LookupHistoryItem", ({ hash, length, slots }) => new LookupHistoryItem(hash, length, slots));
|
|
11197
|
-
const lookupHistoryEntryCodec = codec$1.object({
|
|
11198
|
-
key: codec$1.bytes(HASH_SIZE).asOpaque(),
|
|
11199
|
-
data: codec$1.sequenceVarLen(lookupHistoryItemCodec),
|
|
11200
|
-
});
|
|
11201
|
-
const lookupHistoryCodec = codec$1
|
|
11202
|
-
.sequenceVarLen(lookupHistoryEntryCodec)
|
|
11203
|
-
.convert((dict) => {
|
|
11204
|
-
const entries = [];
|
|
11205
|
-
for (const [key, data] of dict) {
|
|
11206
|
-
entries.push({
|
|
11207
|
-
key,
|
|
11208
|
-
data,
|
|
11223
|
+
// now create a leafdb with shared values db.
|
|
11224
|
+
const leafDb = LeafDb.fromLeaves(leafs, {
|
|
11225
|
+
get: (key) => {
|
|
11226
|
+
const val = this.valuesDb.get(key);
|
|
11227
|
+
if (val === undefined) {
|
|
11228
|
+
throw new Error(`Missing value at key: ${key}`);
|
|
11229
|
+
}
|
|
11230
|
+
return val.raw;
|
|
11231
|
+
},
|
|
11209
11232
|
});
|
|
11233
|
+
return SerializedState.new(this.spec, this.blake2b, leafDb);
|
|
11210
11234
|
}
|
|
11211
|
-
|
|
11212
|
-
}
|
|
11213
|
-
const dict = HashDictionary.new();
|
|
11214
|
-
for (const { key, data } of items) {
|
|
11215
|
-
const items = dict.get(key) ?? [];
|
|
11216
|
-
items.push(...data);
|
|
11217
|
-
dict.set(key, items);
|
|
11218
|
-
}
|
|
11219
|
-
return dict;
|
|
11220
|
-
});
|
|
11221
|
-
class ServiceWithCodec extends InMemoryService {
|
|
11222
|
-
static Codec = codec$1.Class(ServiceWithCodec, {
|
|
11223
|
-
serviceId: codec$1.u32.asOpaque(),
|
|
11224
|
-
data: codec$1.object({
|
|
11225
|
-
info: ServiceAccountInfo.Codec,
|
|
11226
|
-
preimages: codecHashDictionary(PreimageItem.Codec, (x) => x.hash),
|
|
11227
|
-
lookupHistory: lookupHistoryCodec,
|
|
11228
|
-
storage: codecMap(StorageItem.Codec, (x) => x.key.toString()),
|
|
11229
|
-
}),
|
|
11230
|
-
});
|
|
11231
|
-
constructor(id, data) {
|
|
11232
|
-
super(id, data);
|
|
11233
|
-
}
|
|
11234
|
-
static create({ serviceId, data }) {
|
|
11235
|
-
return new ServiceWithCodec(serviceId, data);
|
|
11236
|
-
}
|
|
11237
|
-
}
|
|
11238
|
-
const inMemoryStateCodec = (spec) => codec$1.Class(class State extends InMemoryState {
|
|
11239
|
-
static create(data) {
|
|
11240
|
-
return InMemoryState.new(spec, data);
|
|
11241
|
-
}
|
|
11242
|
-
}, {
|
|
11243
|
-
// alpha
|
|
11244
|
-
authPools: serialize.authPools.Codec,
|
|
11245
|
-
// phi
|
|
11246
|
-
authQueues: serialize.authQueues.Codec,
|
|
11247
|
-
// beta
|
|
11248
|
-
recentBlocks: serialize.recentBlocks.Codec,
|
|
11249
|
-
// gamma_k
|
|
11250
|
-
nextValidatorData: codecPerValidator(ValidatorData.Codec),
|
|
11251
|
-
// gamma_z
|
|
11252
|
-
epochRoot: codec$1.bytes(BANDERSNATCH_RING_ROOT_BYTES).asOpaque(),
|
|
11253
|
-
// gamma_s
|
|
11254
|
-
sealingKeySeries: SafroleSealingKeysData.Codec,
|
|
11255
|
-
// gamma_a
|
|
11256
|
-
ticketsAccumulator: readonlyArray(codec$1.sequenceVarLen(Ticket.Codec)).convert((x) => x, asKnownSize),
|
|
11257
|
-
// psi
|
|
11258
|
-
disputesRecords: serialize.disputesRecords.Codec,
|
|
11259
|
-
// eta
|
|
11260
|
-
entropy: serialize.entropy.Codec,
|
|
11261
|
-
// iota
|
|
11262
|
-
designatedValidatorData: serialize.designatedValidators.Codec,
|
|
11263
|
-
// kappa
|
|
11264
|
-
currentValidatorData: serialize.currentValidators.Codec,
|
|
11265
|
-
// lambda
|
|
11266
|
-
previousValidatorData: serialize.previousValidators.Codec,
|
|
11267
|
-
// rho
|
|
11268
|
-
availabilityAssignment: serialize.availabilityAssignment.Codec,
|
|
11269
|
-
// tau
|
|
11270
|
-
timeslot: serialize.timeslot.Codec,
|
|
11271
|
-
// chi
|
|
11272
|
-
privilegedServices: serialize.privilegedServices.Codec,
|
|
11273
|
-
// pi
|
|
11274
|
-
statistics: serialize.statistics.Codec,
|
|
11275
|
-
// omega
|
|
11276
|
-
accumulationQueue: serialize.accumulationQueue.Codec,
|
|
11277
|
-
// xi
|
|
11278
|
-
recentlyAccumulated: serialize.recentlyAccumulated.Codec,
|
|
11279
|
-
// theta
|
|
11280
|
-
accumulationOutputLog: serialize.accumulationOutputLog.Codec,
|
|
11281
|
-
// delta
|
|
11282
|
-
services: codec$1.dictionary(codec$1.u32.asOpaque(), ServiceWithCodec.Codec, {
|
|
11283
|
-
sortKeys: (a, b) => a - b,
|
|
11284
|
-
}),
|
|
11285
|
-
});
|
|
11235
|
+
async close() { }
|
|
11236
|
+
}
|
|
11286
11237
|
|
|
11287
11238
|
/** A potential error that occured during state update. */
|
|
11288
11239
|
var StateUpdateError;
|
|
@@ -11295,13 +11246,15 @@ var StateUpdateError;
|
|
|
11295
11246
|
class InMemoryStates {
|
|
11296
11247
|
spec;
|
|
11297
11248
|
db = HashDictionary.new();
|
|
11249
|
+
blake2b;
|
|
11298
11250
|
constructor(spec) {
|
|
11299
11251
|
this.spec = spec;
|
|
11252
|
+
this.blake2b = Blake2b.createHasher();
|
|
11300
11253
|
}
|
|
11301
11254
|
async updateAndSetState(headerHash, state, update) {
|
|
11302
11255
|
const res = state.applyUpdate(update);
|
|
11303
11256
|
if (res.isOk) {
|
|
11304
|
-
return await this.
|
|
11257
|
+
return await this.insertInitialState(headerHash, state);
|
|
11305
11258
|
}
|
|
11306
11259
|
switch (res.error) {
|
|
11307
11260
|
case UpdateError.DuplicateService:
|
|
@@ -11313,31 +11266,34 @@ class InMemoryStates {
|
|
|
11313
11266
|
}
|
|
11314
11267
|
}
|
|
11315
11268
|
async getStateRoot(state) {
|
|
11316
|
-
const blake2b = await
|
|
11269
|
+
const blake2b = await this.blake2b;
|
|
11317
11270
|
return StateEntries.serializeInMemory(this.spec, blake2b, state).getRootHash(blake2b);
|
|
11318
11271
|
}
|
|
11319
11272
|
/** Insert a full state into the database. */
|
|
11320
|
-
async
|
|
11321
|
-
const
|
|
11322
|
-
this.db.set(headerHash,
|
|
11273
|
+
async insertInitialState(headerHash, state) {
|
|
11274
|
+
const copy = InMemoryState.copyFrom(this.spec, state, state.intoServicesData());
|
|
11275
|
+
this.db.set(headerHash, copy);
|
|
11323
11276
|
return Result$1.ok(OK);
|
|
11324
11277
|
}
|
|
11325
11278
|
getState(headerHash) {
|
|
11326
|
-
const
|
|
11327
|
-
if (
|
|
11279
|
+
const state = this.db.get(headerHash);
|
|
11280
|
+
if (state === undefined) {
|
|
11328
11281
|
return null;
|
|
11329
11282
|
}
|
|
11330
|
-
return
|
|
11283
|
+
return InMemoryState.copyFrom(this.spec, state, state.intoServicesData());
|
|
11331
11284
|
}
|
|
11285
|
+
async close() { }
|
|
11332
11286
|
}
|
|
11333
11287
|
|
|
11334
11288
|
var index$d = /*#__PURE__*/Object.freeze({
|
|
11335
11289
|
__proto__: null,
|
|
11336
11290
|
InMemoryBlocks: InMemoryBlocks,
|
|
11291
|
+
InMemorySerializedStates: InMemorySerializedStates,
|
|
11337
11292
|
InMemoryStates: InMemoryStates,
|
|
11338
11293
|
LeafDb: LeafDb,
|
|
11339
11294
|
get LeafDbError () { return LeafDbError; },
|
|
11340
|
-
get StateUpdateError () { return StateUpdateError; }
|
|
11295
|
+
get StateUpdateError () { return StateUpdateError; },
|
|
11296
|
+
updateLeafs: updateLeafs
|
|
11341
11297
|
});
|
|
11342
11298
|
|
|
11343
11299
|
/**
|
|
@@ -12395,6 +12351,14 @@ const NoMachineError = Symbol("Machine index not found.");
|
|
|
12395
12351
|
const SegmentExportError = Symbol("Too many segments already exported.");
|
|
12396
12352
|
|
|
12397
12353
|
const InsufficientFundsError = "insufficient funds";
|
|
12354
|
+
/** Deep clone of a map with array. */
|
|
12355
|
+
function deepCloneMapWithArray(map) {
|
|
12356
|
+
const cloned = [];
|
|
12357
|
+
for (const [k, v] of map.entries()) {
|
|
12358
|
+
cloned.push([k, v.slice()]);
|
|
12359
|
+
}
|
|
12360
|
+
return new Map(cloned);
|
|
12361
|
+
}
|
|
12398
12362
|
/**
|
|
12399
12363
|
* State updates that currently accumulating service produced.
|
|
12400
12364
|
*
|
|
@@ -12424,10 +12388,11 @@ class AccumulationStateUpdate {
|
|
|
12424
12388
|
/** Create new empty state update. */
|
|
12425
12389
|
static empty() {
|
|
12426
12390
|
return new AccumulationStateUpdate({
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12391
|
+
created: [],
|
|
12392
|
+
updated: new Map(),
|
|
12393
|
+
removed: [],
|
|
12394
|
+
preimages: new Map(),
|
|
12395
|
+
storage: new Map(),
|
|
12431
12396
|
}, []);
|
|
12432
12397
|
}
|
|
12433
12398
|
/** Create a state update with some existing, yet uncommited services updates. */
|
|
@@ -12439,10 +12404,13 @@ class AccumulationStateUpdate {
|
|
|
12439
12404
|
/** Create a copy of another `StateUpdate`. Used by checkpoints. */
|
|
12440
12405
|
static copyFrom(from) {
|
|
12441
12406
|
const serviceUpdates = {
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12407
|
+
// shallow copy
|
|
12408
|
+
created: [...from.services.created],
|
|
12409
|
+
updated: new Map(from.services.updated),
|
|
12410
|
+
removed: [...from.services.removed],
|
|
12411
|
+
// deep copy
|
|
12412
|
+
preimages: deepCloneMapWithArray(from.services.preimages),
|
|
12413
|
+
storage: deepCloneMapWithArray(from.services.storage),
|
|
12446
12414
|
};
|
|
12447
12415
|
const transfers = [...from.transfers];
|
|
12448
12416
|
const update = new AccumulationStateUpdate(serviceUpdates, transfers, new Map(from.yieldedRoots));
|
|
@@ -12490,9 +12458,9 @@ class PartiallyUpdatedState {
|
|
|
12490
12458
|
if (destination === null) {
|
|
12491
12459
|
return null;
|
|
12492
12460
|
}
|
|
12493
|
-
const
|
|
12494
|
-
if (
|
|
12495
|
-
return
|
|
12461
|
+
const maybeUpdatedServiceInfo = this.stateUpdate.services.updated.get(destination);
|
|
12462
|
+
if (maybeUpdatedServiceInfo !== undefined) {
|
|
12463
|
+
return maybeUpdatedServiceInfo.action.account;
|
|
12496
12464
|
}
|
|
12497
12465
|
const maybeService = this.state.getService(destination);
|
|
12498
12466
|
if (maybeService === null) {
|
|
@@ -12501,7 +12469,8 @@ class PartiallyUpdatedState {
|
|
|
12501
12469
|
return maybeService.getInfo();
|
|
12502
12470
|
}
|
|
12503
12471
|
getStorage(serviceId, rawKey) {
|
|
12504
|
-
const
|
|
12472
|
+
const storages = this.stateUpdate.services.storage.get(serviceId) ?? [];
|
|
12473
|
+
const item = storages.find((x) => x.key.isEqualTo(rawKey));
|
|
12505
12474
|
if (item !== undefined) {
|
|
12506
12475
|
return item.value;
|
|
12507
12476
|
}
|
|
@@ -12516,10 +12485,11 @@ class PartiallyUpdatedState {
|
|
|
12516
12485
|
* the existence in `preimages` map.
|
|
12517
12486
|
*/
|
|
12518
12487
|
hasPreimage(serviceId, hash) {
|
|
12519
|
-
const
|
|
12488
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
12489
|
+
const providedPreimage = preimages.find(
|
|
12520
12490
|
// we ignore the action here, since if there is <any> update on that
|
|
12521
12491
|
// hash it means it has to exist, right?
|
|
12522
|
-
(p) => p.
|
|
12492
|
+
(p) => p.hash.isEqualTo(hash));
|
|
12523
12493
|
if (providedPreimage !== undefined) {
|
|
12524
12494
|
return true;
|
|
12525
12495
|
}
|
|
@@ -12532,7 +12502,8 @@ class PartiallyUpdatedState {
|
|
|
12532
12502
|
}
|
|
12533
12503
|
getPreimage(serviceId, hash) {
|
|
12534
12504
|
// TODO [ToDr] Should we verify availability here?
|
|
12535
|
-
const
|
|
12505
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
12506
|
+
const freshlyProvided = preimages.find((x) => x.hash.isEqualTo(hash));
|
|
12536
12507
|
if (freshlyProvided !== undefined && freshlyProvided.action.kind === UpdatePreimageKind.Provide) {
|
|
12537
12508
|
return freshlyProvided.action.preimage.blob;
|
|
12538
12509
|
}
|
|
@@ -12541,10 +12512,11 @@ class PartiallyUpdatedState {
|
|
|
12541
12512
|
}
|
|
12542
12513
|
/** Get status of a preimage of current service taking into account any updates. */
|
|
12543
12514
|
getLookupHistory(currentTimeslot, serviceId, hash, length) {
|
|
12515
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
12544
12516
|
// TODO [ToDr] This is most likely wrong. We may have `provide` and `remove` within
|
|
12545
12517
|
// the same state update. We should however switch to proper "updated state"
|
|
12546
12518
|
// representation soon.
|
|
12547
|
-
const updatedPreimage =
|
|
12519
|
+
const updatedPreimage = preimages.findLast((update) => update.hash.isEqualTo(hash) && BigInt(update.length) === length);
|
|
12548
12520
|
const stateFallback = () => {
|
|
12549
12521
|
// fallback to state lookup
|
|
12550
12522
|
const service = this.state.getService(serviceId);
|
|
@@ -12581,14 +12553,15 @@ class PartiallyUpdatedState {
|
|
|
12581
12553
|
/* State update functions. */
|
|
12582
12554
|
updateStorage(serviceId, key, value) {
|
|
12583
12555
|
const update = value === null
|
|
12584
|
-
? UpdateStorage.remove({
|
|
12556
|
+
? UpdateStorage.remove({ key })
|
|
12585
12557
|
: UpdateStorage.set({
|
|
12586
|
-
serviceId,
|
|
12587
12558
|
storage: StorageItem.create({ key, value }),
|
|
12588
12559
|
});
|
|
12589
|
-
const
|
|
12560
|
+
const storages = this.stateUpdate.services.storage.get(serviceId) ?? [];
|
|
12561
|
+
const index = storages.findIndex((x) => x.key.isEqualTo(key));
|
|
12590
12562
|
const count = index === -1 ? 0 : 1;
|
|
12591
|
-
|
|
12563
|
+
storages.splice(index, count, update);
|
|
12564
|
+
this.stateUpdate.services.storage.set(serviceId, storages);
|
|
12592
12565
|
}
|
|
12593
12566
|
/**
|
|
12594
12567
|
* Update a preimage.
|
|
@@ -12596,8 +12569,10 @@ class PartiallyUpdatedState {
|
|
|
12596
12569
|
* Note we store all previous entries as well, since there might be a sequence of:
|
|
12597
12570
|
* `provide` -> `remove` and both should update the end state somehow.
|
|
12598
12571
|
*/
|
|
12599
|
-
updatePreimage(newUpdate) {
|
|
12600
|
-
this.stateUpdate.services.preimages.
|
|
12572
|
+
updatePreimage(serviceId, newUpdate) {
|
|
12573
|
+
const updatePreimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
12574
|
+
updatePreimages.push(newUpdate);
|
|
12575
|
+
this.stateUpdate.services.preimages.set(serviceId, updatePreimages);
|
|
12601
12576
|
}
|
|
12602
12577
|
updateServiceStorageUtilisation(serviceId, items, bytes, serviceInfo) {
|
|
12603
12578
|
check `${items >= 0} storageUtilisationCount has to be a positive number, got: ${items}`;
|
|
@@ -12606,11 +12581,11 @@ class PartiallyUpdatedState {
|
|
|
12606
12581
|
const overflowBytes = !isU64(bytes);
|
|
12607
12582
|
// TODO [ToDr] this is not specified in GP, but it seems sensible.
|
|
12608
12583
|
if (overflowItems || overflowBytes) {
|
|
12609
|
-
return Result$1.error(InsufficientFundsError);
|
|
12584
|
+
return Result$1.error(InsufficientFundsError, () => `Storage utilisation overflow: items=${overflowItems}, bytes=${overflowBytes}`);
|
|
12610
12585
|
}
|
|
12611
12586
|
const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(items, bytes, serviceInfo.gratisStorage);
|
|
12612
12587
|
if (serviceInfo.balance < thresholdBalance) {
|
|
12613
|
-
return Result$1.error(InsufficientFundsError);
|
|
12588
|
+
return Result$1.error(InsufficientFundsError, () => `Service balance (${serviceInfo.balance}) below threshold (${thresholdBalance})`);
|
|
12614
12589
|
}
|
|
12615
12590
|
// Update service info with new details.
|
|
12616
12591
|
this.updateServiceInfo(serviceId, ServiceAccountInfo.create({
|
|
@@ -12621,22 +12596,25 @@ class PartiallyUpdatedState {
|
|
|
12621
12596
|
return Result$1.ok(OK);
|
|
12622
12597
|
}
|
|
12623
12598
|
updateServiceInfo(serviceId, newInfo) {
|
|
12624
|
-
const
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
if (existingItem?.action.kind === UpdateServiceKind.Create) {
|
|
12628
|
-
this.stateUpdate.services.servicesUpdates.splice(idx, toRemove, UpdateService.create({
|
|
12629
|
-
serviceId,
|
|
12599
|
+
const existingUpdate = this.stateUpdate.services.updated.get(serviceId);
|
|
12600
|
+
if (existingUpdate?.action.kind === UpdateServiceKind.Create) {
|
|
12601
|
+
this.stateUpdate.services.updated.set(serviceId, UpdateService.create({
|
|
12630
12602
|
serviceInfo: newInfo,
|
|
12631
|
-
lookupHistory:
|
|
12603
|
+
lookupHistory: existingUpdate.action.lookupHistory,
|
|
12632
12604
|
}));
|
|
12633
12605
|
return;
|
|
12634
12606
|
}
|
|
12635
|
-
this.stateUpdate.services.
|
|
12636
|
-
serviceId,
|
|
12607
|
+
this.stateUpdate.services.updated.set(serviceId, UpdateService.update({
|
|
12637
12608
|
serviceInfo: newInfo,
|
|
12638
12609
|
}));
|
|
12639
12610
|
}
|
|
12611
|
+
createService(serviceId, newInfo, newLookupHistory) {
|
|
12612
|
+
this.stateUpdate.services.created.push(serviceId);
|
|
12613
|
+
this.stateUpdate.services.updated.set(serviceId, UpdateService.create({
|
|
12614
|
+
serviceInfo: newInfo,
|
|
12615
|
+
lookupHistory: newLookupHistory,
|
|
12616
|
+
}));
|
|
12617
|
+
}
|
|
12640
12618
|
getPrivilegedServices() {
|
|
12641
12619
|
if (this.stateUpdate.privilegedServices !== null) {
|
|
12642
12620
|
return this.stateUpdate.privilegedServices;
|
|
@@ -14255,7 +14233,7 @@ class ReadablePage extends MemoryPage {
|
|
|
14255
14233
|
loadInto(result, startIndex, length) {
|
|
14256
14234
|
const endIndex = startIndex + length;
|
|
14257
14235
|
if (endIndex > PAGE_SIZE$1) {
|
|
14258
|
-
return Result$1.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE$1));
|
|
14236
|
+
return Result$1.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE$1), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE$1}`);
|
|
14259
14237
|
}
|
|
14260
14238
|
const bytes = this.data.subarray(startIndex, endIndex);
|
|
14261
14239
|
// we zero the bytes, since data might not yet be initialized at `endIndex`.
|
|
@@ -14264,7 +14242,7 @@ class ReadablePage extends MemoryPage {
|
|
|
14264
14242
|
return Result$1.ok(OK);
|
|
14265
14243
|
}
|
|
14266
14244
|
storeFrom(_address, _data) {
|
|
14267
|
-
return Result$1.error(PageFault.fromMemoryIndex(this.start, true));
|
|
14245
|
+
return Result$1.error(PageFault.fromMemoryIndex(this.start, true), () => `Page fault: attempted to write to read-only page at ${this.start}`);
|
|
14268
14246
|
}
|
|
14269
14247
|
setData(pageIndex, data) {
|
|
14270
14248
|
this.data.set(data, pageIndex);
|
|
@@ -14293,7 +14271,7 @@ class WriteablePage extends MemoryPage {
|
|
|
14293
14271
|
loadInto(result, startIndex, length) {
|
|
14294
14272
|
const endIndex = startIndex + length;
|
|
14295
14273
|
if (endIndex > PAGE_SIZE$1) {
|
|
14296
|
-
return Result$1.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE$1));
|
|
14274
|
+
return Result$1.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE$1), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE$1}`);
|
|
14297
14275
|
}
|
|
14298
14276
|
const bytes = this.view.subarray(startIndex, endIndex);
|
|
14299
14277
|
// we zero the bytes, since the view might not yet be initialized at `endIndex`.
|
|
@@ -14363,7 +14341,7 @@ class Memory {
|
|
|
14363
14341
|
logger$3.insane `MEM[${address}] <- ${BytesBlob.blobFrom(bytes)}`;
|
|
14364
14342
|
const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
|
|
14365
14343
|
if (pagesResult.isError) {
|
|
14366
|
-
return Result$1.error(pagesResult.error);
|
|
14344
|
+
return Result$1.error(pagesResult.error, pagesResult.details);
|
|
14367
14345
|
}
|
|
14368
14346
|
const pages = pagesResult.ok;
|
|
14369
14347
|
let currentPosition = address;
|
|
@@ -14388,14 +14366,14 @@ class Memory {
|
|
|
14388
14366
|
const pages = [];
|
|
14389
14367
|
for (const pageNumber of pageRange) {
|
|
14390
14368
|
if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
|
|
14391
|
-
return Result$1.error(PageFault.fromPageNumber(pageNumber, true));
|
|
14369
|
+
return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
|
|
14392
14370
|
}
|
|
14393
14371
|
const page = this.memory.get(pageNumber);
|
|
14394
14372
|
if (page === undefined) {
|
|
14395
|
-
return Result$1.error(PageFault.fromPageNumber(pageNumber));
|
|
14373
|
+
return Result$1.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
|
|
14396
14374
|
}
|
|
14397
14375
|
if (accessType === AccessType.WRITE && !page.isWriteable()) {
|
|
14398
|
-
return Result$1.error(PageFault.fromPageNumber(pageNumber, true));
|
|
14376
|
+
return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
|
|
14399
14377
|
}
|
|
14400
14378
|
pages.push(page);
|
|
14401
14379
|
}
|
|
@@ -14413,7 +14391,7 @@ class Memory {
|
|
|
14413
14391
|
}
|
|
14414
14392
|
const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
|
|
14415
14393
|
if (pagesResult.isError) {
|
|
14416
|
-
return Result$1.error(pagesResult.error);
|
|
14394
|
+
return Result$1.error(pagesResult.error, pagesResult.details);
|
|
14417
14395
|
}
|
|
14418
14396
|
const pages = pagesResult.ok;
|
|
14419
14397
|
let currentPosition = startAddress;
|
|
@@ -16218,7 +16196,7 @@ class ProgramDecoder {
|
|
|
16218
16196
|
}
|
|
16219
16197
|
catch (e) {
|
|
16220
16198
|
logger$2.error `Invalid program: ${e}`;
|
|
16221
|
-
return Result$1.error(ProgramDecoderError.InvalidProgramError);
|
|
16199
|
+
return Result$1.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
|
|
16222
16200
|
}
|
|
16223
16201
|
}
|
|
16224
16202
|
}
|
|
@@ -16499,7 +16477,7 @@ class HostCallMemory {
|
|
|
16499
16477
|
return Result$1.ok(OK);
|
|
16500
16478
|
}
|
|
16501
16479
|
if (address + tryAsU64(bytes.length) > MEMORY_SIZE) {
|
|
16502
|
-
return Result$1.error(new OutOfBounds());
|
|
16480
|
+
return Result$1.error(new OutOfBounds(), () => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`);
|
|
16503
16481
|
}
|
|
16504
16482
|
return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
|
|
16505
16483
|
}
|
|
@@ -16508,13 +16486,10 @@ class HostCallMemory {
|
|
|
16508
16486
|
return Result$1.ok(OK);
|
|
16509
16487
|
}
|
|
16510
16488
|
if (startAddress + tryAsU64(result.length) > MEMORY_SIZE) {
|
|
16511
|
-
return Result$1.error(new OutOfBounds());
|
|
16489
|
+
return Result$1.error(new OutOfBounds(), () => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`);
|
|
16512
16490
|
}
|
|
16513
16491
|
return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
|
|
16514
16492
|
}
|
|
16515
|
-
getMemory() {
|
|
16516
|
-
return this.memory;
|
|
16517
|
-
}
|
|
16518
16493
|
}
|
|
16519
16494
|
|
|
16520
16495
|
class HostCallRegisters {
|
|
@@ -17602,32 +17577,33 @@ class Preimages {
|
|
|
17602
17577
|
}
|
|
17603
17578
|
if (prevPreimage.requester > currPreimage.requester ||
|
|
17604
17579
|
currPreimage.blob.compare(prevPreimage.blob).isLessOrEqual()) {
|
|
17605
|
-
return Result$1.error(PreimagesErrorCode.PreimagesNotSortedUnique);
|
|
17580
|
+
return Result$1.error(PreimagesErrorCode.PreimagesNotSortedUnique, () => `Preimages not sorted/unique at index ${i}`);
|
|
17606
17581
|
}
|
|
17607
17582
|
}
|
|
17608
17583
|
const { preimages, slot } = input;
|
|
17609
|
-
const pendingChanges =
|
|
17584
|
+
const pendingChanges = new Map();
|
|
17610
17585
|
// select preimages for integration
|
|
17611
17586
|
for (const preimage of preimages) {
|
|
17612
17587
|
const { requester, blob } = preimage;
|
|
17613
17588
|
const hash = this.blake2b.hashBytes(blob).asOpaque();
|
|
17614
17589
|
const service = this.state.getService(requester);
|
|
17615
17590
|
if (service === null) {
|
|
17616
|
-
return Result$1.error(PreimagesErrorCode.AccountNotFound);
|
|
17591
|
+
return Result$1.error(PreimagesErrorCode.AccountNotFound, () => `Service not found: ${requester}`);
|
|
17617
17592
|
}
|
|
17618
17593
|
const hasPreimage = service.hasPreimage(hash);
|
|
17619
17594
|
const slots = service.getLookupHistory(hash, tryAsU32(blob.length));
|
|
17620
17595
|
// https://graypaper.fluffylabs.dev/#/5f542d7/181800181900
|
|
17621
17596
|
// https://graypaper.fluffylabs.dev/#/5f542d7/116f0011a500
|
|
17622
17597
|
if (hasPreimage || slots === null || !LookupHistoryItem.isRequested(slots)) {
|
|
17623
|
-
return Result$1.error(PreimagesErrorCode.PreimageUnneeded);
|
|
17598
|
+
return Result$1.error(PreimagesErrorCode.PreimageUnneeded, () => `Preimage unneeded: requester=${requester}, hash=${hash}, hasPreimage=${hasPreimage}, isRequested=${slots !== null && LookupHistoryItem.isRequested(slots)}`);
|
|
17624
17599
|
}
|
|
17625
17600
|
// https://graypaper.fluffylabs.dev/#/5f542d7/18c00018f300
|
|
17626
|
-
pendingChanges.
|
|
17627
|
-
|
|
17601
|
+
const updates = pendingChanges.get(requester) ?? [];
|
|
17602
|
+
updates.push(UpdatePreimage.provide({
|
|
17628
17603
|
preimage: PreimageItem.create({ hash, blob }),
|
|
17629
17604
|
slot,
|
|
17630
17605
|
}));
|
|
17606
|
+
pendingChanges.set(requester, updates);
|
|
17631
17607
|
}
|
|
17632
17608
|
return Result$1.ok({
|
|
17633
17609
|
preimages: pendingChanges,
|