@typeberry/lib 0.1.0-08a9db1 → 0.1.0-b2d0b72
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 +211 -128
- package/index.d.ts +219 -219
- package/index.js +211 -128
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -98,29 +98,17 @@ function isBrowser() {
|
|
|
98
98
|
* We avoid using `node:assert` to keep compatibility with a browser environment.
|
|
99
99
|
* Note the checks should not have any side effects, since we might decide
|
|
100
100
|
* to remove all of them in a post-processing step.
|
|
101
|
-
*/
|
|
102
|
-
function check(condition, message) {
|
|
103
|
-
if (!condition) {
|
|
104
|
-
throw new Error(`Assertion failure: ${message ?? ""}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
function cast(_a, condition) {
|
|
108
|
-
return condition;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Yet another function to perform runtime assertions.
|
|
112
|
-
* This function returns a new type to mark in the code that this value was checked and you don't have to do it again.
|
|
113
101
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* should be replaced with:
|
|
117
|
-
* const x = y as CheckedNumber;
|
|
102
|
+
* NOTE the function is intended to be used as tagged template string for the performance
|
|
103
|
+
* reasons.
|
|
118
104
|
*/
|
|
119
|
-
function
|
|
120
|
-
if (
|
|
121
|
-
|
|
105
|
+
function check(strings, condition, ...data) {
|
|
106
|
+
if (!condition) {
|
|
107
|
+
// add an empty value so that `data.length === strings.length`
|
|
108
|
+
data.unshift("");
|
|
109
|
+
const message = strings.map((v, index) => `${v}${data[index] ?? ""}`);
|
|
110
|
+
throw new Error(`Assertion failure:${message.join("")}`);
|
|
122
111
|
}
|
|
123
|
-
throw new Error(`Assertion failure: ${message ?? ""}`);
|
|
124
112
|
}
|
|
125
113
|
/**
|
|
126
114
|
* The function can be used to make sure that a particular type is `never`
|
|
@@ -287,7 +275,7 @@ function resultToString(res) {
|
|
|
287
275
|
const Result$1 = {
|
|
288
276
|
/** Create new [`Result`] with `Ok` status. */
|
|
289
277
|
ok: (ok) => {
|
|
290
|
-
check
|
|
278
|
+
check `${ok !== undefined} 'ok' type cannot be undefined.`;
|
|
291
279
|
return {
|
|
292
280
|
isOk: true,
|
|
293
281
|
isError: false,
|
|
@@ -296,7 +284,7 @@ const Result$1 = {
|
|
|
296
284
|
},
|
|
297
285
|
/** Create new [`Result`] with `Error` status. */
|
|
298
286
|
error: (error, details = "") => {
|
|
299
|
-
check
|
|
287
|
+
check `${error !== undefined} 'Error' type cannot be undefined.`;
|
|
300
288
|
return {
|
|
301
289
|
isOk: false,
|
|
302
290
|
isError: true,
|
|
@@ -560,7 +548,6 @@ var index$s = /*#__PURE__*/Object.freeze({
|
|
|
560
548
|
assertNever: assertNever,
|
|
561
549
|
check: check,
|
|
562
550
|
deepEqual: deepEqual,
|
|
563
|
-
ensure: ensure,
|
|
564
551
|
inspect: inspect,
|
|
565
552
|
isBrowser: isBrowser,
|
|
566
553
|
measure: measure,
|
|
@@ -594,7 +581,10 @@ class BitVec {
|
|
|
594
581
|
constructor(data, bitLength) {
|
|
595
582
|
this.data = data;
|
|
596
583
|
this.bitLength = bitLength;
|
|
597
|
-
check
|
|
584
|
+
check `
|
|
585
|
+
${data.length * 8 >= bitLength}
|
|
586
|
+
Not enough bytes in the data array. Need ${data.length * 8} has ${bitLength}.
|
|
587
|
+
`;
|
|
598
588
|
this.byteLength = Math.ceil(bitLength / 8);
|
|
599
589
|
}
|
|
600
590
|
/** Return a raw in-memory representation of this [`BitVec`]. */
|
|
@@ -603,7 +593,10 @@ class BitVec {
|
|
|
603
593
|
}
|
|
604
594
|
/** Perform OR operation on all bits in place. */
|
|
605
595
|
sumWith(other) {
|
|
606
|
-
check
|
|
596
|
+
check `
|
|
597
|
+
${other.bitLength === this.bitLength}
|
|
598
|
+
Invalid bit length for sumWith: ${other.bitLength} vs ${this.bitLength}
|
|
599
|
+
`;
|
|
607
600
|
const otherRaw = other.raw;
|
|
608
601
|
for (let i = 0; i < this.byteLength; i++) {
|
|
609
602
|
this.data[i] |= otherRaw[i];
|
|
@@ -613,7 +606,7 @@ class BitVec {
|
|
|
613
606
|
* Set the bit at index `idx` to value `val`.
|
|
614
607
|
*/
|
|
615
608
|
setBit(idx, val) {
|
|
616
|
-
check
|
|
609
|
+
check `${idx >= 0 && idx < this.bitLength} Index out of bounds. Need ${idx} has ${this.bitLength}.`;
|
|
617
610
|
const byteIndex = Math.floor(idx / 8);
|
|
618
611
|
const bitIndexInByte = idx % 8;
|
|
619
612
|
const mask = 1 << bitIndexInByte;
|
|
@@ -628,7 +621,7 @@ class BitVec {
|
|
|
628
621
|
* Return `true` if the bit at index `idx` is set.
|
|
629
622
|
*/
|
|
630
623
|
isSet(idx) {
|
|
631
|
-
check
|
|
624
|
+
check `${idx >= 0 && idx < this.bitLength} Index out of bounds. Need ${idx} has ${this.bitLength}.`;
|
|
632
625
|
const byteIndex = Math.floor(idx / 8);
|
|
633
626
|
const bitIndexInByte = idx % 8;
|
|
634
627
|
const mask = 1 << bitIndexInByte;
|
|
@@ -796,7 +789,7 @@ class BytesBlob {
|
|
|
796
789
|
}
|
|
797
790
|
/** Create a new [`BytesBlob`] from an array of bytes. */
|
|
798
791
|
static blobFromNumbers(v) {
|
|
799
|
-
check
|
|
792
|
+
check `${v.find((x) => (x & 0xff) !== x) === undefined} BytesBlob.blobFromNumbers used with non-byte number array.`;
|
|
800
793
|
const arr = new Uint8Array(v);
|
|
801
794
|
return new BytesBlob(arr);
|
|
802
795
|
}
|
|
@@ -840,7 +833,7 @@ class Bytes extends BytesBlob {
|
|
|
840
833
|
length;
|
|
841
834
|
constructor(raw, len) {
|
|
842
835
|
super(raw);
|
|
843
|
-
check
|
|
836
|
+
check `${raw.byteLength === len} Given buffer has incorrect size ${raw.byteLength} vs expected ${len}`;
|
|
844
837
|
this.length = len;
|
|
845
838
|
}
|
|
846
839
|
/** Create new [`Bytes<X>`] given a backing buffer and it's length. */
|
|
@@ -849,7 +842,7 @@ class Bytes extends BytesBlob {
|
|
|
849
842
|
}
|
|
850
843
|
/** Create new [`Bytes<X>`] given an array of bytes and it's length. */
|
|
851
844
|
static fromNumbers(v, len) {
|
|
852
|
-
check
|
|
845
|
+
check `${v.find((x) => (x & 0xff) !== x) === undefined} Bytes.fromNumbers used with non-byte number array.`;
|
|
853
846
|
const x = new Uint8Array(v);
|
|
854
847
|
return new Bytes(x, len);
|
|
855
848
|
}
|
|
@@ -860,7 +853,7 @@ class Bytes extends BytesBlob {
|
|
|
860
853
|
// TODO [ToDr] `fill` should have the argments swapped to align with the rest.
|
|
861
854
|
/** Create a [`Bytes<X>`] with all bytes filled with given input number. */
|
|
862
855
|
static fill(len, input) {
|
|
863
|
-
check(
|
|
856
|
+
check `${(input & 0xff) === input} Input has to be a byte.`;
|
|
864
857
|
const bytes = Bytes.zero(len);
|
|
865
858
|
bytes.raw.fill(input, 0, len);
|
|
866
859
|
return bytes;
|
|
@@ -883,7 +876,7 @@ class Bytes extends BytesBlob {
|
|
|
883
876
|
}
|
|
884
877
|
/** Compare the sequence to another one. */
|
|
885
878
|
isEqualTo(other) {
|
|
886
|
-
check
|
|
879
|
+
check `${this.length === other.length} Comparing incorrectly typed bytes!`;
|
|
887
880
|
return u8ArraySameLengthEqual(this.raw, other.raw);
|
|
888
881
|
}
|
|
889
882
|
/** Converts current type into some opaque extension. */
|
|
@@ -892,7 +885,7 @@ class Bytes extends BytesBlob {
|
|
|
892
885
|
}
|
|
893
886
|
}
|
|
894
887
|
function byteFromString(s) {
|
|
895
|
-
check
|
|
888
|
+
check `${s.length === 2} Two-character string expected`;
|
|
896
889
|
const a = numberFromCharCode(s.charCodeAt(0));
|
|
897
890
|
const b = numberFromCharCode(s.charCodeAt(1));
|
|
898
891
|
return (a << 4) | b;
|
|
@@ -948,42 +941,53 @@ var index$q = /*#__PURE__*/Object.freeze({
|
|
|
948
941
|
bytesBlobComparator: bytesBlobComparator
|
|
949
942
|
});
|
|
950
943
|
|
|
951
|
-
const
|
|
944
|
+
const asTypedNumber = (v) => v;
|
|
952
945
|
const MAX_VALUE_U8 = 0xff;
|
|
953
946
|
const MAX_VALUE_U16 = 0xffff;
|
|
954
947
|
const MAX_VALUE_U32 = 0xffff_ffff;
|
|
955
948
|
const MAX_VALUE_U64 = 0xffffffffffffffffn;
|
|
956
949
|
/** Attempt to cast an input number into U8. */
|
|
957
|
-
const tryAsU8 = (v) =>
|
|
950
|
+
const tryAsU8 = (v) => {
|
|
951
|
+
check `${isU8(v)} input must have one-byte representation, got ${v}`;
|
|
952
|
+
return asTypedNumber(v);
|
|
953
|
+
};
|
|
958
954
|
/** Check if given number is a valid U8 number. */
|
|
959
955
|
const isU8 = (v) => (v & MAX_VALUE_U8) === v;
|
|
960
956
|
/** Attempt to cast an input number into U16. */
|
|
961
|
-
const tryAsU16 = (v) =>
|
|
957
|
+
const tryAsU16 = (v) => {
|
|
958
|
+
check `${isU16(v)} input must have two-byte representation, got ${v}`;
|
|
959
|
+
return asTypedNumber(v);
|
|
960
|
+
};
|
|
962
961
|
/** Check if given number is a valid U16 number. */
|
|
963
962
|
const isU16 = (v) => (v & MAX_VALUE_U16) === v;
|
|
964
963
|
/** Attempt to cast an input number into U32. */
|
|
965
|
-
const tryAsU32 = (v) =>
|
|
964
|
+
const tryAsU32 = (v) => {
|
|
965
|
+
check `${isU32(v)} input must have four-byte representation, got ${v}`;
|
|
966
|
+
return asTypedNumber(v);
|
|
967
|
+
};
|
|
966
968
|
/** Check if given number is a valid U32 number. */
|
|
967
969
|
const isU32 = (v) => (v & MAX_VALUE_U32) >>> 0 === v;
|
|
968
970
|
/** Attempt to cast an input number into U64. */
|
|
969
971
|
const tryAsU64 = (x) => {
|
|
970
972
|
const v = BigInt(x);
|
|
971
|
-
|
|
973
|
+
check `${isU64(v)} input must have eight-byte representation, got ${x}`;
|
|
974
|
+
return asTypedNumber(v);
|
|
972
975
|
};
|
|
973
976
|
/** Check if given number is a valid U64 number. */
|
|
974
977
|
const isU64 = (v) => (v & MAX_VALUE_U64) === v;
|
|
975
978
|
/** Collate two U32 parts into one U64. */
|
|
976
979
|
const u64FromParts = ({ lower, upper }) => {
|
|
977
980
|
const val = (BigInt(upper) << 32n) + BigInt(lower);
|
|
978
|
-
return
|
|
981
|
+
return asTypedNumber(val);
|
|
979
982
|
};
|
|
980
983
|
/** Split U64 into lower & upper parts. */
|
|
981
984
|
const u64IntoParts = (v) => {
|
|
982
|
-
|
|
983
|
-
const
|
|
985
|
+
// Number(...) safe: both parts are <= 0xffffffff
|
|
986
|
+
const lower = Number(v & (2n ** 32n - 1n));
|
|
987
|
+
const upper = Number(v >> 32n);
|
|
984
988
|
return {
|
|
985
|
-
lower:
|
|
986
|
-
upper:
|
|
989
|
+
lower: asTypedNumber(lower),
|
|
990
|
+
upper: asTypedNumber(upper),
|
|
987
991
|
};
|
|
988
992
|
};
|
|
989
993
|
/**
|
|
@@ -1023,8 +1027,8 @@ function u32AsLeBytes(value) {
|
|
|
1023
1027
|
* Interpret 4-byte `Uint8Array` as U32 written as little endian.
|
|
1024
1028
|
*/
|
|
1025
1029
|
function leBytesAsU32(uint8Array) {
|
|
1026
|
-
check
|
|
1027
|
-
return
|
|
1030
|
+
check `${uint8Array.length === 4} Input must be a Uint8Array of length 4`;
|
|
1031
|
+
return asTypedNumber(uint8Array[0] | (uint8Array[1] << 8) | (uint8Array[2] << 16) | (uint8Array[3] << 24));
|
|
1028
1032
|
}
|
|
1029
1033
|
/** Get the smallest value between U64 a and values given as input parameters. */
|
|
1030
1034
|
const minU64 = (a, ...values) => values.reduce((min, value) => (value > min ? min : value), a);
|
|
@@ -1331,7 +1335,7 @@ class Decoder {
|
|
|
1331
1335
|
this.skip(newOffset - this.offset);
|
|
1332
1336
|
}
|
|
1333
1337
|
else {
|
|
1334
|
-
check
|
|
1338
|
+
check `${newOffset >= 0} The offset has to be positive`;
|
|
1335
1339
|
this.offset = newOffset;
|
|
1336
1340
|
}
|
|
1337
1341
|
}
|
|
@@ -1359,7 +1363,7 @@ class Decoder {
|
|
|
1359
1363
|
return num;
|
|
1360
1364
|
}
|
|
1361
1365
|
ensureHasBytes(bytes) {
|
|
1362
|
-
check
|
|
1366
|
+
check `${bytes >= 0} Negative number of bytes given.`;
|
|
1363
1367
|
if (this.offset + bytes > this.source.length) {
|
|
1364
1368
|
throw new Error(`Attempting to decode more data than there is left. Need ${bytes}, left: ${this.source.length - this.offset}.`);
|
|
1365
1369
|
}
|
|
@@ -1367,7 +1371,7 @@ class Decoder {
|
|
|
1367
1371
|
}
|
|
1368
1372
|
const MASKS = [0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80];
|
|
1369
1373
|
function decodeVariableLengthExtraBytes(firstByte) {
|
|
1370
|
-
check
|
|
1374
|
+
check `${firstByte >= 0 && firstByte < 256} Incorrect byte value: ${firstByte}`;
|
|
1371
1375
|
for (let i = 0; i < MASKS.length; i++) {
|
|
1372
1376
|
if (firstByte >= MASKS[i]) {
|
|
1373
1377
|
return 8 - i;
|
|
@@ -1512,7 +1516,7 @@ class Descriptor {
|
|
|
1512
1516
|
}
|
|
1513
1517
|
|
|
1514
1518
|
function tryAsExactBytes(a) {
|
|
1515
|
-
check
|
|
1519
|
+
check `${a.isExact} The value is not exact size estimation!`;
|
|
1516
1520
|
return a.bytes;
|
|
1517
1521
|
}
|
|
1518
1522
|
function addSizeHints(a, b) {
|
|
@@ -1619,8 +1623,8 @@ class Encoder {
|
|
|
1619
1623
|
// we still allow positive numbers from `[maxNum / 2, maxNum)`.
|
|
1620
1624
|
// So it does not matter if the argument is a negative value,
|
|
1621
1625
|
// OR if someone just gave us two-complement already.
|
|
1622
|
-
check
|
|
1623
|
-
check
|
|
1626
|
+
check `${num < maxNum} Only for numbers up to 2**64 - 1`;
|
|
1627
|
+
check `${-num <= maxNum / 2n} Only for numbers down to -2**63`;
|
|
1624
1628
|
this.ensureBigEnough(8);
|
|
1625
1629
|
this.dataView.setBigInt64(this.offset, num, true);
|
|
1626
1630
|
this.offset += 8;
|
|
@@ -1684,8 +1688,8 @@ class Encoder {
|
|
|
1684
1688
|
// we still allow positive numbers from `[maxNum / 2, maxNum)`.
|
|
1685
1689
|
// So it does not matter if the argument is a negative value,
|
|
1686
1690
|
// OR if someone just gave us two-complement already.
|
|
1687
|
-
check
|
|
1688
|
-
check
|
|
1691
|
+
check `${num < maxNum} Only for numbers up to 2**${BITS * bytesToEncode} - 1`;
|
|
1692
|
+
check `${-num <= maxNum / 2} Only for numbers down to -2**${BITS * bytesToEncode - 1}`;
|
|
1689
1693
|
this.ensureBigEnough(bytesToEncode);
|
|
1690
1694
|
}
|
|
1691
1695
|
/**
|
|
@@ -1696,8 +1700,8 @@ class Encoder {
|
|
|
1696
1700
|
* https://graypaper.fluffylabs.dev/#/579bd12/365202365202
|
|
1697
1701
|
*/
|
|
1698
1702
|
varU32(num) {
|
|
1699
|
-
check
|
|
1700
|
-
check
|
|
1703
|
+
check `${num >= 0} Only for natural numbers.`;
|
|
1704
|
+
check `${num < 2 ** 32} Only for numbers up to 2**32`;
|
|
1701
1705
|
this.varU64(BigInt(num));
|
|
1702
1706
|
}
|
|
1703
1707
|
/**
|
|
@@ -1848,7 +1852,7 @@ class Encoder {
|
|
|
1848
1852
|
* https://graypaper.fluffylabs.dev/#/579bd12/374400374400
|
|
1849
1853
|
*/
|
|
1850
1854
|
sequenceVarLen(encode, elements) {
|
|
1851
|
-
check
|
|
1855
|
+
check `${elements.length <= 2 ** 32} Wow, that's a nice long sequence you've got here.`;
|
|
1852
1856
|
this.varU32(tryAsU32(elements.length));
|
|
1853
1857
|
this.sequenceFixLen(encode, elements);
|
|
1854
1858
|
}
|
|
@@ -1869,7 +1873,7 @@ class Encoder {
|
|
|
1869
1873
|
* anyway, so if we really should throw we will.
|
|
1870
1874
|
*/
|
|
1871
1875
|
ensureBigEnough(length, options = { silent: false }) {
|
|
1872
|
-
check
|
|
1876
|
+
check `${length >= 0} Negative length given`;
|
|
1873
1877
|
const newLength = this.offset + length;
|
|
1874
1878
|
if (newLength > MAX_LENGTH$1) {
|
|
1875
1879
|
if (options.silent) {
|
|
@@ -2000,10 +2004,12 @@ class ObjectView {
|
|
|
2000
2004
|
decodeUpTo(field) {
|
|
2001
2005
|
const index = this.descriptorsKeys.indexOf(field);
|
|
2002
2006
|
const lastField = this.descriptorsKeys[this.lastDecodedFieldIdx];
|
|
2003
|
-
check
|
|
2007
|
+
check `
|
|
2008
|
+
${this.lastDecodedFieldIdx < index}
|
|
2009
|
+
Unjustified call to 'decodeUpTo' -
|
|
2004
2010
|
the index ($Blobindex}, ${String(field)})
|
|
2005
2011
|
is already decoded (${this.lastDecodedFieldIdx}, ${String(lastField)}).
|
|
2006
|
-
|
|
2012
|
+
`;
|
|
2007
2013
|
let lastItem = this.cache.get(lastField);
|
|
2008
2014
|
const skipper = new Skipper(this.decoder);
|
|
2009
2015
|
// now skip all of the fields and further populate the cache.
|
|
@@ -2019,8 +2025,10 @@ class ObjectView {
|
|
|
2019
2025
|
this.cache.set(field, lastItem);
|
|
2020
2026
|
this.lastDecodedFieldIdx = i;
|
|
2021
2027
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2028
|
+
if (lastItem === undefined) {
|
|
2029
|
+
throw new Error("Last item must be set, since the loop turns at least once.");
|
|
2030
|
+
}
|
|
2031
|
+
return lastItem;
|
|
2024
2032
|
}
|
|
2025
2033
|
}
|
|
2026
2034
|
/**
|
|
@@ -2053,8 +2061,10 @@ class SequenceView {
|
|
|
2053
2061
|
*[Symbol.iterator]() {
|
|
2054
2062
|
for (let i = 0; i < this.length; i++) {
|
|
2055
2063
|
const val = this.get(i);
|
|
2056
|
-
|
|
2057
|
-
|
|
2064
|
+
if (val === undefined) {
|
|
2065
|
+
throw new Error("We are within 0..this.length so all items are defined.");
|
|
2066
|
+
}
|
|
2067
|
+
yield val;
|
|
2058
2068
|
}
|
|
2059
2069
|
}
|
|
2060
2070
|
/** Create an array of all views mapped to some particular value. */
|
|
@@ -2097,7 +2107,10 @@ class SequenceView {
|
|
|
2097
2107
|
return BytesBlob.blobFrom(this.decoder.source.subarray(this.initialDecoderOffset, this.decoder.bytesRead()));
|
|
2098
2108
|
}
|
|
2099
2109
|
decodeUpTo(index) {
|
|
2100
|
-
check
|
|
2110
|
+
check `
|
|
2111
|
+
${this.lastDecodedIdx < index}
|
|
2112
|
+
Unjustified call to 'decodeUpTo' - the index (${index}) is already decoded (${this.lastDecodedIdx}).
|
|
2113
|
+
`;
|
|
2101
2114
|
let lastItem = this.cache.get(this.lastDecodedIdx);
|
|
2102
2115
|
const skipper = new Skipper(this.decoder);
|
|
2103
2116
|
// now skip all of the fields and further populate the cache.
|
|
@@ -2112,8 +2125,10 @@ class SequenceView {
|
|
|
2112
2125
|
this.cache.set(i, lastItem);
|
|
2113
2126
|
this.lastDecodedIdx = i;
|
|
2114
2127
|
}
|
|
2115
|
-
|
|
2116
|
-
|
|
2128
|
+
if (lastItem === undefined) {
|
|
2129
|
+
throw new Error("Last item must be set, since the loop turns at least once.");
|
|
2130
|
+
}
|
|
2131
|
+
return lastItem;
|
|
2117
2132
|
}
|
|
2118
2133
|
}
|
|
2119
2134
|
|
|
@@ -2137,7 +2152,10 @@ const TYPICAL_DICTIONARY_LENGTH = 32;
|
|
|
2137
2152
|
*/
|
|
2138
2153
|
function readonlyArray(desc) {
|
|
2139
2154
|
return desc.convert((x) => {
|
|
2140
|
-
check
|
|
2155
|
+
check `
|
|
2156
|
+
${Array.isArray(x)}
|
|
2157
|
+
Non-arrays are not supported as 'readonly': got ${typeof x}, ${x}
|
|
2158
|
+
`;
|
|
2141
2159
|
// NOTE [ToDr] This assumption is incorrect in general, but it's documented
|
|
2142
2160
|
// in the general note. We avoid `.slice()` the array for performance reasons.
|
|
2143
2161
|
return x;
|
|
@@ -3094,7 +3112,7 @@ const BLS_KEY_BYTES = 144;
|
|
|
3094
3112
|
/** Derive a Bandersnatch public key from a seed. */
|
|
3095
3113
|
function publicKey(seed) {
|
|
3096
3114
|
const key = bandersnatch_exports.derive_public_key(seed);
|
|
3097
|
-
check
|
|
3115
|
+
check `${key[0] === 0} Invalid Bandersnatch public key derived from seed`;
|
|
3098
3116
|
return Bytes.fromBlob(key.subarray(1), BANDERSNATCH_KEY_BYTES).asOpaque();
|
|
3099
3117
|
}
|
|
3100
3118
|
|
|
@@ -3536,7 +3554,7 @@ async function verify(input) {
|
|
|
3536
3554
|
data.set(signature.raw, offset);
|
|
3537
3555
|
offset += ED25519_SIGNATURE_BYTES;
|
|
3538
3556
|
const messageLength = message.length;
|
|
3539
|
-
check
|
|
3557
|
+
check `${messageLength < 256} Message needs to be shorter than 256 bytes. Got: ${messageLength}`;
|
|
3540
3558
|
data[offset] = messageLength;
|
|
3541
3559
|
offset += 1;
|
|
3542
3560
|
data.set(message.raw, offset);
|
|
@@ -3625,7 +3643,7 @@ class PageAllocator {
|
|
|
3625
3643
|
// TODO [ToDr] Benchmark the performance!
|
|
3626
3644
|
constructor(hashesPerPage) {
|
|
3627
3645
|
this.hashesPerPage = hashesPerPage;
|
|
3628
|
-
check
|
|
3646
|
+
check `${hashesPerPage > 0 && hashesPerPage >>> 0 === hashesPerPage} Expected a non-zero integer.`;
|
|
3629
3647
|
this.resetPage();
|
|
3630
3648
|
}
|
|
3631
3649
|
resetPage() {
|
|
@@ -5096,8 +5114,8 @@ class MultiMap {
|
|
|
5096
5114
|
* if needed.
|
|
5097
5115
|
*/
|
|
5098
5116
|
constructor(keysLength, keyMappers) {
|
|
5099
|
-
check
|
|
5100
|
-
check
|
|
5117
|
+
check `${keysLength > 0} Keys cannot be empty.`;
|
|
5118
|
+
check `${keyMappers === undefined || keyMappers.length === keysLength} Incorrect number of key mappers given!`;
|
|
5101
5119
|
this.data = new Map();
|
|
5102
5120
|
this.keyMappers = keyMappers === undefined ? Array(keysLength).fill(null) : keyMappers;
|
|
5103
5121
|
}
|
|
@@ -5196,7 +5214,7 @@ class FixedSizeArray extends Array {
|
|
|
5196
5214
|
this.fixedLength = this.length;
|
|
5197
5215
|
}
|
|
5198
5216
|
static new(data, len) {
|
|
5199
|
-
check
|
|
5217
|
+
check `${data.length === len} Expected an array of size: ${len}, got: ${data.length}`;
|
|
5200
5218
|
const arr = new FixedSizeArray(len);
|
|
5201
5219
|
for (let i = 0; i < len; i++) {
|
|
5202
5220
|
arr[i] = data[i];
|
|
@@ -5328,7 +5346,7 @@ class SortedArray {
|
|
|
5328
5346
|
}
|
|
5329
5347
|
/** Create a new SortedSet from two sorted collections. */
|
|
5330
5348
|
static fromTwoSortedCollections(first, second) {
|
|
5331
|
-
check
|
|
5349
|
+
check `${first.comparator === second.comparator} Cannot merge arrays if they do not use the same comparator`;
|
|
5332
5350
|
const comparator = first.comparator;
|
|
5333
5351
|
const arr1 = first.array;
|
|
5334
5352
|
const arr1Length = arr1.length;
|
|
@@ -5445,7 +5463,7 @@ class SortedSet extends SortedArray {
|
|
|
5445
5463
|
}
|
|
5446
5464
|
/** Create a new SortedSet from two sorted collections. */
|
|
5447
5465
|
static fromTwoSortedCollections(first, second) {
|
|
5448
|
-
check
|
|
5466
|
+
check `${first.comparator === second.comparator} Cannot merge arrays if they do not use the same comparator`;
|
|
5449
5467
|
const comparator = first.comparator;
|
|
5450
5468
|
if (first.length === 0) {
|
|
5451
5469
|
return SortedSet.fromSortedArray(comparator, second.array);
|
|
@@ -6107,7 +6125,10 @@ const tryAsCoreIndex = (v) => asOpaqueType(tryAsU16(v));
|
|
|
6107
6125
|
/** Attempt to convert a number into `Epoch`. */
|
|
6108
6126
|
const tryAsEpoch = (v) => asOpaqueType(tryAsU32(v));
|
|
6109
6127
|
function tryAsPerValidator(array, spec) {
|
|
6110
|
-
check
|
|
6128
|
+
check `
|
|
6129
|
+
${array.length === spec.validatorsCount}
|
|
6130
|
+
Invalid per-validator array length. Expected ${spec.validatorsCount}, got: ${array.length}
|
|
6131
|
+
`;
|
|
6111
6132
|
return asKnownSize(array);
|
|
6112
6133
|
}
|
|
6113
6134
|
const codecPerValidator = (val) => codecWithContext((context) => {
|
|
@@ -6116,7 +6137,10 @@ const codecPerValidator = (val) => codecWithContext((context) => {
|
|
|
6116
6137
|
});
|
|
6117
6138
|
});
|
|
6118
6139
|
function tryAsPerEpochBlock(array, spec) {
|
|
6119
|
-
check
|
|
6140
|
+
check `
|
|
6141
|
+
${array.length === spec.epochLength}
|
|
6142
|
+
Invalid per-epoch-block array length. Expected ${spec.epochLength}, got: ${array.length}
|
|
6143
|
+
`;
|
|
6120
6144
|
return asKnownSize(array);
|
|
6121
6145
|
}
|
|
6122
6146
|
const codecPerEpochBlock = (val) => codecWithContext((context) => {
|
|
@@ -6381,7 +6405,11 @@ var workItem = /*#__PURE__*/Object.freeze({
|
|
|
6381
6405
|
|
|
6382
6406
|
/** Verify the value is within the `WorkItemsCount` bounds. */
|
|
6383
6407
|
function tryAsWorkItemsCount(len) {
|
|
6384
|
-
|
|
6408
|
+
check `
|
|
6409
|
+
${len >= MIN_NUMBER_OF_WORK_ITEMS && len <= MAX_NUMBER_OF_WORK_ITEMS}
|
|
6410
|
+
WorkItemsCount: Expected '${MIN_NUMBER_OF_WORK_ITEMS} <= count <= ${MAX_NUMBER_OF_WORK_ITEMS}' got ${len}
|
|
6411
|
+
`;
|
|
6412
|
+
return tryAsU8(len);
|
|
6385
6413
|
}
|
|
6386
6414
|
/** Minimal number of work items in the work package or results in work report. */
|
|
6387
6415
|
const MIN_NUMBER_OF_WORK_ITEMS = 1;
|
|
@@ -8597,7 +8625,10 @@ class AvailabilityAssignment extends WithDebug {
|
|
|
8597
8625
|
|
|
8598
8626
|
/** Check if given array has correct length before casting to the opaque type. */
|
|
8599
8627
|
function tryAsPerCore(array, spec) {
|
|
8600
|
-
check
|
|
8628
|
+
check `
|
|
8629
|
+
${array.length === spec.coresCount}
|
|
8630
|
+
Invalid per-core array length. Expected ${spec.coresCount}, got: ${array.length}
|
|
8631
|
+
`;
|
|
8601
8632
|
return asOpaqueType(array);
|
|
8602
8633
|
}
|
|
8603
8634
|
const codecPerCore = (val) => codecWithContext((context) => {
|
|
@@ -9745,7 +9776,7 @@ class InMemoryState extends WithDebug {
|
|
|
9745
9776
|
}
|
|
9746
9777
|
removeServices(servicesRemoved) {
|
|
9747
9778
|
for (const serviceId of servicesRemoved ?? []) {
|
|
9748
|
-
check
|
|
9779
|
+
check `${this.services.has(serviceId)} Attempting to remove non-existing service: ${serviceId}`;
|
|
9749
9780
|
this.services.delete(serviceId);
|
|
9750
9781
|
}
|
|
9751
9782
|
}
|
|
@@ -9762,7 +9793,10 @@ class InMemoryState extends WithDebug {
|
|
|
9762
9793
|
}
|
|
9763
9794
|
else if (kind === UpdateStorageKind.Remove) {
|
|
9764
9795
|
const { key } = action;
|
|
9765
|
-
check
|
|
9796
|
+
check `
|
|
9797
|
+
${service.data.storage.has(key.toString())}
|
|
9798
|
+
Attempting to remove non-existing storage item at ${serviceId}: ${action.key}
|
|
9799
|
+
`;
|
|
9766
9800
|
service.data.storage.delete(key.toString());
|
|
9767
9801
|
}
|
|
9768
9802
|
else {
|
|
@@ -10441,12 +10475,12 @@ class TrieNode {
|
|
|
10441
10475
|
}
|
|
10442
10476
|
/** View this node as a branch node */
|
|
10443
10477
|
asBranchNode() {
|
|
10444
|
-
check
|
|
10478
|
+
check `${this.getNodeType() === NodeType.Branch} not a branch!`;
|
|
10445
10479
|
return new BranchNode(this);
|
|
10446
10480
|
}
|
|
10447
10481
|
/** View this node as a leaf node */
|
|
10448
10482
|
asLeafNode() {
|
|
10449
|
-
check
|
|
10483
|
+
check `${this.getNodeType() !== NodeType.Branch} not a leaf!`;
|
|
10450
10484
|
return new LeafNode(this);
|
|
10451
10485
|
}
|
|
10452
10486
|
toString() {
|
|
@@ -10924,7 +10958,7 @@ function createSubtreeForBothLeaves(traversedPath, nodes, leafToReplace, leaf) {
|
|
|
10924
10958
|
* Return a single bit from `key` located at `bitIndex`.
|
|
10925
10959
|
*/
|
|
10926
10960
|
function getBit(key, bitIndex) {
|
|
10927
|
-
check
|
|
10961
|
+
check `${bitIndex < TRUNCATED_KEY_BITS} invalid bit index passed ${bitIndex}`;
|
|
10928
10962
|
const byte = bitIndex >>> 3;
|
|
10929
10963
|
const bit = bitIndex - (byte << 3);
|
|
10930
10964
|
const mask = 0b10_00_00_00 >>> bit;
|
|
@@ -11652,7 +11686,6 @@ const N_CHUNKS_REQUIRED = 342;
|
|
|
11652
11686
|
const N_CHUNKS_REDUNDANCY = 681;
|
|
11653
11687
|
/** Total number of chunks generated by EC. */
|
|
11654
11688
|
const N_CHUNKS_TOTAL = 1023;
|
|
11655
|
-
// check(N_CHUNKS_TOTAL === N_CHUNKS_REQUIRED + N_CHUNKS_REDUNDANCY);
|
|
11656
11689
|
/**
|
|
11657
11690
|
* reed-solomon-simd requires point size to be multiple of 64 bytes but we need only 2 bytes.
|
|
11658
11691
|
* It does not matter what indices are selected, but it has to be n and n + 32
|
|
@@ -11664,7 +11697,10 @@ const HALF_POINT_SIZE = 32;
|
|
|
11664
11697
|
*/
|
|
11665
11698
|
const POINT_LENGTH = 2;
|
|
11666
11699
|
const PIECE_SIZE = 684;
|
|
11667
|
-
|
|
11700
|
+
function checkConsistency() {
|
|
11701
|
+
check `${N_CHUNKS_TOTAL === N_CHUNKS_REQUIRED + N_CHUNKS_REDUNDANCY} no of required and redundancy chunks need to match ${N_CHUNKS_TOTAL}`;
|
|
11702
|
+
check `${PIECE_SIZE === N_CHUNKS_REQUIRED * POINT_LENGTH} piece size needs to match ${N_CHUNKS_REQUIRED} * ${POINT_LENGTH}`;
|
|
11703
|
+
}
|
|
11668
11704
|
/**
|
|
11669
11705
|
* Takes arbitrarily long input data, padds it to multiple of `PIECE_SIZE` and returns
|
|
11670
11706
|
* exactly `N_CHUNKS_TOTAL` ec-coded segments.
|
|
@@ -11697,8 +11733,11 @@ function decodeDataAndTrim(input, expectedLength) {
|
|
|
11697
11733
|
function decodeData(input) {
|
|
11698
11734
|
const pointBytes = input[0][1].length;
|
|
11699
11735
|
const points = Math.floor(pointBytes / POINT_LENGTH);
|
|
11700
|
-
check
|
|
11701
|
-
check
|
|
11736
|
+
check `${points * POINT_LENGTH === pointBytes} Each point length needs to be a multiple of ${POINT_LENGTH}`;
|
|
11737
|
+
check `
|
|
11738
|
+
${input.every(([_idx, point]) => point.length === pointBytes)},
|
|
11739
|
+
Every piece must have the same length!
|
|
11740
|
+
`;
|
|
11702
11741
|
const pieces = FixedSizeArray.fill(() => Bytes.zero(PIECE_SIZE), points);
|
|
11703
11742
|
for (let i = 0; i < points; i++) {
|
|
11704
11743
|
const start = i * POINT_LENGTH;
|
|
@@ -11771,7 +11810,7 @@ function decodePiece(input) {
|
|
|
11771
11810
|
if (resultIndices === undefined) {
|
|
11772
11811
|
throw new Error("indices array in decoded result must exist!");
|
|
11773
11812
|
}
|
|
11774
|
-
check
|
|
11813
|
+
check `${resultData.length === resultIndices.length * POINT_ALIGNMENT} incorrect length of data or indices!`;
|
|
11775
11814
|
for (let i = 0; i < resultIndices.length; i++) {
|
|
11776
11815
|
// fill reconstructed shards in result
|
|
11777
11816
|
const index = resultIndices[i];
|
|
@@ -11796,7 +11835,7 @@ function decodePiece(input) {
|
|
|
11796
11835
|
* https://graypaper.fluffylabs.dev/#/9a08063/3eb4013eb401?v=0.6.6
|
|
11797
11836
|
*/
|
|
11798
11837
|
function split(input, n, k) {
|
|
11799
|
-
check
|
|
11838
|
+
check `${n * k === input.length}`;
|
|
11800
11839
|
const result = [];
|
|
11801
11840
|
for (let i = 0; i < k; i++) {
|
|
11802
11841
|
const start = i * n;
|
|
@@ -11909,7 +11948,7 @@ function transpose(input, k) {
|
|
|
11909
11948
|
*/
|
|
11910
11949
|
function chunkingFunction(input) {
|
|
11911
11950
|
const k = Math.floor(input.length / PIECE_SIZE);
|
|
11912
|
-
check
|
|
11951
|
+
check `${k * PIECE_SIZE === input.length} Input length ${input.length} is not divisible by ${PIECE_SIZE}`;
|
|
11913
11952
|
// we get a `k` pieces.
|
|
11914
11953
|
const pieces = unzip(input, PIECE_SIZE, k);
|
|
11915
11954
|
// and each piece get's ec-codec
|
|
@@ -11927,7 +11966,10 @@ function chunkingFunction(input) {
|
|
|
11927
11966
|
function shardsToChunks(spec, shards) {
|
|
11928
11967
|
const result = [];
|
|
11929
11968
|
const shardSize = shards[0].length;
|
|
11930
|
-
check
|
|
11969
|
+
check `
|
|
11970
|
+
${shards.every((s) => s.length === shardSize)}
|
|
11971
|
+
Each shard must be the same length!
|
|
11972
|
+
`;
|
|
11931
11973
|
const totalData = shards.map((s) => s.length).reduce((sum, sLength) => sum + sLength, 0);
|
|
11932
11974
|
const chunkSize = Math.floor(totalData / N_CHUNKS_TOTAL);
|
|
11933
11975
|
const piecesPerChunk = Math.floor(shardSize / chunkSize);
|
|
@@ -11977,6 +12019,7 @@ var index$a = /*#__PURE__*/Object.freeze({
|
|
|
11977
12019
|
N_CHUNKS_TOTAL: N_CHUNKS_TOTAL,
|
|
11978
12020
|
PIECE_SIZE: PIECE_SIZE,
|
|
11979
12021
|
POINT_LENGTH: POINT_LENGTH,
|
|
12022
|
+
checkConsistency: checkConsistency,
|
|
11980
12023
|
chunkingFunction: chunkingFunction,
|
|
11981
12024
|
chunksToShards: chunksToShards,
|
|
11982
12025
|
decodeData: decodeData,
|
|
@@ -12439,8 +12482,8 @@ class PartiallyUpdatedState {
|
|
|
12439
12482
|
this.stateUpdate.services.preimages.push(newUpdate);
|
|
12440
12483
|
}
|
|
12441
12484
|
updateServiceStorageUtilisation(serviceId, items, bytes, serviceInfo) {
|
|
12442
|
-
check
|
|
12443
|
-
check
|
|
12485
|
+
check `${items >= 0} storageUtilisationCount has to be a positive number, got: ${items}`;
|
|
12486
|
+
check `${bytes >= 0} storageUtilisationBytes has to be a positive number, got: ${bytes}`;
|
|
12444
12487
|
const overflowItems = !isU32(items);
|
|
12445
12488
|
const overflowBytes = !isU64(bytes);
|
|
12446
12489
|
// TODO [ToDr] this is not specified in GP, but it seems sensible.
|
|
@@ -12535,7 +12578,7 @@ function getServiceId(serviceId) {
|
|
|
12535
12578
|
return null;
|
|
12536
12579
|
}
|
|
12537
12580
|
function writeServiceIdAsLeBytes(serviceId, destination) {
|
|
12538
|
-
check
|
|
12581
|
+
check `${destination.length >= SERVICE_ID_BYTES} Not enough space in the destination.`;
|
|
12539
12582
|
destination.set(u32AsLeBytes(serviceId));
|
|
12540
12583
|
}
|
|
12541
12584
|
/** Clamp a U64 to the maximum value of a 32-bit unsigned integer. */
|
|
@@ -12703,19 +12746,22 @@ var index$8 = /*#__PURE__*/Object.freeze({
|
|
|
12703
12746
|
|
|
12704
12747
|
const NO_OF_REGISTERS$1 = 13;
|
|
12705
12748
|
const REGISTER_SIZE_SHIFT = 3;
|
|
12706
|
-
const tryAsRegisterIndex = (index) =>
|
|
12749
|
+
const tryAsRegisterIndex = (index) => {
|
|
12750
|
+
check `${index >= 0 && index < NO_OF_REGISTERS$1} Incorrect register index: ${index}!`;
|
|
12751
|
+
return asOpaqueType(index);
|
|
12752
|
+
};
|
|
12707
12753
|
class Registers {
|
|
12708
12754
|
bytes;
|
|
12709
12755
|
asSigned;
|
|
12710
12756
|
asUnsigned;
|
|
12711
12757
|
constructor(bytes = new Uint8Array(NO_OF_REGISTERS$1 << REGISTER_SIZE_SHIFT)) {
|
|
12712
12758
|
this.bytes = bytes;
|
|
12713
|
-
check
|
|
12759
|
+
check `${bytes.length === NO_OF_REGISTERS$1 << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
12714
12760
|
this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
|
|
12715
12761
|
this.asUnsigned = new BigUint64Array(bytes.buffer, bytes.byteOffset);
|
|
12716
12762
|
}
|
|
12717
12763
|
static fromBytes(bytes) {
|
|
12718
|
-
check
|
|
12764
|
+
check `${bytes.length === NO_OF_REGISTERS$1 << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
12719
12765
|
return new Registers(bytes);
|
|
12720
12766
|
}
|
|
12721
12767
|
getBytesAsLittleEndian(index, len) {
|
|
@@ -12851,7 +12897,7 @@ class Mask {
|
|
|
12851
12897
|
return this.lookupTableForward[index] === 0;
|
|
12852
12898
|
}
|
|
12853
12899
|
getNoOfBytesToNextInstruction(index) {
|
|
12854
|
-
check
|
|
12900
|
+
check `${index >= 0} index (${index}) cannot be a negative number`;
|
|
12855
12901
|
return Math.min(this.lookupTableForward[index] ?? 0, MAX_INSTRUCTION_DISTANCE);
|
|
12856
12902
|
}
|
|
12857
12903
|
buildLookupTableForward(mask) {
|
|
@@ -13817,7 +13863,7 @@ const PAGE_SIZE_SHIFT = 12;
|
|
|
13817
13863
|
const PAGE_SIZE$1 = 1 << PAGE_SIZE_SHIFT;
|
|
13818
13864
|
const MIN_ALLOCATION_SHIFT = (() => {
|
|
13819
13865
|
const MIN_ALLOCATION_SHIFT = 7;
|
|
13820
|
-
check
|
|
13866
|
+
check `${MIN_ALLOCATION_SHIFT < PAGE_SIZE_SHIFT} incorrect minimal allocation shift`;
|
|
13821
13867
|
return MIN_ALLOCATION_SHIFT;
|
|
13822
13868
|
})();
|
|
13823
13869
|
const MIN_ALLOCATION_LENGTH = PAGE_SIZE$1 >> MIN_ALLOCATION_SHIFT;
|
|
@@ -13827,13 +13873,25 @@ const RESERVED_NUMBER_OF_PAGES = 16;
|
|
|
13827
13873
|
/** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
|
|
13828
13874
|
const MAX_NUMBER_OF_PAGES = MEMORY_SIZE / PAGE_SIZE$1;
|
|
13829
13875
|
|
|
13830
|
-
const tryAsMemoryIndex = (index) =>
|
|
13831
|
-
|
|
13876
|
+
const tryAsMemoryIndex = (index) => {
|
|
13877
|
+
check `${index >= 0 && index <= MAX_MEMORY_INDEX} Incorrect memory index: ${index}!`;
|
|
13878
|
+
return asOpaqueType(index);
|
|
13879
|
+
};
|
|
13880
|
+
const tryAsSbrkIndex = (index) => {
|
|
13881
|
+
check `${index >= 0 && index <= MAX_MEMORY_INDEX + 1} Incorrect sbrk index: ${index}!`;
|
|
13882
|
+
return asOpaqueType(index);
|
|
13883
|
+
};
|
|
13832
13884
|
|
|
13833
13885
|
/** Ensure that given memory `index` is within `[0...PAGE_SIZE)` and can be used to index a page */
|
|
13834
|
-
const tryAsPageIndex = (index) =>
|
|
13886
|
+
const tryAsPageIndex = (index) => {
|
|
13887
|
+
check `${index >= 0 && index < PAGE_SIZE$1}, Incorect page index: ${index}!`;
|
|
13888
|
+
return asOpaqueType(index);
|
|
13889
|
+
};
|
|
13835
13890
|
/** Ensure that given `index` represents an index of one of the pages. */
|
|
13836
|
-
const tryAsPageNumber = (index) =>
|
|
13891
|
+
const tryAsPageNumber = (index) => {
|
|
13892
|
+
check `${index >= 0 && index <= LAST_PAGE_NUMBER}, Incorect page number: ${index}!`;
|
|
13893
|
+
return asOpaqueType(index);
|
|
13894
|
+
};
|
|
13837
13895
|
/**
|
|
13838
13896
|
* Get the next page number and wrap the result if it is bigger than LAST_PAGE_NUMBER
|
|
13839
13897
|
*
|
|
@@ -14297,10 +14355,10 @@ class MemoryBuilder {
|
|
|
14297
14355
|
*/
|
|
14298
14356
|
setReadablePages(start, end, data = new Uint8Array()) {
|
|
14299
14357
|
this.ensureNotFinalized();
|
|
14300
|
-
check
|
|
14301
|
-
check
|
|
14302
|
-
check
|
|
14303
|
-
check
|
|
14358
|
+
check `${start < end} end has to be bigger than start`;
|
|
14359
|
+
check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14360
|
+
check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14361
|
+
check `${data.length <= end - start} the initial data is longer than address range`;
|
|
14304
14362
|
const length = end - start;
|
|
14305
14363
|
const range = MemoryRange.fromStartAndLength(start, length);
|
|
14306
14364
|
this.ensureNoReservedMemoryUsage(range);
|
|
@@ -14325,10 +14383,10 @@ class MemoryBuilder {
|
|
|
14325
14383
|
*/
|
|
14326
14384
|
setWriteablePages(start, end, data = new Uint8Array()) {
|
|
14327
14385
|
this.ensureNotFinalized();
|
|
14328
|
-
check
|
|
14329
|
-
check
|
|
14330
|
-
check
|
|
14331
|
-
check
|
|
14386
|
+
check `${start < end} end has to be bigger than start`;
|
|
14387
|
+
check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14388
|
+
check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14389
|
+
check `${data.length <= end - start} the initial data is longer than address range`;
|
|
14332
14390
|
const length = end - start;
|
|
14333
14391
|
const range = MemoryRange.fromStartAndLength(start, length);
|
|
14334
14392
|
this.ensureNoReservedMemoryUsage(range);
|
|
@@ -14350,7 +14408,7 @@ class MemoryBuilder {
|
|
|
14350
14408
|
this.ensureNotFinalized();
|
|
14351
14409
|
const pageOffset = start % PAGE_SIZE$1;
|
|
14352
14410
|
const remainingSpaceOnPage = PAGE_SIZE$1 - pageOffset;
|
|
14353
|
-
check
|
|
14411
|
+
check `${data.length <= remainingSpaceOnPage} The data has to fit into a single page.`;
|
|
14354
14412
|
const length = data.length;
|
|
14355
14413
|
const range = MemoryRange.fromStartAndLength(start, length);
|
|
14356
14414
|
this.ensureNoReservedMemoryUsage(range);
|
|
@@ -14364,7 +14422,10 @@ class MemoryBuilder {
|
|
|
14364
14422
|
return this;
|
|
14365
14423
|
}
|
|
14366
14424
|
finalize(startHeapIndex, endHeapIndex) {
|
|
14367
|
-
check
|
|
14425
|
+
check `
|
|
14426
|
+
${startHeapIndex <= endHeapIndex}
|
|
14427
|
+
startHeapIndex (${startHeapIndex}) has to be less than or equal to endHeapIndex (${endHeapIndex})
|
|
14428
|
+
`;
|
|
14368
14429
|
this.ensureNotFinalized();
|
|
14369
14430
|
const range = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
|
|
14370
14431
|
const pages = PageRange.fromMemoryRange(range);
|
|
@@ -14609,7 +14670,7 @@ function mulUpperSS(a, b) {
|
|
|
14609
14670
|
return interpretAsSigned(resultLimitedTo64Bits);
|
|
14610
14671
|
}
|
|
14611
14672
|
function unsignedRightShiftBigInt(value, shift) {
|
|
14612
|
-
check
|
|
14673
|
+
check `${shift >= 0} Shift count must be non-negative`;
|
|
14613
14674
|
const fillBit = value < 0 ? "1" : "0";
|
|
14614
14675
|
// Convert the BigInt to its binary representation
|
|
14615
14676
|
const binaryRepresentation = value.toString(2).padStart(64, fillBit);
|
|
@@ -15935,7 +15996,10 @@ class TwoRegsTwoImmsDispatcher {
|
|
|
15935
15996
|
class JumpTable {
|
|
15936
15997
|
indices;
|
|
15937
15998
|
constructor(itemByteLength, bytes) {
|
|
15938
|
-
check
|
|
15999
|
+
check `
|
|
16000
|
+
${itemByteLength === 0 || bytes.length % itemByteLength === 0}
|
|
16001
|
+
Length of jump table (${bytes.length}) should be a multiple of item lenght (${itemByteLength})!
|
|
16002
|
+
`;
|
|
15939
16003
|
const length = itemByteLength === 0 ? 0 : bytes.length / itemByteLength;
|
|
15940
16004
|
this.indices = new Uint32Array(length);
|
|
15941
16005
|
for (let i = 0; i < length; i++) {
|
|
@@ -16325,7 +16389,10 @@ class ReturnValue {
|
|
|
16325
16389
|
this.consumedGas = consumedGas;
|
|
16326
16390
|
this.status = status;
|
|
16327
16391
|
this.memorySlice = memorySlice;
|
|
16328
|
-
check
|
|
16392
|
+
check `
|
|
16393
|
+
${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
|
|
16394
|
+
'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
|
|
16395
|
+
`;
|
|
16329
16396
|
}
|
|
16330
16397
|
static fromStatus(consumedGas, status) {
|
|
16331
16398
|
return new ReturnValue(consumedGas, status, null);
|
|
@@ -16374,7 +16441,10 @@ class HostCalls {
|
|
|
16374
16441
|
if (status !== Status.HOST) {
|
|
16375
16442
|
return this.getReturnValue(status, pvmInstance);
|
|
16376
16443
|
}
|
|
16377
|
-
check
|
|
16444
|
+
check `
|
|
16445
|
+
${pvmInstance.getExitParam() !== null}
|
|
16446
|
+
"We know that the exit param is not null, because the status is 'Status.HOST'
|
|
16447
|
+
`;
|
|
16378
16448
|
const hostCallIndex = pvmInstance.getExitParam() ?? -1;
|
|
16379
16449
|
const gas = pvmInstance.getGasCounter();
|
|
16380
16450
|
const regs = new HostCallRegisters(pvmInstance.getRegisters());
|
|
@@ -16428,7 +16498,7 @@ class HostCallsManager {
|
|
|
16428
16498
|
constructor({ missing, handlers = [], }) {
|
|
16429
16499
|
this.missing = missing;
|
|
16430
16500
|
for (const handler of handlers) {
|
|
16431
|
-
check
|
|
16501
|
+
check `${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
|
|
16432
16502
|
this.hostCalls.set(handler.index, handler);
|
|
16433
16503
|
}
|
|
16434
16504
|
}
|
|
@@ -16548,13 +16618,27 @@ class SpiProgram extends WithDebug {
|
|
|
16548
16618
|
this.registers = registers;
|
|
16549
16619
|
}
|
|
16550
16620
|
}
|
|
16621
|
+
/**
|
|
16622
|
+
* program = E_3(|o|) ++ E_3(|w|) ++ E_2(z) ++ E_3(s) ++ o ++ w ++ E_4(|c|) ++ c
|
|
16623
|
+
*
|
|
16624
|
+
* E_n - little endian encoding, n - length
|
|
16625
|
+
* o - initial read only data
|
|
16626
|
+
* w - initial heap
|
|
16627
|
+
* z - heap pages filled with zeros
|
|
16628
|
+
* s - stack size
|
|
16629
|
+
* c - program code
|
|
16630
|
+
*
|
|
16631
|
+
* https://graypaper.fluffylabs.dev/#/579bd12/2b92022b9202
|
|
16632
|
+
*/
|
|
16551
16633
|
function decodeStandardProgram(program, args) {
|
|
16552
16634
|
const decoder = Decoder.fromBlob(program);
|
|
16553
16635
|
const oLength = decoder.u24();
|
|
16554
16636
|
const wLength = decoder.u24();
|
|
16555
|
-
|
|
16556
|
-
|
|
16557
|
-
const
|
|
16637
|
+
check `${args.length <= DATA_LEGNTH} Incorrect arguments length`;
|
|
16638
|
+
check `${oLength <= DATA_LEGNTH} Incorrect readonly segment length`;
|
|
16639
|
+
const readOnlyLength = oLength;
|
|
16640
|
+
check `${wLength <= DATA_LEGNTH} Incorrect heap segment length`;
|
|
16641
|
+
const heapLength = wLength;
|
|
16558
16642
|
const noOfHeapZerosPages = decoder.u16();
|
|
16559
16643
|
const stackSize = decoder.u24();
|
|
16560
16644
|
const readOnlyMemory = decoder.bytes(readOnlyLength).raw;
|
|
@@ -16570,14 +16654,14 @@ function decodeStandardProgram(program, args) {
|
|
|
16570
16654
|
const stackStart = STACK_SEGMENT - alignToPageSize(stackSize);
|
|
16571
16655
|
const stackEnd = STACK_SEGMENT;
|
|
16572
16656
|
const argsStart = ARGS_SEGMENT;
|
|
16573
|
-
const argsEnd = argsStart + alignToPageSize(
|
|
16574
|
-
const argsZerosEnd = argsEnd + alignToPageSize(
|
|
16657
|
+
const argsEnd = argsStart + alignToPageSize(args.length);
|
|
16658
|
+
const argsZerosEnd = argsEnd + alignToPageSize(args.length);
|
|
16575
16659
|
function nonEmpty(s) {
|
|
16576
16660
|
return s !== false;
|
|
16577
16661
|
}
|
|
16578
16662
|
const readableMemory = [
|
|
16579
16663
|
readOnlyLength > 0 && getMemorySegment(readonlyDataStart, readonlyDataEnd, readOnlyMemory),
|
|
16580
|
-
|
|
16664
|
+
args.length > 0 && getMemorySegment(argsStart, argsEnd, args),
|
|
16581
16665
|
argsEnd < argsZerosEnd && getMemorySegment(argsEnd, argsZerosEnd),
|
|
16582
16666
|
].filter(nonEmpty);
|
|
16583
16667
|
const writeableMemory = [
|
|
@@ -16708,7 +16792,7 @@ class DebuggerAdapter {
|
|
|
16708
16792
|
return this.pvm.nextStep() === Status.OK;
|
|
16709
16793
|
}
|
|
16710
16794
|
nSteps(steps) {
|
|
16711
|
-
check
|
|
16795
|
+
check `${steps >>> 0 > 0} Expected a positive integer got ${steps}`;
|
|
16712
16796
|
for (let i = 0; i < steps; i++) {
|
|
16713
16797
|
const isOk = this.nextStep();
|
|
16714
16798
|
if (!isOk) {
|
|
@@ -16792,7 +16876,6 @@ var index$3 = /*#__PURE__*/Object.freeze({
|
|
|
16792
16876
|
clampU64ToU32: clampU64ToU32,
|
|
16793
16877
|
createResults: createResults,
|
|
16794
16878
|
decodeStandardProgram: decodeStandardProgram,
|
|
16795
|
-
ensure: ensure,
|
|
16796
16879
|
extractCodeAndMetadata: extractCodeAndMetadata,
|
|
16797
16880
|
getServiceId: getServiceId,
|
|
16798
16881
|
getServiceIdOrCurrent: getServiceIdOrCurrent,
|
|
@@ -16819,7 +16902,7 @@ const ENTROPY_BYTES = 32;
|
|
|
16819
16902
|
* https://graypaper.fluffylabs.dev/#/579bd12/3b9a013b9a01
|
|
16820
16903
|
*/
|
|
16821
16904
|
function fisherYatesShuffle(arr, entropy) {
|
|
16822
|
-
check
|
|
16905
|
+
check `${entropy.length === ENTROPY_BYTES} Expected entropy of length ${ENTROPY_BYTES}, got ${entropy.length}`;
|
|
16823
16906
|
const n = arr.length;
|
|
16824
16907
|
const randomNumbers = hashToNumberSequence(entropy, arr.length);
|
|
16825
16908
|
const result = new Array(n);
|