Skip to main content

Core Hashing Methods

Basic Keccak256 hashing operations that return Keccak256Hash type (branded 32-byte Uint8Array).

hash(data)

Hash raw bytes with Keccak-256. Signature:
function hash(data: Uint8Array): Keccak256Hash
Parameters:
  • data (Uint8Array) - Input bytes to hash
Returns: Keccak256Hash (32-byte hash) Throws: Never throws for valid input
import { Keccak256 } from '@tevm/voltaire/crypto/Keccak256';
import { Hex } from '@tevm/voltaire/primitives/Hex';

const data = Hex.toBytes('0x0102030405');
const hash = Keccak256.hash(data);

console.log(hash.length); // 32
console.log(Hex.fromBytes(hash)); // 0x...
Technical Notes:
  • Constant-time implementation for security
  • Processes arbitrary-length input (0 to 2^64-1 bytes)
  • Output always exactly 32 bytes
  • Deterministic - same input always produces same output

hashString(str)

Hash UTF-8 encoded string with Keccak-256. Signature:
function hashString(str: string): Keccak256Hash
Parameters:
  • str (string) - String to hash (UTF-8 encoded before hashing)
Returns: Keccak256Hash (32-byte hash) Throws: Never throws for valid input
import { Keccak256 } from '@tevm/voltaire/crypto/Keccak256';

const hash = Keccak256.hashString('hello');
// Equivalent to: Keccak256.hash(new TextEncoder().encode('hello'))

console.log(hash.length); // 32
Technical Notes:
  • Uses TextEncoder for UTF-8 conversion
  • Handles all Unicode code points correctly
  • No normalization applied - different encodings produce different hashes
  • Empty string produces: 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
Different string representations hash differently:
  • "hello"" hello""hello " (whitespace matters)
  • "Transfer(address,uint256)""Transfer(address, uint256)" (spaces matter)
  • Normalize function/event signatures before hashing

hashHex(hex)

Hash hex-encoded string with Keccak-256. Signature:
function hashHex(hex: string): Keccak256Hash
Parameters:
  • hex (string) - Hex string to hash (with or without “0x” prefix)
Returns: Keccak256Hash (32-byte hash) Throws: Never throws for valid hex string
import { Keccak256 } from '@tevm/voltaire/crypto/Keccak256';

// With 0x prefix
const hash1 = Keccak256.hashHex('0x1234abcd');

// Without 0x prefix
const hash2 = Keccak256.hashHex('1234abcd');

// Both produce same result
console.log(hash1.length); // 32
Technical Notes:
  • Hex string decoded to bytes before hashing
  • Accepts both uppercase and lowercase hex
  • “0x” prefix optional and stripped automatically
  • Odd-length hex padded with leading zero: "abc""0abc"

hashMultiple(chunks)

Hash multiple byte chunks in sequence. Signature:
function hashMultiple(chunks: readonly Uint8Array[]): Keccak256Hash
Parameters:
  • chunks (readonly Uint8Array[]) - Array of byte chunks to hash
Returns: Keccak256Hash (32-byte hash) Throws: Never throws for valid input
import { Keccak256 } from '@tevm/voltaire/crypto/Keccak256';
import { Hex } from '@tevm/voltaire/primitives/Hex';

const chunk1 = Hex.toBytes('0x010203');
const chunk2 = Hex.toBytes('0x040506');
const chunk3 = Hex.toBytes('0x070809');

const hash = Keccak256.hashMultiple([chunk1, chunk2, chunk3]);
// Same as: Keccak256.hash(Hex.toBytes('0x010203040506070809'))
Technical Notes:
  • Equivalent to hashing concatenation of all chunks
  • More efficient than manual concatenation for large data
  • Preserves order - [A, B][B, A]
  • Empty chunks array produces empty input hash

Return Type: Keccak256Hash

All hash methods return Keccak256Hash, a branded Uint8Array type:
type Keccak256Hash = Uint8Array & { readonly __tag: "Keccak256Hash" }
Properties:
  • Always exactly 32 bytes (256 bits)
  • Behaves like Uint8Array at runtime
  • Type-safe at compile time
  • Zero runtime overhead
Usage:
import { Keccak256 } from '@tevm/voltaire/crypto/Keccak256';
import { Hex } from '@tevm/voltaire/primitives/Hex';

const hash: Keccak256Hash = Keccak256.hash(data);

// Use as Uint8Array
hash[0];          // First byte
hash.length;      // Always 32
hash.slice(0, 4); // First 4 bytes

// Convert to hex
const hexHash = Hex.fromBytes(hash);

// Convert to bigint
const hashNum = BigInt('0x' + Hex.fromBytes(hash).slice(2));

Test Vectors

Verify implementation correctness:
import { Keccak256 } from '@tevm/voltaire/crypto/Keccak256';
import { Hex } from '@tevm/voltaire/primitives/Hex';

// Empty string
const empty = Keccak256.hashString("");
console.assert(
  Hex.fromBytes(empty) ===
  '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
);

// "abc"
const abc = Keccak256.hashString("abc");
console.assert(
  Hex.fromBytes(abc) ===
  '0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45'
);

// "hello"
const hello = Keccak256.hashString("hello");
console.assert(
  Hex.fromBytes(hello) ===
  '0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8'
);

// Function signature
const selector = Keccak256.hashString("transfer(address,uint256)");
console.assert(
  Hex.fromBytes(selector.slice(0, 4)) === '0xa9059cbb'
);