@typeberry/lib 0.2.0-e767e74 → 0.2.0-f506473
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 +252 -209
- package/index.d.ts +1025 -957
- package/index.js +252 -209
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -322,7 +322,7 @@ type ErrorResult<Error> = {
|
|
|
322
322
|
isOk: false;
|
|
323
323
|
isError: true;
|
|
324
324
|
error: Error;
|
|
325
|
-
details: string;
|
|
325
|
+
details: () => string;
|
|
326
326
|
};
|
|
327
327
|
|
|
328
328
|
/**
|
|
@@ -383,7 +383,7 @@ declare function resultToString<Ok, Error>(res: Result$2<Ok, Error>) {
|
|
|
383
383
|
if (res.isOk) {
|
|
384
384
|
return `OK: ${typeof res.ok === "symbol" ? res.ok.toString() : res.ok}`;
|
|
385
385
|
}
|
|
386
|
-
return `${res.details}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
386
|
+
return `${res.details()}\nError: ${maybeTaggedErrorToString(res.error)}`;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
/** An indication of two possible outcomes returned from a function. */
|
|
@@ -402,7 +402,7 @@ declare const Result$2 = {
|
|
|
402
402
|
},
|
|
403
403
|
|
|
404
404
|
/** Create new [`Result`] with `Error` status. */
|
|
405
|
-
error: <Error>(error: Error, details
|
|
405
|
+
error: <Error>(error: Error, details: () => string): ErrorResult<Error> => {
|
|
406
406
|
check`${error !== undefined} 'Error' type cannot be undefined.`;
|
|
407
407
|
return {
|
|
408
408
|
isOk: false,
|
|
@@ -556,7 +556,7 @@ declare function deepEqual<T>(
|
|
|
556
556
|
|
|
557
557
|
if (actual.isError && expected.isError) {
|
|
558
558
|
deepEqual(actual.error, expected.error, { context: ctx.concat(["error"]), errorsCollector: errors, ignore });
|
|
559
|
-
deepEqual(actual.details, expected.details, {
|
|
559
|
+
deepEqual(actual.details(), expected.details(), {
|
|
560
560
|
context: ctx.concat(["details"]),
|
|
561
561
|
errorsCollector: errors,
|
|
562
562
|
// display details when error does not match
|
|
@@ -1467,8 +1467,8 @@ declare class Decoder {
|
|
|
1467
1467
|
/**
|
|
1468
1468
|
* Create a new [`Decoder`] instance given a raw array of bytes as a source.
|
|
1469
1469
|
*/
|
|
1470
|
-
static fromBlob(source: Uint8Array) {
|
|
1471
|
-
return new Decoder(source);
|
|
1470
|
+
static fromBlob(source: Uint8Array, context?: unknown) {
|
|
1471
|
+
return new Decoder(source, undefined, context);
|
|
1472
1472
|
}
|
|
1473
1473
|
|
|
1474
1474
|
/**
|
|
@@ -1818,7 +1818,7 @@ declare class Decoder {
|
|
|
1818
1818
|
private ensureHasBytes(bytes: number) {
|
|
1819
1819
|
check`${bytes >= 0} Negative number of bytes given.`;
|
|
1820
1820
|
if (this.offset + bytes > this.source.length) {
|
|
1821
|
-
throw new
|
|
1821
|
+
throw new EndOfDataError(
|
|
1822
1822
|
`Attempting to decode more data than there is left. Need ${bytes}, left: ${this.source.length - this.offset}.`,
|
|
1823
1823
|
);
|
|
1824
1824
|
}
|
|
@@ -1837,6 +1837,8 @@ declare function decodeVariableLengthExtraBytes(firstByte: number) {
|
|
|
1837
1837
|
return 0;
|
|
1838
1838
|
}
|
|
1839
1839
|
|
|
1840
|
+
declare class EndOfDataError extends Error {}
|
|
1841
|
+
|
|
1840
1842
|
/** Hint for how big the encoded object will be. */
|
|
1841
1843
|
type SizeHint = {
|
|
1842
1844
|
/** Number of bytes in the encoding. */
|
|
@@ -3346,6 +3348,9 @@ declare function forEachDescriptor<T>(
|
|
|
3346
3348
|
try {
|
|
3347
3349
|
f(k, descriptors[k]);
|
|
3348
3350
|
} catch (e) {
|
|
3351
|
+
if (e instanceof EndOfDataError) {
|
|
3352
|
+
throw new EndOfDataError(`${key}: ${e}`);
|
|
3353
|
+
}
|
|
3349
3354
|
throw new Error(`${key}: ${e}`);
|
|
3350
3355
|
}
|
|
3351
3356
|
}
|
|
@@ -3469,6 +3474,8 @@ type index$q_DescriptorRecord<T> = DescriptorRecord<T>;
|
|
|
3469
3474
|
type index$q_Encode<T> = Encode<T>;
|
|
3470
3475
|
type index$q_Encoder = Encoder;
|
|
3471
3476
|
declare const index$q_Encoder: typeof Encoder;
|
|
3477
|
+
type index$q_EndOfDataError = EndOfDataError;
|
|
3478
|
+
declare const index$q_EndOfDataError: typeof EndOfDataError;
|
|
3472
3479
|
type index$q_LengthRange = LengthRange;
|
|
3473
3480
|
declare const index$q_MASKS: typeof MASKS;
|
|
3474
3481
|
declare const index$q_MAX_LENGTH: typeof MAX_LENGTH;
|
|
@@ -3497,7 +3504,7 @@ declare const index$q_sequenceViewVarLen: typeof sequenceViewVarLen;
|
|
|
3497
3504
|
declare const index$q_tryAsExactBytes: typeof tryAsExactBytes;
|
|
3498
3505
|
declare const index$q_validateLength: typeof validateLength;
|
|
3499
3506
|
declare namespace index$q {
|
|
3500
|
-
export { index$q_DEFAULT_START_LENGTH as DEFAULT_START_LENGTH, index$q_Decoder as Decoder, index$q_Descriptor as Descriptor, index$q_Encoder as Encoder, index$q_MASKS as MASKS, index$q_MAX_LENGTH as MAX_LENGTH, index$q_ObjectView as ObjectView, index$q_SequenceView as SequenceView, index$q_TYPICAL_DICTIONARY_LENGTH as TYPICAL_DICTIONARY_LENGTH, index$q_TYPICAL_SEQUENCE_LENGTH as TYPICAL_SEQUENCE_LENGTH, index$q_ViewField as ViewField, index$q_addSizeHints as addSizeHints, codec$1 as codec, index$q_decodeVariableLengthExtraBytes as decodeVariableLengthExtraBytes, index$q_exactHint as exactHint, index$q_forEachDescriptor as forEachDescriptor, index$q_hasUniqueView as hasUniqueView, index$q_objectView as objectView, index$q_readonlyArray as readonlyArray, index$q_sequenceViewFixLen as sequenceViewFixLen, index$q_sequenceViewVarLen as sequenceViewVarLen, index$q_tryAsExactBytes as tryAsExactBytes, index$q_validateLength as validateLength };
|
|
3507
|
+
export { index$q_DEFAULT_START_LENGTH as DEFAULT_START_LENGTH, index$q_Decoder as Decoder, index$q_Descriptor as Descriptor, index$q_Encoder as Encoder, index$q_EndOfDataError as EndOfDataError, index$q_MASKS as MASKS, index$q_MAX_LENGTH as MAX_LENGTH, index$q_ObjectView as ObjectView, index$q_SequenceView as SequenceView, index$q_TYPICAL_DICTIONARY_LENGTH as TYPICAL_DICTIONARY_LENGTH, index$q_TYPICAL_SEQUENCE_LENGTH as TYPICAL_SEQUENCE_LENGTH, index$q_ViewField as ViewField, index$q_addSizeHints as addSizeHints, codec$1 as codec, index$q_decodeVariableLengthExtraBytes as decodeVariableLengthExtraBytes, index$q_exactHint as exactHint, index$q_forEachDescriptor as forEachDescriptor, index$q_hasUniqueView as hasUniqueView, index$q_objectView as objectView, index$q_readonlyArray as readonlyArray, index$q_sequenceViewFixLen as sequenceViewFixLen, index$q_sequenceViewVarLen as sequenceViewVarLen, index$q_tryAsExactBytes as tryAsExactBytes, index$q_validateLength as validateLength };
|
|
3501
3508
|
export type { index$q_ClassConstructor as ClassConstructor, index$q_Codec as Codec, index$q_CodecRecord as CodecRecord, index$q_CodecWithView as CodecWithView, index$q_Decode as Decode, index$q_DescribedBy as DescribedBy, index$q_DescriptorRecord as DescriptorRecord, index$q_Encode as Encode, index$q_LengthRange as LengthRange, index$q_OptionalRecord as OptionalRecord, Options$1 as Options, index$q_PropertyKeys as PropertyKeys, index$q_SimpleDescriptorRecord as SimpleDescriptorRecord, index$q_SizeHint as SizeHint, index$q_ViewOf as ViewOf };
|
|
3502
3509
|
}
|
|
3503
3510
|
|
|
@@ -10659,7 +10666,6 @@ declare enum UpdatePreimageKind {
|
|
|
10659
10666
|
*/
|
|
10660
10667
|
declare class UpdatePreimage {
|
|
10661
10668
|
private constructor(
|
|
10662
|
-
public readonly serviceId: ServiceId,
|
|
10663
10669
|
public readonly action:
|
|
10664
10670
|
| {
|
|
10665
10671
|
kind: UpdatePreimageKind.Provide;
|
|
@@ -10679,16 +10685,8 @@ declare class UpdatePreimage {
|
|
|
10679
10685
|
) {}
|
|
10680
10686
|
|
|
10681
10687
|
/** A preimage is provided. We should update the lookuphistory and add the preimage to db. */
|
|
10682
|
-
static provide({
|
|
10683
|
-
|
|
10684
|
-
preimage,
|
|
10685
|
-
slot,
|
|
10686
|
-
}: {
|
|
10687
|
-
serviceId: ServiceId;
|
|
10688
|
-
preimage: PreimageItem;
|
|
10689
|
-
slot: TimeSlot | null;
|
|
10690
|
-
}) {
|
|
10691
|
-
return new UpdatePreimage(serviceId, {
|
|
10688
|
+
static provide({ preimage, slot }: { preimage: PreimageItem; slot: TimeSlot | null }) {
|
|
10689
|
+
return new UpdatePreimage({
|
|
10692
10690
|
kind: UpdatePreimageKind.Provide,
|
|
10693
10691
|
preimage,
|
|
10694
10692
|
slot,
|
|
@@ -10696,8 +10694,8 @@ declare class UpdatePreimage {
|
|
|
10696
10694
|
}
|
|
10697
10695
|
|
|
10698
10696
|
/** The preimage should be removed completely from the database. */
|
|
10699
|
-
static remove({
|
|
10700
|
-
return new UpdatePreimage(
|
|
10697
|
+
static remove({ hash, length }: { hash: PreimageHash; length: U32 }) {
|
|
10698
|
+
return new UpdatePreimage({
|
|
10701
10699
|
kind: UpdatePreimageKind.Remove,
|
|
10702
10700
|
hash,
|
|
10703
10701
|
length,
|
|
@@ -10705,8 +10703,8 @@ declare class UpdatePreimage {
|
|
|
10705
10703
|
}
|
|
10706
10704
|
|
|
10707
10705
|
/** Update the lookup history of some preimage or add a new one (request). */
|
|
10708
|
-
static updateOrAdd({
|
|
10709
|
-
return new UpdatePreimage(
|
|
10706
|
+
static updateOrAdd({ lookupHistory }: { lookupHistory: LookupHistoryItem }) {
|
|
10707
|
+
return new UpdatePreimage({
|
|
10710
10708
|
kind: UpdatePreimageKind.UpdateOrAdd,
|
|
10711
10709
|
item: lookupHistory,
|
|
10712
10710
|
});
|
|
@@ -10744,12 +10742,12 @@ declare enum UpdateServiceKind {
|
|
|
10744
10742
|
/** Create a new `Service` instance. */
|
|
10745
10743
|
Create = 1,
|
|
10746
10744
|
}
|
|
10745
|
+
|
|
10747
10746
|
/**
|
|
10748
|
-
* Update service info
|
|
10747
|
+
* Update service info or create a new one.
|
|
10749
10748
|
*/
|
|
10750
10749
|
declare class UpdateService {
|
|
10751
10750
|
private constructor(
|
|
10752
|
-
public readonly serviceId: ServiceId,
|
|
10753
10751
|
public readonly action:
|
|
10754
10752
|
| {
|
|
10755
10753
|
kind: UpdateServiceKind.Update;
|
|
@@ -10762,23 +10760,21 @@ declare class UpdateService {
|
|
|
10762
10760
|
},
|
|
10763
10761
|
) {}
|
|
10764
10762
|
|
|
10765
|
-
static update({
|
|
10766
|
-
return new UpdateService(
|
|
10763
|
+
static update({ serviceInfo }: { serviceInfo: ServiceAccountInfo }) {
|
|
10764
|
+
return new UpdateService({
|
|
10767
10765
|
kind: UpdateServiceKind.Update,
|
|
10768
10766
|
account: serviceInfo,
|
|
10769
10767
|
});
|
|
10770
10768
|
}
|
|
10771
10769
|
|
|
10772
10770
|
static create({
|
|
10773
|
-
serviceId,
|
|
10774
10771
|
serviceInfo,
|
|
10775
10772
|
lookupHistory,
|
|
10776
10773
|
}: {
|
|
10777
|
-
serviceId: ServiceId;
|
|
10778
10774
|
serviceInfo: ServiceAccountInfo;
|
|
10779
10775
|
lookupHistory: LookupHistoryItem | null;
|
|
10780
10776
|
}) {
|
|
10781
|
-
return new UpdateService(
|
|
10777
|
+
return new UpdateService({
|
|
10782
10778
|
kind: UpdateServiceKind.Create,
|
|
10783
10779
|
account: serviceInfo,
|
|
10784
10780
|
lookupHistory,
|
|
@@ -10800,7 +10796,6 @@ declare enum UpdateStorageKind {
|
|
|
10800
10796
|
*/
|
|
10801
10797
|
declare class UpdateStorage {
|
|
10802
10798
|
private constructor(
|
|
10803
|
-
public readonly serviceId: ServiceId,
|
|
10804
10799
|
public readonly action:
|
|
10805
10800
|
| {
|
|
10806
10801
|
kind: UpdateStorageKind.Set;
|
|
@@ -10812,12 +10807,12 @@ declare class UpdateStorage {
|
|
|
10812
10807
|
},
|
|
10813
10808
|
) {}
|
|
10814
10809
|
|
|
10815
|
-
static set({
|
|
10816
|
-
return new UpdateStorage(
|
|
10810
|
+
static set({ storage }: { storage: StorageItem }) {
|
|
10811
|
+
return new UpdateStorage({ kind: UpdateStorageKind.Set, storage });
|
|
10817
10812
|
}
|
|
10818
10813
|
|
|
10819
|
-
static remove({
|
|
10820
|
-
return new UpdateStorage(
|
|
10814
|
+
static remove({ key }: { key: StorageKey }) {
|
|
10815
|
+
return new UpdateStorage({ kind: UpdateStorageKind.Remove, key });
|
|
10821
10816
|
}
|
|
10822
10817
|
|
|
10823
10818
|
get key() {
|
|
@@ -10835,16 +10830,17 @@ declare class UpdateStorage {
|
|
|
10835
10830
|
}
|
|
10836
10831
|
}
|
|
10837
10832
|
|
|
10838
|
-
// TODO [ToDr] This would be more convenient to use if the data was grouped by `ServiceId`.
|
|
10839
10833
|
type ServicesUpdate = {
|
|
10840
10834
|
/** Service ids to remove from state alongside all their data. */
|
|
10841
|
-
|
|
10842
|
-
/** Services
|
|
10843
|
-
|
|
10835
|
+
removed: ServiceId[];
|
|
10836
|
+
/** Services newly created. */
|
|
10837
|
+
created: ServiceId[];
|
|
10838
|
+
/** Services to update. */
|
|
10839
|
+
updated: Map<ServiceId, UpdateService>;
|
|
10844
10840
|
/** Service preimages to update and potentially lookup history */
|
|
10845
|
-
preimages: UpdatePreimage[]
|
|
10841
|
+
preimages: Map<ServiceId, UpdatePreimage[]>;
|
|
10846
10842
|
/** Service storage to update. */
|
|
10847
|
-
storage: UpdateStorage[]
|
|
10843
|
+
storage: Map<ServiceId, UpdateStorage[]>;
|
|
10848
10844
|
};
|
|
10849
10845
|
|
|
10850
10846
|
declare enum UpdateError {
|
|
@@ -11040,13 +11036,13 @@ declare class InMemoryState extends WithDebug implements State, WithStateView, E
|
|
|
11040
11036
|
* Modify the state and apply a single state update.
|
|
11041
11037
|
*/
|
|
11042
11038
|
applyUpdate(update: Partial<State & ServicesUpdate>): Result$2<OK, UpdateError> {
|
|
11043
|
-
const {
|
|
11039
|
+
const { removed, created: _, updated, preimages, storage, ...rest } = update;
|
|
11044
11040
|
// just assign all other variables
|
|
11045
11041
|
Object.assign(this, rest);
|
|
11046
11042
|
|
|
11047
11043
|
// and update the services state
|
|
11048
11044
|
let result: Result<OK, UpdateError>;
|
|
11049
|
-
result = this.updateServices(
|
|
11045
|
+
result = this.updateServices(updated);
|
|
11050
11046
|
if (result.isError) {
|
|
11051
11047
|
return result;
|
|
11052
11048
|
}
|
|
@@ -11058,7 +11054,7 @@ declare class InMemoryState extends WithDebug implements State, WithStateView, E
|
|
|
11058
11054
|
if (result.isError) {
|
|
11059
11055
|
return result;
|
|
11060
11056
|
}
|
|
11061
|
-
this.removeServices(
|
|
11057
|
+
this.removeServices(removed);
|
|
11062
11058
|
|
|
11063
11059
|
return Result.ok(OK);
|
|
11064
11060
|
}
|
|
@@ -11070,93 +11066,108 @@ declare class InMemoryState extends WithDebug implements State, WithStateView, E
|
|
|
11070
11066
|
}
|
|
11071
11067
|
}
|
|
11072
11068
|
|
|
11073
|
-
private updateStorage(
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
)
|
|
11082
|
-
|
|
11069
|
+
private updateStorage(storageUpdates: Map<ServiceId, UpdateStorage[]> | undefined): Result$2<OK, UpdateError> {
|
|
11070
|
+
if (storageUpdates === undefined) {
|
|
11071
|
+
return Result.ok(OK);
|
|
11072
|
+
}
|
|
11073
|
+
for (const [serviceId, updates] of storageUpdates.entries()) {
|
|
11074
|
+
for (const update of updates) {
|
|
11075
|
+
const { kind } = update.action;
|
|
11076
|
+
const service = this.services.get(serviceId);
|
|
11077
|
+
if (service === undefined) {
|
|
11078
|
+
return Result.error(
|
|
11079
|
+
UpdateError.NoService,
|
|
11080
|
+
() => `Attempting to update storage of non-existing service: ${serviceId}`,
|
|
11081
|
+
);
|
|
11082
|
+
}
|
|
11083
11083
|
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11084
|
+
if (kind === UpdateStorageKind.Set) {
|
|
11085
|
+
const { key, value } = update.action.storage;
|
|
11086
|
+
service.data.storage.set(key.toString(), StorageItem.create({ key, value }));
|
|
11087
|
+
} else if (kind === UpdateStorageKind.Remove) {
|
|
11088
|
+
const { key } = update.action;
|
|
11089
|
+
check`
|
|
11090
11090
|
${service.data.storage.has(key.toString())}
|
|
11091
|
-
Attempting to remove non-existing storage item at ${serviceId}: ${action.key}
|
|
11091
|
+
Attempting to remove non-existing storage item at ${serviceId}: ${update.action.key}
|
|
11092
11092
|
`;
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11093
|
+
service.data.storage.delete(key.toString());
|
|
11094
|
+
} else {
|
|
11095
|
+
assertNever(kind);
|
|
11096
|
+
}
|
|
11096
11097
|
}
|
|
11097
11098
|
}
|
|
11098
|
-
|
|
11099
11099
|
return Result.ok(OK);
|
|
11100
11100
|
}
|
|
11101
11101
|
|
|
11102
|
-
private updatePreimages(
|
|
11103
|
-
|
|
11102
|
+
private updatePreimages(preimagesUpdates: Map<ServiceId, UpdatePreimage[]> | undefined): Result$2<OK, UpdateError> {
|
|
11103
|
+
if (preimagesUpdates === undefined) {
|
|
11104
|
+
return Result.ok(OK);
|
|
11105
|
+
}
|
|
11106
|
+
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
11104
11107
|
const service = this.services.get(serviceId);
|
|
11105
11108
|
if (service === undefined) {
|
|
11106
11109
|
return Result.error(
|
|
11107
11110
|
UpdateError.NoService,
|
|
11108
|
-
`Attempting to update preimage of non-existing service: ${serviceId}`,
|
|
11111
|
+
() => `Attempting to update preimage of non-existing service: ${serviceId}`,
|
|
11109
11112
|
);
|
|
11110
11113
|
}
|
|
11111
|
-
const
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
const length = tryAsU32(preimage.blob.length);
|
|
11121
|
-
const lookup = new LookupHistoryItem(preimage.hash, length, tryAsLookupHistorySlots([slot]));
|
|
11122
|
-
if (lookupHistory === undefined) {
|
|
11123
|
-
// no lookup history for that preimage at all (edge case, should be requested)
|
|
11124
|
-
service.data.lookupHistory.set(preimage.hash, [lookup]);
|
|
11125
|
-
} else {
|
|
11126
|
-
// insert or replace exiting entry
|
|
11127
|
-
const index = lookupHistory.map((x) => x.length).indexOf(length);
|
|
11128
|
-
lookupHistory.splice(index, index === -1 ? 0 : 1, lookup);
|
|
11114
|
+
for (const update of updates) {
|
|
11115
|
+
const { kind } = update.action;
|
|
11116
|
+
if (kind === UpdatePreimageKind.Provide) {
|
|
11117
|
+
const { preimage, slot } = update.action;
|
|
11118
|
+
if (service.data.preimages.has(preimage.hash)) {
|
|
11119
|
+
return Result.error(
|
|
11120
|
+
UpdateError.PreimageExists,
|
|
11121
|
+
() => `Overwriting existing preimage at ${serviceId}: ${preimage}`,
|
|
11122
|
+
);
|
|
11129
11123
|
}
|
|
11124
|
+
service.data.preimages.set(preimage.hash, preimage);
|
|
11125
|
+
if (slot !== null) {
|
|
11126
|
+
const lookupHistory = service.data.lookupHistory.get(preimage.hash);
|
|
11127
|
+
const length = tryAsU32(preimage.blob.length);
|
|
11128
|
+
const lookup = new LookupHistoryItem(preimage.hash, length, tryAsLookupHistorySlots([slot]));
|
|
11129
|
+
if (lookupHistory === undefined) {
|
|
11130
|
+
// no lookup history for that preimage at all (edge case, should be requested)
|
|
11131
|
+
service.data.lookupHistory.set(preimage.hash, [lookup]);
|
|
11132
|
+
} else {
|
|
11133
|
+
// insert or replace exiting entry
|
|
11134
|
+
const index = lookupHistory.map((x) => x.length).indexOf(length);
|
|
11135
|
+
lookupHistory.splice(index, index === -1 ? 0 : 1, lookup);
|
|
11136
|
+
}
|
|
11137
|
+
}
|
|
11138
|
+
} else if (kind === UpdatePreimageKind.Remove) {
|
|
11139
|
+
const { hash, length } = update.action;
|
|
11140
|
+
service.data.preimages.delete(hash);
|
|
11141
|
+
const history = service.data.lookupHistory.get(hash) ?? [];
|
|
11142
|
+
const idx = history.map((x) => x.length).indexOf(length);
|
|
11143
|
+
if (idx !== -1) {
|
|
11144
|
+
history.splice(idx, 1);
|
|
11145
|
+
}
|
|
11146
|
+
} else if (kind === UpdatePreimageKind.UpdateOrAdd) {
|
|
11147
|
+
const { item } = update.action;
|
|
11148
|
+
const history = service.data.lookupHistory.get(item.hash) ?? [];
|
|
11149
|
+
const existingIdx = history.map((x) => x.length).indexOf(item.length);
|
|
11150
|
+
const removeCount = existingIdx === -1 ? 0 : 1;
|
|
11151
|
+
history.splice(existingIdx, removeCount, item);
|
|
11152
|
+
service.data.lookupHistory.set(item.hash, history);
|
|
11153
|
+
} else {
|
|
11154
|
+
assertNever(kind);
|
|
11130
11155
|
}
|
|
11131
|
-
} else if (kind === UpdatePreimageKind.Remove) {
|
|
11132
|
-
const { hash, length } = action;
|
|
11133
|
-
service.data.preimages.delete(hash);
|
|
11134
|
-
const history = service.data.lookupHistory.get(hash) ?? [];
|
|
11135
|
-
const idx = history.map((x) => x.length).indexOf(length);
|
|
11136
|
-
if (idx !== -1) {
|
|
11137
|
-
history.splice(idx, 1);
|
|
11138
|
-
}
|
|
11139
|
-
} else if (kind === UpdatePreimageKind.UpdateOrAdd) {
|
|
11140
|
-
const { item } = action;
|
|
11141
|
-
const history = service.data.lookupHistory.get(item.hash) ?? [];
|
|
11142
|
-
const existingIdx = history.map((x) => x.length).indexOf(item.length);
|
|
11143
|
-
const removeCount = existingIdx === -1 ? 0 : 1;
|
|
11144
|
-
history.splice(existingIdx, removeCount, item);
|
|
11145
|
-
service.data.lookupHistory.set(item.hash, history);
|
|
11146
|
-
} else {
|
|
11147
|
-
assertNever(kind);
|
|
11148
11156
|
}
|
|
11149
11157
|
}
|
|
11150
11158
|
return Result.ok(OK);
|
|
11151
11159
|
}
|
|
11152
11160
|
|
|
11153
|
-
private updateServices(servicesUpdates
|
|
11154
|
-
|
|
11155
|
-
|
|
11161
|
+
private updateServices(servicesUpdates: Map<ServiceId, UpdateService> | undefined): Result$2<OK, UpdateError> {
|
|
11162
|
+
if (servicesUpdates === undefined) {
|
|
11163
|
+
return Result.ok(OK);
|
|
11164
|
+
}
|
|
11165
|
+
for (const [serviceId, update] of servicesUpdates.entries()) {
|
|
11166
|
+
const { kind, account } = update.action;
|
|
11156
11167
|
if (kind === UpdateServiceKind.Create) {
|
|
11157
|
-
const { lookupHistory } = action;
|
|
11168
|
+
const { lookupHistory } = update.action;
|
|
11158
11169
|
if (this.services.has(serviceId)) {
|
|
11159
|
-
return Result.error(UpdateError.DuplicateService, `${serviceId} already exists!`);
|
|
11170
|
+
return Result.error(UpdateError.DuplicateService, () => `${serviceId} already exists!`);
|
|
11160
11171
|
}
|
|
11161
11172
|
this.services.set(
|
|
11162
11173
|
serviceId,
|
|
@@ -11172,7 +11183,7 @@ declare class InMemoryState extends WithDebug implements State, WithStateView, E
|
|
|
11172
11183
|
} else if (kind === UpdateServiceKind.Update) {
|
|
11173
11184
|
const existingService = this.services.get(serviceId);
|
|
11174
11185
|
if (existingService === undefined) {
|
|
11175
|
-
return Result.error(UpdateError.NoService, `Cannot update ${serviceId} because it does not exist.`);
|
|
11186
|
+
return Result.error(UpdateError.NoService, () => `Cannot update ${serviceId} because it does not exist.`);
|
|
11176
11187
|
}
|
|
11177
11188
|
existingService.data.info = account;
|
|
11178
11189
|
} else {
|
|
@@ -11975,89 +11986,104 @@ declare function* serializeStateUpdate(
|
|
|
11975
11986
|
const encode = <T>(codec: Encode<T>, val: T) => Encoder.encodeObject(codec, val, spec);
|
|
11976
11987
|
|
|
11977
11988
|
// then let's proceed with service updates
|
|
11978
|
-
yield* serializeServiceUpdates(update.
|
|
11989
|
+
yield* serializeServiceUpdates(update.updated, encode, blake2b);
|
|
11979
11990
|
yield* serializePreimages(update.preimages, encode, blake2b);
|
|
11980
11991
|
yield* serializeStorage(update.storage, blake2b);
|
|
11981
|
-
yield* serializeRemovedServices(update.
|
|
11992
|
+
yield* serializeRemovedServices(update.removed);
|
|
11982
11993
|
}
|
|
11983
11994
|
|
|
11984
11995
|
declare function* serializeRemovedServices(servicesRemoved: ServiceId[] | undefined): Generator<StateEntryUpdate> {
|
|
11985
|
-
|
|
11996
|
+
if (servicesRemoved === undefined) {
|
|
11997
|
+
return;
|
|
11998
|
+
}
|
|
11999
|
+
for (const serviceId of servicesRemoved) {
|
|
11986
12000
|
// TODO [ToDr] what about all data associated with a service?
|
|
11987
12001
|
const codec = serialize.serviceData(serviceId);
|
|
11988
12002
|
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
11989
12003
|
}
|
|
11990
12004
|
}
|
|
11991
12005
|
|
|
11992
|
-
declare function* serializeStorage(
|
|
11993
|
-
|
|
11994
|
-
|
|
11995
|
-
|
|
11996
|
-
|
|
11997
|
-
|
|
11998
|
-
|
|
11999
|
-
|
|
12000
|
-
|
|
12001
|
-
|
|
12002
|
-
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
12006
|
+
declare function* serializeStorage(
|
|
12007
|
+
storageUpdates: Map<ServiceId, UpdateStorage[]> | undefined,
|
|
12008
|
+
blake2b: Blake2b,
|
|
12009
|
+
): Generator<StateEntryUpdate> {
|
|
12010
|
+
if (storageUpdates === undefined) {
|
|
12011
|
+
return;
|
|
12012
|
+
}
|
|
12013
|
+
for (const [serviceId, updates] of storageUpdates.entries()) {
|
|
12014
|
+
for (const { action } of updates) {
|
|
12015
|
+
switch (action.kind) {
|
|
12016
|
+
case UpdateStorageKind.Set: {
|
|
12017
|
+
const key = action.storage.key;
|
|
12018
|
+
const codec = serialize.serviceStorage(blake2b, serviceId, key);
|
|
12019
|
+
yield [StateEntryUpdateAction.Insert, codec.key, action.storage.value];
|
|
12020
|
+
break;
|
|
12021
|
+
}
|
|
12022
|
+
case UpdateStorageKind.Remove: {
|
|
12023
|
+
const key = action.key;
|
|
12024
|
+
const codec = serialize.serviceStorage(blake2b, serviceId, key);
|
|
12025
|
+
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12026
|
+
break;
|
|
12027
|
+
}
|
|
12006
12028
|
}
|
|
12007
|
-
default:
|
|
12008
|
-
assertNever(action);
|
|
12009
12029
|
}
|
|
12010
12030
|
}
|
|
12011
12031
|
}
|
|
12012
12032
|
|
|
12013
12033
|
declare function* serializePreimages(
|
|
12014
|
-
|
|
12034
|
+
preimagesUpdates: Map<ServiceId, UpdatePreimage[]> | undefined,
|
|
12015
12035
|
encode: EncodeFun,
|
|
12016
12036
|
blake2b: Blake2b,
|
|
12017
12037
|
): Generator<StateEntryUpdate> {
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
const
|
|
12027
|
-
yield [
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12038
|
+
if (preimagesUpdates === undefined) {
|
|
12039
|
+
return;
|
|
12040
|
+
}
|
|
12041
|
+
for (const [serviceId, updates] of preimagesUpdates.entries()) {
|
|
12042
|
+
for (const { action } of updates) {
|
|
12043
|
+
switch (action.kind) {
|
|
12044
|
+
case UpdatePreimageKind.Provide: {
|
|
12045
|
+
const { hash, blob } = action.preimage;
|
|
12046
|
+
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
12047
|
+
yield [StateEntryUpdateAction.Insert, codec.key, blob];
|
|
12048
|
+
|
|
12049
|
+
if (action.slot !== null) {
|
|
12050
|
+
const codec2 = serialize.serviceLookupHistory(blake2b, serviceId, hash, tryAsU32(blob.length));
|
|
12051
|
+
yield [
|
|
12052
|
+
StateEntryUpdateAction.Insert,
|
|
12053
|
+
codec2.key,
|
|
12054
|
+
encode(codec2.Codec, tryAsLookupHistorySlots([action.slot])),
|
|
12055
|
+
];
|
|
12056
|
+
}
|
|
12057
|
+
break;
|
|
12032
12058
|
}
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
12044
|
-
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12059
|
+
case UpdatePreimageKind.UpdateOrAdd: {
|
|
12060
|
+
const { hash, length, slots } = action.item;
|
|
12061
|
+
const codec = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
12062
|
+
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, slots)];
|
|
12063
|
+
break;
|
|
12064
|
+
}
|
|
12065
|
+
case UpdatePreimageKind.Remove: {
|
|
12066
|
+
const { hash, length } = action;
|
|
12067
|
+
const codec = serialize.servicePreimages(blake2b, serviceId, hash);
|
|
12068
|
+
yield [StateEntryUpdateAction.Remove, codec.key, EMPTY_BLOB];
|
|
12045
12069
|
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12070
|
+
const codec2 = serialize.serviceLookupHistory(blake2b, serviceId, hash, length);
|
|
12071
|
+
yield [StateEntryUpdateAction.Remove, codec2.key, EMPTY_BLOB];
|
|
12072
|
+
break;
|
|
12073
|
+
}
|
|
12049
12074
|
}
|
|
12050
|
-
default:
|
|
12051
|
-
assertNever(action);
|
|
12052
12075
|
}
|
|
12053
12076
|
}
|
|
12054
12077
|
}
|
|
12055
12078
|
declare function* serializeServiceUpdates(
|
|
12056
|
-
servicesUpdates: UpdateService
|
|
12079
|
+
servicesUpdates: Map<ServiceId, UpdateService> | undefined,
|
|
12057
12080
|
encode: EncodeFun,
|
|
12058
12081
|
blake2b: Blake2b,
|
|
12059
12082
|
): Generator<StateEntryUpdate> {
|
|
12060
|
-
|
|
12083
|
+
if (servicesUpdates === undefined) {
|
|
12084
|
+
return;
|
|
12085
|
+
}
|
|
12086
|
+
for (const [serviceId, { action }] of servicesUpdates.entries()) {
|
|
12061
12087
|
// new service being created or updated
|
|
12062
12088
|
const codec = serialize.serviceData(serviceId);
|
|
12063
12089
|
yield [StateEntryUpdateAction.Insert, codec.key, encode(codec.Codec, action.account)];
|
|
@@ -12663,7 +12689,7 @@ declare class LeafDb implements SerializedStateBackend {
|
|
|
12663
12689
|
if (blob.length % TRIE_NODE_BYTES !== 0) {
|
|
12664
12690
|
return Result.error(
|
|
12665
12691
|
LeafDbError.InvalidLeafData,
|
|
12666
|
-
`${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`,
|
|
12692
|
+
() => `${blob.length} is not a multiply of ${TRIE_NODE_BYTES}: ${blob}`,
|
|
12667
12693
|
);
|
|
12668
12694
|
}
|
|
12669
12695
|
|
|
@@ -12671,7 +12697,7 @@ declare class LeafDb implements SerializedStateBackend {
|
|
|
12671
12697
|
for (const nodeData of blob.chunks(TRIE_NODE_BYTES)) {
|
|
12672
12698
|
const node = new TrieNode(nodeData.raw);
|
|
12673
12699
|
if (node.getNodeType() === NodeType.Branch) {
|
|
12674
|
-
return Result.error(LeafDbError.InvalidLeafData, `Branch node detected: ${nodeData}`);
|
|
12700
|
+
return Result.error(LeafDbError.InvalidLeafData, () => `Branch node detected: ${nodeData}`);
|
|
12675
12701
|
}
|
|
12676
12702
|
leaves.insert(node.asLeafNode());
|
|
12677
12703
|
}
|
|
@@ -14196,6 +14222,82 @@ interface GasCounter {
|
|
|
14196
14222
|
sub(g: Gas): boolean;
|
|
14197
14223
|
}
|
|
14198
14224
|
|
|
14225
|
+
declare const NO_OF_REGISTERS$1 = 13;
|
|
14226
|
+
|
|
14227
|
+
type RegisterIndex = Opaque<number, "register index">;
|
|
14228
|
+
|
|
14229
|
+
declare class Registers {
|
|
14230
|
+
private asSigned: BigInt64Array;
|
|
14231
|
+
private asUnsigned: BigUint64Array;
|
|
14232
|
+
|
|
14233
|
+
constructor(private readonly bytes = safeAllocUint8Array(NO_OF_REGISTERS << REGISTER_SIZE_SHIFT)) {
|
|
14234
|
+
check`${bytes.length === NO_OF_REGISTERS << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
14235
|
+
this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
|
|
14236
|
+
this.asUnsigned = new BigUint64Array(bytes.buffer, bytes.byteOffset);
|
|
14237
|
+
}
|
|
14238
|
+
|
|
14239
|
+
static fromBytes(bytes: Uint8Array) {
|
|
14240
|
+
check`${bytes.length === NO_OF_REGISTERS << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
14241
|
+
return new Registers(bytes);
|
|
14242
|
+
}
|
|
14243
|
+
|
|
14244
|
+
getBytesAsLittleEndian(index: number, len: number) {
|
|
14245
|
+
const offset = index << REGISTER_SIZE_SHIFT;
|
|
14246
|
+
return this.bytes.subarray(offset, offset + len);
|
|
14247
|
+
}
|
|
14248
|
+
|
|
14249
|
+
getAllBytesAsLittleEndian() {
|
|
14250
|
+
return this.bytes;
|
|
14251
|
+
}
|
|
14252
|
+
|
|
14253
|
+
copyFrom(regs: Registers | BigUint64Array) {
|
|
14254
|
+
const array = regs instanceof BigUint64Array ? regs : regs.asUnsigned;
|
|
14255
|
+
this.asUnsigned.set(array);
|
|
14256
|
+
}
|
|
14257
|
+
|
|
14258
|
+
reset() {
|
|
14259
|
+
for (let i = 0; i < NO_OF_REGISTERS; i++) {
|
|
14260
|
+
this.asUnsigned[i] = 0n;
|
|
14261
|
+
}
|
|
14262
|
+
}
|
|
14263
|
+
|
|
14264
|
+
getLowerU32(registerIndex: number) {
|
|
14265
|
+
return Number(this.asUnsigned[registerIndex] & 0xff_ff_ff_ffn);
|
|
14266
|
+
}
|
|
14267
|
+
|
|
14268
|
+
getLowerI32(registerIndex: number) {
|
|
14269
|
+
return Number(this.getLowerU32(registerIndex)) >> 0;
|
|
14270
|
+
}
|
|
14271
|
+
|
|
14272
|
+
setU32(registerIndex: number, value: number) {
|
|
14273
|
+
this.asUnsigned[registerIndex] = signExtend32To64(value);
|
|
14274
|
+
}
|
|
14275
|
+
|
|
14276
|
+
setI32(registerIndex: number, value: number) {
|
|
14277
|
+
this.asSigned[registerIndex] = signExtend32To64(value);
|
|
14278
|
+
}
|
|
14279
|
+
|
|
14280
|
+
getU64(registerIndex: number) {
|
|
14281
|
+
return this.asUnsigned[registerIndex];
|
|
14282
|
+
}
|
|
14283
|
+
|
|
14284
|
+
getI64(registerIndex: number) {
|
|
14285
|
+
return this.asSigned[registerIndex];
|
|
14286
|
+
}
|
|
14287
|
+
|
|
14288
|
+
setU64(registerIndex: number, value: bigint) {
|
|
14289
|
+
this.asUnsigned[registerIndex] = value;
|
|
14290
|
+
}
|
|
14291
|
+
|
|
14292
|
+
setI64(registerIndex: number, value: bigint) {
|
|
14293
|
+
this.asSigned[registerIndex] = value;
|
|
14294
|
+
}
|
|
14295
|
+
|
|
14296
|
+
getAllU64() {
|
|
14297
|
+
return this.asUnsigned;
|
|
14298
|
+
}
|
|
14299
|
+
}
|
|
14300
|
+
|
|
14199
14301
|
/**
|
|
14200
14302
|
* Mask class is an implementation of skip function defined in GP.
|
|
14201
14303
|
*
|
|
@@ -14365,82 +14467,6 @@ declare class ImmediateDecoder {
|
|
|
14365
14467
|
}
|
|
14366
14468
|
}
|
|
14367
14469
|
|
|
14368
|
-
declare const NO_OF_REGISTERS$1 = 13;
|
|
14369
|
-
|
|
14370
|
-
type RegisterIndex = Opaque<number, "register index">;
|
|
14371
|
-
|
|
14372
|
-
declare class Registers {
|
|
14373
|
-
private asSigned: BigInt64Array;
|
|
14374
|
-
private asUnsigned: BigUint64Array;
|
|
14375
|
-
|
|
14376
|
-
constructor(private readonly bytes = safeAllocUint8Array(NO_OF_REGISTERS << REGISTER_SIZE_SHIFT)) {
|
|
14377
|
-
check`${bytes.length === NO_OF_REGISTERS << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
14378
|
-
this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
|
|
14379
|
-
this.asUnsigned = new BigUint64Array(bytes.buffer, bytes.byteOffset);
|
|
14380
|
-
}
|
|
14381
|
-
|
|
14382
|
-
static fromBytes(bytes: Uint8Array) {
|
|
14383
|
-
check`${bytes.length === NO_OF_REGISTERS << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
14384
|
-
return new Registers(bytes);
|
|
14385
|
-
}
|
|
14386
|
-
|
|
14387
|
-
getBytesAsLittleEndian(index: number, len: number) {
|
|
14388
|
-
const offset = index << REGISTER_SIZE_SHIFT;
|
|
14389
|
-
return this.bytes.subarray(offset, offset + len);
|
|
14390
|
-
}
|
|
14391
|
-
|
|
14392
|
-
getAllBytesAsLittleEndian() {
|
|
14393
|
-
return this.bytes;
|
|
14394
|
-
}
|
|
14395
|
-
|
|
14396
|
-
copyFrom(regs: Registers | BigUint64Array) {
|
|
14397
|
-
const array = regs instanceof BigUint64Array ? regs : regs.asUnsigned;
|
|
14398
|
-
this.asUnsigned.set(array);
|
|
14399
|
-
}
|
|
14400
|
-
|
|
14401
|
-
reset() {
|
|
14402
|
-
for (let i = 0; i < NO_OF_REGISTERS; i++) {
|
|
14403
|
-
this.asUnsigned[i] = 0n;
|
|
14404
|
-
}
|
|
14405
|
-
}
|
|
14406
|
-
|
|
14407
|
-
getLowerU32(registerIndex: number) {
|
|
14408
|
-
return Number(this.asUnsigned[registerIndex] & 0xff_ff_ff_ffn);
|
|
14409
|
-
}
|
|
14410
|
-
|
|
14411
|
-
getLowerI32(registerIndex: number) {
|
|
14412
|
-
return Number(this.getLowerU32(registerIndex)) >> 0;
|
|
14413
|
-
}
|
|
14414
|
-
|
|
14415
|
-
setU32(registerIndex: number, value: number) {
|
|
14416
|
-
this.asUnsigned[registerIndex] = signExtend32To64(value);
|
|
14417
|
-
}
|
|
14418
|
-
|
|
14419
|
-
setI32(registerIndex: number, value: number) {
|
|
14420
|
-
this.asSigned[registerIndex] = signExtend32To64(value);
|
|
14421
|
-
}
|
|
14422
|
-
|
|
14423
|
-
getU64(registerIndex: number) {
|
|
14424
|
-
return this.asUnsigned[registerIndex];
|
|
14425
|
-
}
|
|
14426
|
-
|
|
14427
|
-
getI64(registerIndex: number) {
|
|
14428
|
-
return this.asSigned[registerIndex];
|
|
14429
|
-
}
|
|
14430
|
-
|
|
14431
|
-
setU64(registerIndex: number, value: bigint) {
|
|
14432
|
-
this.asUnsigned[registerIndex] = value;
|
|
14433
|
-
}
|
|
14434
|
-
|
|
14435
|
-
setI64(registerIndex: number, value: bigint) {
|
|
14436
|
-
this.asSigned[registerIndex] = value;
|
|
14437
|
-
}
|
|
14438
|
-
|
|
14439
|
-
getAllU64() {
|
|
14440
|
-
return this.asUnsigned;
|
|
14441
|
-
}
|
|
14442
|
-
}
|
|
14443
|
-
|
|
14444
14470
|
declare class NibblesDecoder {
|
|
14445
14471
|
private byte = new Int8Array(1);
|
|
14446
14472
|
|
|
@@ -15483,7 +15509,7 @@ declare class Memory {
|
|
|
15483
15509
|
const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
|
|
15484
15510
|
|
|
15485
15511
|
if (pagesResult.isError) {
|
|
15486
|
-
return Result.error(pagesResult.error);
|
|
15512
|
+
return Result.error(pagesResult.error, pagesResult.details);
|
|
15487
15513
|
}
|
|
15488
15514
|
|
|
15489
15515
|
const pages = pagesResult.ok;
|
|
@@ -15516,17 +15542,23 @@ declare class Memory {
|
|
|
15516
15542
|
|
|
15517
15543
|
for (const pageNumber of pageRange) {
|
|
15518
15544
|
if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
|
|
15519
|
-
return Result.error(
|
|
15545
|
+
return Result.error(
|
|
15546
|
+
PageFault.fromPageNumber(pageNumber, true),
|
|
15547
|
+
() => `Page fault: attempted to access reserved page ${pageNumber}`,
|
|
15548
|
+
);
|
|
15520
15549
|
}
|
|
15521
15550
|
|
|
15522
15551
|
const page = this.memory.get(pageNumber);
|
|
15523
15552
|
|
|
15524
15553
|
if (page === undefined) {
|
|
15525
|
-
return Result.error(PageFault.fromPageNumber(pageNumber));
|
|
15554
|
+
return Result.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
|
|
15526
15555
|
}
|
|
15527
15556
|
|
|
15528
15557
|
if (accessType === AccessType.WRITE && !page.isWriteable()) {
|
|
15529
|
-
return Result.error(
|
|
15558
|
+
return Result.error(
|
|
15559
|
+
PageFault.fromPageNumber(pageNumber, true),
|
|
15560
|
+
() => `Page fault: attempted to write to read-only page ${pageNumber}`,
|
|
15561
|
+
);
|
|
15530
15562
|
}
|
|
15531
15563
|
|
|
15532
15564
|
pages.push(page);
|
|
@@ -15548,7 +15580,7 @@ declare class Memory {
|
|
|
15548
15580
|
const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
|
|
15549
15581
|
|
|
15550
15582
|
if (pagesResult.isError) {
|
|
15551
|
-
return Result.error(pagesResult.error);
|
|
15583
|
+
return Result.error(pagesResult.error, pagesResult.details);
|
|
15552
15584
|
}
|
|
15553
15585
|
|
|
15554
15586
|
const pages = pagesResult.ok;
|
|
@@ -17533,7 +17565,7 @@ declare class ProgramDecoder {
|
|
|
17533
17565
|
return Result.ok(new ProgramDecoder(program));
|
|
17534
17566
|
} catch (e) {
|
|
17535
17567
|
logger.error`Invalid program: ${e}`;
|
|
17536
|
-
return Result.error(ProgramDecoderError.InvalidProgramError);
|
|
17568
|
+
return Result.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
|
|
17537
17569
|
}
|
|
17538
17570
|
}
|
|
17539
17571
|
}
|
|
@@ -17877,870 +17909,896 @@ declare namespace index$8 {
|
|
|
17877
17909
|
export type { index$8_BigGas as BigGas, index$8_Gas as Gas, index$8_GasCounter as GasCounter, index$8_InterpreterOptions as InterpreterOptions, index$8_MemoryIndex as MemoryIndex, index$8_SbrkIndex as SbrkIndex, index$8_SmallGas as SmallGas };
|
|
17878
17910
|
}
|
|
17879
17911
|
|
|
17880
|
-
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
|
|
17884
|
-
*/
|
|
17885
|
-
type ProgramCounter = Opaque<U64, "ProgramCounter[u64]">;
|
|
17886
|
-
/** Convert a number into ProgramCounter. */
|
|
17887
|
-
declare const tryAsProgramCounter = (v: number | bigint): ProgramCounter => asOpaqueType(tryAsU64(v));
|
|
17912
|
+
interface IHostCallMemory {
|
|
17913
|
+
storeFrom(address: U64, bytes: Uint8Array): Result$2<OK, PageFault | OutOfBounds>;
|
|
17914
|
+
loadInto(result: Uint8Array, startAddress: U64): Result$2<OK, PageFault | OutOfBounds>;
|
|
17915
|
+
}
|
|
17888
17916
|
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
/** Convert a number into PVM instance identifier. */
|
|
17892
|
-
declare const tryAsMachineId = (v: number | bigint): MachineId => asOpaqueType(tryAsU64(v));
|
|
17917
|
+
declare class HostCallMemory implements IHostCallMemory {
|
|
17918
|
+
constructor(private readonly memory: Memory) {}
|
|
17893
17919
|
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
result: {
|
|
17898
|
-
status: Status.OK,
|
|
17899
|
-
},
|
|
17900
|
-
gas,
|
|
17901
|
-
registers,
|
|
17902
|
-
};
|
|
17903
|
-
}
|
|
17904
|
-
}
|
|
17905
|
-
|
|
17906
|
-
type MachineStatus =
|
|
17907
|
-
| {
|
|
17908
|
-
status: typeof Status.HOST;
|
|
17909
|
-
hostCallIndex: U64;
|
|
17920
|
+
storeFrom(address: U64, bytes: Uint8Array): Result$2<OK, PageFault | OutOfBounds> {
|
|
17921
|
+
if (bytes.length === 0) {
|
|
17922
|
+
return Result.ok(OK);
|
|
17910
17923
|
}
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17924
|
+
|
|
17925
|
+
if (address + tryAsU64(bytes.length) > MEMORY_SIZE) {
|
|
17926
|
+
return Result.error(
|
|
17927
|
+
new OutOfBounds(),
|
|
17928
|
+
() => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`,
|
|
17929
|
+
);
|
|
17914
17930
|
}
|
|
17915
|
-
| {
|
|
17916
|
-
status: typeof Status.OK | typeof Status.HALT | typeof Status.PANIC | typeof Status.OOG;
|
|
17917
|
-
};
|
|
17918
17931
|
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
result: MachineStatus;
|
|
17922
|
-
gas: BigGas;
|
|
17923
|
-
registers: Registers;
|
|
17924
|
-
};
|
|
17932
|
+
return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
|
|
17933
|
+
}
|
|
17925
17934
|
|
|
17926
|
-
|
|
17927
|
-
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
/** Zeroes memory and set access to read-only. */
|
|
17931
|
-
ZeroRead = 1,
|
|
17932
|
-
/** Zeroes memory and set access to read-write. */
|
|
17933
|
-
ZeroWrite = 2,
|
|
17934
|
-
/** Preserve memory and set access to read-only. */
|
|
17935
|
-
Read = 3,
|
|
17936
|
-
/** Preserve memory and set access to read-write. */
|
|
17937
|
-
Write = 4,
|
|
17938
|
-
}
|
|
17935
|
+
loadInto(result: Uint8Array, startAddress: U64): Result$2<OK, PageFault | OutOfBounds> {
|
|
17936
|
+
if (result.length === 0) {
|
|
17937
|
+
return Result.ok(OK);
|
|
17938
|
+
}
|
|
17939
17939
|
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17940
|
+
if (startAddress + tryAsU64(result.length) > MEMORY_SIZE) {
|
|
17941
|
+
return Result.error(
|
|
17942
|
+
new OutOfBounds(),
|
|
17943
|
+
() => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`,
|
|
17944
|
+
);
|
|
17945
|
+
}
|
|
17943
17946
|
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
/** Source page fault. */
|
|
17947
|
-
SourcePageFault = 0,
|
|
17948
|
-
/** Destination page fault. */
|
|
17949
|
-
DestinationPageFault = 1,
|
|
17950
|
-
/** No machine under given machine index. */
|
|
17951
|
-
NoMachine = 2,
|
|
17947
|
+
return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
|
|
17948
|
+
}
|
|
17952
17949
|
}
|
|
17953
17950
|
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
/** Attempting to void or zero non-accessible page. */
|
|
17958
|
-
InvalidPage = 1,
|
|
17951
|
+
interface IHostCallRegisters {
|
|
17952
|
+
get(registerIndex: number): U64;
|
|
17953
|
+
set(registerIndex: number, value: U64): void;
|
|
17959
17954
|
}
|
|
17960
17955
|
|
|
17961
|
-
declare
|
|
17962
|
-
|
|
17963
|
-
NoMachine = 0,
|
|
17964
|
-
/** Invalid memory operation. */
|
|
17965
|
-
InvalidOperation = 1,
|
|
17966
|
-
/** Attempting to change non-accessible page or trying to preserve value of voided page. */
|
|
17967
|
-
InvalidPage = 2,
|
|
17968
|
-
}
|
|
17956
|
+
declare class HostCallRegisters implements IHostCallRegisters {
|
|
17957
|
+
constructor(private readonly registers: Registers) {}
|
|
17969
17958
|
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17959
|
+
get(registerIndex: number): U64 {
|
|
17960
|
+
return tryAsU64(this.registers.getU64(registerIndex));
|
|
17961
|
+
}
|
|
17973
17962
|
|
|
17974
|
-
|
|
17975
|
-
|
|
17976
|
-
|
|
17963
|
+
set(registerIndex: number, value: U64) {
|
|
17964
|
+
this.registers.setU64(registerIndex, value);
|
|
17965
|
+
}
|
|
17966
|
+
}
|
|
17977
17967
|
|
|
17978
|
-
/**
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
17968
|
+
/** Strictly-typed host call index. */
|
|
17969
|
+
type HostCallIndex = Opaque<U32, "HostCallIndex[U32]">;
|
|
17970
|
+
/** Attempt to convert a number into `HostCallIndex`. */
|
|
17971
|
+
declare const tryAsHostCallIndex = (v: number): HostCallIndex => asOpaqueType(tryAsU32(v));
|
|
17982
17972
|
|
|
17983
|
-
|
|
17984
|
-
|
|
17973
|
+
/**
|
|
17974
|
+
* Host-call exit reason.
|
|
17975
|
+
*
|
|
17976
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/24a30124a501?v=0.7.2
|
|
17977
|
+
*/
|
|
17978
|
+
declare enum PvmExecution {
|
|
17979
|
+
Halt = 0,
|
|
17980
|
+
Panic = 1,
|
|
17981
|
+
OOG = 2, // out-of-gas
|
|
17982
|
+
}
|
|
17985
17983
|
|
|
17986
|
-
|
|
17987
|
-
|
|
17984
|
+
/** A utility function to easily trace a bunch of registers. */
|
|
17985
|
+
declare function traceRegisters(...regs: number[]) {
|
|
17986
|
+
return regs.map(tryAsRegisterIndex);
|
|
17987
|
+
}
|
|
17988
17988
|
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
17993
|
-
sourceStart: U64,
|
|
17994
|
-
length: U64,
|
|
17995
|
-
destination: Memory,
|
|
17996
|
-
): Promise<Result$2<OK, PeekPokeError>>;
|
|
17989
|
+
/** An interface for a host call implementation */
|
|
17990
|
+
interface HostCallHandler {
|
|
17991
|
+
/** Index of that host call (i.e. what PVM invokes via `ecalli`) */
|
|
17992
|
+
readonly index: HostCallIndex;
|
|
17997
17993
|
|
|
17998
|
-
/**
|
|
17999
|
-
|
|
18000
|
-
|
|
18001
|
-
|
|
18002
|
-
|
|
18003
|
-
|
|
18004
|
-
source: Memory,
|
|
18005
|
-
): Promise<Result$2<OK, PeekPokeError>>;
|
|
17994
|
+
/**
|
|
17995
|
+
* The gas cost of invocation of that host call.
|
|
17996
|
+
*
|
|
17997
|
+
* NOTE: `((reg: IHostCallRegisters) => Gas)` function is for compatibility reasons: pre GP 0.7.2
|
|
17998
|
+
*/
|
|
17999
|
+
readonly basicGasCost: SmallGas | ((reg: IHostCallRegisters) => Gas);
|
|
18006
18000
|
|
|
18007
|
-
/**
|
|
18008
|
-
|
|
18001
|
+
/** Currently executing service id. */
|
|
18002
|
+
readonly currentServiceId: U32;
|
|
18009
18003
|
|
|
18010
|
-
/**
|
|
18011
|
-
|
|
18012
|
-
machineIndex: MachineId,
|
|
18013
|
-
gas: BigGas,
|
|
18014
|
-
registers: Registers,
|
|
18015
|
-
): Promise<Result$2<MachineResult, NoMachineError>>;
|
|
18004
|
+
/** Input&Output registers that we should add to tracing log. */
|
|
18005
|
+
readonly tracedRegisters: RegisterIndex[];
|
|
18016
18006
|
|
|
18017
18007
|
/**
|
|
18018
|
-
*
|
|
18008
|
+
* Actually execute the host call.
|
|
18019
18009
|
*
|
|
18020
|
-
*
|
|
18010
|
+
* NOTE the call is ALLOWED and expected to modify registers and memory.
|
|
18021
18011
|
*/
|
|
18022
|
-
|
|
18023
|
-
|
|
18024
|
-
/** Lookup a historical preimage. */
|
|
18025
|
-
historicalLookup(serviceId: ServiceId | null, hash: Blake2bHash): Promise<BytesBlob | null>;
|
|
18026
|
-
|
|
18027
|
-
/** Change access to and/or zero the value of memory. */
|
|
18028
|
-
machinePages(
|
|
18029
|
-
machineIndex: MachineId,
|
|
18030
|
-
pageStart: U64,
|
|
18031
|
-
pageCount: U64,
|
|
18032
|
-
requestType: MemoryOperation | null,
|
|
18033
|
-
): Promise<Result$2<OK, PagesError>>;
|
|
18012
|
+
execute(gas: GasCounter, regs: IHostCallRegisters, memory: IHostCallMemory): Promise<undefined | PvmExecution>;
|
|
18034
18013
|
}
|
|
18035
18014
|
|
|
18036
|
-
|
|
18037
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18040
|
-
type ServiceStateUpdate = Partial<Pick<State, "privilegedServices" | "authQueues" | "designatedValidatorData">> &
|
|
18041
|
-
ServicesUpdate;
|
|
18015
|
+
/** Container for all available host calls. */
|
|
18016
|
+
declare class HostCallsManager {
|
|
18017
|
+
private readonly hostCalls = new Map<HostCallIndex, HostCallHandler>();
|
|
18018
|
+
private readonly missing;
|
|
18042
18019
|
|
|
18043
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
|
|
18047
|
-
|
|
18048
|
-
|
|
18049
|
-
|
|
18050
|
-
|
|
18051
|
-
new Map();
|
|
18052
|
-
/** New validators data. */
|
|
18053
|
-
public validatorsData: PerValidator<ValidatorData> | null = null;
|
|
18054
|
-
/** Updated priviliged services. */
|
|
18055
|
-
public privilegedServices: PrivilegedServices | null = null;
|
|
18020
|
+
constructor({
|
|
18021
|
+
missing,
|
|
18022
|
+
handlers = [],
|
|
18023
|
+
}: {
|
|
18024
|
+
missing: HostCallHandler;
|
|
18025
|
+
handlers?: HostCallHandler[];
|
|
18026
|
+
}) {
|
|
18027
|
+
this.missing = missing;
|
|
18056
18028
|
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18060
|
-
|
|
18061
|
-
|
|
18062
|
-
/** Yielded accumulation root. */
|
|
18063
|
-
public readonly yieldedRoots: Map<ServiceId, OpaqueHash> = new Map(),
|
|
18064
|
-
) {}
|
|
18029
|
+
for (const handler of handlers) {
|
|
18030
|
+
check`${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
|
|
18031
|
+
this.hostCalls.set(handler.index, handler);
|
|
18032
|
+
}
|
|
18033
|
+
}
|
|
18065
18034
|
|
|
18066
|
-
/**
|
|
18067
|
-
|
|
18068
|
-
return
|
|
18069
|
-
{
|
|
18070
|
-
servicesUpdates: [],
|
|
18071
|
-
servicesRemoved: [],
|
|
18072
|
-
preimages: [],
|
|
18073
|
-
storage: [],
|
|
18074
|
-
},
|
|
18075
|
-
[],
|
|
18076
|
-
);
|
|
18035
|
+
/** Get a host call by index. */
|
|
18036
|
+
get(hostCallIndex: HostCallIndex): HostCallHandler {
|
|
18037
|
+
return this.hostCalls.get(hostCallIndex) ?? this.missing;
|
|
18077
18038
|
}
|
|
18078
18039
|
|
|
18079
|
-
|
|
18080
|
-
|
|
18081
|
-
|
|
18082
|
-
|
|
18083
|
-
|
|
18084
|
-
|
|
18085
|
-
|
|
18086
|
-
|
|
18040
|
+
traceHostCall(
|
|
18041
|
+
context: string,
|
|
18042
|
+
hostCallIndex: HostCallIndex,
|
|
18043
|
+
hostCallHandler: HostCallHandler,
|
|
18044
|
+
registers: IHostCallRegisters,
|
|
18045
|
+
gas: Gas,
|
|
18046
|
+
) {
|
|
18047
|
+
const { currentServiceId } = hostCallHandler;
|
|
18048
|
+
const requested = hostCallIndex !== hostCallHandler.index ? ` (${hostCallIndex})` : "";
|
|
18049
|
+
const name = `${hostCallHandler.constructor.name}:${hostCallHandler.index}`;
|
|
18050
|
+
const registerValues = hostCallHandler.tracedRegisters
|
|
18051
|
+
.map((idx) => [idx.toString().padStart(2, "0"), registers.get(idx)] as const)
|
|
18052
|
+
.filter((v) => v[1] !== 0n)
|
|
18053
|
+
.map(([idx, value]) => {
|
|
18054
|
+
return `r${idx}=${value} (0x${value.toString(16)})`;
|
|
18055
|
+
})
|
|
18056
|
+
.join(", ");
|
|
18057
|
+
logger.insane`[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
|
|
18087
18058
|
}
|
|
18059
|
+
}
|
|
18088
18060
|
|
|
18089
|
-
|
|
18090
|
-
static copyFrom(from: AccumulationStateUpdate): AccumulationStateUpdate {
|
|
18091
|
-
const serviceUpdates: ServicesUpdate = {
|
|
18092
|
-
servicesUpdates: [...from.services.servicesUpdates],
|
|
18093
|
-
servicesRemoved: [...from.services.servicesRemoved],
|
|
18094
|
-
preimages: [...from.services.preimages],
|
|
18095
|
-
storage: [...from.services.storage],
|
|
18096
|
-
};
|
|
18097
|
-
const transfers = [...from.transfers];
|
|
18098
|
-
const update = new AccumulationStateUpdate(serviceUpdates, transfers, new Map(from.yieldedRoots));
|
|
18061
|
+
type ResolveFn = (pvm: Interpreter) => void;
|
|
18099
18062
|
|
|
18100
|
-
|
|
18101
|
-
|
|
18102
|
-
|
|
18103
|
-
}
|
|
18063
|
+
declare class InterpreterInstanceManager {
|
|
18064
|
+
private instances: Interpreter[] = [];
|
|
18065
|
+
private waitingQueue: ResolveFn[] = [];
|
|
18104
18066
|
|
|
18105
|
-
|
|
18106
|
-
|
|
18067
|
+
constructor(noOfPvmInstances: number) {
|
|
18068
|
+
for (let i = 0; i < noOfPvmInstances; i++) {
|
|
18069
|
+
this.instances.push(
|
|
18070
|
+
new Interpreter({
|
|
18071
|
+
useSbrkGas: false,
|
|
18072
|
+
}),
|
|
18073
|
+
);
|
|
18107
18074
|
}
|
|
18075
|
+
}
|
|
18108
18076
|
|
|
18109
|
-
|
|
18110
|
-
|
|
18111
|
-
|
|
18112
|
-
|
|
18113
|
-
});
|
|
18077
|
+
async getInstance(): Promise<Interpreter> {
|
|
18078
|
+
const instance = this.instances.pop();
|
|
18079
|
+
if (instance !== undefined) {
|
|
18080
|
+
return Promise.resolve(instance);
|
|
18114
18081
|
}
|
|
18115
|
-
return
|
|
18082
|
+
return new Promise((resolve) => {
|
|
18083
|
+
this.waitingQueue.push(resolve);
|
|
18084
|
+
});
|
|
18116
18085
|
}
|
|
18117
18086
|
|
|
18118
|
-
|
|
18119
|
-
|
|
18120
|
-
|
|
18121
|
-
|
|
18122
|
-
|
|
18087
|
+
releaseInstance(pvm: Interpreter) {
|
|
18088
|
+
const waiting = this.waitingQueue.shift();
|
|
18089
|
+
if (waiting !== undefined) {
|
|
18090
|
+
return waiting(pvm);
|
|
18091
|
+
}
|
|
18092
|
+
this.instances.push(pvm);
|
|
18123
18093
|
}
|
|
18124
18094
|
}
|
|
18125
18095
|
|
|
18126
|
-
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18131
|
-
|
|
18132
|
-
constructor(
|
|
18133
|
-
/** Original (unmodified state). */
|
|
18134
|
-
public readonly state: T,
|
|
18135
|
-
stateUpdate?: AccumulationStateUpdate,
|
|
18096
|
+
declare class ReturnValue {
|
|
18097
|
+
private constructor(
|
|
18098
|
+
public consumedGas: Gas,
|
|
18099
|
+
public status: Status | null,
|
|
18100
|
+
public memorySlice: Uint8Array | null,
|
|
18136
18101
|
) {
|
|
18137
|
-
|
|
18138
|
-
|
|
18102
|
+
check`
|
|
18103
|
+
${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
|
|
18104
|
+
'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
|
|
18105
|
+
`;
|
|
18139
18106
|
}
|
|
18140
18107
|
|
|
18141
|
-
|
|
18142
|
-
|
|
18143
|
-
|
|
18144
|
-
* NOTE the info may be updated compared to what is in the state.
|
|
18145
|
-
*
|
|
18146
|
-
* Takes into account ejected and newly created services as well.
|
|
18147
|
-
*/
|
|
18148
|
-
getServiceInfo(destination: ServiceId | null): ServiceAccountInfo | null {
|
|
18149
|
-
if (destination === null) {
|
|
18150
|
-
return null;
|
|
18151
|
-
}
|
|
18152
|
-
|
|
18153
|
-
const maybeNewService = this.stateUpdate.services.servicesUpdates.find(
|
|
18154
|
-
(update) => update.serviceId === destination,
|
|
18155
|
-
);
|
|
18156
|
-
|
|
18157
|
-
if (maybeNewService !== undefined) {
|
|
18158
|
-
return maybeNewService.action.account;
|
|
18159
|
-
}
|
|
18160
|
-
|
|
18161
|
-
const maybeService = this.state.getService(destination);
|
|
18162
|
-
if (maybeService === null) {
|
|
18163
|
-
return null;
|
|
18164
|
-
}
|
|
18108
|
+
static fromStatus(consumedGas: Gas, status: Status) {
|
|
18109
|
+
return new ReturnValue(consumedGas, status, null);
|
|
18110
|
+
}
|
|
18165
18111
|
|
|
18166
|
-
|
|
18112
|
+
static fromMemorySlice(consumedGas: Gas, memorySlice: Uint8Array) {
|
|
18113
|
+
return new ReturnValue(consumedGas, null, memorySlice);
|
|
18167
18114
|
}
|
|
18168
18115
|
|
|
18169
|
-
|
|
18170
|
-
|
|
18171
|
-
|
|
18172
|
-
return item.value;
|
|
18173
|
-
}
|
|
18116
|
+
hasMemorySlice(): this is this & { status: null; memorySlice: Uint8Array } {
|
|
18117
|
+
return this.memorySlice instanceof Uint8Array && this.status === null;
|
|
18118
|
+
}
|
|
18174
18119
|
|
|
18175
|
-
|
|
18176
|
-
return
|
|
18120
|
+
hasStatus(): this is this & { status: Status; memorySlice: null } {
|
|
18121
|
+
return !this.hasMemorySlice();
|
|
18177
18122
|
}
|
|
18123
|
+
}
|
|
18124
|
+
declare class HostCalls {
|
|
18125
|
+
constructor(
|
|
18126
|
+
private pvmInstanceManager: InterpreterInstanceManager,
|
|
18127
|
+
private hostCalls: HostCallsManager,
|
|
18128
|
+
) {}
|
|
18178
18129
|
|
|
18179
|
-
|
|
18180
|
-
|
|
18181
|
-
|
|
18182
|
-
|
|
18183
|
-
* NOTE: Does not check if the preimage is available, we just check
|
|
18184
|
-
* the existence in `preimages` map.
|
|
18185
|
-
*/
|
|
18186
|
-
hasPreimage(serviceId: ServiceId, hash: PreimageHash): boolean {
|
|
18187
|
-
const providedPreimage = this.stateUpdate.services.preimages.find(
|
|
18188
|
-
// we ignore the action here, since if there is <any> update on that
|
|
18189
|
-
// hash it means it has to exist, right?
|
|
18190
|
-
(p) => p.serviceId === serviceId && p.hash.isEqualTo(hash),
|
|
18191
|
-
);
|
|
18192
|
-
if (providedPreimage !== undefined) {
|
|
18193
|
-
return true;
|
|
18130
|
+
private getReturnValue(status: Status, pvmInstance: Interpreter): ReturnValue {
|
|
18131
|
+
const gasConsumed = pvmInstance.getGasConsumed();
|
|
18132
|
+
if (status === Status.OOG) {
|
|
18133
|
+
return ReturnValue.fromStatus(gasConsumed, status);
|
|
18194
18134
|
}
|
|
18195
18135
|
|
|
18196
|
-
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18136
|
+
if (status === Status.HALT) {
|
|
18137
|
+
const memory = pvmInstance.getMemory();
|
|
18138
|
+
const regs = pvmInstance.getRegisters();
|
|
18139
|
+
const maybeAddress = regs.getLowerU32(7);
|
|
18140
|
+
const maybeLength = regs.getLowerU32(8);
|
|
18201
18141
|
|
|
18202
|
-
|
|
18203
|
-
|
|
18142
|
+
const result = safeAllocUint8Array(maybeLength);
|
|
18143
|
+
const startAddress = tryAsMemoryIndex(maybeAddress);
|
|
18144
|
+
const loadResult = memory.loadInto(result, startAddress);
|
|
18204
18145
|
|
|
18205
|
-
|
|
18206
|
-
|
|
18207
|
-
|
|
18208
|
-
|
|
18209
|
-
|
|
18210
|
-
if (freshlyProvided !== undefined && freshlyProvided.action.kind === UpdatePreimageKind.Provide) {
|
|
18211
|
-
return freshlyProvided.action.preimage.blob;
|
|
18146
|
+
if (loadResult.isError) {
|
|
18147
|
+
return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
|
|
18148
|
+
}
|
|
18149
|
+
|
|
18150
|
+
return ReturnValue.fromMemorySlice(gasConsumed, result);
|
|
18212
18151
|
}
|
|
18213
18152
|
|
|
18214
|
-
|
|
18215
|
-
return service?.getPreimage(hash) ?? null;
|
|
18153
|
+
return ReturnValue.fromStatus(gasConsumed, Status.PANIC);
|
|
18216
18154
|
}
|
|
18217
18155
|
|
|
18218
|
-
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
): LookupHistoryItem | null {
|
|
18225
|
-
// TODO [ToDr] This is most likely wrong. We may have `provide` and `remove` within
|
|
18226
|
-
// the same state update. We should however switch to proper "updated state"
|
|
18227
|
-
// representation soon.
|
|
18228
|
-
const updatedPreimage = this.stateUpdate.services.preimages.findLast(
|
|
18229
|
-
(update) => update.serviceId === serviceId && update.hash.isEqualTo(hash) && BigInt(update.length) === length,
|
|
18230
|
-
);
|
|
18231
|
-
|
|
18232
|
-
const stateFallback = () => {
|
|
18233
|
-
// fallback to state lookup
|
|
18234
|
-
const service = this.state.getService(serviceId);
|
|
18235
|
-
const lenU32 = preimageLenAsU32(length);
|
|
18236
|
-
if (lenU32 === null || service === null) {
|
|
18237
|
-
return null;
|
|
18156
|
+
private async execute(pvmInstance: Interpreter) {
|
|
18157
|
+
pvmInstance.runProgram();
|
|
18158
|
+
for (;;) {
|
|
18159
|
+
let status = pvmInstance.getStatus();
|
|
18160
|
+
if (status !== Status.HOST) {
|
|
18161
|
+
return this.getReturnValue(status, pvmInstance);
|
|
18238
18162
|
}
|
|
18163
|
+
check`
|
|
18164
|
+
${pvmInstance.getExitParam() !== null}
|
|
18165
|
+
"We know that the exit param is not null, because the status is 'Status.HOST'
|
|
18166
|
+
`;
|
|
18167
|
+
const hostCallIndex = pvmInstance.getExitParam() ?? -1;
|
|
18168
|
+
const gas = pvmInstance.getGasCounter();
|
|
18169
|
+
const regs = new HostCallRegisters(pvmInstance.getRegisters());
|
|
18170
|
+
const memory = new HostCallMemory(pvmInstance.getMemory());
|
|
18171
|
+
const index = tryAsHostCallIndex(hostCallIndex);
|
|
18239
18172
|
|
|
18240
|
-
const
|
|
18241
|
-
|
|
18242
|
-
|
|
18173
|
+
const hostCall = this.hostCalls.get(index);
|
|
18174
|
+
const gasBefore = gas.get();
|
|
18175
|
+
// NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
|
|
18176
|
+
const basicGasCost =
|
|
18177
|
+
typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
|
|
18178
|
+
const underflow = gas.sub(basicGasCost);
|
|
18243
18179
|
|
|
18244
|
-
|
|
18245
|
-
|
|
18246
|
-
|
|
18180
|
+
const pcLog = `[PC: ${pvmInstance.getPC()}]`;
|
|
18181
|
+
if (underflow) {
|
|
18182
|
+
this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
|
|
18183
|
+
return ReturnValue.fromStatus(pvmInstance.getGasConsumed(), Status.OOG);
|
|
18184
|
+
}
|
|
18185
|
+
this.hostCalls.traceHostCall(`${pcLog} Invoking`, index, hostCall, regs, gasBefore);
|
|
18186
|
+
const result = await hostCall.execute(gas, regs, memory);
|
|
18187
|
+
this.hostCalls.traceHostCall(
|
|
18188
|
+
result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`,
|
|
18189
|
+
index,
|
|
18190
|
+
hostCall,
|
|
18191
|
+
regs,
|
|
18192
|
+
gas.get(),
|
|
18193
|
+
);
|
|
18247
18194
|
|
|
18248
|
-
|
|
18249
|
-
|
|
18250
|
-
|
|
18251
|
-
// casting to U32 is safe, since we compare with object we have in memory.
|
|
18252
|
-
return new LookupHistoryItem(hash, updatedPreimage.length, tryAsLookupHistorySlots([currentTimeslot]));
|
|
18195
|
+
if (result === PvmExecution.Halt) {
|
|
18196
|
+
status = Status.HALT;
|
|
18197
|
+
return this.getReturnValue(status, pvmInstance);
|
|
18253
18198
|
}
|
|
18254
|
-
case UpdatePreimageKind.Remove: {
|
|
18255
|
-
const state = stateFallback();
|
|
18256
|
-
// kinda impossible, since we know it's there because it's removed.
|
|
18257
|
-
if (state === null) {
|
|
18258
|
-
return null;
|
|
18259
|
-
}
|
|
18260
18199
|
|
|
18261
|
-
|
|
18200
|
+
if (result === PvmExecution.Panic) {
|
|
18201
|
+
status = Status.PANIC;
|
|
18202
|
+
return this.getReturnValue(status, pvmInstance);
|
|
18262
18203
|
}
|
|
18263
|
-
|
|
18264
|
-
|
|
18204
|
+
|
|
18205
|
+
if (result === PvmExecution.OOG) {
|
|
18206
|
+
status = Status.OOG;
|
|
18207
|
+
return this.getReturnValue(status, pvmInstance);
|
|
18265
18208
|
}
|
|
18266
|
-
}
|
|
18267
18209
|
|
|
18268
|
-
|
|
18269
|
-
|
|
18210
|
+
if (result === undefined) {
|
|
18211
|
+
pvmInstance.runProgram();
|
|
18212
|
+
status = pvmInstance.getStatus();
|
|
18213
|
+
continue;
|
|
18214
|
+
}
|
|
18270
18215
|
|
|
18271
|
-
|
|
18216
|
+
assertNever(result);
|
|
18217
|
+
}
|
|
18218
|
+
}
|
|
18272
18219
|
|
|
18273
|
-
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
18280
|
-
|
|
18281
|
-
|
|
18282
|
-
|
|
18283
|
-
|
|
18284
|
-
|
|
18285
|
-
|
|
18286
|
-
|
|
18220
|
+
async runProgram(
|
|
18221
|
+
rawProgram: Uint8Array,
|
|
18222
|
+
initialPc: number,
|
|
18223
|
+
initialGas: Gas,
|
|
18224
|
+
maybeRegisters?: Registers,
|
|
18225
|
+
maybeMemory?: Memory,
|
|
18226
|
+
): Promise<ReturnValue> {
|
|
18227
|
+
const pvmInstance = await this.pvmInstanceManager.getInstance();
|
|
18228
|
+
pvmInstance.reset(rawProgram, initialPc, initialGas, maybeRegisters, maybeMemory);
|
|
18229
|
+
try {
|
|
18230
|
+
return await this.execute(pvmInstance);
|
|
18231
|
+
} finally {
|
|
18232
|
+
this.pvmInstanceManager.releaseInstance(pvmInstance);
|
|
18233
|
+
}
|
|
18287
18234
|
}
|
|
18235
|
+
}
|
|
18288
18236
|
|
|
18289
|
-
|
|
18290
|
-
|
|
18291
|
-
|
|
18292
|
-
|
|
18293
|
-
|
|
18294
|
-
|
|
18295
|
-
|
|
18296
|
-
|
|
18297
|
-
|
|
18237
|
+
type index$7_HostCallHandler = HostCallHandler;
|
|
18238
|
+
type index$7_HostCallMemory = HostCallMemory;
|
|
18239
|
+
declare const index$7_HostCallMemory: typeof HostCallMemory;
|
|
18240
|
+
type index$7_HostCallRegisters = HostCallRegisters;
|
|
18241
|
+
declare const index$7_HostCallRegisters: typeof HostCallRegisters;
|
|
18242
|
+
type index$7_IHostCallMemory = IHostCallMemory;
|
|
18243
|
+
type index$7_IHostCallRegisters = IHostCallRegisters;
|
|
18244
|
+
type index$7_PvmExecution = PvmExecution;
|
|
18245
|
+
declare const index$7_PvmExecution: typeof PvmExecution;
|
|
18246
|
+
declare const index$7_traceRegisters: typeof traceRegisters;
|
|
18247
|
+
declare const index$7_tryAsHostCallIndex: typeof tryAsHostCallIndex;
|
|
18248
|
+
declare namespace index$7 {
|
|
18249
|
+
export { index$7_HostCallMemory as HostCallMemory, index$7_HostCallRegisters as HostCallRegisters, HostCallsManager as HostCalls, index$7_PvmExecution as PvmExecution, HostCalls as PvmHostCallExtension, InterpreterInstanceManager as PvmInstanceManager, index$7_traceRegisters as traceRegisters, index$7_tryAsHostCallIndex as tryAsHostCallIndex };
|
|
18250
|
+
export type { index$7_HostCallHandler as HostCallHandler, index$7_IHostCallMemory as IHostCallMemory, index$7_IHostCallRegisters as IHostCallRegisters };
|
|
18251
|
+
}
|
|
18298
18252
|
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18253
|
+
/**
|
|
18254
|
+
* Program counter is a 64-bit unsigned integer that points to the next instruction
|
|
18255
|
+
*
|
|
18256
|
+
* https://graypaper.fluffylabs.dev/#/1c979cb/2e3f012e3f01?v=0.7.1
|
|
18257
|
+
*/
|
|
18258
|
+
type ProgramCounter = Opaque<U64, "ProgramCounter[u64]">;
|
|
18259
|
+
/** Convert a number into ProgramCounter. */
|
|
18260
|
+
declare const tryAsProgramCounter = (v: number | bigint): ProgramCounter => asOpaqueType(tryAsU64(v));
|
|
18307
18261
|
|
|
18308
|
-
|
|
18309
|
-
|
|
18262
|
+
/** Running PVM instance identifier. */
|
|
18263
|
+
type MachineId = Opaque<U64, "MachineId[u64]">;
|
|
18264
|
+
/** Convert a number into PVM instance identifier. */
|
|
18265
|
+
declare const tryAsMachineId = (v: number | bigint): MachineId => asOpaqueType(tryAsU64(v));
|
|
18310
18266
|
|
|
18311
|
-
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18267
|
+
declare class MachineInstance {
|
|
18268
|
+
async run(gas: BigGas, registers: Registers): Promise<MachineResult> {
|
|
18269
|
+
return {
|
|
18270
|
+
result: {
|
|
18271
|
+
status: Status.OK,
|
|
18272
|
+
},
|
|
18273
|
+
gas,
|
|
18274
|
+
registers,
|
|
18275
|
+
};
|
|
18276
|
+
}
|
|
18277
|
+
}
|
|
18315
18278
|
|
|
18316
|
-
|
|
18317
|
-
|
|
18318
|
-
|
|
18279
|
+
type MachineStatus =
|
|
18280
|
+
| {
|
|
18281
|
+
status: typeof Status.HOST;
|
|
18282
|
+
hostCallIndex: U64;
|
|
18319
18283
|
}
|
|
18284
|
+
| {
|
|
18285
|
+
status: typeof Status.FAULT;
|
|
18286
|
+
address: U64;
|
|
18287
|
+
}
|
|
18288
|
+
| {
|
|
18289
|
+
status: typeof Status.OK | typeof Status.HALT | typeof Status.PANIC | typeof Status.OOG;
|
|
18290
|
+
};
|
|
18320
18291
|
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
storageUtilisationCount: items,
|
|
18328
|
-
}),
|
|
18329
|
-
);
|
|
18330
|
-
return Result.ok(OK);
|
|
18331
|
-
}
|
|
18292
|
+
/** Data returned by a machine invocation. */
|
|
18293
|
+
type MachineResult = {
|
|
18294
|
+
result: MachineStatus;
|
|
18295
|
+
gas: BigGas;
|
|
18296
|
+
registers: Registers;
|
|
18297
|
+
};
|
|
18332
18298
|
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
|
|
18345
|
-
|
|
18346
|
-
}),
|
|
18347
|
-
);
|
|
18299
|
+
/** Types of possbile operations to request by Pages host call. */
|
|
18300
|
+
declare enum MemoryOperation {
|
|
18301
|
+
/** Zeroes memory and set access to unreadable. */
|
|
18302
|
+
Void = 0,
|
|
18303
|
+
/** Zeroes memory and set access to read-only. */
|
|
18304
|
+
ZeroRead = 1,
|
|
18305
|
+
/** Zeroes memory and set access to read-write. */
|
|
18306
|
+
ZeroWrite = 2,
|
|
18307
|
+
/** Preserve memory and set access to read-only. */
|
|
18308
|
+
Read = 3,
|
|
18309
|
+
/** Preserve memory and set access to read-write. */
|
|
18310
|
+
Write = 4,
|
|
18311
|
+
}
|
|
18348
18312
|
|
|
18349
|
-
|
|
18350
|
-
|
|
18313
|
+
/** Convert a number into MemoryOperation or null (if invalid). */
|
|
18314
|
+
declare const toMemoryOperation = (v: number | bigint): MemoryOperation | null =>
|
|
18315
|
+
v <= MemoryOperation.Write && v >= MemoryOperation.Void ? Number(v) : null;
|
|
18351
18316
|
|
|
18352
|
-
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18317
|
+
/** An error that may occur during `peek` or `poke` host call. */
|
|
18318
|
+
declare enum PeekPokeError {
|
|
18319
|
+
/** Source page fault. */
|
|
18320
|
+
SourcePageFault = 0,
|
|
18321
|
+
/** Destination page fault. */
|
|
18322
|
+
DestinationPageFault = 1,
|
|
18323
|
+
/** No machine under given machine index. */
|
|
18324
|
+
NoMachine = 2,
|
|
18325
|
+
}
|
|
18361
18326
|
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18327
|
+
declare enum ZeroVoidError {
|
|
18328
|
+
/** No machine under given machine index. */
|
|
18329
|
+
NoMachine = 0,
|
|
18330
|
+
/** Attempting to void or zero non-accessible page. */
|
|
18331
|
+
InvalidPage = 1,
|
|
18332
|
+
}
|
|
18366
18333
|
|
|
18367
|
-
|
|
18368
|
-
|
|
18334
|
+
declare enum PagesError {
|
|
18335
|
+
/** No machine under given machine index. */
|
|
18336
|
+
NoMachine = 0,
|
|
18337
|
+
/** Invalid memory operation. */
|
|
18338
|
+
InvalidOperation = 1,
|
|
18339
|
+
/** Attempting to change non-accessible page or trying to preserve value of voided page. */
|
|
18340
|
+
InvalidPage = 2,
|
|
18369
18341
|
}
|
|
18370
18342
|
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
|
|
18343
|
+
/** Error machine is not found. */
|
|
18344
|
+
declare const NoMachineError = Symbol("Machine index not found.");
|
|
18345
|
+
type NoMachineError = typeof NoMachineError;
|
|
18346
|
+
|
|
18347
|
+
/** Too many segments already exported. */
|
|
18348
|
+
declare const SegmentExportError = Symbol("Too many segments already exported.");
|
|
18349
|
+
type SegmentExportError = typeof SegmentExportError;
|
|
18350
|
+
|
|
18351
|
+
/** Host functions external invocations available during refine phase. */
|
|
18352
|
+
interface RefineExternalities {
|
|
18353
|
+
/** Forget a previously started nested VM. */
|
|
18354
|
+
machineExpunge(machineIndex: MachineId): Promise<Result$2<ProgramCounter, NoMachineError>>;
|
|
18355
|
+
|
|
18356
|
+
/** Set given range of pages as non-accessible and re-initialize them with zeros. */
|
|
18357
|
+
machineVoidPages(machineIndex: MachineId, pageStart: U64, pageCount: U64): Promise<Result$2<OK, ZeroVoidError>>;
|
|
18358
|
+
|
|
18359
|
+
/** Set given range of pages as writeable and initialize them with zeros. */
|
|
18360
|
+
machineZeroPages(machineIndex: MachineId, pageStart: U64, pageCount: U64): Promise<Result$2<OK, ZeroVoidError>>;
|
|
18361
|
+
|
|
18362
|
+
/** Copy a fragment of memory from `machineIndex` into given destination memory. */
|
|
18363
|
+
machinePeekFrom(
|
|
18364
|
+
machineIndex: MachineId,
|
|
18365
|
+
destinationStart: U64,
|
|
18366
|
+
sourceStart: U64,
|
|
18367
|
+
length: U64,
|
|
18368
|
+
destination: IHostCallMemory,
|
|
18369
|
+
): Promise<Result$2<OK, PeekPokeError>>;
|
|
18370
|
+
|
|
18371
|
+
/** Write a fragment of memory into `machineIndex` from given source memory. */
|
|
18372
|
+
machinePokeInto(
|
|
18373
|
+
machineIndex: MachineId,
|
|
18374
|
+
sourceStart: U64,
|
|
18375
|
+
destinationStart: U64,
|
|
18376
|
+
length: U64,
|
|
18377
|
+
source: IHostCallMemory,
|
|
18378
|
+
): Promise<Result$2<OK, PeekPokeError>>;
|
|
18379
|
+
|
|
18380
|
+
/** Start an inner PVM instance with given entry point and starting code. */
|
|
18381
|
+
machineInit(code: BytesBlob, programCounter: ProgramCounter): Promise<Result$2<MachineId, ProgramDecoderError>>;
|
|
18382
|
+
|
|
18383
|
+
/** Run a previously initialized PVM instance with given gas and registers. */
|
|
18384
|
+
machineInvoke(
|
|
18385
|
+
machineIndex: MachineId,
|
|
18386
|
+
gas: BigGas,
|
|
18387
|
+
registers: Registers,
|
|
18388
|
+
): Promise<Result$2<MachineResult, NoMachineError>>;
|
|
18389
|
+
|
|
18390
|
+
/**
|
|
18391
|
+
* Export segment for future retrieval.
|
|
18392
|
+
*
|
|
18393
|
+
* Returns the index assigned to that segment or an error if there is too many already exported.
|
|
18394
|
+
*/
|
|
18395
|
+
exportSegment(segment: Segment): Result$2<SegmentIndex, SegmentExportError>;
|
|
18396
|
+
|
|
18397
|
+
/** Lookup a historical preimage. */
|
|
18398
|
+
historicalLookup(serviceId: ServiceId | null, hash: Blake2bHash): Promise<BytesBlob | null>;
|
|
18399
|
+
|
|
18400
|
+
/** Change access to and/or zero the value of memory. */
|
|
18401
|
+
machinePages(
|
|
18402
|
+
machineIndex: MachineId,
|
|
18403
|
+
pageStart: U64,
|
|
18404
|
+
pageCount: U64,
|
|
18405
|
+
requestType: MemoryOperation | null,
|
|
18406
|
+
): Promise<Result$2<OK, PagesError>>;
|
|
18374
18407
|
}
|
|
18375
18408
|
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
*
|
|
18379
|
-
* https://graypaper.fluffylabs.dev/#/85129da/2c7c022c7c02?v=0.6.3
|
|
18380
|
-
*/
|
|
18381
|
-
declare const HostCallResult = {
|
|
18382
|
-
/** The return value indicating an item does not exist. */
|
|
18383
|
-
NONE: tryAsU64(0xffff_ffff_ffff_ffffn), // 2**64 - 1
|
|
18384
|
-
/** Name unknown. */
|
|
18385
|
-
WHAT: tryAsU64(0xffff_ffff_ffff_fffen), // 2**64 - 2
|
|
18386
|
-
/** The inner PVM memory index provided for reading/writing is not accessible. */
|
|
18387
|
-
OOB: tryAsU64(0xffff_ffff_ffff_fffdn), // 2**64 - 3
|
|
18388
|
-
/** Index unknown. */
|
|
18389
|
-
WHO: tryAsU64(0xffff_ffff_ffff_fffcn), // 2**64 - 4
|
|
18390
|
-
/** Storage full or resource already allocated. */
|
|
18391
|
-
FULL: tryAsU64(0xffff_ffff_ffff_fffbn), // 2**64 - 5
|
|
18392
|
-
/** Core index unknown. */
|
|
18393
|
-
CORE: tryAsU64(0xffff_ffff_ffff_fffan), // 2**64 - 6
|
|
18394
|
-
/** Insufficient funds. */
|
|
18395
|
-
CASH: tryAsU64(0xffff_ffff_ffff_fff9n), // 2**64 - 7
|
|
18396
|
-
/** Gas limit too low. */
|
|
18397
|
-
LOW: tryAsU64(0xffff_ffff_ffff_fff8n), // 2**64 - 8
|
|
18398
|
-
/** The item is already solicited, cannot be forgotten or the operation is invalid due to privilege level. */
|
|
18399
|
-
HUH: tryAsU64(0xffff_ffff_ffff_fff7n), // 2**64 - 9
|
|
18400
|
-
/** The return value indicating general success. */
|
|
18401
|
-
OK: tryAsU64(0n),
|
|
18402
|
-
} as const;
|
|
18409
|
+
declare const InsufficientFundsError = "insufficient funds";
|
|
18410
|
+
type InsufficientFundsError = typeof InsufficientFundsError;
|
|
18403
18411
|
|
|
18404
|
-
|
|
18405
|
-
|
|
18406
|
-
|
|
18407
|
-
|
|
18412
|
+
/** Update of the state entries coming from accumulation of a single service. */
|
|
18413
|
+
type ServiceStateUpdate = Partial<Pick<State, "privilegedServices" | "authQueues" | "designatedValidatorData">> &
|
|
18414
|
+
ServicesUpdate;
|
|
18415
|
+
|
|
18416
|
+
/** Deep clone of a map with array. */
|
|
18417
|
+
declare function deepCloneMapWithArray<K, V>(map: Map<K, V[]>): Map<K, V[]> {
|
|
18418
|
+
const cloned: [K, V[]][] = [];
|
|
18419
|
+
|
|
18420
|
+
for (const [k, v] of map.entries()) {
|
|
18421
|
+
cloned.push([k, v.slice()]);
|
|
18422
|
+
}
|
|
18423
|
+
|
|
18424
|
+
return new Map(cloned);
|
|
18408
18425
|
}
|
|
18409
18426
|
|
|
18410
|
-
|
|
18411
|
-
|
|
18427
|
+
/**
|
|
18428
|
+
* State updates that currently accumulating service produced.
|
|
18429
|
+
*
|
|
18430
|
+
* `x_u`: https://graypaper.fluffylabs.dev/#/9a08063/2f31012f3101?v=0.6.6
|
|
18431
|
+
*/
|
|
18432
|
+
declare class AccumulationStateUpdate {
|
|
18433
|
+
/** Updated authorization queues for cores. */
|
|
18434
|
+
public readonly authorizationQueues: Map<CoreIndex, FixedSizeArray<AuthorizerHash, AUTHORIZATION_QUEUE_SIZE>> =
|
|
18435
|
+
new Map();
|
|
18436
|
+
/** New validators data. */
|
|
18437
|
+
public validatorsData: PerValidator<ValidatorData> | null = null;
|
|
18438
|
+
/** Updated priviliged services. */
|
|
18439
|
+
public privilegedServices: PrivilegedServices | null = null;
|
|
18412
18440
|
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18441
|
+
private constructor(
|
|
18442
|
+
/** Services state updates. */
|
|
18443
|
+
public readonly services: ServicesUpdate,
|
|
18444
|
+
/** Pending transfers. */
|
|
18445
|
+
public transfers: PendingTransfer[],
|
|
18446
|
+
/** Yielded accumulation root. */
|
|
18447
|
+
public readonly yieldedRoots: Map<ServiceId, OpaqueHash> = new Map(),
|
|
18448
|
+
) {}
|
|
18417
18449
|
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
|
|
18450
|
+
/** Create new empty state update. */
|
|
18451
|
+
static empty(): AccumulationStateUpdate {
|
|
18452
|
+
return new AccumulationStateUpdate(
|
|
18453
|
+
{
|
|
18454
|
+
created: [],
|
|
18455
|
+
updated: new Map(),
|
|
18456
|
+
removed: [],
|
|
18457
|
+
preimages: new Map(),
|
|
18458
|
+
storage: new Map(),
|
|
18459
|
+
},
|
|
18460
|
+
[],
|
|
18461
|
+
);
|
|
18462
|
+
}
|
|
18421
18463
|
|
|
18422
|
-
|
|
18464
|
+
/** Create a state update with some existing, yet uncommited services updates. */
|
|
18465
|
+
static new(update: ServicesUpdate): AccumulationStateUpdate {
|
|
18466
|
+
return new AccumulationStateUpdate(
|
|
18467
|
+
{
|
|
18468
|
+
...update,
|
|
18469
|
+
},
|
|
18470
|
+
[],
|
|
18471
|
+
);
|
|
18423
18472
|
}
|
|
18424
18473
|
|
|
18425
|
-
|
|
18426
|
-
|
|
18427
|
-
|
|
18474
|
+
/** Create a copy of another `StateUpdate`. Used by checkpoints. */
|
|
18475
|
+
static copyFrom(from: AccumulationStateUpdate): AccumulationStateUpdate {
|
|
18476
|
+
const serviceUpdates: ServicesUpdate = {
|
|
18477
|
+
// shallow copy
|
|
18478
|
+
created: [...from.services.created],
|
|
18479
|
+
updated: new Map(from.services.updated),
|
|
18480
|
+
removed: [...from.services.removed],
|
|
18481
|
+
// deep copy
|
|
18482
|
+
preimages: deepCloneMapWithArray(from.services.preimages),
|
|
18483
|
+
storage: deepCloneMapWithArray(from.services.storage),
|
|
18484
|
+
};
|
|
18485
|
+
const transfers = [...from.transfers];
|
|
18486
|
+
const update = new AccumulationStateUpdate(serviceUpdates, transfers, new Map(from.yieldedRoots));
|
|
18487
|
+
|
|
18488
|
+
// update entries
|
|
18489
|
+
for (const [k, v] of from.authorizationQueues) {
|
|
18490
|
+
update.authorizationQueues.set(k, v);
|
|
18428
18491
|
}
|
|
18429
18492
|
|
|
18430
|
-
if (
|
|
18431
|
-
|
|
18493
|
+
if (from.validatorsData !== null) {
|
|
18494
|
+
update.validatorsData = asKnownSize([...from.validatorsData]);
|
|
18432
18495
|
}
|
|
18433
18496
|
|
|
18434
|
-
|
|
18497
|
+
if (from.privilegedServices !== null) {
|
|
18498
|
+
update.privilegedServices = PrivilegedServices.create({
|
|
18499
|
+
...from.privilegedServices,
|
|
18500
|
+
assigners: asKnownSize([...from.privilegedServices.assigners]),
|
|
18501
|
+
});
|
|
18502
|
+
}
|
|
18503
|
+
return update;
|
|
18435
18504
|
}
|
|
18436
18505
|
|
|
18437
|
-
|
|
18438
|
-
|
|
18506
|
+
/** Retrieve and clear pending transfers. */
|
|
18507
|
+
takeTransfers() {
|
|
18508
|
+
const transfers = this.transfers;
|
|
18509
|
+
this.transfers = [];
|
|
18510
|
+
return transfers;
|
|
18439
18511
|
}
|
|
18440
18512
|
}
|
|
18441
18513
|
|
|
18442
|
-
|
|
18443
|
-
get(registerIndex: number): U64;
|
|
18444
|
-
set(registerIndex: number, value: U64): void;
|
|
18445
|
-
}
|
|
18446
|
-
|
|
18447
|
-
declare class HostCallRegisters implements IHostCallRegisters {
|
|
18448
|
-
constructor(private readonly registers: Registers) {}
|
|
18514
|
+
type StateSlice = Pick<State, "getService" | "privilegedServices">;
|
|
18449
18515
|
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
18516
|
+
declare class PartiallyUpdatedState<T extends StateSlice = StateSlice> {
|
|
18517
|
+
/** A collection of state updates. */
|
|
18518
|
+
public readonly stateUpdate;
|
|
18453
18519
|
|
|
18454
|
-
|
|
18455
|
-
|
|
18520
|
+
constructor(
|
|
18521
|
+
/** Original (unmodified state). */
|
|
18522
|
+
public readonly state: T,
|
|
18523
|
+
stateUpdate?: AccumulationStateUpdate,
|
|
18524
|
+
) {
|
|
18525
|
+
this.stateUpdate =
|
|
18526
|
+
stateUpdate === undefined ? AccumulationStateUpdate.empty() : AccumulationStateUpdate.copyFrom(stateUpdate);
|
|
18456
18527
|
}
|
|
18457
|
-
}
|
|
18458
18528
|
|
|
18459
|
-
/**
|
|
18460
|
-
|
|
18461
|
-
|
|
18462
|
-
|
|
18529
|
+
/**
|
|
18530
|
+
* Retrieve info of service with given id.
|
|
18531
|
+
*
|
|
18532
|
+
* NOTE the info may be updated compared to what is in the state.
|
|
18533
|
+
*
|
|
18534
|
+
* Takes into account ejected and newly created services as well.
|
|
18535
|
+
*/
|
|
18536
|
+
getServiceInfo(destination: ServiceId | null): ServiceAccountInfo | null {
|
|
18537
|
+
if (destination === null) {
|
|
18538
|
+
return null;
|
|
18539
|
+
}
|
|
18463
18540
|
|
|
18464
|
-
|
|
18465
|
-
* Host-call exit reason.
|
|
18466
|
-
*
|
|
18467
|
-
* https://graypaper.fluffylabs.dev/#/ab2cdbd/24a30124a501?v=0.7.2
|
|
18468
|
-
*/
|
|
18469
|
-
declare enum PvmExecution {
|
|
18470
|
-
Halt = 0,
|
|
18471
|
-
Panic = 1,
|
|
18472
|
-
OOG = 2, // out-of-gas
|
|
18473
|
-
}
|
|
18541
|
+
const maybeUpdatedServiceInfo = this.stateUpdate.services.updated.get(destination);
|
|
18474
18542
|
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
}
|
|
18543
|
+
if (maybeUpdatedServiceInfo !== undefined) {
|
|
18544
|
+
return maybeUpdatedServiceInfo.action.account;
|
|
18545
|
+
}
|
|
18479
18546
|
|
|
18480
|
-
|
|
18481
|
-
|
|
18482
|
-
|
|
18483
|
-
|
|
18547
|
+
const maybeService = this.state.getService(destination);
|
|
18548
|
+
if (maybeService === null) {
|
|
18549
|
+
return null;
|
|
18550
|
+
}
|
|
18484
18551
|
|
|
18485
|
-
|
|
18486
|
-
|
|
18487
|
-
*
|
|
18488
|
-
* NOTE: `((reg: IHostCallRegisters) => Gas)` function is for compatibility reasons: pre GP 0.7.2
|
|
18489
|
-
*/
|
|
18490
|
-
readonly basicGasCost: SmallGas | ((reg: IHostCallRegisters) => Gas);
|
|
18552
|
+
return maybeService.getInfo();
|
|
18553
|
+
}
|
|
18491
18554
|
|
|
18492
|
-
|
|
18493
|
-
|
|
18555
|
+
getStorage(serviceId: ServiceId, rawKey: StorageKey): BytesBlob | null {
|
|
18556
|
+
const storages = this.stateUpdate.services.storage.get(serviceId) ?? [];
|
|
18557
|
+
const item = storages.find((x) => x.key.isEqualTo(rawKey));
|
|
18558
|
+
if (item !== undefined) {
|
|
18559
|
+
return item.value;
|
|
18560
|
+
}
|
|
18494
18561
|
|
|
18495
|
-
|
|
18496
|
-
|
|
18562
|
+
const service = this.state.getService(serviceId);
|
|
18563
|
+
return service?.getStorage(rawKey) ?? null;
|
|
18564
|
+
}
|
|
18497
18565
|
|
|
18498
18566
|
/**
|
|
18499
|
-
*
|
|
18567
|
+
* Returns `true` if the preimage is already provided either in current
|
|
18568
|
+
* accumulation scope or earlier.
|
|
18500
18569
|
*
|
|
18501
|
-
* NOTE
|
|
18570
|
+
* NOTE: Does not check if the preimage is available, we just check
|
|
18571
|
+
* the existence in `preimages` map.
|
|
18502
18572
|
*/
|
|
18503
|
-
|
|
18504
|
-
|
|
18573
|
+
hasPreimage(serviceId: ServiceId, hash: PreimageHash): boolean {
|
|
18574
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
18575
|
+
const providedPreimage = preimages.find(
|
|
18576
|
+
// we ignore the action here, since if there is <any> update on that
|
|
18577
|
+
// hash it means it has to exist, right?
|
|
18578
|
+
(p) => p.hash.isEqualTo(hash),
|
|
18579
|
+
);
|
|
18580
|
+
if (providedPreimage !== undefined) {
|
|
18581
|
+
return true;
|
|
18582
|
+
}
|
|
18505
18583
|
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18584
|
+
// fallback to state preimages
|
|
18585
|
+
const service = this.state.getService(serviceId);
|
|
18586
|
+
if (service === undefined) {
|
|
18587
|
+
return false;
|
|
18588
|
+
}
|
|
18510
18589
|
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
handlers = [],
|
|
18514
|
-
}: {
|
|
18515
|
-
missing: HostCallHandler;
|
|
18516
|
-
handlers?: HostCallHandler[];
|
|
18517
|
-
}) {
|
|
18518
|
-
this.missing = missing;
|
|
18590
|
+
return service?.hasPreimage(hash) ?? false;
|
|
18591
|
+
}
|
|
18519
18592
|
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18593
|
+
getPreimage(serviceId: ServiceId, hash: PreimageHash): BytesBlob | null {
|
|
18594
|
+
// TODO [ToDr] Should we verify availability here?
|
|
18595
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
18596
|
+
const freshlyProvided = preimages.find((x) => x.hash.isEqualTo(hash));
|
|
18597
|
+
if (freshlyProvided !== undefined && freshlyProvided.action.kind === UpdatePreimageKind.Provide) {
|
|
18598
|
+
return freshlyProvided.action.preimage.blob;
|
|
18523
18599
|
}
|
|
18524
|
-
}
|
|
18525
18600
|
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
return this.hostCalls.get(hostCallIndex) ?? this.missing;
|
|
18601
|
+
const service = this.state.getService(serviceId);
|
|
18602
|
+
return service?.getPreimage(hash) ?? null;
|
|
18529
18603
|
}
|
|
18530
18604
|
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
|
|
18535
|
-
|
|
18536
|
-
|
|
18537
|
-
) {
|
|
18538
|
-
const
|
|
18539
|
-
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
18544
|
-
|
|
18545
|
-
return `r${idx}=${value} (0x${value.toString(16)})`;
|
|
18546
|
-
})
|
|
18547
|
-
.join(", ");
|
|
18548
|
-
logger.insane`[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
|
|
18549
|
-
}
|
|
18550
|
-
}
|
|
18605
|
+
/** Get status of a preimage of current service taking into account any updates. */
|
|
18606
|
+
getLookupHistory(
|
|
18607
|
+
currentTimeslot: TimeSlot,
|
|
18608
|
+
serviceId: ServiceId,
|
|
18609
|
+
hash: PreimageHash,
|
|
18610
|
+
length: U64,
|
|
18611
|
+
): LookupHistoryItem | null {
|
|
18612
|
+
const preimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
18613
|
+
// TODO [ToDr] This is most likely wrong. We may have `provide` and `remove` within
|
|
18614
|
+
// the same state update. We should however switch to proper "updated state"
|
|
18615
|
+
// representation soon.
|
|
18616
|
+
const updatedPreimage = preimages.findLast(
|
|
18617
|
+
(update) => update.hash.isEqualTo(hash) && BigInt(update.length) === length,
|
|
18618
|
+
);
|
|
18551
18619
|
|
|
18552
|
-
|
|
18620
|
+
const stateFallback = () => {
|
|
18621
|
+
// fallback to state lookup
|
|
18622
|
+
const service = this.state.getService(serviceId);
|
|
18623
|
+
const lenU32 = preimageLenAsU32(length);
|
|
18624
|
+
if (lenU32 === null || service === null) {
|
|
18625
|
+
return null;
|
|
18626
|
+
}
|
|
18553
18627
|
|
|
18554
|
-
|
|
18555
|
-
|
|
18556
|
-
|
|
18628
|
+
const slots = service.getLookupHistory(hash, lenU32);
|
|
18629
|
+
return slots === null ? null : new LookupHistoryItem(hash, lenU32, slots);
|
|
18630
|
+
};
|
|
18557
18631
|
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
this.instances.push(
|
|
18561
|
-
new Interpreter({
|
|
18562
|
-
useSbrkGas: false,
|
|
18563
|
-
}),
|
|
18564
|
-
);
|
|
18632
|
+
if (updatedPreimage === undefined) {
|
|
18633
|
+
return stateFallback();
|
|
18565
18634
|
}
|
|
18566
|
-
}
|
|
18567
18635
|
|
|
18568
|
-
|
|
18569
|
-
|
|
18570
|
-
|
|
18571
|
-
|
|
18636
|
+
const { action } = updatedPreimage;
|
|
18637
|
+
switch (action.kind) {
|
|
18638
|
+
case UpdatePreimageKind.Provide: {
|
|
18639
|
+
// casting to U32 is safe, since we compare with object we have in memory.
|
|
18640
|
+
return new LookupHistoryItem(hash, updatedPreimage.length, tryAsLookupHistorySlots([currentTimeslot]));
|
|
18641
|
+
}
|
|
18642
|
+
case UpdatePreimageKind.Remove: {
|
|
18643
|
+
const state = stateFallback();
|
|
18644
|
+
// kinda impossible, since we know it's there because it's removed.
|
|
18645
|
+
if (state === null) {
|
|
18646
|
+
return null;
|
|
18647
|
+
}
|
|
18648
|
+
|
|
18649
|
+
return new LookupHistoryItem(hash, state.length, tryAsLookupHistorySlots([...state.slots, currentTimeslot]));
|
|
18650
|
+
}
|
|
18651
|
+
case UpdatePreimageKind.UpdateOrAdd: {
|
|
18652
|
+
return action.item;
|
|
18653
|
+
}
|
|
18572
18654
|
}
|
|
18573
|
-
return new Promise((resolve) => {
|
|
18574
|
-
this.waitingQueue.push(resolve);
|
|
18575
|
-
});
|
|
18576
|
-
}
|
|
18577
18655
|
|
|
18578
|
-
|
|
18579
|
-
const waiting = this.waitingQueue.shift();
|
|
18580
|
-
if (waiting !== undefined) {
|
|
18581
|
-
return waiting(pvm);
|
|
18582
|
-
}
|
|
18583
|
-
this.instances.push(pvm);
|
|
18656
|
+
assertNever(action);
|
|
18584
18657
|
}
|
|
18585
|
-
}
|
|
18586
18658
|
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
|
|
18590
|
-
|
|
18591
|
-
|
|
18592
|
-
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
|
|
18596
|
-
`;
|
|
18597
|
-
}
|
|
18659
|
+
/* State update functions. */
|
|
18660
|
+
updateStorage(serviceId: ServiceId, key: StorageKey, value: BytesBlob | null) {
|
|
18661
|
+
const update =
|
|
18662
|
+
value === null
|
|
18663
|
+
? UpdateStorage.remove({ key })
|
|
18664
|
+
: UpdateStorage.set({
|
|
18665
|
+
storage: StorageItem.create({ key, value }),
|
|
18666
|
+
});
|
|
18598
18667
|
|
|
18599
|
-
|
|
18600
|
-
|
|
18668
|
+
const storages = this.stateUpdate.services.storage.get(serviceId) ?? [];
|
|
18669
|
+
const index = storages.findIndex((x) => x.key.isEqualTo(key));
|
|
18670
|
+
const count = index === -1 ? 0 : 1;
|
|
18671
|
+
storages.splice(index, count, update);
|
|
18672
|
+
this.stateUpdate.services.storage.set(serviceId, storages);
|
|
18601
18673
|
}
|
|
18602
18674
|
|
|
18603
|
-
|
|
18604
|
-
|
|
18675
|
+
/**
|
|
18676
|
+
* Update a preimage.
|
|
18677
|
+
*
|
|
18678
|
+
* Note we store all previous entries as well, since there might be a sequence of:
|
|
18679
|
+
* `provide` -> `remove` and both should update the end state somehow.
|
|
18680
|
+
*/
|
|
18681
|
+
updatePreimage(serviceId: ServiceId, newUpdate: UpdatePreimage) {
|
|
18682
|
+
const updatePreimages = this.stateUpdate.services.preimages.get(serviceId) ?? [];
|
|
18683
|
+
updatePreimages.push(newUpdate);
|
|
18684
|
+
this.stateUpdate.services.preimages.set(serviceId, updatePreimages);
|
|
18605
18685
|
}
|
|
18606
18686
|
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18687
|
+
updateServiceStorageUtilisation(
|
|
18688
|
+
serviceId: ServiceId,
|
|
18689
|
+
items: number,
|
|
18690
|
+
bytes: bigint,
|
|
18691
|
+
serviceInfo: ServiceAccountInfo,
|
|
18692
|
+
): Result$2<OK, InsufficientFundsError> {
|
|
18693
|
+
check`${items >= 0} storageUtilisationCount has to be a positive number, got: ${items}`;
|
|
18694
|
+
check`${bytes >= 0} storageUtilisationBytes has to be a positive number, got: ${bytes}`;
|
|
18610
18695
|
|
|
18611
|
-
|
|
18612
|
-
|
|
18613
|
-
}
|
|
18614
|
-
}
|
|
18615
|
-
declare class HostCalls {
|
|
18616
|
-
constructor(
|
|
18617
|
-
private pvmInstanceManager: InterpreterInstanceManager,
|
|
18618
|
-
private hostCalls: HostCallsManager,
|
|
18619
|
-
) {}
|
|
18696
|
+
const overflowItems = !isU32(items);
|
|
18697
|
+
const overflowBytes = !isU64(bytes);
|
|
18620
18698
|
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18699
|
+
// TODO [ToDr] this is not specified in GP, but it seems sensible.
|
|
18700
|
+
if (overflowItems || overflowBytes) {
|
|
18701
|
+
return Result.error(
|
|
18702
|
+
InsufficientFundsError,
|
|
18703
|
+
() => `Storage utilisation overflow: items=${overflowItems}, bytes=${overflowBytes}`,
|
|
18704
|
+
);
|
|
18625
18705
|
}
|
|
18626
18706
|
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
18632
|
-
|
|
18633
|
-
const result = safeAllocUint8Array(maybeLength);
|
|
18634
|
-
const startAddress = tryAsMemoryIndex(maybeAddress);
|
|
18635
|
-
const loadResult = memory.loadInto(result, startAddress);
|
|
18636
|
-
|
|
18637
|
-
if (loadResult.isError) {
|
|
18638
|
-
return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
|
|
18639
|
-
}
|
|
18640
|
-
|
|
18641
|
-
return ReturnValue.fromMemorySlice(gasConsumed, result);
|
|
18707
|
+
const thresholdBalance = ServiceAccountInfo.calculateThresholdBalance(items, bytes, serviceInfo.gratisStorage);
|
|
18708
|
+
if (serviceInfo.balance < thresholdBalance) {
|
|
18709
|
+
return Result.error(
|
|
18710
|
+
InsufficientFundsError,
|
|
18711
|
+
() => `Service balance (${serviceInfo.balance}) below threshold (${thresholdBalance})`,
|
|
18712
|
+
);
|
|
18642
18713
|
}
|
|
18643
18714
|
|
|
18644
|
-
|
|
18715
|
+
// Update service info with new details.
|
|
18716
|
+
this.updateServiceInfo(
|
|
18717
|
+
serviceId,
|
|
18718
|
+
ServiceAccountInfo.create({
|
|
18719
|
+
...serviceInfo,
|
|
18720
|
+
storageUtilisationBytes: bytes,
|
|
18721
|
+
storageUtilisationCount: items,
|
|
18722
|
+
}),
|
|
18723
|
+
);
|
|
18724
|
+
return Result.ok(OK);
|
|
18645
18725
|
}
|
|
18646
18726
|
|
|
18647
|
-
|
|
18648
|
-
|
|
18649
|
-
for (;;) {
|
|
18650
|
-
let status = pvmInstance.getStatus();
|
|
18651
|
-
if (status !== Status.HOST) {
|
|
18652
|
-
return this.getReturnValue(status, pvmInstance);
|
|
18653
|
-
}
|
|
18654
|
-
check`
|
|
18655
|
-
${pvmInstance.getExitParam() !== null}
|
|
18656
|
-
"We know that the exit param is not null, because the status is 'Status.HOST'
|
|
18657
|
-
`;
|
|
18658
|
-
const hostCallIndex = pvmInstance.getExitParam() ?? -1;
|
|
18659
|
-
const gas = pvmInstance.getGasCounter();
|
|
18660
|
-
const regs = new HostCallRegisters(pvmInstance.getRegisters());
|
|
18661
|
-
const memory = new HostCallMemory(pvmInstance.getMemory());
|
|
18662
|
-
const index = tryAsHostCallIndex(hostCallIndex);
|
|
18663
|
-
|
|
18664
|
-
const hostCall = this.hostCalls.get(index);
|
|
18665
|
-
const gasBefore = gas.get();
|
|
18666
|
-
// NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
|
|
18667
|
-
const basicGasCost =
|
|
18668
|
-
typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
|
|
18669
|
-
const underflow = gas.sub(basicGasCost);
|
|
18727
|
+
updateServiceInfo(serviceId: ServiceId, newInfo: ServiceAccountInfo) {
|
|
18728
|
+
const existingUpdate = this.stateUpdate.services.updated.get(serviceId);
|
|
18670
18729
|
|
|
18671
|
-
|
|
18672
|
-
|
|
18673
|
-
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
this.hostCalls.traceHostCall(
|
|
18679
|
-
result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`,
|
|
18680
|
-
index,
|
|
18681
|
-
hostCall,
|
|
18682
|
-
regs,
|
|
18683
|
-
gas.get(),
|
|
18730
|
+
if (existingUpdate?.action.kind === UpdateServiceKind.Create) {
|
|
18731
|
+
this.stateUpdate.services.updated.set(
|
|
18732
|
+
serviceId,
|
|
18733
|
+
UpdateService.create({
|
|
18734
|
+
serviceInfo: newInfo,
|
|
18735
|
+
lookupHistory: existingUpdate.action.lookupHistory,
|
|
18736
|
+
}),
|
|
18684
18737
|
);
|
|
18738
|
+
return;
|
|
18739
|
+
}
|
|
18685
18740
|
|
|
18686
|
-
|
|
18687
|
-
|
|
18688
|
-
|
|
18689
|
-
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
|
|
18693
|
-
return this.getReturnValue(status, pvmInstance);
|
|
18694
|
-
}
|
|
18695
|
-
|
|
18696
|
-
if (result === PvmExecution.OOG) {
|
|
18697
|
-
status = Status.OOG;
|
|
18698
|
-
return this.getReturnValue(status, pvmInstance);
|
|
18699
|
-
}
|
|
18700
|
-
|
|
18701
|
-
if (result === undefined) {
|
|
18702
|
-
pvmInstance.runProgram();
|
|
18703
|
-
status = pvmInstance.getStatus();
|
|
18704
|
-
continue;
|
|
18705
|
-
}
|
|
18741
|
+
this.stateUpdate.services.updated.set(
|
|
18742
|
+
serviceId,
|
|
18743
|
+
UpdateService.update({
|
|
18744
|
+
serviceInfo: newInfo,
|
|
18745
|
+
}),
|
|
18746
|
+
);
|
|
18747
|
+
}
|
|
18706
18748
|
|
|
18707
|
-
|
|
18708
|
-
|
|
18749
|
+
createService(serviceId: ServiceId, newInfo: ServiceAccountInfo, newLookupHistory: LookupHistoryItem) {
|
|
18750
|
+
this.stateUpdate.services.created.push(serviceId);
|
|
18751
|
+
this.stateUpdate.services.updated.set(
|
|
18752
|
+
serviceId,
|
|
18753
|
+
UpdateService.create({
|
|
18754
|
+
serviceInfo: newInfo,
|
|
18755
|
+
lookupHistory: newLookupHistory,
|
|
18756
|
+
}),
|
|
18757
|
+
);
|
|
18709
18758
|
}
|
|
18710
18759
|
|
|
18711
|
-
|
|
18712
|
-
|
|
18713
|
-
|
|
18714
|
-
initialGas: Gas,
|
|
18715
|
-
maybeRegisters?: Registers,
|
|
18716
|
-
maybeMemory?: Memory,
|
|
18717
|
-
): Promise<ReturnValue> {
|
|
18718
|
-
const pvmInstance = await this.pvmInstanceManager.getInstance();
|
|
18719
|
-
pvmInstance.reset(rawProgram, initialPc, initialGas, maybeRegisters, maybeMemory);
|
|
18720
|
-
try {
|
|
18721
|
-
return await this.execute(pvmInstance);
|
|
18722
|
-
} finally {
|
|
18723
|
-
this.pvmInstanceManager.releaseInstance(pvmInstance);
|
|
18760
|
+
getPrivilegedServices() {
|
|
18761
|
+
if (this.stateUpdate.privilegedServices !== null) {
|
|
18762
|
+
return this.stateUpdate.privilegedServices;
|
|
18724
18763
|
}
|
|
18764
|
+
|
|
18765
|
+
return this.state.privilegedServices;
|
|
18725
18766
|
}
|
|
18726
18767
|
}
|
|
18727
18768
|
|
|
18728
|
-
|
|
18729
|
-
|
|
18730
|
-
|
|
18731
|
-
type index$7_HostCallRegisters = HostCallRegisters;
|
|
18732
|
-
declare const index$7_HostCallRegisters: typeof HostCallRegisters;
|
|
18733
|
-
type index$7_IHostCallMemory = IHostCallMemory;
|
|
18734
|
-
type index$7_IHostCallRegisters = IHostCallRegisters;
|
|
18735
|
-
type index$7_PvmExecution = PvmExecution;
|
|
18736
|
-
declare const index$7_PvmExecution: typeof PvmExecution;
|
|
18737
|
-
declare const index$7_traceRegisters: typeof traceRegisters;
|
|
18738
|
-
declare const index$7_tryAsHostCallIndex: typeof tryAsHostCallIndex;
|
|
18739
|
-
declare namespace index$7 {
|
|
18740
|
-
export { index$7_HostCallMemory as HostCallMemory, index$7_HostCallRegisters as HostCallRegisters, HostCallsManager as HostCalls, index$7_PvmExecution as PvmExecution, HostCalls as PvmHostCallExtension, InterpreterInstanceManager as PvmInstanceManager, index$7_traceRegisters as traceRegisters, index$7_tryAsHostCallIndex as tryAsHostCallIndex };
|
|
18741
|
-
export type { index$7_HostCallHandler as HostCallHandler, index$7_IHostCallMemory as IHostCallMemory, index$7_IHostCallRegisters as IHostCallRegisters };
|
|
18769
|
+
declare function preimageLenAsU32(length: U64) {
|
|
18770
|
+
// Safe to convert to Number and U32: we check that len < 2^32 before conversion
|
|
18771
|
+
return length >= 2n ** 32n ? null : tryAsU32(Number(length));
|
|
18742
18772
|
}
|
|
18743
18773
|
|
|
18774
|
+
/**
|
|
18775
|
+
* Host call result constants.
|
|
18776
|
+
*
|
|
18777
|
+
* https://graypaper.fluffylabs.dev/#/85129da/2c7c022c7c02?v=0.6.3
|
|
18778
|
+
*/
|
|
18779
|
+
declare const HostCallResult = {
|
|
18780
|
+
/** The return value indicating an item does not exist. */
|
|
18781
|
+
NONE: tryAsU64(0xffff_ffff_ffff_ffffn), // 2**64 - 1
|
|
18782
|
+
/** Name unknown. */
|
|
18783
|
+
WHAT: tryAsU64(0xffff_ffff_ffff_fffen), // 2**64 - 2
|
|
18784
|
+
/** The inner PVM memory index provided for reading/writing is not accessible. */
|
|
18785
|
+
OOB: tryAsU64(0xffff_ffff_ffff_fffdn), // 2**64 - 3
|
|
18786
|
+
/** Index unknown. */
|
|
18787
|
+
WHO: tryAsU64(0xffff_ffff_ffff_fffcn), // 2**64 - 4
|
|
18788
|
+
/** Storage full or resource already allocated. */
|
|
18789
|
+
FULL: tryAsU64(0xffff_ffff_ffff_fffbn), // 2**64 - 5
|
|
18790
|
+
/** Core index unknown. */
|
|
18791
|
+
CORE: tryAsU64(0xffff_ffff_ffff_fffan), // 2**64 - 6
|
|
18792
|
+
/** Insufficient funds. */
|
|
18793
|
+
CASH: tryAsU64(0xffff_ffff_ffff_fff9n), // 2**64 - 7
|
|
18794
|
+
/** Gas limit too low. */
|
|
18795
|
+
LOW: tryAsU64(0xffff_ffff_ffff_fff8n), // 2**64 - 8
|
|
18796
|
+
/** The item is already solicited, cannot be forgotten or the operation is invalid due to privilege level. */
|
|
18797
|
+
HUH: tryAsU64(0xffff_ffff_ffff_fff7n), // 2**64 - 9
|
|
18798
|
+
/** The return value indicating general success. */
|
|
18799
|
+
OK: tryAsU64(0n),
|
|
18800
|
+
} as const;
|
|
18801
|
+
|
|
18744
18802
|
declare const MAX_U32 = tryAsU32(2 ** 32 - 1);
|
|
18745
18803
|
declare const MAX_U32_BIG_INT = tryAsU64(MAX_U32);
|
|
18746
18804
|
declare const SERVICE_ID_BYTES = 4;
|
|
@@ -18831,6 +18889,7 @@ declare const index$6_UpdatePrivilegesError: typeof UpdatePrivilegesError;
|
|
|
18831
18889
|
type index$6_ZeroVoidError = ZeroVoidError;
|
|
18832
18890
|
declare const index$6_ZeroVoidError: typeof ZeroVoidError;
|
|
18833
18891
|
declare const index$6_clampU64ToU32: typeof clampU64ToU32;
|
|
18892
|
+
declare const index$6_deepCloneMapWithArray: typeof deepCloneMapWithArray;
|
|
18834
18893
|
declare const index$6_getServiceId: typeof getServiceId;
|
|
18835
18894
|
declare const index$6_getServiceIdOrCurrent: typeof getServiceIdOrCurrent;
|
|
18836
18895
|
declare const index$6_preimageLenAsU32: typeof preimageLenAsU32;
|
|
@@ -18840,7 +18899,7 @@ declare const index$6_tryAsMachineId: typeof tryAsMachineId;
|
|
|
18840
18899
|
declare const index$6_tryAsProgramCounter: typeof tryAsProgramCounter;
|
|
18841
18900
|
declare const index$6_writeServiceIdAsLeBytes: typeof writeServiceIdAsLeBytes;
|
|
18842
18901
|
declare namespace index$6 {
|
|
18843
|
-
export { index$6_AccumulationStateUpdate as AccumulationStateUpdate, index$6_CURRENT_SERVICE_ID as CURRENT_SERVICE_ID, index$6_EjectError as EjectError, index$6_ForgetPreimageError as ForgetPreimageError, index$6_HostCallResult as HostCallResult, index$6_MAX_U32 as MAX_U32, index$6_MAX_U32_BIG_INT as MAX_U32_BIG_INT, index$6_MachineInstance as MachineInstance, index$6_MemoryOperation as MemoryOperation, index$6_NewServiceError as NewServiceError, index$6_PagesError as PagesError, index$6_PartiallyUpdatedState as PartiallyUpdatedState, index$6_PeekPokeError as PeekPokeError, index$6_PendingTransfer as PendingTransfer, index$6_PreimageStatusKind as PreimageStatusKind, index$6_ProvidePreimageError as ProvidePreimageError, index$6_RequestPreimageError as RequestPreimageError, index$6_SERVICE_ID_BYTES as SERVICE_ID_BYTES, index$6_TransferError as TransferError, index$6_UpdatePrivilegesError as UpdatePrivilegesError, index$6_ZeroVoidError as ZeroVoidError, index$6_clampU64ToU32 as clampU64ToU32, index$6_getServiceId as getServiceId, index$6_getServiceIdOrCurrent as getServiceIdOrCurrent, index$6_preimageLenAsU32 as preimageLenAsU32, index$6_slotsToPreimageStatus as slotsToPreimageStatus, index$6_toMemoryOperation as toMemoryOperation, index$6_tryAsMachineId as tryAsMachineId, index$6_tryAsProgramCounter as tryAsProgramCounter, index$6_writeServiceIdAsLeBytes as writeServiceIdAsLeBytes };
|
|
18902
|
+
export { index$6_AccumulationStateUpdate as AccumulationStateUpdate, index$6_CURRENT_SERVICE_ID as CURRENT_SERVICE_ID, index$6_EjectError as EjectError, index$6_ForgetPreimageError as ForgetPreimageError, index$6_HostCallResult as HostCallResult, index$6_MAX_U32 as MAX_U32, index$6_MAX_U32_BIG_INT as MAX_U32_BIG_INT, index$6_MachineInstance as MachineInstance, index$6_MemoryOperation as MemoryOperation, index$6_NewServiceError as NewServiceError, index$6_PagesError as PagesError, index$6_PartiallyUpdatedState as PartiallyUpdatedState, index$6_PeekPokeError as PeekPokeError, index$6_PendingTransfer as PendingTransfer, index$6_PreimageStatusKind as PreimageStatusKind, index$6_ProvidePreimageError as ProvidePreimageError, index$6_RequestPreimageError as RequestPreimageError, index$6_SERVICE_ID_BYTES as SERVICE_ID_BYTES, index$6_TransferError as TransferError, index$6_UpdatePrivilegesError as UpdatePrivilegesError, index$6_ZeroVoidError as ZeroVoidError, index$6_clampU64ToU32 as clampU64ToU32, index$6_deepCloneMapWithArray as deepCloneMapWithArray, index$6_getServiceId as getServiceId, index$6_getServiceIdOrCurrent as getServiceIdOrCurrent, index$6_preimageLenAsU32 as preimageLenAsU32, index$6_slotsToPreimageStatus as slotsToPreimageStatus, index$6_toMemoryOperation as toMemoryOperation, index$6_tryAsMachineId as tryAsMachineId, index$6_tryAsProgramCounter as tryAsProgramCounter, index$6_writeServiceIdAsLeBytes as writeServiceIdAsLeBytes };
|
|
18844
18903
|
export type { index$6_InsufficientFundsError as InsufficientFundsError, index$6_MachineId as MachineId, index$6_MachineResult as MachineResult, index$6_MachineStatus as MachineStatus, index$6_NoMachineError as NoMachineError, index$6_PartialState as PartialState, index$6_PreimageStatus as PreimageStatus, index$6_ProgramCounter as ProgramCounter, index$6_RefineExternalities as RefineExternalities, index$6_SegmentExportError as SegmentExportError, index$6_ServiceStateUpdate as ServiceStateUpdate, index$6_StateSlice as StateSlice, index$6_TRANSFER_MEMO_BYTES as TRANSFER_MEMO_BYTES, index$6_UnprivilegedError as UnprivilegedError };
|
|
18845
18904
|
}
|
|
18846
18905
|
|
|
@@ -19241,6 +19300,7 @@ declare const index$3_check: typeof check;
|
|
|
19241
19300
|
declare const index$3_clampU64ToU32: typeof clampU64ToU32;
|
|
19242
19301
|
declare const index$3_createResults: typeof createResults;
|
|
19243
19302
|
declare const index$3_decodeStandardProgram: typeof decodeStandardProgram;
|
|
19303
|
+
declare const index$3_deepCloneMapWithArray: typeof deepCloneMapWithArray;
|
|
19244
19304
|
declare const index$3_extractCodeAndMetadata: typeof extractCodeAndMetadata;
|
|
19245
19305
|
declare const index$3_getServiceId: typeof getServiceId;
|
|
19246
19306
|
declare const index$3_getServiceIdOrCurrent: typeof getServiceIdOrCurrent;
|
|
@@ -19259,7 +19319,7 @@ declare const index$3_tryAsMachineId: typeof tryAsMachineId;
|
|
|
19259
19319
|
declare const index$3_tryAsProgramCounter: typeof tryAsProgramCounter;
|
|
19260
19320
|
declare const index$3_writeServiceIdAsLeBytes: typeof writeServiceIdAsLeBytes;
|
|
19261
19321
|
declare namespace index$3 {
|
|
19262
|
-
export { index$3_AccumulationStateUpdate as AccumulationStateUpdate, index$3_ArgsDecoder as ArgsDecoder, index$3_ArgumentType as ArgumentType, index$3_BasicBlocks as BasicBlocks, index$3_CURRENT_SERVICE_ID as CURRENT_SERVICE_ID, index$3_EjectError as EjectError, index$3_ExtendedWitdthImmediateDecoder as ExtendedWitdthImmediateDecoder, index$3_ForgetPreimageError as ForgetPreimageError, index$3_HostCallMemory as HostCallMemory, index$3_HostCallRegisters as HostCallRegisters, index$3_HostCallResult as HostCallResult, index$3_ImmediateDecoder as ImmediateDecoder, index$3_MAX_U32 as MAX_U32, index$3_MAX_U32_BIG_INT as MAX_U32_BIG_INT, index$3_MachineInstance as MachineInstance, index$3_Mask as Mask, index$3_MemoryOperation as MemoryOperation, index$3_MemorySegment as MemorySegment, NO_OF_REGISTERS$1 as NO_OF_REGISTERS, index$3_NewServiceError as NewServiceError, index$3_NibblesDecoder as NibblesDecoder, index$3_PagesError as PagesError, index$3_PartiallyUpdatedState as PartiallyUpdatedState, index$3_PeekPokeError as PeekPokeError, index$3_PendingTransfer as PendingTransfer, index$3_PreimageStatusKind as PreimageStatusKind, index$3_Program as Program, index$3_ProgramDecoder as ProgramDecoder, index$3_ProvidePreimageError as ProvidePreimageError, DebuggerAdapter as Pvm, index$3_Registers as Registers, index$3_RequestPreimageError as RequestPreimageError, Result$2 as Result, index$3_RichTaggedError as RichTaggedError, index$3_SERVICE_ID_BYTES as SERVICE_ID_BYTES, index$3_SpiMemory as SpiMemory, index$3_SpiProgram as SpiProgram, index$3_TransferError as TransferError, index$3_UpdatePrivilegesError as UpdatePrivilegesError, index$3_WithDebug as WithDebug, index$3_ZeroVoidError as ZeroVoidError, index$3___OPAQUE_TYPE__ as __OPAQUE_TYPE__, index$3_asOpaqueType as asOpaqueType, index$3_assertEmpty as assertEmpty, index$3_assertNever as assertNever, index$l as block, index$s as bytes, index$3_check as check, index$3_clampU64ToU32 as clampU64ToU32, index$3_createResults as createResults, index$3_decodeStandardProgram as decodeStandardProgram, index$3_extractCodeAndMetadata as extractCodeAndMetadata, index$3_getServiceId as getServiceId, index$3_getServiceIdOrCurrent as getServiceIdOrCurrent, index$p as hash, index$3_inspect as inspect, index$3_instructionArgumentTypeMap as instructionArgumentTypeMap, index$8 as interpreter, index$3_isBrowser as isBrowser, index$3_isTaggedError as isTaggedError, index$3_maybeTaggedErrorToString as maybeTaggedErrorToString, index$3_measure as measure, index$r as numbers, index$3_preimageLenAsU32 as preimageLenAsU32, index$3_resultToString as resultToString, index$3_seeThrough as seeThrough, index$3_slotsToPreimageStatus as slotsToPreimageStatus, index$3_toMemoryOperation as toMemoryOperation, index$3_tryAsMachineId as tryAsMachineId, index$3_tryAsProgramCounter as tryAsProgramCounter, index$3_writeServiceIdAsLeBytes as writeServiceIdAsLeBytes };
|
|
19322
|
+
export { index$3_AccumulationStateUpdate as AccumulationStateUpdate, index$3_ArgsDecoder as ArgsDecoder, index$3_ArgumentType as ArgumentType, index$3_BasicBlocks as BasicBlocks, index$3_CURRENT_SERVICE_ID as CURRENT_SERVICE_ID, index$3_EjectError as EjectError, index$3_ExtendedWitdthImmediateDecoder as ExtendedWitdthImmediateDecoder, index$3_ForgetPreimageError as ForgetPreimageError, index$3_HostCallMemory as HostCallMemory, index$3_HostCallRegisters as HostCallRegisters, index$3_HostCallResult as HostCallResult, index$3_ImmediateDecoder as ImmediateDecoder, index$3_MAX_U32 as MAX_U32, index$3_MAX_U32_BIG_INT as MAX_U32_BIG_INT, index$3_MachineInstance as MachineInstance, index$3_Mask as Mask, index$3_MemoryOperation as MemoryOperation, index$3_MemorySegment as MemorySegment, NO_OF_REGISTERS$1 as NO_OF_REGISTERS, index$3_NewServiceError as NewServiceError, index$3_NibblesDecoder as NibblesDecoder, index$3_PagesError as PagesError, index$3_PartiallyUpdatedState as PartiallyUpdatedState, index$3_PeekPokeError as PeekPokeError, index$3_PendingTransfer as PendingTransfer, index$3_PreimageStatusKind as PreimageStatusKind, index$3_Program as Program, index$3_ProgramDecoder as ProgramDecoder, index$3_ProvidePreimageError as ProvidePreimageError, DebuggerAdapter as Pvm, index$3_Registers as Registers, index$3_RequestPreimageError as RequestPreimageError, Result$2 as Result, index$3_RichTaggedError as RichTaggedError, index$3_SERVICE_ID_BYTES as SERVICE_ID_BYTES, index$3_SpiMemory as SpiMemory, index$3_SpiProgram as SpiProgram, index$3_TransferError as TransferError, index$3_UpdatePrivilegesError as UpdatePrivilegesError, index$3_WithDebug as WithDebug, index$3_ZeroVoidError as ZeroVoidError, index$3___OPAQUE_TYPE__ as __OPAQUE_TYPE__, index$3_asOpaqueType as asOpaqueType, index$3_assertEmpty as assertEmpty, index$3_assertNever as assertNever, index$l as block, index$s as bytes, index$3_check as check, index$3_clampU64ToU32 as clampU64ToU32, index$3_createResults as createResults, index$3_decodeStandardProgram as decodeStandardProgram, index$3_deepCloneMapWithArray as deepCloneMapWithArray, index$3_extractCodeAndMetadata as extractCodeAndMetadata, index$3_getServiceId as getServiceId, index$3_getServiceIdOrCurrent as getServiceIdOrCurrent, index$p as hash, index$3_inspect as inspect, index$3_instructionArgumentTypeMap as instructionArgumentTypeMap, index$8 as interpreter, index$3_isBrowser as isBrowser, index$3_isTaggedError as isTaggedError, index$3_maybeTaggedErrorToString as maybeTaggedErrorToString, index$3_measure as measure, index$r as numbers, index$3_preimageLenAsU32 as preimageLenAsU32, index$3_resultToString as resultToString, index$3_seeThrough as seeThrough, index$3_slotsToPreimageStatus as slotsToPreimageStatus, index$3_toMemoryOperation as toMemoryOperation, index$3_tryAsMachineId as tryAsMachineId, index$3_tryAsProgramCounter as tryAsProgramCounter, index$3_writeServiceIdAsLeBytes as writeServiceIdAsLeBytes };
|
|
19263
19323
|
export type { index$3_Args as Args, index$3_EnumMapping as EnumMapping, index$3_ErrorResult as ErrorResult, index$3_IHostCallMemory as IHostCallMemory, index$3_IHostCallRegisters as IHostCallRegisters, index$3_InsufficientFundsError as InsufficientFundsError, index$3_MachineId as MachineId, index$3_MachineResult as MachineResult, index$3_MachineStatus as MachineStatus, index$3_NoMachineError as NoMachineError, index$3_OK as OK, index$3_OkResult as OkResult, index$3_Opaque as Opaque, index$3_PartialState as PartialState, index$3_PreimageStatus as PreimageStatus, index$3_ProgramCounter as ProgramCounter, index$3_RefineExternalities as RefineExternalities, index$3_SegmentExportError as SegmentExportError, index$3_ServiceStateUpdate as ServiceStateUpdate, index$3_StateSlice as StateSlice, index$3_StringLiteral as StringLiteral, index$3_TRANSFER_MEMO_BYTES as TRANSFER_MEMO_BYTES, index$3_TaggedError as TaggedError, index$3_TokenOf as TokenOf, index$3_Uninstantiable as Uninstantiable, index$3_UnprivilegedError as UnprivilegedError, index$3_WithOpaque as WithOpaque };
|
|
19264
19324
|
}
|
|
19265
19325
|
|
|
@@ -20089,12 +20149,15 @@ declare class Preimages {
|
|
|
20089
20149
|
prevPreimage.requester > currPreimage.requester ||
|
|
20090
20150
|
currPreimage.blob.compare(prevPreimage.blob).isLessOrEqual()
|
|
20091
20151
|
) {
|
|
20092
|
-
return Result.error(
|
|
20152
|
+
return Result.error(
|
|
20153
|
+
PreimagesErrorCode.PreimagesNotSortedUnique,
|
|
20154
|
+
() => `Preimages not sorted/unique at index ${i}`,
|
|
20155
|
+
);
|
|
20093
20156
|
}
|
|
20094
20157
|
}
|
|
20095
20158
|
|
|
20096
20159
|
const { preimages, slot } = input;
|
|
20097
|
-
const pendingChanges
|
|
20160
|
+
const pendingChanges = new Map<ServiceId, UpdatePreimage[]>();
|
|
20098
20161
|
|
|
20099
20162
|
// select preimages for integration
|
|
20100
20163
|
for (const preimage of preimages) {
|
|
@@ -20103,7 +20166,7 @@ declare class Preimages {
|
|
|
20103
20166
|
|
|
20104
20167
|
const service = this.state.getService(requester);
|
|
20105
20168
|
if (service === null) {
|
|
20106
|
-
return Result.error(PreimagesErrorCode.AccountNotFound);
|
|
20169
|
+
return Result.error(PreimagesErrorCode.AccountNotFound, () => `Service not found: ${requester}`);
|
|
20107
20170
|
}
|
|
20108
20171
|
|
|
20109
20172
|
const hasPreimage = service.hasPreimage(hash);
|
|
@@ -20111,17 +20174,22 @@ declare class Preimages {
|
|
|
20111
20174
|
// https://graypaper.fluffylabs.dev/#/5f542d7/181800181900
|
|
20112
20175
|
// https://graypaper.fluffylabs.dev/#/5f542d7/116f0011a500
|
|
20113
20176
|
if (hasPreimage || slots === null || !LookupHistoryItem.isRequested(slots)) {
|
|
20114
|
-
return Result.error(
|
|
20177
|
+
return Result.error(
|
|
20178
|
+
PreimagesErrorCode.PreimageUnneeded,
|
|
20179
|
+
() =>
|
|
20180
|
+
`Preimage unneeded: requester=${requester}, hash=${hash}, hasPreimage=${hasPreimage}, isRequested=${slots !== null && LookupHistoryItem.isRequested(slots)}`,
|
|
20181
|
+
);
|
|
20115
20182
|
}
|
|
20116
20183
|
|
|
20117
20184
|
// https://graypaper.fluffylabs.dev/#/5f542d7/18c00018f300
|
|
20118
|
-
pendingChanges.
|
|
20185
|
+
const updates = pendingChanges.get(requester) ?? [];
|
|
20186
|
+
updates.push(
|
|
20119
20187
|
UpdatePreimage.provide({
|
|
20120
|
-
serviceId: requester,
|
|
20121
20188
|
preimage: PreimageItem.create({ hash, blob }),
|
|
20122
20189
|
slot,
|
|
20123
20190
|
}),
|
|
20124
20191
|
);
|
|
20192
|
+
pendingChanges.set(requester, updates);
|
|
20125
20193
|
}
|
|
20126
20194
|
|
|
20127
20195
|
return Result.ok({
|