@typeberry/jam 0.4.0 → 0.4.1-0a3acb2

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/README.md CHANGED
@@ -8,6 +8,11 @@ Typeberry is a TypeScript implementation of [JAM protocol](https://graypaper.com
8
8
  PRs unless the contributor waives any claims to the prize and copy rights for
9
9
  the submitted code. By creating the PR you accept this requirement.**
10
10
 
11
+ ## Links
12
+
13
+ - [Documentation](https://fluffylabs.dev/typeberry)
14
+ - [Performance Charts](https://typeberry.fluffylabs.dev)
15
+
11
16
  ## Implementation status
12
17
 
13
18
  Gray Paper compliance can be controlled via `GP_VERSION` environment variable.
@@ -2878,7 +2878,11 @@ var TestSuite;
2878
2878
  })(TestSuite || (TestSuite = {}));
2879
2879
  const ALL_VERSIONS_IN_ORDER = [GpVersion.V0_6_7, GpVersion.V0_7_0, GpVersion.V0_7_1, GpVersion.V0_7_2];
2880
2880
  const DEFAULT_SUITE = TestSuite.W3F_DAVXY;
2881
- const DEFAULT_VERSION = GpVersion.V0_7_2;
2881
+ /**
2882
+ * Current version is set to track the jam-conformance testing.
2883
+ * Since we are currently at 0.7.1 not 0.7.2, we set our default version accordingly.
2884
+ */
2885
+ const DEFAULT_VERSION = GpVersion.V0_7_1;
2882
2886
  const env = typeof process === "undefined" ? {} : process.env;
2883
2887
  let CURRENT_VERSION = parseCurrentVersion(env.GP_VERSION) ?? DEFAULT_VERSION;
2884
2888
  let CURRENT_SUITE = parseCurrentSuite(env.TEST_SUITE) ?? DEFAULT_SUITE;
@@ -2937,8 +2941,8 @@ class Compatibility {
2937
2941
  /**
2938
2942
  * Allows selecting different values for different Gray Paper versions from one record.
2939
2943
  *
2940
- * @param fallback The default value to return if no value is found for the current.
2941
- * @param record A record mapping versions to values, checking if the version is greater or equal to the current version.
2944
+ * fallback The default value to return if no value is found for the current.
2945
+ * versions A record mapping versions to values, checking if the version is greater or equal to the current version.
2942
2946
  * @returns The value for the current version, or the default value.
2943
2947
  */
2944
2948
  static selectIfGreaterOrEqual({ fallback, versions, }) {
@@ -3101,7 +3105,7 @@ const workspacePathFix = dev_env.NODE_ENV === "development"
3101
3105
 
3102
3106
  ;// CONCATENATED MODULE: ./packages/core/utils/opaque.ts
3103
3107
  /**
3104
- * @fileoverview `Opaque<Type, Token>` constructs a unique type which is a subset of Type with a
3108
+ * `Opaque<Type, Token>` constructs a unique type which is a subset of Type with a
3105
3109
  * specified unique token Token. It means that base type cannot be assigned to unique type by accident.
3106
3110
  * Good examples of opaque types include:
3107
3111
  * - JWTs or other tokens - these are special kinds of string used for authorization purposes.
@@ -6708,9 +6712,438 @@ class ArrayView {
6708
6712
  }
6709
6713
  }
6710
6714
 
6715
+ ;// CONCATENATED MODULE: ./packages/core/collections/blob-dictionary.ts
6716
+
6717
+
6718
+ /** A map which uses byte blobs as keys */
6719
+ class BlobDictionary extends WithDebug {
6720
+ mapNodeThreshold;
6721
+ /**
6722
+ * The root node of the dictionary.
6723
+ *
6724
+ * This is the main internal data structure that organizes entries
6725
+ * in a tree-like fashion (array-based nodes up to `mapNodeThreshold`,
6726
+ * map-based nodes beyond it). All insertions, updates, and deletions
6727
+ * operate through this structure.
6728
+ */
6729
+ root = Node.withList();
6730
+ /**
6731
+ * Auxiliary map that stores references to the original keys and their values.
6732
+ *
6733
+ * - Overriding a value in the main structure does not replace the original key reference.
6734
+ * - Used for efficient iteration over `keys()`, `values()`, `entries()`, and computing `size`.
6735
+ */
6736
+ keyvals = new Map();
6737
+ /**
6738
+ * Protected constructor used internally by `BlobDictionary.new`
6739
+ * and `BlobDictionary.fromEntries`.
6740
+ *
6741
+ * This enforces controlled instantiation — users should create instances
6742
+ * through the provided static factory methods instead of calling the
6743
+ * constructor directly.
6744
+ *
6745
+ * @param mapNodeThreshold - The threshold that determines when the dictionary
6746
+ * switches from using an array-based (`ListChildren`) node to a map-based (`MapChildren`) node for storing entries.
6747
+ */
6748
+ constructor(mapNodeThreshold) {
6749
+ super();
6750
+ this.mapNodeThreshold = mapNodeThreshold;
6751
+ }
6752
+ /**
6753
+ * Returns the number of entries in the dictionary.
6754
+ *
6755
+ * The count is derived from the auxiliary `keyvals` map, which stores
6756
+ * all original key references and their associated values. This ensures
6757
+ * that the `size` reflects the actual number of entries, independent of
6758
+ * internal overrides in the main `root` structure.
6759
+ *
6760
+ * @returns The total number of entries in the dictionary.
6761
+ */
6762
+ get size() {
6763
+ return this.keyvals.size;
6764
+ }
6765
+ [TEST_COMPARE_USING]() {
6766
+ const vals = Array.from(this);
6767
+ vals.sort((a, b) => a[0].compare(b[0]).value);
6768
+ return vals;
6769
+ }
6770
+ /**
6771
+ * Creates an empty `BlobDictionary`.
6772
+ *
6773
+ * @param mapNodeThreshold - The threshold that determines when the dictionary
6774
+ * switches from using an array-based (`ListChildren`) node to a map-based (`MapChildren`) node for storing entries.
6775
+ * Defaults to `0`.
6776
+ *
6777
+ * @returns A new, empty `BlobDictionary` instance.
6778
+ */
6779
+ static new(mapNodeThreshold = 0) {
6780
+ return new BlobDictionary(mapNodeThreshold);
6781
+ }
6782
+ /**
6783
+ * Creates a new `BlobDictionary` initialized with the given entries.
6784
+ *
6785
+ * @param entries - An array of `[key, value]` pairs used to populate the dictionary.
6786
+ * @param mapNodeThreshold - The threshold that determines when the dictionary
6787
+ * switches from using an array-based (`ListChildren`) node to a map-based (`MapChildren`) node for storing entries.
6788
+ * Defaults to `0`.
6789
+ *
6790
+ * @returns A new `BlobDictionary` containing the provided entries.
6791
+ */
6792
+ static fromEntries(entries, mapNodeThreshold) {
6793
+ const dict = BlobDictionary.new(mapNodeThreshold);
6794
+ for (const [key, value] of entries) {
6795
+ dict.set(key, value);
6796
+ }
6797
+ return dict;
6798
+ }
6799
+ /**
6800
+ * Internal helper that inserts, updates or deletes an entry in the dictionary.
6801
+ *
6802
+ * Behaviour details:
6803
+ * - Passing `undefined` as `value` indicates a deletion. (E.g. `delete` uses `internalSet(key, undefined)`.)
6804
+ * - When an add (new entry) or a delete actually changes the structure, the method returns the affected leaf node.
6805
+ * - When the call only overrides an existing value (no structural add/delete), the method returns `null`.
6806
+ *
6807
+ * This method is intended for internal use by the dictionary implementation and allows `undefined` as a
6808
+ * sentinel value to signal removals.
6809
+ *
6810
+ * @param key - The key to insert, update or remove.
6811
+ * @param value - The value to associate with the key, or `undefined` to remove the key.
6812
+ * @returns The leaf node created or removed on add/delete, or `null` if the operation only overwrote an existing value.
6813
+ */
6814
+ internalSet(key, value) {
6815
+ let node = this.root;
6816
+ const keyChunkGenerator = key.chunks(CHUNK_SIZE);
6817
+ let depth = 0;
6818
+ for (;;) {
6819
+ const maybeKeyChunk = keyChunkGenerator.next().value;
6820
+ if (maybeKeyChunk === undefined) {
6821
+ if (value === undefined) {
6822
+ return node.remove(key);
6823
+ }
6824
+ return node.set(key, value);
6825
+ }
6826
+ const keyChunk = opaque_asOpaqueType(maybeKeyChunk);
6827
+ if (node.children instanceof ListChildren) {
6828
+ const subkey = bytes_BytesBlob.blobFrom(key.raw.subarray(CHUNK_SIZE * depth));
6829
+ const leaf = value !== undefined ? node.children.insert(subkey, { key, value }) : node.children.remove(subkey);
6830
+ if (subkey.length > CHUNK_SIZE && node.children.children.length > this.mapNodeThreshold) {
6831
+ node.convertListChildrenToMap();
6832
+ }
6833
+ return leaf;
6834
+ }
6835
+ depth += 1;
6836
+ const children = node.children;
6837
+ if (children instanceof ListChildren) {
6838
+ throw new Error("We handle list node earlier. If we fall through, we know it's for the `Map` case.");
6839
+ }
6840
+ if (children instanceof MapChildren) {
6841
+ const maybeNode = children.getChild(keyChunk);
6842
+ if (maybeNode !== undefined) {
6843
+ // simply go one level deeper
6844
+ node = maybeNode;
6845
+ }
6846
+ else {
6847
+ // we are trying to remove an item, but it does not exist
6848
+ if (value === undefined) {
6849
+ return null;
6850
+ }
6851
+ // no more child nodes, we insert a new one.
6852
+ const newNode = Node.withList();
6853
+ children.setChild(keyChunk, newNode);
6854
+ node = newNode;
6855
+ }
6856
+ continue;
6857
+ }
6858
+ debug_assertNever(children);
6859
+ }
6860
+ }
6861
+ /**
6862
+ * Adds a new entry to the dictionary or updates the value of an existing key.
6863
+ *
6864
+ * If an entry with the given key already exists, its value is replaced
6865
+ * with the new one.
6866
+ *
6867
+ * @param key - The key to add or update in the dictionary.
6868
+ * @param value - The value to associate with the specified key.
6869
+ * @returns Nothing (`void`).
6870
+ */
6871
+ set(key, value) {
6872
+ const leaf = this.internalSet(key, value);
6873
+ if (leaf !== null) {
6874
+ this.keyvals.set(leaf.key, leaf);
6875
+ }
6876
+ }
6877
+ /**
6878
+ * Retrieves the value associated with the given key from the dictionary.
6879
+ *
6880
+ * If the key does not exist, this method returns `undefined`.
6881
+ *
6882
+ * @param key - The key whose associated value should be retrieved.
6883
+ * @returns The value associated with the specified key, or `undefined` if the key is not present.
6884
+ */
6885
+ get(key) {
6886
+ let node = this.root;
6887
+ const pathChunksGenerator = key.chunks(CHUNK_SIZE);
6888
+ let depth = 0;
6889
+ while (node !== undefined) {
6890
+ const maybePathChunk = pathChunksGenerator.next().value;
6891
+ if (node.children instanceof ListChildren) {
6892
+ const subkey = bytes_BytesBlob.blobFrom(key.raw.subarray(depth * CHUNK_SIZE));
6893
+ const child = node.children.find(subkey);
6894
+ if (child !== null) {
6895
+ return child.value;
6896
+ }
6897
+ }
6898
+ if (maybePathChunk === undefined) {
6899
+ return node.getLeaf()?.value;
6900
+ }
6901
+ if (node.children instanceof MapChildren) {
6902
+ const pathChunk = opaque_asOpaqueType(maybePathChunk);
6903
+ node = node.children.getChild(pathChunk);
6904
+ depth += 1;
6905
+ }
6906
+ }
6907
+ return undefined;
6908
+ }
6909
+ /**
6910
+ * Checks whether the dictionary contains an entry for the given key.
6911
+ *
6912
+ * ⚠️ **Note:** Avoid using `has(...)` together with `get(...)` in a pattern like this:
6913
+ *
6914
+ * ```ts
6915
+ * if (dict.has(key)) {
6916
+ * const value = dict.get(key);
6917
+ * ...
6918
+ * }
6919
+ * ```
6920
+ *
6921
+ * This approach performs two lookups for the same key.
6922
+ *
6923
+ * Instead, prefer the following pattern, which retrieves the value once:
6924
+ *
6925
+ * ```ts
6926
+ * const value = dict.get(key);
6927
+ * if (value !== undefined) {
6928
+ * ...
6929
+ * }
6930
+ * ```
6931
+ *
6932
+ * @param key - The key to check for.
6933
+ * @returns `true` if the dictionary contains an entry for the given key, otherwise `false`.
6934
+ */
6935
+ has(key) {
6936
+ return this.get(key) !== undefined;
6937
+ }
6938
+ /**
6939
+ * Removes an entry with the specified key from the dictionary.
6940
+ *
6941
+ * Internally, this calls {@link internalSet} with `undefined` to mark the entry as deleted.
6942
+ *
6943
+ * @param key - The key of the entry to remove.
6944
+ * @returns `true` if an entry was removed (i.e. the key existed), otherwise `false`.
6945
+ */
6946
+ delete(key) {
6947
+ const leaf = this.internalSet(key, undefined);
6948
+ if (leaf !== null) {
6949
+ this.keyvals.delete(leaf.key);
6950
+ return true;
6951
+ }
6952
+ return false;
6953
+ }
6954
+ /**
6955
+ * Returns an iterator over the keys in the dictionary.
6956
+ *
6957
+ * The iterator yields each key in insertion order.
6958
+ *
6959
+ * @returns An iterator over all keys in the dictionary.
6960
+ */
6961
+ keys() {
6962
+ return this.keyvals.keys();
6963
+ }
6964
+ /**
6965
+ * Returns an iterator over the values in the dictionary.
6966
+ *
6967
+ * The iterator yields each value in insertion order.
6968
+ *
6969
+ * @returns An iterator over all values in the dictionary.
6970
+ */
6971
+ *values() {
6972
+ for (const leaf of this.keyvals.values()) {
6973
+ yield leaf.value;
6974
+ }
6975
+ }
6976
+ /**
6977
+ * Returns an iterator over the `[key, value]` pairs in the dictionary.
6978
+ *
6979
+ * The iterator yields entries in insertion order.
6980
+ *
6981
+ * @returns An iterator over `[key, value]` tuples for each entry in the dictionary.
6982
+ */
6983
+ *entries() {
6984
+ for (const leaf of this.keyvals.values()) {
6985
+ yield [leaf.key, leaf.value];
6986
+ }
6987
+ }
6988
+ /**
6989
+ * Default iterator for the dictionary.
6990
+ *
6991
+ * Equivalent to calling {@link entries}.
6992
+ * Enables iteration with `for...of`:
6993
+ *
6994
+ * ```ts
6995
+ * for (const [key, value] of dict) {
6996
+ * ...
6997
+ * }
6998
+ * ```
6999
+ *
7000
+ * @returns An iterator over `[key, value]` pairs.
7001
+ */
7002
+ [Symbol.iterator]() {
7003
+ return this.entries();
7004
+ }
7005
+ /**
7006
+ * Creates a new sorted array of values, ordered by their corresponding keys.
7007
+ *
7008
+ * Iterates over all entries in the dictionary and sorts them according
7009
+ * to the provided comparator function applied to the keys.
7010
+ *
7011
+ * @param comparator - A comparator function that can compare two keys.
7012
+ *
7013
+ * @returns A new array containing all values from the dictionary,
7014
+ * sorted according to their keys.
7015
+ */
7016
+ toSortedArray(comparator) {
7017
+ const vals = Array.from(this);
7018
+ vals.sort((a, b) => comparator(a[0], b[0]).value);
7019
+ return vals.map((x) => x[1]);
7020
+ }
7021
+ }
7022
+ const CHUNK_SIZE = 6;
7023
+ /**
7024
+ * A function to transform a bytes chunk (up to 6 bytes into U48 number)
7025
+ *
7026
+ * Note that it uses 3 additional bits to store length(`value * 8 + len;`),
7027
+ * It is needed to distinguish shorter chunks that have 0s at the end, for example: [1, 2] and [1, 2, 0]
7028
+ * */
7029
+ function bytesAsU48(bytes) {
7030
+ const len = bytes.length;
7031
+ debug_check `${len <= CHUNK_SIZE} Length has to be <= ${CHUNK_SIZE}, got: ${len}`;
7032
+ let value = bytes[3] | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24);
7033
+ for (let i = 4; i < bytes.length; i++) {
7034
+ value = value * 256 + bytes[i];
7035
+ }
7036
+ return value * 8 + len;
7037
+ }
7038
+ class Node {
7039
+ leaf;
7040
+ children;
7041
+ convertListChildrenToMap() {
7042
+ if (!(this.children instanceof ListChildren)) {
7043
+ return;
7044
+ }
7045
+ this.children = MapChildren.fromListNode(this.children);
7046
+ }
7047
+ static withList() {
7048
+ return new Node(undefined, ListChildren.new());
7049
+ }
7050
+ static withMap() {
7051
+ return new Node(undefined, MapChildren.new());
7052
+ }
7053
+ constructor(leaf, children) {
7054
+ this.leaf = leaf;
7055
+ this.children = children;
7056
+ }
7057
+ getLeaf() {
7058
+ return this.leaf;
7059
+ }
7060
+ remove(_key) {
7061
+ if (this.leaf === undefined) {
7062
+ return null;
7063
+ }
7064
+ const removedLeaf = this.leaf;
7065
+ this.leaf = undefined;
7066
+ return removedLeaf;
7067
+ }
7068
+ set(key, value) {
7069
+ if (this.leaf === undefined) {
7070
+ this.leaf = { key, value };
7071
+ return this.leaf;
7072
+ }
7073
+ this.leaf.value = value;
7074
+ return null;
7075
+ }
7076
+ }
7077
+ class ListChildren {
7078
+ children = [];
7079
+ constructor() { }
7080
+ find(key) {
7081
+ const result = this.children.find((item) => item[0].isEqualTo(key));
7082
+ if (result !== undefined) {
7083
+ return result[1];
7084
+ }
7085
+ return null;
7086
+ }
7087
+ remove(key) {
7088
+ const existingIndex = this.children.findIndex((item) => item[0].isEqualTo(key));
7089
+ if (existingIndex >= 0) {
7090
+ const ret = this.children.splice(existingIndex, 1);
7091
+ return ret[0][1];
7092
+ }
7093
+ return null;
7094
+ }
7095
+ insert(key, leaf) {
7096
+ const existingIndex = this.children.findIndex((item) => item[0].isEqualTo(key));
7097
+ if (existingIndex >= 0) {
7098
+ const existing = this.children[existingIndex];
7099
+ existing[1].value = leaf.value;
7100
+ return null;
7101
+ }
7102
+ this.children.push([key, leaf]);
7103
+ return leaf;
7104
+ }
7105
+ static new() {
7106
+ return new ListChildren();
7107
+ }
7108
+ }
7109
+ class MapChildren {
7110
+ children = new Map();
7111
+ constructor() { }
7112
+ static new() {
7113
+ return new MapChildren();
7114
+ }
7115
+ static fromListNode(node) {
7116
+ const mapNode = new MapChildren();
7117
+ for (const [key, leaf] of node.children) {
7118
+ const currentKeyChunk = opaque_asOpaqueType(bytes_BytesBlob.blobFrom(key.raw.subarray(0, CHUNK_SIZE)));
7119
+ const subKey = bytes_BytesBlob.blobFrom(key.raw.subarray(CHUNK_SIZE));
7120
+ let child = mapNode.getChild(currentKeyChunk);
7121
+ if (child === undefined) {
7122
+ child = Node.withList();
7123
+ mapNode.setChild(currentKeyChunk, child);
7124
+ }
7125
+ const children = child.children;
7126
+ children.insert(subKey, leaf);
7127
+ }
7128
+ return mapNode;
7129
+ }
7130
+ getChild(keyChunk) {
7131
+ const chunkAsNumber = bytesAsU48(keyChunk.raw);
7132
+ return this.children.get(chunkAsNumber);
7133
+ }
7134
+ setChild(keyChunk, node) {
7135
+ const chunkAsNumber = bytesAsU48(keyChunk.raw);
7136
+ this.children.set(chunkAsNumber, node);
7137
+ }
7138
+ }
7139
+
6711
7140
  ;// CONCATENATED MODULE: ./packages/core/collections/hash-dictionary.ts
6712
- /** A map which uses hashes as keys. */
6713
- class HashDictionary {
7141
+ /**
7142
+ * A map which uses hashes as keys.
7143
+ *
7144
+ * @deprecated
7145
+ * */
7146
+ class StringHashDictionary {
6714
7147
  // TODO [ToDr] [crit] We can't use `TrieHash` directly in the map,
6715
7148
  // because of the way it's being compared. Hence having `string` here.
6716
7149
  // This has to be benchmarked and re-written to a custom map most likely.
@@ -6776,6 +7209,17 @@ class HashDictionary {
6776
7209
  }
6777
7210
  }
6778
7211
 
7212
+ /**
7213
+ * A value that indicates when `BlobDictionary` transforms Array nodes into Map nodes.
7214
+ * In practice, it doesn't matter much because, in real life, arrays in this structure usually have a length close to 1.
7215
+ */
7216
+ const BLOB_DICTIONARY_THRESHOLD = 5;
7217
+ class HashDictionary extends BlobDictionary {
7218
+ constructor() {
7219
+ super(BLOB_DICTIONARY_THRESHOLD);
7220
+ }
7221
+ }
7222
+
6779
7223
  ;// CONCATENATED MODULE: ./packages/core/collections/hash-set.ts
6780
7224
 
6781
7225
  /** A set specialized for storing hashes. */
@@ -7240,6 +7684,18 @@ class SortedSet extends SortedArray {
7240
7684
 
7241
7685
 
7242
7686
 
7687
+ function getTruncatedKey(key) {
7688
+ // Always return exactly TRUNCATED_HASH_SIZE bytes.
7689
+ if (key.length === TRUNCATED_HASH_SIZE) {
7690
+ return key;
7691
+ }
7692
+ return bytes_Bytes.fromBlob(key.raw.subarray(0, TRUNCATED_HASH_SIZE), TRUNCATED_HASH_SIZE);
7693
+ }
7694
+ /**
7695
+ * A value that indicates when `BlobDictionary` transforms Array nodes into Map nodes.
7696
+ * In practice, it doesn't matter much because, in real life, arrays in this structure usually have a length close to 1.
7697
+ */
7698
+ const truncated_hash_dictionary_BLOB_DICTIONARY_THRESHOLD = 5;
7243
7699
  /**
7244
7700
  * A collection of hash-based keys (likely `StateKey`s) which ignores
7245
7701
  * differences on the last byte.
@@ -7252,48 +7708,37 @@ class TruncatedHashDictionary {
7252
7708
  * Each key will be copied and have the last byte replace with a 0.
7253
7709
  */
7254
7710
  static fromEntries(entries) {
7255
- /** Copy key bytes of an entry and replace the last one with 0. */
7256
- const mapped = Array.from(entries).map(([key, value]) => {
7257
- const newKey = bytes_Bytes.zero(HASH_SIZE).asOpaque();
7258
- newKey.raw.set(key.raw.subarray(0, TRUNCATED_HASH_SIZE));
7259
- return [newKey, value];
7260
- });
7261
- return new TruncatedHashDictionary(HashDictionary.fromEntries(mapped));
7711
+ return new TruncatedHashDictionary(BlobDictionary.fromEntries(Array.from(entries).map(([key, value]) => [getTruncatedKey(key), value]), truncated_hash_dictionary_BLOB_DICTIONARY_THRESHOLD));
7262
7712
  }
7263
- /** A truncated key which we re-use to query the dictionary. */
7264
- truncatedKey = bytes_Bytes.zero(HASH_SIZE).asOpaque();
7265
7713
  constructor(dict) {
7266
7714
  this.dict = dict;
7267
7715
  }
7268
7716
  [TEST_COMPARE_USING]() {
7269
- return this.dict;
7717
+ return Array.from(this.dict);
7270
7718
  }
7271
7719
  /** Return number of items in the dictionary. */
7272
7720
  get size() {
7273
7721
  return this.dict.size;
7274
7722
  }
7275
7723
  /** Retrieve a value that matches the key on `TRUNCATED_HASH_SIZE`. */
7276
- get(fullKey) {
7277
- this.truncatedKey.raw.set(fullKey.raw.subarray(0, TRUNCATED_HASH_SIZE));
7278
- return this.dict.get(this.truncatedKey);
7724
+ get(key) {
7725
+ const truncatedKey = getTruncatedKey(key);
7726
+ return this.dict.get(truncatedKey);
7279
7727
  }
7280
7728
  /** Return true if the key is present in the dictionary */
7281
- has(fullKey) {
7282
- this.truncatedKey.raw.set(fullKey.raw.subarray(0, TRUNCATED_HASH_SIZE));
7283
- return this.dict.has(this.truncatedKey);
7729
+ has(key) {
7730
+ const truncatedKey = getTruncatedKey(key);
7731
+ return this.dict.has(truncatedKey);
7284
7732
  }
7285
7733
  /** Set or update a value that matches the key on `TRUNCATED_HASH_SIZE`. */
7286
- set(fullKey, value) {
7287
- // NOTE we can't use the the shared key here, since the collection will
7288
- // store the key for us, hence the copy.
7289
- const key = bytes_Bytes.zero(HASH_SIZE);
7290
- key.raw.set(fullKey.raw.subarray(0, TRUNCATED_HASH_SIZE));
7291
- this.dict.set(key.asOpaque(), value);
7734
+ set(key, value) {
7735
+ const truncatedKey = getTruncatedKey(key);
7736
+ this.dict.set(truncatedKey, value);
7292
7737
  }
7293
7738
  /** Remove a value that matches the key on `TRUNCATED_HASH_SIZE`. */
7294
- delete(fullKey) {
7295
- this.truncatedKey.raw.set(fullKey.raw.subarray(0, TRUNCATED_HASH_SIZE));
7296
- this.dict.delete(this.truncatedKey);
7739
+ delete(key) {
7740
+ const truncatedKey = getTruncatedKey(key);
7741
+ this.dict.delete(truncatedKey);
7297
7742
  }
7298
7743
  /** Iterator over values of the dictionary. */
7299
7744
  values() {
@@ -7301,9 +7746,7 @@ class TruncatedHashDictionary {
7301
7746
  }
7302
7747
  /** Iterator over entries of the dictionary (with truncated keys) */
7303
7748
  *entries() {
7304
- for (const [key, value] of this.dict.entries()) {
7305
- yield [bytes_Bytes.fromBlob(key.raw.subarray(0, TRUNCATED_HASH_SIZE), TRUNCATED_HASH_SIZE).asOpaque(), value];
7306
- }
7749
+ yield* this.dict.entries();
7307
7750
  }
7308
7751
  [Symbol.iterator]() {
7309
7752
  return this.entries();
@@ -7320,6 +7763,7 @@ class TruncatedHashDictionary {
7320
7763
 
7321
7764
 
7322
7765
 
7766
+
7323
7767
  ;// CONCATENATED MODULE: ./packages/jam/config/chain-spec.ts
7324
7768
 
7325
7769
 
@@ -9024,11 +9468,9 @@ function reencodeAsView(codec, object, chainSpec) {
9024
9468
 
9025
9469
  /** Helper function to create most used hashes in the block */
9026
9470
  class TransitionHasher {
9027
- context;
9028
9471
  keccakHasher;
9029
9472
  blake2b;
9030
- constructor(context, keccakHasher, blake2b) {
9031
- this.context = context;
9473
+ constructor(keccakHasher, blake2b) {
9032
9474
  this.keccakHasher = keccakHasher;
9033
9475
  this.blake2b = blake2b;
9034
9476
  }
@@ -10202,11 +10644,32 @@ const ENTROPY_ENTRIES = 4;
10202
10644
 
10203
10645
  var UpdatePreimageKind;
10204
10646
  (function (UpdatePreimageKind) {
10205
- /** Insert new preimage and optionally update it's lookup history. */
10647
+ /**
10648
+ * Insert new preimage and optionally update it's lookup history.
10649
+ *
10650
+ * Used in: `provide`
10651
+ *
10652
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/383904383904?v=0.7.2
10653
+ */
10206
10654
  UpdatePreimageKind[UpdatePreimageKind["Provide"] = 0] = "Provide";
10207
- /** Remove a preimage and it's lookup history. */
10655
+ /**
10656
+ * Remove a preimage and it's lookup history.
10657
+ *
10658
+ * Used in: `forget` and `eject`
10659
+ *
10660
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/38c701380202?v=0.7.2
10661
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/379102379302?v=0.7.2
10662
+ */
10208
10663
  UpdatePreimageKind[UpdatePreimageKind["Remove"] = 1] = "Remove";
10209
- /** update or add lookup history for preimage hash/len to given value. */
10664
+ /**
10665
+ * Update or add lookup history for preimage hash/len to given value.
10666
+ *
10667
+ * Used in: `solicit` and `forget`
10668
+ *
10669
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/382802382802?v=0.7.2
10670
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/384002384b02?v=0.7.2
10671
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/38c60038ea00?v=0.7.2
10672
+ */
10210
10673
  UpdatePreimageKind[UpdatePreimageKind["UpdateOrAdd"] = 2] = "UpdateOrAdd";
10211
10674
  })(UpdatePreimageKind || (UpdatePreimageKind = {}));
10212
10675
  /**
@@ -10214,7 +10677,7 @@ var UpdatePreimageKind;
10214
10677
  *
10215
10678
  * Can be one of the following cases:
10216
10679
  * 1. Provide a new preimage blob and set the lookup history to available at `slot`.
10217
- * 2. Remove (expunge) a preimage and it's lookup history.
10680
+ * 2. Remove (forget) a preimage and it's lookup history.
10218
10681
  * 3. Update `LookupHistory` with given value.
10219
10682
  */
10220
10683
  class state_update_UpdatePreimage {
@@ -10965,7 +11428,7 @@ class Generator {
10965
11428
  // select validator for block
10966
11429
  const validatorId = tryAsValidatorIndex(newTimeSlot % 6);
10967
11430
  // retriev data from previous block
10968
- const hasher = new TransitionHasher(this.chainSpec, this.keccakHasher, this.blake2b);
11431
+ const hasher = new TransitionHasher(this.keccakHasher, this.blake2b);
10969
11432
  const parentHeaderHash = this.lastHeaderHash;
10970
11433
  const stateRoot = this.states.getStateRoot(this.lastState);
10971
11434
  // create extrinsic