@typeberry/convert 0.1.3-707962d → 0.1.3-d3752d8
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.js +205 -91
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -5264,6 +5264,20 @@ const result_Result = {
|
|
|
5264
5264
|
},
|
|
5265
5265
|
};
|
|
5266
5266
|
|
|
5267
|
+
;// CONCATENATED MODULE: ./packages/core/utils/safe-alloc-uint8array.ts
|
|
5268
|
+
// about 2GB, the maximum ArrayBuffer length on Chrome confirmed by several sources:
|
|
5269
|
+
// - https://issues.chromium.org/issues/40055619
|
|
5270
|
+
// - https://stackoverflow.com/a/72124984
|
|
5271
|
+
// - https://onnxruntime.ai/docs/tutorials/web/large-models.html#maximum-size-of-arraybuffer
|
|
5272
|
+
const MAX_LENGTH = 2145386496;
|
|
5273
|
+
function safe_alloc_uint8array_safeAllocUint8Array(length) {
|
|
5274
|
+
if (length > MAX_LENGTH) {
|
|
5275
|
+
// biome-ignore lint/suspicious/noConsole: can't have a dependency on logger here
|
|
5276
|
+
console.warn(`Trying to allocate ${length} bytes, which is greater than the maximum of ${MAX_LENGTH}.`);
|
|
5277
|
+
}
|
|
5278
|
+
return new Uint8Array(Math.min(MAX_LENGTH, length));
|
|
5279
|
+
}
|
|
5280
|
+
|
|
5267
5281
|
;// CONCATENATED MODULE: external "node:assert"
|
|
5268
5282
|
const external_node_assert_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:assert");
|
|
5269
5283
|
;// CONCATENATED MODULE: ./packages/core/utils/test.ts
|
|
@@ -5507,6 +5521,7 @@ function isResult(x) {
|
|
|
5507
5521
|
|
|
5508
5522
|
|
|
5509
5523
|
|
|
5524
|
+
|
|
5510
5525
|
// EXTERNAL MODULE: ./node_modules/minimist/index.js
|
|
5511
5526
|
var minimist = __nccwpck_require__(595);
|
|
5512
5527
|
var minimist_default = /*#__PURE__*/__nccwpck_require__.n(minimist);
|
|
@@ -5533,7 +5548,7 @@ class bitvec_BitVec {
|
|
|
5533
5548
|
* Create new [`BitVec`] with all values set to `false`.
|
|
5534
5549
|
*/
|
|
5535
5550
|
static empty(bitLength) {
|
|
5536
|
-
const data =
|
|
5551
|
+
const data = safe_alloc_uint8array_safeAllocUint8Array(Math.ceil(bitLength / 8));
|
|
5537
5552
|
return new bitvec_BitVec(data, bitLength);
|
|
5538
5553
|
}
|
|
5539
5554
|
byteLength;
|
|
@@ -5733,7 +5748,7 @@ class bytes_BytesBlob {
|
|
|
5733
5748
|
static blobFromParts(v, ...rest) {
|
|
5734
5749
|
const vArr = v instanceof Uint8Array ? [v] : v;
|
|
5735
5750
|
const totalLength = vArr.reduce((a, v) => a + v.length, 0) + rest.reduce((a, v) => a + v.length, 0);
|
|
5736
|
-
const buffer =
|
|
5751
|
+
const buffer = safe_alloc_uint8array_safeAllocUint8Array(totalLength);
|
|
5737
5752
|
let offset = 0;
|
|
5738
5753
|
for (const r of vArr) {
|
|
5739
5754
|
buffer.set(r, offset);
|
|
@@ -5806,7 +5821,7 @@ class bytes_Bytes extends bytes_BytesBlob {
|
|
|
5806
5821
|
}
|
|
5807
5822
|
/** Create an empty [`Bytes<X>`] of given length. */
|
|
5808
5823
|
static zero(len) {
|
|
5809
|
-
return new bytes_Bytes(
|
|
5824
|
+
return new bytes_Bytes(safe_alloc_uint8array_safeAllocUint8Array(len), len);
|
|
5810
5825
|
}
|
|
5811
5826
|
// TODO [ToDr] `fill` should have the argments swapped to align with the rest.
|
|
5812
5827
|
/** Create a [`Bytes<X>`] with all bytes filled with given input number. */
|
|
@@ -6476,7 +6491,7 @@ function addSizeHints(a, b) {
|
|
|
6476
6491
|
};
|
|
6477
6492
|
}
|
|
6478
6493
|
const DEFAULT_START_LENGTH = 512; // 512B
|
|
6479
|
-
const
|
|
6494
|
+
const encoder_MAX_LENGTH = 10 * 1024 * 1024; // 10MB
|
|
6480
6495
|
/**
|
|
6481
6496
|
* JAM encoder.
|
|
6482
6497
|
*/
|
|
@@ -6492,7 +6507,7 @@ class encoder_Encoder {
|
|
|
6492
6507
|
return new encoder_Encoder(options.destination);
|
|
6493
6508
|
}
|
|
6494
6509
|
const startLength = options?.expectedLength ?? DEFAULT_START_LENGTH;
|
|
6495
|
-
const buffer = new ArrayBuffer(Math.min(
|
|
6510
|
+
const buffer = new ArrayBuffer(Math.min(encoder_MAX_LENGTH, startLength), { maxByteLength: encoder_MAX_LENGTH });
|
|
6496
6511
|
const destination = new Uint8Array(buffer);
|
|
6497
6512
|
return new encoder_Encoder(destination, buffer);
|
|
6498
6513
|
}
|
|
@@ -6825,11 +6840,11 @@ class encoder_Encoder {
|
|
|
6825
6840
|
ensureBigEnough(length, options = { silent: false }) {
|
|
6826
6841
|
debug_check `${length >= 0} Negative length given`;
|
|
6827
6842
|
const newLength = this.offset + length;
|
|
6828
|
-
if (newLength >
|
|
6843
|
+
if (newLength > encoder_MAX_LENGTH) {
|
|
6829
6844
|
if (options.silent) {
|
|
6830
6845
|
return;
|
|
6831
6846
|
}
|
|
6832
|
-
throw new Error(`The encoded size would reach the maximum of ${
|
|
6847
|
+
throw new Error(`The encoded size would reach the maximum of ${encoder_MAX_LENGTH}.`);
|
|
6833
6848
|
}
|
|
6834
6849
|
if (newLength > this.destination.length) {
|
|
6835
6850
|
// we can try to resize the underlying buffer
|
|
@@ -6837,7 +6852,7 @@ class encoder_Encoder {
|
|
|
6837
6852
|
// make sure we at least double the size of the buffer every time.
|
|
6838
6853
|
const minExtend = Math.max(newLength, this.buffer.byteLength << 1);
|
|
6839
6854
|
// but we must never exceed the max length.
|
|
6840
|
-
this.buffer.resize(Math.min(
|
|
6855
|
+
this.buffer.resize(Math.min(encoder_MAX_LENGTH, minExtend));
|
|
6841
6856
|
}
|
|
6842
6857
|
// and then check again
|
|
6843
6858
|
if (newLength > this.destination.length) {
|
|
@@ -8169,7 +8184,7 @@ async function verify(input) {
|
|
|
8169
8184
|
return Promise.resolve([]);
|
|
8170
8185
|
}
|
|
8171
8186
|
const dataLength = input.reduce((acc, { message, key, signature }) => acc + key.length + signature.length + message.length + 1, 0);
|
|
8172
|
-
const data =
|
|
8187
|
+
const data = safeAllocUint8Array(dataLength);
|
|
8173
8188
|
let offset = 0;
|
|
8174
8189
|
for (const { key, message, signature } of input) {
|
|
8175
8190
|
data.set(key.raw, offset);
|
|
@@ -8256,7 +8271,7 @@ class allocator_SimpleAllocator {
|
|
|
8256
8271
|
/** An allocator that works by allocating larger (continuous) pages of memory. */
|
|
8257
8272
|
class PageAllocator {
|
|
8258
8273
|
hashesPerPage;
|
|
8259
|
-
page =
|
|
8274
|
+
page = safeAllocUint8Array(0);
|
|
8260
8275
|
currentHash = 0;
|
|
8261
8276
|
// TODO [ToDr] Benchmark the performance!
|
|
8262
8277
|
constructor(hashesPerPage) {
|
|
@@ -8267,7 +8282,7 @@ class PageAllocator {
|
|
|
8267
8282
|
resetPage() {
|
|
8268
8283
|
const pageSizeBytes = this.hashesPerPage * HASH_SIZE;
|
|
8269
8284
|
this.currentHash = 0;
|
|
8270
|
-
this.page =
|
|
8285
|
+
this.page = safeAllocUint8Array(pageSizeBytes);
|
|
8271
8286
|
}
|
|
8272
8287
|
emptyHash() {
|
|
8273
8288
|
const startIdx = this.currentHash * HASH_SIZE;
|
|
@@ -12190,6 +12205,10 @@ class disputes_DisputesRecords {
|
|
|
12190
12205
|
static create({ goodSet, badSet, wonkySet, punishSet }) {
|
|
12191
12206
|
return new disputes_DisputesRecords(goodSet, badSet, wonkySet, punishSet);
|
|
12192
12207
|
}
|
|
12208
|
+
goodSetDict;
|
|
12209
|
+
badSetDict;
|
|
12210
|
+
wonkySetDict;
|
|
12211
|
+
punishSetDict;
|
|
12193
12212
|
constructor(
|
|
12194
12213
|
/** `goodSet`: all work-reports hashes which were judged to be correct */
|
|
12195
12214
|
goodSet,
|
|
@@ -12203,6 +12222,18 @@ class disputes_DisputesRecords {
|
|
|
12203
12222
|
this.badSet = badSet;
|
|
12204
12223
|
this.wonkySet = wonkySet;
|
|
12205
12224
|
this.punishSet = punishSet;
|
|
12225
|
+
this.goodSetDict = hash_set_HashSet.from(goodSet.array);
|
|
12226
|
+
this.badSetDict = hash_set_HashSet.from(badSet.array);
|
|
12227
|
+
this.wonkySetDict = hash_set_HashSet.from(wonkySet.array);
|
|
12228
|
+
this.punishSetDict = hash_set_HashSet.from(punishSet.array);
|
|
12229
|
+
}
|
|
12230
|
+
asDictionaries() {
|
|
12231
|
+
return {
|
|
12232
|
+
goodSet: this.goodSetDict,
|
|
12233
|
+
badSet: this.badSetDict,
|
|
12234
|
+
wonkySet: this.wonkySetDict,
|
|
12235
|
+
punishSet: this.punishSetDict,
|
|
12236
|
+
};
|
|
12206
12237
|
}
|
|
12207
12238
|
static fromSortedArrays({ goodSet, badSet, wonkySet, punishSet, }) {
|
|
12208
12239
|
return new disputes_DisputesRecords(sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, goodSet), sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, badSet), sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, wonkySet), sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, punishSet));
|
|
@@ -14645,7 +14676,7 @@ class SerializedService {
|
|
|
14645
14676
|
getStorage(rawKey) {
|
|
14646
14677
|
if (compatibility_Compatibility.isLessThan(compatibility_GpVersion.V0_6_7)) {
|
|
14647
14678
|
const SERVICE_ID_BYTES = 4;
|
|
14648
|
-
const serviceIdAndKey =
|
|
14679
|
+
const serviceIdAndKey = safe_alloc_uint8array_safeAllocUint8Array(SERVICE_ID_BYTES + rawKey.length);
|
|
14649
14680
|
serviceIdAndKey.set(numbers_u32AsLeBytes(this.serviceId));
|
|
14650
14681
|
serviceIdAndKey.set(rawKey.raw, SERVICE_ID_BYTES);
|
|
14651
14682
|
const key = opaque_asOpaqueType(bytes_BytesBlob.blobFrom(hashBytes(serviceIdAndKey).raw));
|
|
@@ -14736,7 +14767,7 @@ class nodes_TrieNode {
|
|
|
14736
14767
|
raw;
|
|
14737
14768
|
constructor(
|
|
14738
14769
|
/** Exactly 512 bits / 64 bytes */
|
|
14739
|
-
raw =
|
|
14770
|
+
raw = safe_alloc_uint8array_safeAllocUint8Array(nodes_TRIE_NODE_BYTES)) {
|
|
14740
14771
|
this.raw = raw;
|
|
14741
14772
|
}
|
|
14742
14773
|
/** Returns the type of the node */
|
|
@@ -16171,7 +16202,7 @@ class registers_Registers {
|
|
|
16171
16202
|
bytes;
|
|
16172
16203
|
asSigned;
|
|
16173
16204
|
asUnsigned;
|
|
16174
|
-
constructor(bytes =
|
|
16205
|
+
constructor(bytes = safeAllocUint8Array(registers_NO_OF_REGISTERS << REGISTER_SIZE_SHIFT)) {
|
|
16175
16206
|
this.bytes = bytes;
|
|
16176
16207
|
check `${bytes.length === registers_NO_OF_REGISTERS << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
16177
16208
|
this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
|
|
@@ -16247,10 +16278,16 @@ function registers_signExtend32To64(value) {
|
|
|
16247
16278
|
|
|
16248
16279
|
/** Attempt to convert a number into `HostCallIndex`. */
|
|
16249
16280
|
const host_call_handler_tryAsHostCallIndex = (v) => opaque_asOpaqueType(numbers_tryAsU32(v));
|
|
16281
|
+
/**
|
|
16282
|
+
* Host-call exit reason.
|
|
16283
|
+
*
|
|
16284
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/24a30124a501?v=0.7.2
|
|
16285
|
+
*/
|
|
16250
16286
|
var host_call_handler_PvmExecution;
|
|
16251
16287
|
(function (PvmExecution) {
|
|
16252
16288
|
PvmExecution[PvmExecution["Halt"] = 0] = "Halt";
|
|
16253
16289
|
PvmExecution[PvmExecution["Panic"] = 1] = "Panic";
|
|
16290
|
+
PvmExecution[PvmExecution["OOG"] = 2] = "OOG";
|
|
16254
16291
|
})(host_call_handler_PvmExecution || (host_call_handler_PvmExecution = {}));
|
|
16255
16292
|
/** A utility function to easily trace a bunch of registers. */
|
|
16256
16293
|
function host_call_handler_traceRegisters(...regs) {
|
|
@@ -16328,7 +16365,7 @@ class mask_Mask {
|
|
|
16328
16365
|
return Math.min(this.lookupTableForward[index] ?? 0, MAX_INSTRUCTION_DISTANCE);
|
|
16329
16366
|
}
|
|
16330
16367
|
buildLookupTableForward(mask) {
|
|
16331
|
-
const table =
|
|
16368
|
+
const table = safeAllocUint8Array(mask.bitLength);
|
|
16332
16369
|
let lastInstructionOffset = 0;
|
|
16333
16370
|
for (let i = mask.bitLength - 1; i >= 0; i--) {
|
|
16334
16371
|
if (mask.isSet(i)) {
|
|
@@ -19839,7 +19876,7 @@ class host_calls_HostCalls {
|
|
|
19839
19876
|
const regs = pvmInstance.getRegisters();
|
|
19840
19877
|
const maybeAddress = regs.getLowerU32(7);
|
|
19841
19878
|
const maybeLength = regs.getLowerU32(8);
|
|
19842
|
-
const result =
|
|
19879
|
+
const result = safeAllocUint8Array(maybeLength);
|
|
19843
19880
|
const startAddress = tryAsMemoryIndex(maybeAddress);
|
|
19844
19881
|
const loadResult = memory.loadInto(result, startAddress);
|
|
19845
19882
|
if (loadResult.isError) {
|
|
@@ -19867,8 +19904,9 @@ class host_calls_HostCalls {
|
|
|
19867
19904
|
const index = tryAsHostCallIndex(hostCallIndex);
|
|
19868
19905
|
const hostCall = this.hostCalls.get(index);
|
|
19869
19906
|
const gasBefore = gas.get();
|
|
19870
|
-
|
|
19871
|
-
const
|
|
19907
|
+
// NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
|
|
19908
|
+
const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
|
|
19909
|
+
const underflow = gas.sub(basicGasCost);
|
|
19872
19910
|
const pcLog = `[PC: ${pvmInstance.getPC()}]`;
|
|
19873
19911
|
if (underflow) {
|
|
19874
19912
|
this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
|
|
@@ -19885,6 +19923,10 @@ class host_calls_HostCalls {
|
|
|
19885
19923
|
status = Status.PANIC;
|
|
19886
19924
|
return this.getReturnValue(status, pvmInstance);
|
|
19887
19925
|
}
|
|
19926
|
+
if (result === PvmExecution.OOG) {
|
|
19927
|
+
status = Status.OOG;
|
|
19928
|
+
return this.getReturnValue(status, pvmInstance);
|
|
19929
|
+
}
|
|
19888
19930
|
if (result === undefined) {
|
|
19889
19931
|
pvmInstance.runProgram();
|
|
19890
19932
|
status = pvmInstance.getStatus();
|
|
@@ -19943,7 +19985,7 @@ class host_calls_manager_HostCallsManager {
|
|
|
19943
19985
|
}
|
|
19944
19986
|
class NoopMissing {
|
|
19945
19987
|
index = tryAsHostCallIndex(2 ** 32 - 1);
|
|
19946
|
-
|
|
19988
|
+
basicGasCost = tryAsSmallGas(0);
|
|
19947
19989
|
currentServiceId = tryAsU32(0);
|
|
19948
19990
|
tracedRegisters = [];
|
|
19949
19991
|
async execute() {
|
|
@@ -20057,7 +20099,7 @@ function utils_clampU64ToU32(value) {
|
|
|
20057
20099
|
|
|
20058
20100
|
class missing_Missing {
|
|
20059
20101
|
index = tryAsHostCallIndex(2 ** 32 - 1);
|
|
20060
|
-
|
|
20102
|
+
basicGasCost = tryAsSmallGas(10);
|
|
20061
20103
|
currentServiceId = CURRENT_SERVICE_ID;
|
|
20062
20104
|
tracedRegisters = traceRegisters(7);
|
|
20063
20105
|
execute(_gas, regs, _memory) {
|
|
@@ -20434,7 +20476,7 @@ class disputes_Disputes {
|
|
|
20434
20476
|
const { key, workReportHash } = disputes.culprits[i];
|
|
20435
20477
|
// check if some offenders weren't reported earlier
|
|
20436
20478
|
// https://graypaper.fluffylabs.dev/#/579bd12/125501125501
|
|
20437
|
-
const isInPunishSet = this.state.disputesRecords.punishSet.
|
|
20479
|
+
const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
|
|
20438
20480
|
if (isInPunishSet) {
|
|
20439
20481
|
return Result.error(DisputesErrorCode.OffenderAlreadyReported);
|
|
20440
20482
|
}
|
|
@@ -20445,8 +20487,8 @@ class disputes_Disputes {
|
|
|
20445
20487
|
}
|
|
20446
20488
|
// verify if the culprit will be in new bad set
|
|
20447
20489
|
// https://graypaper.fluffylabs.dev/#/579bd12/124601124601
|
|
20448
|
-
const isInNewBadSet = newItems.
|
|
20449
|
-
if (isInNewBadSet
|
|
20490
|
+
const isInNewBadSet = newItems.asDictionaries().badSet.has(workReportHash);
|
|
20491
|
+
if (!isInNewBadSet) {
|
|
20450
20492
|
return Result.error(DisputesErrorCode.CulpritsVerdictNotBad);
|
|
20451
20493
|
}
|
|
20452
20494
|
// verify culprit signature
|
|
@@ -20469,7 +20511,7 @@ class disputes_Disputes {
|
|
|
20469
20511
|
const { key, workReportHash, wasConsideredValid } = disputes.faults[i];
|
|
20470
20512
|
// check if some offenders weren't reported earlier
|
|
20471
20513
|
// https://graypaper.fluffylabs.dev/#/579bd12/12a20112a201
|
|
20472
|
-
const isInPunishSet = this.state.disputesRecords.punishSet.
|
|
20514
|
+
const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
|
|
20473
20515
|
if (isInPunishSet) {
|
|
20474
20516
|
return Result.error(DisputesErrorCode.OffenderAlreadyReported);
|
|
20475
20517
|
}
|
|
@@ -20484,9 +20526,10 @@ class disputes_Disputes {
|
|
|
20484
20526
|
// but it does not pass the tests
|
|
20485
20527
|
// https://graypaper.fluffylabs.dev/#/579bd12/128a01129601
|
|
20486
20528
|
if (wasConsideredValid) {
|
|
20487
|
-
const
|
|
20488
|
-
const
|
|
20489
|
-
|
|
20529
|
+
const { goodSet, badSet } = newItems.asDictionaries();
|
|
20530
|
+
const isInNewGoodSet = goodSet.has(workReportHash);
|
|
20531
|
+
const isInNewBadSet = badSet.has(workReportHash);
|
|
20532
|
+
if (isInNewGoodSet || !isInNewBadSet) {
|
|
20490
20533
|
return Result.error(DisputesErrorCode.FaultVerdictWrong);
|
|
20491
20534
|
}
|
|
20492
20535
|
}
|
|
@@ -20539,10 +20582,11 @@ class disputes_Disputes {
|
|
|
20539
20582
|
for (const verdict of disputes.verdicts) {
|
|
20540
20583
|
// current verdicts should not be reported earlier
|
|
20541
20584
|
// https://graypaper.fluffylabs.dev/#/579bd12/122202122202
|
|
20542
|
-
const
|
|
20543
|
-
const
|
|
20544
|
-
const
|
|
20545
|
-
|
|
20585
|
+
const { goodSet, badSet, wonkySet } = this.state.disputesRecords.asDictionaries();
|
|
20586
|
+
const isInGoodSet = goodSet.has(verdict.workReportHash);
|
|
20587
|
+
const isInBadSet = badSet.has(verdict.workReportHash);
|
|
20588
|
+
const isInWonkySet = wonkySet.has(verdict.workReportHash);
|
|
20589
|
+
if (isInGoodSet || isInBadSet || isInWonkySet) {
|
|
20546
20590
|
return Result.error(DisputesErrorCode.AlreadyJudged);
|
|
20547
20591
|
}
|
|
20548
20592
|
}
|
|
@@ -20612,11 +20656,12 @@ class disputes_Disputes {
|
|
|
20612
20656
|
toAddToWonkySet.push(r);
|
|
20613
20657
|
}
|
|
20614
20658
|
}
|
|
20615
|
-
return {
|
|
20616
|
-
|
|
20617
|
-
|
|
20618
|
-
|
|
20619
|
-
|
|
20659
|
+
return DisputesRecords.create({
|
|
20660
|
+
goodSet: SortedSet.fromArrayUnique(hashComparator, toAddToGoodSet),
|
|
20661
|
+
badSet: SortedSet.fromArrayUnique(hashComparator, toAddToBadSet),
|
|
20662
|
+
wonkySet: SortedSet.fromArrayUnique(hashComparator, toAddToWonkySet),
|
|
20663
|
+
punishSet: SortedSet.fromArray(hashComparator, []),
|
|
20664
|
+
});
|
|
20620
20665
|
}
|
|
20621
20666
|
getClearedCoreAssignment(v) {
|
|
20622
20667
|
/**
|
|
@@ -20651,9 +20696,9 @@ class disputes_Disputes {
|
|
|
20651
20696
|
const toAddToPunishSet = SortedArray.fromArray(hashComparator, Array.from(offenders));
|
|
20652
20697
|
return DisputesRecords.create({
|
|
20653
20698
|
// https://graypaper.fluffylabs.dev/#/579bd12/12690312bc03
|
|
20654
|
-
goodSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.goodSet, newItems.
|
|
20655
|
-
badSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.badSet, newItems.
|
|
20656
|
-
wonkySet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.wonkySet, newItems.
|
|
20699
|
+
goodSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.goodSet, newItems.goodSet),
|
|
20700
|
+
badSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.badSet, newItems.badSet),
|
|
20701
|
+
wonkySet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.wonkySet, newItems.wonkySet),
|
|
20657
20702
|
punishSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.punishSet, toAddToPunishSet),
|
|
20658
20703
|
});
|
|
20659
20704
|
}
|
|
@@ -20755,6 +20800,15 @@ var ResultValues;
|
|
|
20755
20800
|
ResultValues[ResultValues["Ok"] = 0] = "Ok";
|
|
20756
20801
|
ResultValues[ResultValues["Error"] = 1] = "Error";
|
|
20757
20802
|
})(ResultValues || (ResultValues = {}));
|
|
20803
|
+
/**
|
|
20804
|
+
* Getting a ring commitment is pretty expensive (hundreds of ms),
|
|
20805
|
+
* yet the validators do not always change.
|
|
20806
|
+
* For current benchmarks, we get a huge hit every epoch, hence
|
|
20807
|
+
* to overcome that we cache the results of getting ring commitment.
|
|
20808
|
+
* Note we can also tentatively populate this cache, before we even
|
|
20809
|
+
* reach the epoch change block.
|
|
20810
|
+
*/
|
|
20811
|
+
const ringCommitmentCache = [];
|
|
20758
20812
|
// TODO [ToDr] We export the entire object to allow mocking in tests.
|
|
20759
20813
|
// Ideally we would just export functions and figure out how to mock
|
|
20760
20814
|
// properly in ESM.
|
|
@@ -20770,9 +20824,27 @@ async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUn
|
|
|
20770
20824
|
}
|
|
20771
20825
|
return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
|
|
20772
20826
|
}
|
|
20773
|
-
|
|
20774
|
-
const keys = bytes_BytesBlob.blobFromParts(validators.map((x) => x.raw))
|
|
20775
|
-
|
|
20827
|
+
function getRingCommitment(bandersnatch, validators) {
|
|
20828
|
+
const keys = bytes_BytesBlob.blobFromParts(validators.map((x) => x.raw));
|
|
20829
|
+
// We currently compare the large bytes blob, but the number of entries in the cache
|
|
20830
|
+
// must be low. If the cache ever grows larger, we should rather consider hashing the keys.
|
|
20831
|
+
const MAX_CACHE_ENTRIES = 3;
|
|
20832
|
+
const cacheEntry = ringCommitmentCache.find((v) => v.keys.isEqualTo(keys));
|
|
20833
|
+
if (cacheEntry !== undefined) {
|
|
20834
|
+
return cacheEntry.value;
|
|
20835
|
+
}
|
|
20836
|
+
const value = getRingCommitmentNoCache(bandersnatch, keys);
|
|
20837
|
+
ringCommitmentCache.push({
|
|
20838
|
+
keys,
|
|
20839
|
+
value,
|
|
20840
|
+
});
|
|
20841
|
+
if (ringCommitmentCache.length > MAX_CACHE_ENTRIES) {
|
|
20842
|
+
ringCommitmentCache.shift();
|
|
20843
|
+
}
|
|
20844
|
+
return value;
|
|
20845
|
+
}
|
|
20846
|
+
async function getRingCommitmentNoCache(bandersnatch, keys) {
|
|
20847
|
+
const commitmentResult = await bandersnatch.getRingCommitment(keys.raw);
|
|
20776
20848
|
if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
|
|
20777
20849
|
return result_Result.error(null);
|
|
20778
20850
|
}
|
|
@@ -20898,6 +20970,18 @@ class safrole_Safrole {
|
|
|
20898
20970
|
}
|
|
20899
20971
|
return FixedSizeArray.new([newRandomnessAcc, ...rest], 4);
|
|
20900
20972
|
}
|
|
20973
|
+
/**
|
|
20974
|
+
* Pre-populate cache for validator keys, and especially the ring commitment.
|
|
20975
|
+
*
|
|
20976
|
+
* NOTE the function is still doing quite some work, so it should only be used
|
|
20977
|
+
* once per epoch. The optimisation relies on the fact that the `bandersnatch.getRingCommitment`
|
|
20978
|
+
* call will be cached.
|
|
20979
|
+
*/
|
|
20980
|
+
async prepareValidatorKeysForNextEpoch(postOffenders) {
|
|
20981
|
+
const stateEpoch = Math.floor(this.state.timeslot / this.chainSpec.epochLength);
|
|
20982
|
+
const nextEpochStart = (stateEpoch + 1) * this.chainSpec.epochLength;
|
|
20983
|
+
return await this.getValidatorKeys(tryAsTimeSlot(nextEpochStart), postOffenders);
|
|
20984
|
+
}
|
|
20901
20985
|
async getValidatorKeys(timeslot, postOffenders) {
|
|
20902
20986
|
/**
|
|
20903
20987
|
* Epoch is not changed so the previous state is returned
|
|
@@ -23037,7 +23121,7 @@ class Assign {
|
|
|
23037
23121
|
partialState;
|
|
23038
23122
|
chainSpec;
|
|
23039
23123
|
index = host_call_handler_tryAsHostCallIndex(15);
|
|
23040
|
-
|
|
23124
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23041
23125
|
tracedRegisters = host_call_handler_traceRegisters(IN_OUT_REG, 8);
|
|
23042
23126
|
constructor(currentServiceId, partialState, chainSpec) {
|
|
23043
23127
|
this.currentServiceId = currentServiceId;
|
|
@@ -23051,7 +23135,7 @@ class Assign {
|
|
|
23051
23135
|
const authorizationQueueStart = regs.get(8);
|
|
23052
23136
|
// a
|
|
23053
23137
|
const authManager = getServiceId(regs.get(9));
|
|
23054
|
-
const res =
|
|
23138
|
+
const res = safe_alloc_uint8array_safeAllocUint8Array(hash_HASH_SIZE * gp_constants_AUTHORIZATION_QUEUE_SIZE);
|
|
23055
23139
|
const memoryReadResult = memory.loadInto(res, authorizationQueueStart);
|
|
23056
23140
|
// error while reading the memory.
|
|
23057
23141
|
if (memoryReadResult.isError) {
|
|
@@ -23115,7 +23199,7 @@ class Bless {
|
|
|
23115
23199
|
partialState;
|
|
23116
23200
|
chainSpec;
|
|
23117
23201
|
index = host_call_handler_tryAsHostCallIndex(14);
|
|
23118
|
-
|
|
23202
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23119
23203
|
tracedRegisters = host_call_handler_traceRegisters(bless_IN_OUT_REG, 8, 9, 10, 11);
|
|
23120
23204
|
constructor(currentServiceId, partialState, chainSpec) {
|
|
23121
23205
|
this.currentServiceId = currentServiceId;
|
|
@@ -23139,7 +23223,7 @@ class Bless {
|
|
|
23139
23223
|
* https://graypaper.fluffylabs.dev/#/7e6ff6a/368100368100?v=0.6.7
|
|
23140
23224
|
*/
|
|
23141
23225
|
const autoAccumulateEntries = [];
|
|
23142
|
-
const result =
|
|
23226
|
+
const result = safe_alloc_uint8array_safeAllocUint8Array(tryAsExactBytes(serviceIdAndGasCodec.sizeHint));
|
|
23143
23227
|
const decoder = decoder_Decoder.fromBlob(result);
|
|
23144
23228
|
let memIndex = sourceStart;
|
|
23145
23229
|
for (let i = 0n; i < numberOfItems; i += 1n) {
|
|
@@ -23156,7 +23240,7 @@ class Bless {
|
|
|
23156
23240
|
memIndex = numbers_tryAsU64(memIndex + numbers_tryAsU64(decoder.bytesRead()));
|
|
23157
23241
|
}
|
|
23158
23242
|
// https://graypaper.fluffylabs.dev/#/7e6ff6a/367200367200?v=0.6.7
|
|
23159
|
-
const res =
|
|
23243
|
+
const res = safe_alloc_uint8array_safeAllocUint8Array(tryAsExactBytes(descriptors_codec.u32.sizeHint) * this.chainSpec.coresCount);
|
|
23160
23244
|
const authorizersDecoder = decoder_Decoder.fromBlob(res);
|
|
23161
23245
|
const memoryReadResult = memory.loadInto(res, authorization);
|
|
23162
23246
|
if (memoryReadResult.isError) {
|
|
@@ -23200,7 +23284,7 @@ class Bless {
|
|
|
23200
23284
|
class gas_GasHostCall {
|
|
23201
23285
|
currentServiceId;
|
|
23202
23286
|
index = host_call_handler_tryAsHostCallIndex(0);
|
|
23203
|
-
|
|
23287
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23204
23288
|
tracedRegisters = host_call_handler_traceRegisters(7);
|
|
23205
23289
|
constructor(currentServiceId) {
|
|
23206
23290
|
this.currentServiceId = currentServiceId;
|
|
@@ -23227,7 +23311,7 @@ class Checkpoint {
|
|
|
23227
23311
|
currentServiceId;
|
|
23228
23312
|
partialState;
|
|
23229
23313
|
index = host_call_handler_tryAsHostCallIndex(17);
|
|
23230
|
-
|
|
23314
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23231
23315
|
tracedRegisters;
|
|
23232
23316
|
gasHostCall;
|
|
23233
23317
|
constructor(currentServiceId, partialState) {
|
|
@@ -23252,6 +23336,7 @@ class Checkpoint {
|
|
|
23252
23336
|
|
|
23253
23337
|
|
|
23254
23338
|
|
|
23339
|
+
|
|
23255
23340
|
const designate_IN_OUT_REG = 7;
|
|
23256
23341
|
const VALIDATOR_DATA_BYTES = tryAsExactBytes(validator_data_ValidatorData.Codec.sizeHint);
|
|
23257
23342
|
/**
|
|
@@ -23264,7 +23349,7 @@ class Designate {
|
|
|
23264
23349
|
partialState;
|
|
23265
23350
|
chainSpec;
|
|
23266
23351
|
index = host_call_handler_tryAsHostCallIndex(16);
|
|
23267
|
-
|
|
23352
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23268
23353
|
tracedRegisters = host_call_handler_traceRegisters(designate_IN_OUT_REG);
|
|
23269
23354
|
constructor(currentServiceId, partialState, chainSpec) {
|
|
23270
23355
|
this.currentServiceId = currentServiceId;
|
|
@@ -23274,7 +23359,7 @@ class Designate {
|
|
|
23274
23359
|
async execute(_gas, regs, memory) {
|
|
23275
23360
|
// `o`
|
|
23276
23361
|
const validatorsStart = regs.get(designate_IN_OUT_REG);
|
|
23277
|
-
const res =
|
|
23362
|
+
const res = safe_alloc_uint8array_safeAllocUint8Array(VALIDATOR_DATA_BYTES * this.chainSpec.validatorsCount);
|
|
23278
23363
|
const memoryReadResult = memory.loadInto(res, validatorsStart);
|
|
23279
23364
|
// error while reading the memory.
|
|
23280
23365
|
if (memoryReadResult.isError) {
|
|
@@ -23315,7 +23400,7 @@ class Eject {
|
|
|
23315
23400
|
currentServiceId;
|
|
23316
23401
|
partialState;
|
|
23317
23402
|
index = host_call_handler_tryAsHostCallIndex(21);
|
|
23318
|
-
|
|
23403
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23319
23404
|
tracedRegisters = host_call_handler_traceRegisters(eject_IN_OUT_REG, 8);
|
|
23320
23405
|
constructor(currentServiceId, partialState) {
|
|
23321
23406
|
this.currentServiceId = currentServiceId;
|
|
@@ -23377,7 +23462,7 @@ class Forget {
|
|
|
23377
23462
|
currentServiceId;
|
|
23378
23463
|
partialState;
|
|
23379
23464
|
index = host_call_handler_tryAsHostCallIndex(24);
|
|
23380
|
-
|
|
23465
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23381
23466
|
tracedRegisters = host_call_handler_traceRegisters(forget_IN_OUT_REG, 8);
|
|
23382
23467
|
constructor(currentServiceId, partialState) {
|
|
23383
23468
|
this.currentServiceId = currentServiceId;
|
|
@@ -23427,7 +23512,7 @@ class New {
|
|
|
23427
23512
|
currentServiceId;
|
|
23428
23513
|
partialState;
|
|
23429
23514
|
index = host_call_handler_tryAsHostCallIndex(18);
|
|
23430
|
-
|
|
23515
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23431
23516
|
tracedRegisters = host_call_handler_traceRegisters(new_IN_OUT_REG, 8, 9, 10, 11);
|
|
23432
23517
|
constructor(currentServiceId, partialState) {
|
|
23433
23518
|
this.currentServiceId = currentServiceId;
|
|
@@ -23490,7 +23575,7 @@ class Provide {
|
|
|
23490
23575
|
currentServiceId;
|
|
23491
23576
|
partialState;
|
|
23492
23577
|
index = host_call_handler_tryAsHostCallIndex(26);
|
|
23493
|
-
|
|
23578
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23494
23579
|
tracedRegisters = host_call_handler_traceRegisters(provide_IN_OUT_REG, 8, 9);
|
|
23495
23580
|
constructor(currentServiceId, partialState) {
|
|
23496
23581
|
this.currentServiceId = currentServiceId;
|
|
@@ -23505,7 +23590,7 @@ class Provide {
|
|
|
23505
23590
|
const preimageLength = regs.get(9);
|
|
23506
23591
|
const length = utils_clampU64ToU32(preimageLength);
|
|
23507
23592
|
// `i`
|
|
23508
|
-
const preimage = bytes_BytesBlob.blobFrom(
|
|
23593
|
+
const preimage = bytes_BytesBlob.blobFrom(safe_alloc_uint8array_safeAllocUint8Array(length));
|
|
23509
23594
|
const memoryReadResult = memory.loadInto(preimage.raw, preimageStart);
|
|
23510
23595
|
if (memoryReadResult.isError) {
|
|
23511
23596
|
logger_logger.trace `PROVIDE(${serviceId}, ${preimage.toStringTruncated()}) <- PANIC`;
|
|
@@ -23551,7 +23636,7 @@ class Query {
|
|
|
23551
23636
|
currentServiceId;
|
|
23552
23637
|
partialState;
|
|
23553
23638
|
index = host_call_handler_tryAsHostCallIndex(22);
|
|
23554
|
-
|
|
23639
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23555
23640
|
tracedRegisters = host_call_handler_traceRegisters(IN_OUT_REG_1, IN_OUT_REG_2);
|
|
23556
23641
|
constructor(currentServiceId, partialState) {
|
|
23557
23642
|
this.currentServiceId = currentServiceId;
|
|
@@ -23617,7 +23702,7 @@ class Solicit {
|
|
|
23617
23702
|
currentServiceId;
|
|
23618
23703
|
partialState;
|
|
23619
23704
|
index = host_call_handler_tryAsHostCallIndex(23);
|
|
23620
|
-
|
|
23705
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23621
23706
|
tracedRegisters = host_call_handler_traceRegisters(solicit_IN_OUT_REG, 8);
|
|
23622
23707
|
constructor(currentServiceId, partialState) {
|
|
23623
23708
|
this.currentServiceId = currentServiceId;
|
|
@@ -23665,12 +23750,12 @@ class Solicit {
|
|
|
23665
23750
|
|
|
23666
23751
|
const transfer_IN_OUT_REG = 7; // `d`
|
|
23667
23752
|
const AMOUNT_REG = 8; // `a`
|
|
23668
|
-
const
|
|
23753
|
+
const TRANSFER_GAS_FEE_REG = 9; // `l`
|
|
23669
23754
|
const MEMO_START_REG = 10; // `o`
|
|
23670
23755
|
/**
|
|
23671
23756
|
* Transfer balance from one service account to another.
|
|
23672
23757
|
*
|
|
23673
|
-
* https://graypaper.fluffylabs.dev/#/
|
|
23758
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/373f00373f00?v=0.7.2
|
|
23674
23759
|
*/
|
|
23675
23760
|
class Transfer {
|
|
23676
23761
|
currentServiceId;
|
|
@@ -23682,38 +23767,50 @@ class Transfer {
|
|
|
23682
23767
|
},
|
|
23683
23768
|
}));
|
|
23684
23769
|
/**
|
|
23685
|
-
* `g = 10 +
|
|
23686
|
-
*
|
|
23770
|
+
* `g = 10 + t`
|
|
23771
|
+
*
|
|
23772
|
+
* `t` has positive value, only when status of a transfer is `OK`
|
|
23773
|
+
* `0` otherwise
|
|
23774
|
+
*
|
|
23775
|
+
* Pre0.7.2: `g = 10 + ω9`
|
|
23776
|
+
*
|
|
23777
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/373f00373f00?v=0.7.2
|
|
23687
23778
|
*/
|
|
23688
|
-
|
|
23689
|
-
|
|
23690
|
-
|
|
23691
|
-
|
|
23692
|
-
tracedRegisters = host_call_handler_traceRegisters(transfer_IN_OUT_REG, AMOUNT_REG, ON_TRANSFER_GAS_REG, MEMO_START_REG);
|
|
23779
|
+
basicGasCost = compatibility_Compatibility.isGreaterOrEqual(compatibility_GpVersion.V0_7_2)
|
|
23780
|
+
? gas_tryAsSmallGas(10)
|
|
23781
|
+
: (regs) => gas_tryAsGas(10n + regs.get(TRANSFER_GAS_FEE_REG));
|
|
23782
|
+
tracedRegisters = host_call_handler_traceRegisters(transfer_IN_OUT_REG, AMOUNT_REG, TRANSFER_GAS_FEE_REG, MEMO_START_REG);
|
|
23693
23783
|
constructor(currentServiceId, partialState) {
|
|
23694
23784
|
this.currentServiceId = currentServiceId;
|
|
23695
23785
|
this.partialState = partialState;
|
|
23696
23786
|
}
|
|
23697
|
-
async execute(
|
|
23787
|
+
async execute(gas, regs, memory) {
|
|
23698
23788
|
// `d`: destination
|
|
23699
23789
|
const destination = getServiceId(regs.get(transfer_IN_OUT_REG));
|
|
23700
23790
|
// `a`: amount
|
|
23701
23791
|
const amount = regs.get(AMOUNT_REG);
|
|
23702
23792
|
// `l`: gas
|
|
23703
|
-
const
|
|
23793
|
+
const transferGasFee = common_tryAsServiceGas(regs.get(TRANSFER_GAS_FEE_REG));
|
|
23704
23794
|
// `o`: transfer memo
|
|
23705
23795
|
const memoStart = regs.get(MEMO_START_REG);
|
|
23706
23796
|
const memo = bytes_Bytes.zero(TRANSFER_MEMO_BYTES);
|
|
23707
23797
|
const memoryReadResult = memory.loadInto(memo.raw, memoStart);
|
|
23708
23798
|
// page fault while reading the memory.
|
|
23709
23799
|
if (memoryReadResult.isError) {
|
|
23710
|
-
logger_logger.trace `TRANSFER(${destination}, ${amount}, ${
|
|
23800
|
+
logger_logger.trace `TRANSFER(${destination}, ${amount}, ${transferGasFee}, ${memo}) <- PANIC`;
|
|
23711
23801
|
return host_call_handler_PvmExecution.Panic;
|
|
23712
23802
|
}
|
|
23713
|
-
const transferResult = this.partialState.transfer(destination, amount,
|
|
23714
|
-
logger_logger.trace `TRANSFER(${destination}, ${amount}, ${
|
|
23803
|
+
const transferResult = this.partialState.transfer(destination, amount, transferGasFee, memo);
|
|
23804
|
+
logger_logger.trace `TRANSFER(${destination}, ${amount}, ${transferGasFee}, ${memo}) <- ${result_resultToString(transferResult)}`;
|
|
23715
23805
|
// All good!
|
|
23716
23806
|
if (transferResult.isOk) {
|
|
23807
|
+
if (compatibility_Compatibility.isGreaterOrEqual(compatibility_GpVersion.V0_7_2)) {
|
|
23808
|
+
// substracting value `t`
|
|
23809
|
+
const underflow = gas.sub(gas_tryAsGas(transferGasFee));
|
|
23810
|
+
if (underflow) {
|
|
23811
|
+
return host_call_handler_PvmExecution.OOG;
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23717
23814
|
regs.set(transfer_IN_OUT_REG, results_HostCallResult.OK);
|
|
23718
23815
|
return;
|
|
23719
23816
|
}
|
|
@@ -23753,7 +23850,7 @@ class Upgrade {
|
|
|
23753
23850
|
currentServiceId;
|
|
23754
23851
|
partialState;
|
|
23755
23852
|
index = host_call_handler_tryAsHostCallIndex(19);
|
|
23756
|
-
|
|
23853
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23757
23854
|
tracedRegisters = host_call_handler_traceRegisters(upgrade_IN_OUT_REG, GAS_REG, ALLOWANCE_REG);
|
|
23758
23855
|
constructor(currentServiceId, partialState) {
|
|
23759
23856
|
this.currentServiceId = currentServiceId;
|
|
@@ -23796,7 +23893,7 @@ class Yield {
|
|
|
23796
23893
|
currentServiceId;
|
|
23797
23894
|
partialState;
|
|
23798
23895
|
index = host_call_handler_tryAsHostCallIndex(25);
|
|
23799
|
-
|
|
23896
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23800
23897
|
tracedRegisters = host_call_handler_traceRegisters(yield_IN_OUT_REG);
|
|
23801
23898
|
constructor(currentServiceId, partialState) {
|
|
23802
23899
|
this.currentServiceId = currentServiceId;
|
|
@@ -23832,7 +23929,7 @@ class fetch_Fetch {
|
|
|
23832
23929
|
currentServiceId;
|
|
23833
23930
|
fetch;
|
|
23834
23931
|
index = tryAsHostCallIndex(1);
|
|
23835
|
-
|
|
23932
|
+
basicGasCost = tryAsSmallGas(10);
|
|
23836
23933
|
tracedRegisters = traceRegisters(fetch_IN_OUT_REG, 8, 9, 10, 11, 12);
|
|
23837
23934
|
constructor(currentServiceId, fetch) {
|
|
23838
23935
|
this.currentServiceId = currentServiceId;
|
|
@@ -23989,7 +24086,7 @@ class info_Info {
|
|
|
23989
24086
|
currentServiceId;
|
|
23990
24087
|
account;
|
|
23991
24088
|
index = tryAsHostCallIndex(5);
|
|
23992
|
-
|
|
24089
|
+
basicGasCost = tryAsSmallGas(10);
|
|
23993
24090
|
tracedRegisters = traceRegisters(info_IN_OUT_REG, 8, OFFSET_REG, LEN_REG);
|
|
23994
24091
|
constructor(currentServiceId, account) {
|
|
23995
24092
|
this.currentServiceId = currentServiceId;
|
|
@@ -24055,6 +24152,7 @@ const codecServiceAccountInfoWithThresholdBalance = descriptors_codec.object({
|
|
|
24055
24152
|
|
|
24056
24153
|
|
|
24057
24154
|
|
|
24155
|
+
|
|
24058
24156
|
const decoder = new TextDecoder("utf8");
|
|
24059
24157
|
/**
|
|
24060
24158
|
* Log message to the console
|
|
@@ -24064,7 +24162,7 @@ const decoder = new TextDecoder("utf8");
|
|
|
24064
24162
|
class log_LogHostCall {
|
|
24065
24163
|
currentServiceId;
|
|
24066
24164
|
index = tryAsHostCallIndex(100);
|
|
24067
|
-
|
|
24165
|
+
basicGasCost = tryAsSmallGas(0);
|
|
24068
24166
|
// intentionally not tracing anything here, since the message will be printed anyway.
|
|
24069
24167
|
tracedRegisters = traceRegisters();
|
|
24070
24168
|
constructor(currentServiceId) {
|
|
@@ -24076,8 +24174,8 @@ class log_LogHostCall {
|
|
|
24076
24174
|
const targetLength = regs.get(9);
|
|
24077
24175
|
const msgStart = regs.get(10);
|
|
24078
24176
|
const msgLength = regs.get(11);
|
|
24079
|
-
const target =
|
|
24080
|
-
const message =
|
|
24177
|
+
const target = safeAllocUint8Array(clampU64ToU32(targetLength));
|
|
24178
|
+
const message = safeAllocUint8Array(clampU64ToU32(msgLength));
|
|
24081
24179
|
if (targetStart !== 0n) {
|
|
24082
24180
|
memory.loadInto(target, targetStart);
|
|
24083
24181
|
}
|
|
@@ -24096,6 +24194,7 @@ class log_LogHostCall {
|
|
|
24096
24194
|
|
|
24097
24195
|
|
|
24098
24196
|
|
|
24197
|
+
|
|
24099
24198
|
const lookup_IN_OUT_REG = 7;
|
|
24100
24199
|
/**
|
|
24101
24200
|
* Lookup a preimage.
|
|
@@ -24106,7 +24205,7 @@ class lookup_Lookup {
|
|
|
24106
24205
|
currentServiceId;
|
|
24107
24206
|
account;
|
|
24108
24207
|
index = tryAsHostCallIndex(2);
|
|
24109
|
-
|
|
24208
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24110
24209
|
tracedRegisters = traceRegisters(lookup_IN_OUT_REG, 8, 9, 10, 11);
|
|
24111
24210
|
constructor(currentServiceId, account) {
|
|
24112
24211
|
this.currentServiceId = currentServiceId;
|
|
@@ -24138,7 +24237,7 @@ class lookup_Lookup {
|
|
|
24138
24237
|
// NOTE [MaSo] this is ok to cast to number, because we are bounded by the
|
|
24139
24238
|
// valueLength in both cases and valueLength is WC (4,000,000,000) + metadata
|
|
24140
24239
|
// which is less than 2^32
|
|
24141
|
-
const chunk = preImage === null ?
|
|
24240
|
+
const chunk = preImage === null ? safeAllocUint8Array(0) : preImage.raw.subarray(Number(offset), Number(offset + length));
|
|
24142
24241
|
const memoryWriteResult = memory.storeFrom(destinationAddress, chunk);
|
|
24143
24242
|
if (memoryWriteResult.isError) {
|
|
24144
24243
|
return PvmExecution.Panic;
|
|
@@ -24159,6 +24258,7 @@ class lookup_Lookup {
|
|
|
24159
24258
|
|
|
24160
24259
|
|
|
24161
24260
|
|
|
24261
|
+
|
|
24162
24262
|
const read_IN_OUT_REG = 7;
|
|
24163
24263
|
/**
|
|
24164
24264
|
* Read account storage.
|
|
@@ -24169,7 +24269,7 @@ class read_Read {
|
|
|
24169
24269
|
currentServiceId;
|
|
24170
24270
|
account;
|
|
24171
24271
|
index = tryAsHostCallIndex(3);
|
|
24172
|
-
|
|
24272
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24173
24273
|
tracedRegisters = traceRegisters(read_IN_OUT_REG, 8, 9, 10, 11, 12);
|
|
24174
24274
|
constructor(currentServiceId, account) {
|
|
24175
24275
|
this.currentServiceId = currentServiceId;
|
|
@@ -24186,7 +24286,7 @@ class read_Read {
|
|
|
24186
24286
|
const destinationAddress = regs.get(10);
|
|
24187
24287
|
const storageKeyLengthClamped = clampU64ToU32(storageKeyLength);
|
|
24188
24288
|
// k
|
|
24189
|
-
const rawKey = BytesBlob.blobFrom(
|
|
24289
|
+
const rawKey = BytesBlob.blobFrom(safeAllocUint8Array(storageKeyLengthClamped));
|
|
24190
24290
|
const memoryReadResult = memory.loadInto(rawKey.raw, storageKeyStartAddress);
|
|
24191
24291
|
if (memoryReadResult.isError) {
|
|
24192
24292
|
logger.trace `READ(${serviceId}, ${rawKey}) <- PANIC`;
|
|
@@ -24204,7 +24304,7 @@ class read_Read {
|
|
|
24204
24304
|
// NOTE [MaSo] this is ok to cast to number, because we are bounded by the
|
|
24205
24305
|
// valueLength in both cases and valueLength is WC (4,000,000,000) + metadata
|
|
24206
24306
|
// which is less than 2^32
|
|
24207
|
-
const chunk = value === null ?
|
|
24307
|
+
const chunk = value === null ? safeAllocUint8Array(0) : value.raw.subarray(Number(offset), Number(offset + blobLength));
|
|
24208
24308
|
const memoryWriteResult = memory.storeFrom(destinationAddress, chunk);
|
|
24209
24309
|
if (memoryWriteResult.isError) {
|
|
24210
24310
|
logger.trace `READ(${serviceId}, ${rawKey}) <- PANIC`;
|
|
@@ -24239,7 +24339,7 @@ class write_Write {
|
|
|
24239
24339
|
currentServiceId;
|
|
24240
24340
|
account;
|
|
24241
24341
|
index = tryAsHostCallIndex(4);
|
|
24242
|
-
|
|
24342
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24243
24343
|
tracedRegisters = traceRegisters(write_IN_OUT_REG, 8, 9, 10);
|
|
24244
24344
|
constructor(currentServiceId, account) {
|
|
24245
24345
|
this.currentServiceId = currentServiceId;
|
|
@@ -24255,7 +24355,7 @@ class write_Write {
|
|
|
24255
24355
|
// v_z
|
|
24256
24356
|
const valueLength = regs.get(10);
|
|
24257
24357
|
const storageKeyLengthClamped = clampU64ToU32(storageKeyLength);
|
|
24258
|
-
const rawStorageKey =
|
|
24358
|
+
const rawStorageKey = safeAllocUint8Array(storageKeyLengthClamped);
|
|
24259
24359
|
const keyLoadingResult = memory.loadInto(rawStorageKey, storageKeyStartAddress);
|
|
24260
24360
|
if (keyLoadingResult.isError) {
|
|
24261
24361
|
logger.trace `WRITE() <- PANIC`;
|
|
@@ -24264,7 +24364,7 @@ class write_Write {
|
|
|
24264
24364
|
// k
|
|
24265
24365
|
const storageKey = asOpaqueType(BytesBlob.blobFrom(rawStorageKey));
|
|
24266
24366
|
const valueLengthClamped = clampU64ToU32(valueLength);
|
|
24267
|
-
const value =
|
|
24367
|
+
const value = safeAllocUint8Array(valueLengthClamped);
|
|
24268
24368
|
const valueLoadingResult = memory.loadInto(value, valueStart);
|
|
24269
24369
|
// Note [MaSo] this is ok to return bcs if valueLength is 0, then this panic won't happen
|
|
24270
24370
|
if (valueLoadingResult.isError) {
|
|
@@ -25153,7 +25253,7 @@ function shuffling_fisherYatesShuffle(arr, entropy) {
|
|
|
25153
25253
|
}
|
|
25154
25254
|
function hashToNumberSequence(entropy, length) {
|
|
25155
25255
|
const result = new Array(length);
|
|
25156
|
-
const randomBytes =
|
|
25256
|
+
const randomBytes = safeAllocUint8Array(ENTROPY_BYTES + 4);
|
|
25157
25257
|
randomBytes.set(entropy.raw);
|
|
25158
25258
|
for (let i = 0; i < length; i++) {
|
|
25159
25259
|
randomBytes.set(u32AsLeBytes(tryAsU32(Math.floor(i / 8))), ENTROPY_BYTES);
|
|
@@ -26183,6 +26283,7 @@ class chain_stf_OnChain {
|
|
|
26183
26283
|
authorization;
|
|
26184
26284
|
// chapter 13: https://graypaper.fluffylabs.dev/#/68eaa1f/18b60118b601?v=0.6.4
|
|
26185
26285
|
statistics;
|
|
26286
|
+
isReadyForNextEpoch = Promise.resolve(false);
|
|
26186
26287
|
constructor(chainSpec, state, blocks, hasher) {
|
|
26187
26288
|
this.chainSpec = chainSpec;
|
|
26188
26289
|
this.state = state;
|
|
@@ -26201,6 +26302,14 @@ class chain_stf_OnChain {
|
|
|
26201
26302
|
this.preimages = new Preimages(state);
|
|
26202
26303
|
this.authorization = new Authorization(chainSpec, state);
|
|
26203
26304
|
}
|
|
26305
|
+
/** Pre-populate things worth caching for the next epoch. */
|
|
26306
|
+
async prepareForNextEpoch() {
|
|
26307
|
+
if (await this.isReadyForNextEpoch) {
|
|
26308
|
+
return;
|
|
26309
|
+
}
|
|
26310
|
+
const ready = this.safrole.prepareValidatorKeysForNextEpoch(this.state.disputesRecords.punishSet);
|
|
26311
|
+
this.isReadyForNextEpoch = ready.then((_) => true);
|
|
26312
|
+
}
|
|
26204
26313
|
async verifySeal(timeSlot, block) {
|
|
26205
26314
|
const sealState = this.safrole.getSafroleSealState(timeSlot);
|
|
26206
26315
|
return await this.safroleSeal.verifyHeaderSeal(block.header.view(), sealState);
|
|
@@ -26209,6 +26318,10 @@ class chain_stf_OnChain {
|
|
|
26209
26318
|
const headerView = block.header.view();
|
|
26210
26319
|
const header = block.header.materialize();
|
|
26211
26320
|
const timeSlot = header.timeSlotIndex;
|
|
26321
|
+
// reset the epoch cache state
|
|
26322
|
+
if (headerView.epochMarker.view() !== null) {
|
|
26323
|
+
this.isReadyForNextEpoch = Promise.resolve(false);
|
|
26324
|
+
}
|
|
26212
26325
|
// safrole seal
|
|
26213
26326
|
let newEntropyHash;
|
|
26214
26327
|
if (omitSealVerification) {
|
|
@@ -26673,6 +26786,7 @@ async function runWorkPackageTest(test, file) {
|
|
|
26673
26786
|
|
|
26674
26787
|
|
|
26675
26788
|
|
|
26789
|
+
|
|
26676
26790
|
class MemoryChunkItem {
|
|
26677
26791
|
static fromJson = {
|
|
26678
26792
|
address: "number",
|
|
@@ -26730,10 +26844,10 @@ async function runPvmTest(testContent) {
|
|
|
26730
26844
|
const endPageIndex = tryAsMemoryIndex(startPageIndex + page.length);
|
|
26731
26845
|
const isWriteable = page["is-writable"];
|
|
26732
26846
|
if (isWriteable) {
|
|
26733
|
-
memoryBuilder.setWriteablePages(startPageIndex, endPageIndex,
|
|
26847
|
+
memoryBuilder.setWriteablePages(startPageIndex, endPageIndex, safeAllocUint8Array(page.length));
|
|
26734
26848
|
}
|
|
26735
26849
|
else {
|
|
26736
|
-
memoryBuilder.setReadablePages(startPageIndex, endPageIndex,
|
|
26850
|
+
memoryBuilder.setReadablePages(startPageIndex, endPageIndex, safeAllocUint8Array(page.length));
|
|
26737
26851
|
}
|
|
26738
26852
|
}
|
|
26739
26853
|
for (const memoryChunk of initialMemory) {
|
|
@@ -26785,7 +26899,7 @@ async function runPvmTest(testContent) {
|
|
|
26785
26899
|
}, {});
|
|
26786
26900
|
for (const [pageNumberAsString, memoryChunks] of Object.entries(expectedMemoryByPageNumber)) {
|
|
26787
26901
|
const pageNumber = tryAsPageNumber(Number(pageNumberAsString));
|
|
26788
|
-
const expectedPage =
|
|
26902
|
+
const expectedPage = safeAllocUint8Array(PAGE_SIZE);
|
|
26789
26903
|
for (const memoryChunk of memoryChunks) {
|
|
26790
26904
|
const pageIndex = memoryChunk.address % PAGE_SIZE;
|
|
26791
26905
|
expectedPage.set(memoryChunk.contents, pageIndex);
|