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.
Try it Live Run RLP examples in the interactive playground
RLP WASM Implementation
High-performance WebAssembly RLP encoder compiled from Zig for performance-critical operations.
Overview
The WASM implementation provides accelerated RLP encoding methods compiled from Zig. Currently supports encoding operations with significant performance improvements over JavaScript.
Features:
Fast encoding - Compiled Zig code for maximum performance
Memory efficient - Zero-copy operations where possible
Type safe - TypeScript bindings with full type safety
Drop-in replacement - Compatible with JavaScript API
Currently Available:
encodeBytes - Encode byte arrays
encodeUint - Encode 256-bit unsigned integers
toHex / fromHex - Hex conversion utilities
Setup
WASM module loads automatically when available:
import * as RlpWasm from 'tevm/Rlp.wasm'
// WASM methods available immediately
const encoded = RlpWasm . encodeBytes ( new Uint8Array ([ 1 , 2 , 3 ]))
encodeBytes
Encode byte arrays using WASM.
WASM encodeBytes significantly faster than JavaScript:
import { Rlp } from 'tevm'
import * as RlpWasm from 'tevm/Rlp.wasm'
// Benchmark encoding 10,000 byte arrays
const items = Array ({ length: 10000 }, () =>
new Uint8Array ( 100 ). fill ( 0x42 )
)
// JavaScript implementation
console . time ( 'JS encode' )
for ( const item of items ) {
Rlp . encodeBytes ( item )
}
console . timeEnd ( 'JS encode' )
// JS encode: ~50ms
// WASM implementation
console . time ( 'WASM encode' )
for ( const item of items ) {
RlpWasm . encodeBytes ( item )
}
console . timeEnd ( 'WASM encode' )
// WASM encode: ~10ms (5x faster)
encodeUint
Encode 256-bit unsigned integers.
encodeUintFromBigInt
Encode bigint directly to RLP.
Hex Utilities
Convert between RLP bytes and hex strings.
Architecture
//! RLP encoding implementation in Zig
//! Compiled to WebAssembly for browser/Node.js use
const std = @import ( "std" );
const Hex = @import ( "../Hex/Hex.zig" );
/// Maximum recursion depth
pub const MAX_RLP_DEPTH : u32 = 32 ;
/// Encode byte array to RLP
pub fn encodeBytes ( allocator : Allocator , bytes : [] const u8 ) ! [] u8 {
// Efficient implementation with minimal allocations
}
/// Encode u256 value to RLP
pub fn encodeUint ( allocator : Allocator , value : [ 32 ] u8 ) ! [] u8 {
// Optimized integer encoding
}
Source: Rlp.zig:1-1489
Benefits
Performance:
Compiled to optimized WASM bytecode
No JIT warmup time
Predictable performance characteristics
Memory:
Manual memory management for efficiency
Zero-copy operations where possible
Minimal allocations
Safety:
Zig’s compile-time safety checks
No undefined behavior
Bounds checking in debug mode
When to Use WASM
Use WASM implementation for:
High-throughput encoding:
import * as RlpWasm from 'tevm/Rlp.wasm'
// Encoding many transactions
async function encodeBatch ( transactions : Transaction []) {
return Promise . all (
transactions . map ( async ( tx ) => {
const fields = await prepareFields ( tx )
return fields . map ( field => RlpWasm . encodeBytes ( field ))
})
)
}
Large data structures:
import * as RlpWasm from 'tevm/Rlp.wasm'
// Encoding block with many transactions
function encodeBlock ( block : Block ) {
return {
header: block . header . map ( field => RlpWasm . encodeBytes ( field )),
transactions: block . transactions . map ( tx =>
tx . fields . map ( field => RlpWasm . encodeBytes ( field ))
),
uncles: block . uncles . map ( uncle =>
uncle . map ( field => RlpWasm . encodeBytes ( field ))
)
}
}
Performance-critical paths:
import * as RlpWasm from 'tevm/Rlp.wasm'
// Real-time transaction signing
async function signTransaction ( tx : Transaction ) {
// Use WASM for encoding (faster)
const encoded = encodeTransactionFields ( tx ). map ( field =>
RlpWasm . encodeBytes ( field )
)
// Sign encoded data
const signature = await sign ( encoded )
return { encoded , signature }
}
Fallback to JavaScript
WASM loader handles fallback automatically:
import * as RlpWasm from 'tevm/Rlp.wasm'
// Uses WASM if available, falls back to JS
const encoded = RlpWasm . encodeBytes ( data )
// Check WASM availability
if ( typeof WebAssembly !== 'undefined' ) {
console . log ( 'WASM available' )
} else {
console . log ( 'Using JavaScript fallback' )
}
Limitations
Current WASM implementation has limitations:
No decoding yet:
// Available: encoding
import * as RlpWasm from 'tevm/Rlp.wasm'
const encoded = RlpWasm . encodeBytes ( data )
// Not available: decoding (use JS)
import { Rlp } from 'tevm'
const decoded = Rlp . decode ( encoded )
No list encoding:
// Not available: encodeList (use JS)
import { Rlp } from 'tevm'
const encoded = Rlp . encodeList ([ bytes1 , bytes2 ])
32-byte constraint for uint:
// Must be exactly 32 bytes
const value = Bytes32 ()
RlpWasm . encodeUint ( value ) // OK
const wrong = Bytes16 ()
RlpWasm . encodeUint ( wrong ) // Error
Future Enhancements
Planned WASM features:
decode - WASM decoding implementation
encodeList - WASM list encoding
stream encoding - Streaming encode support
parallel encoding - Multi-threaded encoding for large data
Override Patterns
Replace JavaScript methods with WASM:
import { Rlp } from 'tevm'
import * as RlpWasm from 'tevm/Rlp.wasm'
// Override encodeBytes with WASM version
const originalEncodeBytes = Rlp . encodeBytes
Rlp . encodeBytes = RlpWasm . encodeBytes
// Now Rlp.encodeBytes uses WASM
const encoded = Rlp . encodeBytes ( new Uint8Array ([ 1 , 2 , 3 ]))
// Restore original
Rlp . encodeBytes = originalEncodeBytes
Or create hybrid encoder:
import { Rlp } from 'tevm'
import * as RlpWasm from 'tevm/Rlp.wasm'
function encodeBytes ( data : Uint8Array ) : Uint8Array {
// Use WASM for large data
if ( data . length > 1000 ) {
return RlpWasm . encodeBytes ( data )
}
// Use JS for small data (less overhead)
return Rlp . encodeBytes ( data )
}