@typeberry/convert 0.1.3-af70ed0 → 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 +167 -72
- 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;
|
|
@@ -14661,7 +14676,7 @@ class SerializedService {
|
|
|
14661
14676
|
getStorage(rawKey) {
|
|
14662
14677
|
if (compatibility_Compatibility.isLessThan(compatibility_GpVersion.V0_6_7)) {
|
|
14663
14678
|
const SERVICE_ID_BYTES = 4;
|
|
14664
|
-
const serviceIdAndKey =
|
|
14679
|
+
const serviceIdAndKey = safe_alloc_uint8array_safeAllocUint8Array(SERVICE_ID_BYTES + rawKey.length);
|
|
14665
14680
|
serviceIdAndKey.set(numbers_u32AsLeBytes(this.serviceId));
|
|
14666
14681
|
serviceIdAndKey.set(rawKey.raw, SERVICE_ID_BYTES);
|
|
14667
14682
|
const key = opaque_asOpaqueType(bytes_BytesBlob.blobFrom(hashBytes(serviceIdAndKey).raw));
|
|
@@ -14752,7 +14767,7 @@ class nodes_TrieNode {
|
|
|
14752
14767
|
raw;
|
|
14753
14768
|
constructor(
|
|
14754
14769
|
/** Exactly 512 bits / 64 bytes */
|
|
14755
|
-
raw =
|
|
14770
|
+
raw = safe_alloc_uint8array_safeAllocUint8Array(nodes_TRIE_NODE_BYTES)) {
|
|
14756
14771
|
this.raw = raw;
|
|
14757
14772
|
}
|
|
14758
14773
|
/** Returns the type of the node */
|
|
@@ -16187,7 +16202,7 @@ class registers_Registers {
|
|
|
16187
16202
|
bytes;
|
|
16188
16203
|
asSigned;
|
|
16189
16204
|
asUnsigned;
|
|
16190
|
-
constructor(bytes =
|
|
16205
|
+
constructor(bytes = safeAllocUint8Array(registers_NO_OF_REGISTERS << REGISTER_SIZE_SHIFT)) {
|
|
16191
16206
|
this.bytes = bytes;
|
|
16192
16207
|
check `${bytes.length === registers_NO_OF_REGISTERS << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
16193
16208
|
this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
|
|
@@ -16263,10 +16278,16 @@ function registers_signExtend32To64(value) {
|
|
|
16263
16278
|
|
|
16264
16279
|
/** Attempt to convert a number into `HostCallIndex`. */
|
|
16265
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
|
+
*/
|
|
16266
16286
|
var host_call_handler_PvmExecution;
|
|
16267
16287
|
(function (PvmExecution) {
|
|
16268
16288
|
PvmExecution[PvmExecution["Halt"] = 0] = "Halt";
|
|
16269
16289
|
PvmExecution[PvmExecution["Panic"] = 1] = "Panic";
|
|
16290
|
+
PvmExecution[PvmExecution["OOG"] = 2] = "OOG";
|
|
16270
16291
|
})(host_call_handler_PvmExecution || (host_call_handler_PvmExecution = {}));
|
|
16271
16292
|
/** A utility function to easily trace a bunch of registers. */
|
|
16272
16293
|
function host_call_handler_traceRegisters(...regs) {
|
|
@@ -16344,7 +16365,7 @@ class mask_Mask {
|
|
|
16344
16365
|
return Math.min(this.lookupTableForward[index] ?? 0, MAX_INSTRUCTION_DISTANCE);
|
|
16345
16366
|
}
|
|
16346
16367
|
buildLookupTableForward(mask) {
|
|
16347
|
-
const table =
|
|
16368
|
+
const table = safeAllocUint8Array(mask.bitLength);
|
|
16348
16369
|
let lastInstructionOffset = 0;
|
|
16349
16370
|
for (let i = mask.bitLength - 1; i >= 0; i--) {
|
|
16350
16371
|
if (mask.isSet(i)) {
|
|
@@ -19855,7 +19876,7 @@ class host_calls_HostCalls {
|
|
|
19855
19876
|
const regs = pvmInstance.getRegisters();
|
|
19856
19877
|
const maybeAddress = regs.getLowerU32(7);
|
|
19857
19878
|
const maybeLength = regs.getLowerU32(8);
|
|
19858
|
-
const result =
|
|
19879
|
+
const result = safeAllocUint8Array(maybeLength);
|
|
19859
19880
|
const startAddress = tryAsMemoryIndex(maybeAddress);
|
|
19860
19881
|
const loadResult = memory.loadInto(result, startAddress);
|
|
19861
19882
|
if (loadResult.isError) {
|
|
@@ -19883,8 +19904,9 @@ class host_calls_HostCalls {
|
|
|
19883
19904
|
const index = tryAsHostCallIndex(hostCallIndex);
|
|
19884
19905
|
const hostCall = this.hostCalls.get(index);
|
|
19885
19906
|
const gasBefore = gas.get();
|
|
19886
|
-
|
|
19887
|
-
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);
|
|
19888
19910
|
const pcLog = `[PC: ${pvmInstance.getPC()}]`;
|
|
19889
19911
|
if (underflow) {
|
|
19890
19912
|
this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
|
|
@@ -19901,6 +19923,10 @@ class host_calls_HostCalls {
|
|
|
19901
19923
|
status = Status.PANIC;
|
|
19902
19924
|
return this.getReturnValue(status, pvmInstance);
|
|
19903
19925
|
}
|
|
19926
|
+
if (result === PvmExecution.OOG) {
|
|
19927
|
+
status = Status.OOG;
|
|
19928
|
+
return this.getReturnValue(status, pvmInstance);
|
|
19929
|
+
}
|
|
19904
19930
|
if (result === undefined) {
|
|
19905
19931
|
pvmInstance.runProgram();
|
|
19906
19932
|
status = pvmInstance.getStatus();
|
|
@@ -19959,7 +19985,7 @@ class host_calls_manager_HostCallsManager {
|
|
|
19959
19985
|
}
|
|
19960
19986
|
class NoopMissing {
|
|
19961
19987
|
index = tryAsHostCallIndex(2 ** 32 - 1);
|
|
19962
|
-
|
|
19988
|
+
basicGasCost = tryAsSmallGas(0);
|
|
19963
19989
|
currentServiceId = tryAsU32(0);
|
|
19964
19990
|
tracedRegisters = [];
|
|
19965
19991
|
async execute() {
|
|
@@ -20073,7 +20099,7 @@ function utils_clampU64ToU32(value) {
|
|
|
20073
20099
|
|
|
20074
20100
|
class missing_Missing {
|
|
20075
20101
|
index = tryAsHostCallIndex(2 ** 32 - 1);
|
|
20076
|
-
|
|
20102
|
+
basicGasCost = tryAsSmallGas(10);
|
|
20077
20103
|
currentServiceId = CURRENT_SERVICE_ID;
|
|
20078
20104
|
tracedRegisters = traceRegisters(7);
|
|
20079
20105
|
execute(_gas, regs, _memory) {
|
|
@@ -20774,6 +20800,15 @@ var ResultValues;
|
|
|
20774
20800
|
ResultValues[ResultValues["Ok"] = 0] = "Ok";
|
|
20775
20801
|
ResultValues[ResultValues["Error"] = 1] = "Error";
|
|
20776
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 = [];
|
|
20777
20812
|
// TODO [ToDr] We export the entire object to allow mocking in tests.
|
|
20778
20813
|
// Ideally we would just export functions and figure out how to mock
|
|
20779
20814
|
// properly in ESM.
|
|
@@ -20789,9 +20824,27 @@ async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUn
|
|
|
20789
20824
|
}
|
|
20790
20825
|
return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
|
|
20791
20826
|
}
|
|
20792
|
-
|
|
20793
|
-
const keys = bytes_BytesBlob.blobFromParts(validators.map((x) => x.raw))
|
|
20794
|
-
|
|
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);
|
|
20795
20848
|
if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
|
|
20796
20849
|
return result_Result.error(null);
|
|
20797
20850
|
}
|
|
@@ -20917,6 +20970,18 @@ class safrole_Safrole {
|
|
|
20917
20970
|
}
|
|
20918
20971
|
return FixedSizeArray.new([newRandomnessAcc, ...rest], 4);
|
|
20919
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
|
+
}
|
|
20920
20985
|
async getValidatorKeys(timeslot, postOffenders) {
|
|
20921
20986
|
/**
|
|
20922
20987
|
* Epoch is not changed so the previous state is returned
|
|
@@ -23056,7 +23121,7 @@ class Assign {
|
|
|
23056
23121
|
partialState;
|
|
23057
23122
|
chainSpec;
|
|
23058
23123
|
index = host_call_handler_tryAsHostCallIndex(15);
|
|
23059
|
-
|
|
23124
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23060
23125
|
tracedRegisters = host_call_handler_traceRegisters(IN_OUT_REG, 8);
|
|
23061
23126
|
constructor(currentServiceId, partialState, chainSpec) {
|
|
23062
23127
|
this.currentServiceId = currentServiceId;
|
|
@@ -23070,7 +23135,7 @@ class Assign {
|
|
|
23070
23135
|
const authorizationQueueStart = regs.get(8);
|
|
23071
23136
|
// a
|
|
23072
23137
|
const authManager = getServiceId(regs.get(9));
|
|
23073
|
-
const res =
|
|
23138
|
+
const res = safe_alloc_uint8array_safeAllocUint8Array(hash_HASH_SIZE * gp_constants_AUTHORIZATION_QUEUE_SIZE);
|
|
23074
23139
|
const memoryReadResult = memory.loadInto(res, authorizationQueueStart);
|
|
23075
23140
|
// error while reading the memory.
|
|
23076
23141
|
if (memoryReadResult.isError) {
|
|
@@ -23134,7 +23199,7 @@ class Bless {
|
|
|
23134
23199
|
partialState;
|
|
23135
23200
|
chainSpec;
|
|
23136
23201
|
index = host_call_handler_tryAsHostCallIndex(14);
|
|
23137
|
-
|
|
23202
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23138
23203
|
tracedRegisters = host_call_handler_traceRegisters(bless_IN_OUT_REG, 8, 9, 10, 11);
|
|
23139
23204
|
constructor(currentServiceId, partialState, chainSpec) {
|
|
23140
23205
|
this.currentServiceId = currentServiceId;
|
|
@@ -23158,7 +23223,7 @@ class Bless {
|
|
|
23158
23223
|
* https://graypaper.fluffylabs.dev/#/7e6ff6a/368100368100?v=0.6.7
|
|
23159
23224
|
*/
|
|
23160
23225
|
const autoAccumulateEntries = [];
|
|
23161
|
-
const result =
|
|
23226
|
+
const result = safe_alloc_uint8array_safeAllocUint8Array(tryAsExactBytes(serviceIdAndGasCodec.sizeHint));
|
|
23162
23227
|
const decoder = decoder_Decoder.fromBlob(result);
|
|
23163
23228
|
let memIndex = sourceStart;
|
|
23164
23229
|
for (let i = 0n; i < numberOfItems; i += 1n) {
|
|
@@ -23175,7 +23240,7 @@ class Bless {
|
|
|
23175
23240
|
memIndex = numbers_tryAsU64(memIndex + numbers_tryAsU64(decoder.bytesRead()));
|
|
23176
23241
|
}
|
|
23177
23242
|
// https://graypaper.fluffylabs.dev/#/7e6ff6a/367200367200?v=0.6.7
|
|
23178
|
-
const res =
|
|
23243
|
+
const res = safe_alloc_uint8array_safeAllocUint8Array(tryAsExactBytes(descriptors_codec.u32.sizeHint) * this.chainSpec.coresCount);
|
|
23179
23244
|
const authorizersDecoder = decoder_Decoder.fromBlob(res);
|
|
23180
23245
|
const memoryReadResult = memory.loadInto(res, authorization);
|
|
23181
23246
|
if (memoryReadResult.isError) {
|
|
@@ -23219,7 +23284,7 @@ class Bless {
|
|
|
23219
23284
|
class gas_GasHostCall {
|
|
23220
23285
|
currentServiceId;
|
|
23221
23286
|
index = host_call_handler_tryAsHostCallIndex(0);
|
|
23222
|
-
|
|
23287
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23223
23288
|
tracedRegisters = host_call_handler_traceRegisters(7);
|
|
23224
23289
|
constructor(currentServiceId) {
|
|
23225
23290
|
this.currentServiceId = currentServiceId;
|
|
@@ -23246,7 +23311,7 @@ class Checkpoint {
|
|
|
23246
23311
|
currentServiceId;
|
|
23247
23312
|
partialState;
|
|
23248
23313
|
index = host_call_handler_tryAsHostCallIndex(17);
|
|
23249
|
-
|
|
23314
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23250
23315
|
tracedRegisters;
|
|
23251
23316
|
gasHostCall;
|
|
23252
23317
|
constructor(currentServiceId, partialState) {
|
|
@@ -23271,6 +23336,7 @@ class Checkpoint {
|
|
|
23271
23336
|
|
|
23272
23337
|
|
|
23273
23338
|
|
|
23339
|
+
|
|
23274
23340
|
const designate_IN_OUT_REG = 7;
|
|
23275
23341
|
const VALIDATOR_DATA_BYTES = tryAsExactBytes(validator_data_ValidatorData.Codec.sizeHint);
|
|
23276
23342
|
/**
|
|
@@ -23283,7 +23349,7 @@ class Designate {
|
|
|
23283
23349
|
partialState;
|
|
23284
23350
|
chainSpec;
|
|
23285
23351
|
index = host_call_handler_tryAsHostCallIndex(16);
|
|
23286
|
-
|
|
23352
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23287
23353
|
tracedRegisters = host_call_handler_traceRegisters(designate_IN_OUT_REG);
|
|
23288
23354
|
constructor(currentServiceId, partialState, chainSpec) {
|
|
23289
23355
|
this.currentServiceId = currentServiceId;
|
|
@@ -23293,7 +23359,7 @@ class Designate {
|
|
|
23293
23359
|
async execute(_gas, regs, memory) {
|
|
23294
23360
|
// `o`
|
|
23295
23361
|
const validatorsStart = regs.get(designate_IN_OUT_REG);
|
|
23296
|
-
const res =
|
|
23362
|
+
const res = safe_alloc_uint8array_safeAllocUint8Array(VALIDATOR_DATA_BYTES * this.chainSpec.validatorsCount);
|
|
23297
23363
|
const memoryReadResult = memory.loadInto(res, validatorsStart);
|
|
23298
23364
|
// error while reading the memory.
|
|
23299
23365
|
if (memoryReadResult.isError) {
|
|
@@ -23334,7 +23400,7 @@ class Eject {
|
|
|
23334
23400
|
currentServiceId;
|
|
23335
23401
|
partialState;
|
|
23336
23402
|
index = host_call_handler_tryAsHostCallIndex(21);
|
|
23337
|
-
|
|
23403
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23338
23404
|
tracedRegisters = host_call_handler_traceRegisters(eject_IN_OUT_REG, 8);
|
|
23339
23405
|
constructor(currentServiceId, partialState) {
|
|
23340
23406
|
this.currentServiceId = currentServiceId;
|
|
@@ -23396,7 +23462,7 @@ class Forget {
|
|
|
23396
23462
|
currentServiceId;
|
|
23397
23463
|
partialState;
|
|
23398
23464
|
index = host_call_handler_tryAsHostCallIndex(24);
|
|
23399
|
-
|
|
23465
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23400
23466
|
tracedRegisters = host_call_handler_traceRegisters(forget_IN_OUT_REG, 8);
|
|
23401
23467
|
constructor(currentServiceId, partialState) {
|
|
23402
23468
|
this.currentServiceId = currentServiceId;
|
|
@@ -23446,7 +23512,7 @@ class New {
|
|
|
23446
23512
|
currentServiceId;
|
|
23447
23513
|
partialState;
|
|
23448
23514
|
index = host_call_handler_tryAsHostCallIndex(18);
|
|
23449
|
-
|
|
23515
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23450
23516
|
tracedRegisters = host_call_handler_traceRegisters(new_IN_OUT_REG, 8, 9, 10, 11);
|
|
23451
23517
|
constructor(currentServiceId, partialState) {
|
|
23452
23518
|
this.currentServiceId = currentServiceId;
|
|
@@ -23509,7 +23575,7 @@ class Provide {
|
|
|
23509
23575
|
currentServiceId;
|
|
23510
23576
|
partialState;
|
|
23511
23577
|
index = host_call_handler_tryAsHostCallIndex(26);
|
|
23512
|
-
|
|
23578
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23513
23579
|
tracedRegisters = host_call_handler_traceRegisters(provide_IN_OUT_REG, 8, 9);
|
|
23514
23580
|
constructor(currentServiceId, partialState) {
|
|
23515
23581
|
this.currentServiceId = currentServiceId;
|
|
@@ -23524,7 +23590,7 @@ class Provide {
|
|
|
23524
23590
|
const preimageLength = regs.get(9);
|
|
23525
23591
|
const length = utils_clampU64ToU32(preimageLength);
|
|
23526
23592
|
// `i`
|
|
23527
|
-
const preimage = bytes_BytesBlob.blobFrom(
|
|
23593
|
+
const preimage = bytes_BytesBlob.blobFrom(safe_alloc_uint8array_safeAllocUint8Array(length));
|
|
23528
23594
|
const memoryReadResult = memory.loadInto(preimage.raw, preimageStart);
|
|
23529
23595
|
if (memoryReadResult.isError) {
|
|
23530
23596
|
logger_logger.trace `PROVIDE(${serviceId}, ${preimage.toStringTruncated()}) <- PANIC`;
|
|
@@ -23570,7 +23636,7 @@ class Query {
|
|
|
23570
23636
|
currentServiceId;
|
|
23571
23637
|
partialState;
|
|
23572
23638
|
index = host_call_handler_tryAsHostCallIndex(22);
|
|
23573
|
-
|
|
23639
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23574
23640
|
tracedRegisters = host_call_handler_traceRegisters(IN_OUT_REG_1, IN_OUT_REG_2);
|
|
23575
23641
|
constructor(currentServiceId, partialState) {
|
|
23576
23642
|
this.currentServiceId = currentServiceId;
|
|
@@ -23636,7 +23702,7 @@ class Solicit {
|
|
|
23636
23702
|
currentServiceId;
|
|
23637
23703
|
partialState;
|
|
23638
23704
|
index = host_call_handler_tryAsHostCallIndex(23);
|
|
23639
|
-
|
|
23705
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23640
23706
|
tracedRegisters = host_call_handler_traceRegisters(solicit_IN_OUT_REG, 8);
|
|
23641
23707
|
constructor(currentServiceId, partialState) {
|
|
23642
23708
|
this.currentServiceId = currentServiceId;
|
|
@@ -23684,12 +23750,12 @@ class Solicit {
|
|
|
23684
23750
|
|
|
23685
23751
|
const transfer_IN_OUT_REG = 7; // `d`
|
|
23686
23752
|
const AMOUNT_REG = 8; // `a`
|
|
23687
|
-
const
|
|
23753
|
+
const TRANSFER_GAS_FEE_REG = 9; // `l`
|
|
23688
23754
|
const MEMO_START_REG = 10; // `o`
|
|
23689
23755
|
/**
|
|
23690
23756
|
* Transfer balance from one service account to another.
|
|
23691
23757
|
*
|
|
23692
|
-
* https://graypaper.fluffylabs.dev/#/
|
|
23758
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/373f00373f00?v=0.7.2
|
|
23693
23759
|
*/
|
|
23694
23760
|
class Transfer {
|
|
23695
23761
|
currentServiceId;
|
|
@@ -23701,38 +23767,50 @@ class Transfer {
|
|
|
23701
23767
|
},
|
|
23702
23768
|
}));
|
|
23703
23769
|
/**
|
|
23704
|
-
* `g = 10 +
|
|
23705
|
-
*
|
|
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
|
|
23706
23778
|
*/
|
|
23707
|
-
|
|
23708
|
-
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
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);
|
|
23712
23783
|
constructor(currentServiceId, partialState) {
|
|
23713
23784
|
this.currentServiceId = currentServiceId;
|
|
23714
23785
|
this.partialState = partialState;
|
|
23715
23786
|
}
|
|
23716
|
-
async execute(
|
|
23787
|
+
async execute(gas, regs, memory) {
|
|
23717
23788
|
// `d`: destination
|
|
23718
23789
|
const destination = getServiceId(regs.get(transfer_IN_OUT_REG));
|
|
23719
23790
|
// `a`: amount
|
|
23720
23791
|
const amount = regs.get(AMOUNT_REG);
|
|
23721
23792
|
// `l`: gas
|
|
23722
|
-
const
|
|
23793
|
+
const transferGasFee = common_tryAsServiceGas(regs.get(TRANSFER_GAS_FEE_REG));
|
|
23723
23794
|
// `o`: transfer memo
|
|
23724
23795
|
const memoStart = regs.get(MEMO_START_REG);
|
|
23725
23796
|
const memo = bytes_Bytes.zero(TRANSFER_MEMO_BYTES);
|
|
23726
23797
|
const memoryReadResult = memory.loadInto(memo.raw, memoStart);
|
|
23727
23798
|
// page fault while reading the memory.
|
|
23728
23799
|
if (memoryReadResult.isError) {
|
|
23729
|
-
logger_logger.trace `TRANSFER(${destination}, ${amount}, ${
|
|
23800
|
+
logger_logger.trace `TRANSFER(${destination}, ${amount}, ${transferGasFee}, ${memo}) <- PANIC`;
|
|
23730
23801
|
return host_call_handler_PvmExecution.Panic;
|
|
23731
23802
|
}
|
|
23732
|
-
const transferResult = this.partialState.transfer(destination, amount,
|
|
23733
|
-
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)}`;
|
|
23734
23805
|
// All good!
|
|
23735
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
|
+
}
|
|
23736
23814
|
regs.set(transfer_IN_OUT_REG, results_HostCallResult.OK);
|
|
23737
23815
|
return;
|
|
23738
23816
|
}
|
|
@@ -23772,7 +23850,7 @@ class Upgrade {
|
|
|
23772
23850
|
currentServiceId;
|
|
23773
23851
|
partialState;
|
|
23774
23852
|
index = host_call_handler_tryAsHostCallIndex(19);
|
|
23775
|
-
|
|
23853
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23776
23854
|
tracedRegisters = host_call_handler_traceRegisters(upgrade_IN_OUT_REG, GAS_REG, ALLOWANCE_REG);
|
|
23777
23855
|
constructor(currentServiceId, partialState) {
|
|
23778
23856
|
this.currentServiceId = currentServiceId;
|
|
@@ -23815,7 +23893,7 @@ class Yield {
|
|
|
23815
23893
|
currentServiceId;
|
|
23816
23894
|
partialState;
|
|
23817
23895
|
index = host_call_handler_tryAsHostCallIndex(25);
|
|
23818
|
-
|
|
23896
|
+
basicGasCost = gas_tryAsSmallGas(10);
|
|
23819
23897
|
tracedRegisters = host_call_handler_traceRegisters(yield_IN_OUT_REG);
|
|
23820
23898
|
constructor(currentServiceId, partialState) {
|
|
23821
23899
|
this.currentServiceId = currentServiceId;
|
|
@@ -23851,7 +23929,7 @@ class fetch_Fetch {
|
|
|
23851
23929
|
currentServiceId;
|
|
23852
23930
|
fetch;
|
|
23853
23931
|
index = tryAsHostCallIndex(1);
|
|
23854
|
-
|
|
23932
|
+
basicGasCost = tryAsSmallGas(10);
|
|
23855
23933
|
tracedRegisters = traceRegisters(fetch_IN_OUT_REG, 8, 9, 10, 11, 12);
|
|
23856
23934
|
constructor(currentServiceId, fetch) {
|
|
23857
23935
|
this.currentServiceId = currentServiceId;
|
|
@@ -24008,7 +24086,7 @@ class info_Info {
|
|
|
24008
24086
|
currentServiceId;
|
|
24009
24087
|
account;
|
|
24010
24088
|
index = tryAsHostCallIndex(5);
|
|
24011
|
-
|
|
24089
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24012
24090
|
tracedRegisters = traceRegisters(info_IN_OUT_REG, 8, OFFSET_REG, LEN_REG);
|
|
24013
24091
|
constructor(currentServiceId, account) {
|
|
24014
24092
|
this.currentServiceId = currentServiceId;
|
|
@@ -24074,6 +24152,7 @@ const codecServiceAccountInfoWithThresholdBalance = descriptors_codec.object({
|
|
|
24074
24152
|
|
|
24075
24153
|
|
|
24076
24154
|
|
|
24155
|
+
|
|
24077
24156
|
const decoder = new TextDecoder("utf8");
|
|
24078
24157
|
/**
|
|
24079
24158
|
* Log message to the console
|
|
@@ -24083,7 +24162,7 @@ const decoder = new TextDecoder("utf8");
|
|
|
24083
24162
|
class log_LogHostCall {
|
|
24084
24163
|
currentServiceId;
|
|
24085
24164
|
index = tryAsHostCallIndex(100);
|
|
24086
|
-
|
|
24165
|
+
basicGasCost = tryAsSmallGas(0);
|
|
24087
24166
|
// intentionally not tracing anything here, since the message will be printed anyway.
|
|
24088
24167
|
tracedRegisters = traceRegisters();
|
|
24089
24168
|
constructor(currentServiceId) {
|
|
@@ -24095,8 +24174,8 @@ class log_LogHostCall {
|
|
|
24095
24174
|
const targetLength = regs.get(9);
|
|
24096
24175
|
const msgStart = regs.get(10);
|
|
24097
24176
|
const msgLength = regs.get(11);
|
|
24098
|
-
const target =
|
|
24099
|
-
const message =
|
|
24177
|
+
const target = safeAllocUint8Array(clampU64ToU32(targetLength));
|
|
24178
|
+
const message = safeAllocUint8Array(clampU64ToU32(msgLength));
|
|
24100
24179
|
if (targetStart !== 0n) {
|
|
24101
24180
|
memory.loadInto(target, targetStart);
|
|
24102
24181
|
}
|
|
@@ -24115,6 +24194,7 @@ class log_LogHostCall {
|
|
|
24115
24194
|
|
|
24116
24195
|
|
|
24117
24196
|
|
|
24197
|
+
|
|
24118
24198
|
const lookup_IN_OUT_REG = 7;
|
|
24119
24199
|
/**
|
|
24120
24200
|
* Lookup a preimage.
|
|
@@ -24125,7 +24205,7 @@ class lookup_Lookup {
|
|
|
24125
24205
|
currentServiceId;
|
|
24126
24206
|
account;
|
|
24127
24207
|
index = tryAsHostCallIndex(2);
|
|
24128
|
-
|
|
24208
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24129
24209
|
tracedRegisters = traceRegisters(lookup_IN_OUT_REG, 8, 9, 10, 11);
|
|
24130
24210
|
constructor(currentServiceId, account) {
|
|
24131
24211
|
this.currentServiceId = currentServiceId;
|
|
@@ -24157,7 +24237,7 @@ class lookup_Lookup {
|
|
|
24157
24237
|
// NOTE [MaSo] this is ok to cast to number, because we are bounded by the
|
|
24158
24238
|
// valueLength in both cases and valueLength is WC (4,000,000,000) + metadata
|
|
24159
24239
|
// which is less than 2^32
|
|
24160
|
-
const chunk = preImage === null ?
|
|
24240
|
+
const chunk = preImage === null ? safeAllocUint8Array(0) : preImage.raw.subarray(Number(offset), Number(offset + length));
|
|
24161
24241
|
const memoryWriteResult = memory.storeFrom(destinationAddress, chunk);
|
|
24162
24242
|
if (memoryWriteResult.isError) {
|
|
24163
24243
|
return PvmExecution.Panic;
|
|
@@ -24178,6 +24258,7 @@ class lookup_Lookup {
|
|
|
24178
24258
|
|
|
24179
24259
|
|
|
24180
24260
|
|
|
24261
|
+
|
|
24181
24262
|
const read_IN_OUT_REG = 7;
|
|
24182
24263
|
/**
|
|
24183
24264
|
* Read account storage.
|
|
@@ -24188,7 +24269,7 @@ class read_Read {
|
|
|
24188
24269
|
currentServiceId;
|
|
24189
24270
|
account;
|
|
24190
24271
|
index = tryAsHostCallIndex(3);
|
|
24191
|
-
|
|
24272
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24192
24273
|
tracedRegisters = traceRegisters(read_IN_OUT_REG, 8, 9, 10, 11, 12);
|
|
24193
24274
|
constructor(currentServiceId, account) {
|
|
24194
24275
|
this.currentServiceId = currentServiceId;
|
|
@@ -24205,7 +24286,7 @@ class read_Read {
|
|
|
24205
24286
|
const destinationAddress = regs.get(10);
|
|
24206
24287
|
const storageKeyLengthClamped = clampU64ToU32(storageKeyLength);
|
|
24207
24288
|
// k
|
|
24208
|
-
const rawKey = BytesBlob.blobFrom(
|
|
24289
|
+
const rawKey = BytesBlob.blobFrom(safeAllocUint8Array(storageKeyLengthClamped));
|
|
24209
24290
|
const memoryReadResult = memory.loadInto(rawKey.raw, storageKeyStartAddress);
|
|
24210
24291
|
if (memoryReadResult.isError) {
|
|
24211
24292
|
logger.trace `READ(${serviceId}, ${rawKey}) <- PANIC`;
|
|
@@ -24223,7 +24304,7 @@ class read_Read {
|
|
|
24223
24304
|
// NOTE [MaSo] this is ok to cast to number, because we are bounded by the
|
|
24224
24305
|
// valueLength in both cases and valueLength is WC (4,000,000,000) + metadata
|
|
24225
24306
|
// which is less than 2^32
|
|
24226
|
-
const chunk = value === null ?
|
|
24307
|
+
const chunk = value === null ? safeAllocUint8Array(0) : value.raw.subarray(Number(offset), Number(offset + blobLength));
|
|
24227
24308
|
const memoryWriteResult = memory.storeFrom(destinationAddress, chunk);
|
|
24228
24309
|
if (memoryWriteResult.isError) {
|
|
24229
24310
|
logger.trace `READ(${serviceId}, ${rawKey}) <- PANIC`;
|
|
@@ -24258,7 +24339,7 @@ class write_Write {
|
|
|
24258
24339
|
currentServiceId;
|
|
24259
24340
|
account;
|
|
24260
24341
|
index = tryAsHostCallIndex(4);
|
|
24261
|
-
|
|
24342
|
+
basicGasCost = tryAsSmallGas(10);
|
|
24262
24343
|
tracedRegisters = traceRegisters(write_IN_OUT_REG, 8, 9, 10);
|
|
24263
24344
|
constructor(currentServiceId, account) {
|
|
24264
24345
|
this.currentServiceId = currentServiceId;
|
|
@@ -24274,7 +24355,7 @@ class write_Write {
|
|
|
24274
24355
|
// v_z
|
|
24275
24356
|
const valueLength = regs.get(10);
|
|
24276
24357
|
const storageKeyLengthClamped = clampU64ToU32(storageKeyLength);
|
|
24277
|
-
const rawStorageKey =
|
|
24358
|
+
const rawStorageKey = safeAllocUint8Array(storageKeyLengthClamped);
|
|
24278
24359
|
const keyLoadingResult = memory.loadInto(rawStorageKey, storageKeyStartAddress);
|
|
24279
24360
|
if (keyLoadingResult.isError) {
|
|
24280
24361
|
logger.trace `WRITE() <- PANIC`;
|
|
@@ -24283,7 +24364,7 @@ class write_Write {
|
|
|
24283
24364
|
// k
|
|
24284
24365
|
const storageKey = asOpaqueType(BytesBlob.blobFrom(rawStorageKey));
|
|
24285
24366
|
const valueLengthClamped = clampU64ToU32(valueLength);
|
|
24286
|
-
const value =
|
|
24367
|
+
const value = safeAllocUint8Array(valueLengthClamped);
|
|
24287
24368
|
const valueLoadingResult = memory.loadInto(value, valueStart);
|
|
24288
24369
|
// Note [MaSo] this is ok to return bcs if valueLength is 0, then this panic won't happen
|
|
24289
24370
|
if (valueLoadingResult.isError) {
|
|
@@ -25172,7 +25253,7 @@ function shuffling_fisherYatesShuffle(arr, entropy) {
|
|
|
25172
25253
|
}
|
|
25173
25254
|
function hashToNumberSequence(entropy, length) {
|
|
25174
25255
|
const result = new Array(length);
|
|
25175
|
-
const randomBytes =
|
|
25256
|
+
const randomBytes = safeAllocUint8Array(ENTROPY_BYTES + 4);
|
|
25176
25257
|
randomBytes.set(entropy.raw);
|
|
25177
25258
|
for (let i = 0; i < length; i++) {
|
|
25178
25259
|
randomBytes.set(u32AsLeBytes(tryAsU32(Math.floor(i / 8))), ENTROPY_BYTES);
|
|
@@ -26202,6 +26283,7 @@ class chain_stf_OnChain {
|
|
|
26202
26283
|
authorization;
|
|
26203
26284
|
// chapter 13: https://graypaper.fluffylabs.dev/#/68eaa1f/18b60118b601?v=0.6.4
|
|
26204
26285
|
statistics;
|
|
26286
|
+
isReadyForNextEpoch = Promise.resolve(false);
|
|
26205
26287
|
constructor(chainSpec, state, blocks, hasher) {
|
|
26206
26288
|
this.chainSpec = chainSpec;
|
|
26207
26289
|
this.state = state;
|
|
@@ -26220,6 +26302,14 @@ class chain_stf_OnChain {
|
|
|
26220
26302
|
this.preimages = new Preimages(state);
|
|
26221
26303
|
this.authorization = new Authorization(chainSpec, state);
|
|
26222
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
|
+
}
|
|
26223
26313
|
async verifySeal(timeSlot, block) {
|
|
26224
26314
|
const sealState = this.safrole.getSafroleSealState(timeSlot);
|
|
26225
26315
|
return await this.safroleSeal.verifyHeaderSeal(block.header.view(), sealState);
|
|
@@ -26228,6 +26318,10 @@ class chain_stf_OnChain {
|
|
|
26228
26318
|
const headerView = block.header.view();
|
|
26229
26319
|
const header = block.header.materialize();
|
|
26230
26320
|
const timeSlot = header.timeSlotIndex;
|
|
26321
|
+
// reset the epoch cache state
|
|
26322
|
+
if (headerView.epochMarker.view() !== null) {
|
|
26323
|
+
this.isReadyForNextEpoch = Promise.resolve(false);
|
|
26324
|
+
}
|
|
26231
26325
|
// safrole seal
|
|
26232
26326
|
let newEntropyHash;
|
|
26233
26327
|
if (omitSealVerification) {
|
|
@@ -26692,6 +26786,7 @@ async function runWorkPackageTest(test, file) {
|
|
|
26692
26786
|
|
|
26693
26787
|
|
|
26694
26788
|
|
|
26789
|
+
|
|
26695
26790
|
class MemoryChunkItem {
|
|
26696
26791
|
static fromJson = {
|
|
26697
26792
|
address: "number",
|
|
@@ -26749,10 +26844,10 @@ async function runPvmTest(testContent) {
|
|
|
26749
26844
|
const endPageIndex = tryAsMemoryIndex(startPageIndex + page.length);
|
|
26750
26845
|
const isWriteable = page["is-writable"];
|
|
26751
26846
|
if (isWriteable) {
|
|
26752
|
-
memoryBuilder.setWriteablePages(startPageIndex, endPageIndex,
|
|
26847
|
+
memoryBuilder.setWriteablePages(startPageIndex, endPageIndex, safeAllocUint8Array(page.length));
|
|
26753
26848
|
}
|
|
26754
26849
|
else {
|
|
26755
|
-
memoryBuilder.setReadablePages(startPageIndex, endPageIndex,
|
|
26850
|
+
memoryBuilder.setReadablePages(startPageIndex, endPageIndex, safeAllocUint8Array(page.length));
|
|
26756
26851
|
}
|
|
26757
26852
|
}
|
|
26758
26853
|
for (const memoryChunk of initialMemory) {
|
|
@@ -26804,7 +26899,7 @@ async function runPvmTest(testContent) {
|
|
|
26804
26899
|
}, {});
|
|
26805
26900
|
for (const [pageNumberAsString, memoryChunks] of Object.entries(expectedMemoryByPageNumber)) {
|
|
26806
26901
|
const pageNumber = tryAsPageNumber(Number(pageNumberAsString));
|
|
26807
|
-
const expectedPage =
|
|
26902
|
+
const expectedPage = safeAllocUint8Array(PAGE_SIZE);
|
|
26808
26903
|
for (const memoryChunk of memoryChunks) {
|
|
26809
26904
|
const pageIndex = memoryChunk.address % PAGE_SIZE;
|
|
26810
26905
|
expectedPage.set(memoryChunk.contents, pageIndex);
|