Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Additional utility functions for working with storage keys.
hashCode()
Computes a hash code for a storage key, useful for hash-based data structures.
Signature
Parameters
- key (
BrandedStorageKey) - Storage key to hash
Returns
number - 32-bit hash code (JavaScript) or u64 (Zig)
Examples
Use Cases
HashMap Keys
import * as State from 'tevm/State';
// Custom hash map implementation
class StorageHashMap {
private buckets: Array<Array<{ key: BrandedStorageKey, value: bigint }>> = [];
private size = 1024; // Bucket count
set(key: BrandedStorageKey, value: bigint): void {
const hash = State.StorageKey.hashCode(key);
const bucketIndex = Math.abs(hash) % this.size;
if (!this.buckets[bucketIndex]) {
this.buckets[bucketIndex] = [];
}
const bucket = this.buckets[bucketIndex];
const existing = bucket.findIndex(entry =>
State.StorageKey.equals(entry.key, key)
);
if (existing >= 0) {
bucket[existing].value = value;
} else {
bucket.push({ key, value });
}
}
get(key: BrandedStorageKey): bigint | undefined {
const hash = State.StorageKey.hashCode(key);
const bucketIndex = Math.abs(hash) % this.size;
const bucket = this.buckets[bucketIndex];
if (!bucket) return undefined;
const entry = bucket.find(e => State.StorageKey.equals(e.key, key));
return entry?.value;
}
}
const map = new StorageHashMap();
const key = State.StorageKey(contractAddr, 0n);
map.set(key, 1000n);
console.log(map.get(key)); // 1000n
Partitioning
import * as State from 'tevm/State';
// Partition storage keys into buckets for parallel processing
function partitionKeys(
keys: BrandedStorageKey[],
partitionCount: number
): BrandedStorageKey[][] {
const partitions: BrandedStorageKey[][] = Array(
{ length: partitionCount },
() => []
);
for (const key of keys) {
const hash = State.StorageKey.hashCode(key);
const partitionIndex = Math.abs(hash) % partitionCount;
partitions[partitionIndex].push(key);
}
return partitions;
}
const keys = [
State.StorageKey(contractAddr, 0n),
State.StorageKey(contractAddr, 1n),
State.StorageKey(contractAddr, 2n),
State.StorageKey(contractAddr, 3n),
State.StorageKey(contractAddr, 4n)
];
// Split into 2 partitions
const partitions = partitionKeys(keys, 2);
console.log(`Partition 0: ${partitions[0].length} keys`);
console.log(`Partition 1: ${partitions[1].length} keys`);
// Process partitions in parallel
await Promise.all(
partitions.map(async (partition, index) => {
console.log(`Processing partition ${index}...`);
for (const key of partition) {
await processStorageKey(key);
}
})
);
Caching
import * as State from 'tevm/State';
// LRU cache with hash-based bucketing
class StorageLRUCache {
private cache = new Map<number, { key: BrandedStorageKey, value: bigint, timestamp: number }>();
private maxSize = 1000;
set(key: BrandedStorageKey, value: bigint): void {
const hash = State.StorageKey.hashCode(key);
// Evict oldest if at capacity
if (this.cache.size >= this.maxSize) {
let oldestHash = -1;
let oldestTime = Infinity;
for (const [h, entry] of this.cache.entries()) {
if (entry.timestamp < oldestTime) {
oldestTime = entry.timestamp;
oldestHash = h;
}
}
this.cache.delete(oldestHash);
}
this.cache.set(hash, { key, value, timestamp: Date.now() });
}
get(key: BrandedStorageKey): bigint | undefined {
const hash = State.StorageKey.hashCode(key);
const entry = this.cache.get(hash);
if (entry && State.StorageKey.equals(entry.key, key)) {
// Update timestamp for LRU
entry.timestamp = Date.now();
return entry.value;
}
return undefined;
}
}
Sharding
import * as State from 'tevm/State';
// Distribute storage keys across shards
function getShardForKey(key: BrandedStorageKey, shardCount: number): number {
const hash = State.StorageKey.hashCode(key);
return Math.abs(hash) % shardCount;
}
// Example: Route requests to different database shards
async function getStorageValue(
key: BrandedStorageKey,
shards: Database[]
): Promise<bigint | undefined> {
const shardIndex = getShardForKey(key, shards.length);
const shard = shards[shardIndex];
const keyStr = State.StorageKey.toString(key);
return await shard.get(keyStr);
}
// Setup 4 shards
const shards = [
new Database('shard0'),
new Database('shard1'),
new Database('shard2'),
new Database('shard3')
];
const key = State.StorageKey(contractAddr, 0n);
const value = await getStorageValue(key, shards);
console.log(`Shard ${getShardForKey(key, 4)}: ${value}`);
Implementation Notes
- Hash code is computed from both address and slot
- Same key always produces same hash (deterministic)
- Different keys may produce same hash (collisions possible)
- Hash distribution is pseudo-random for good bucketing
Properties
- Deterministic: Same input always produces same output
- Fast: O(1) time complexity
- Collision-resistant: Good distribution, but collisions possible
- 32-bit: JavaScript returns 32-bit signed integer
- 64-bit: Zig returns 64-bit unsigned integer