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
Validation Rules
RLP validation checks:
Canonical encoding - Minimal representation
Length consistency - Declared vs actual
Depth limits - Max 32 levels
No leading zeros - In length encodings
Proper prefixes - Valid prefix ranges
Valid Examples
import { Rlp } from 'tevm'
// Single byte < 0x80
Rlp . validate ( new Uint8Array ([ 0x7f ]))
// => true
// Empty bytes
Rlp . validate ( new Uint8Array ([ 0x80 ]))
// => true
// Short string
Rlp . validate ( new Uint8Array ([ 0x83 , 1 , 2 , 3 ]))
// => true
// Long string
const long = new Uint8Array ([ 0xb8 , 56 , ... Array ( 56 ). fill ( 0x42 )])
Rlp . validate ( long )
// => true
// Empty list
Rlp . validate ( new Uint8Array ([ 0xc0 ]))
// => true
// Short list
Rlp . validate ( new Uint8Array ([ 0xc2 , 0x01 , 0x02 ]))
// => true
Invalid Examples
import { Rlp } from 'tevm'
// Incomplete data
Rlp . validate ( new Uint8Array ([ 0x83 , 1 ]))
// => false (says 3 bytes but only 1 provided)
// Non-canonical single byte
Rlp . validate ( new Uint8Array ([ 0x81 , 0x7f ]))
// => false (single byte < 0x80 should not be prefixed)
// Non-canonical short form
Rlp . validate ( new Uint8Array ([ 0xb8 , 0x03 , 1 , 2 , 3 ]))
// => false (< 56 bytes should use short form)
// Leading zeros
Rlp . validate ( new Uint8Array ([ 0xb9 , 0x00 , 0x38 , ... Array ( 56 ). fill ( 0x42 )]))
// => false (length has leading zeros)
// Empty input
Rlp . validate ( Bytes ())
// => false
// Extra data
Rlp . validate ( new Uint8Array ([ 0x01 , 0x02 ]))
// => false (multiple values without stream mode)
Usage Patterns
Pre-flight Validation
Validate before decoding:
import { Rlp } from 'tevm'
function safelyDecode ( bytes : Uint8Array ) {
if ( ! Rlp . validate ( bytes )) {
throw new Error ( 'Invalid RLP encoding' )
}
return Rlp . decode ( bytes )
}
try {
const data = safelyDecode ( untrustedInput )
// Process data
} catch ( error ) {
console . error ( 'Invalid input:' , error . message )
}
Transaction Validation
Validate transaction bytes before processing:
import { Rlp } from 'tevm'
function validateTransaction ( txBytes : Uint8Array ) : boolean {
// First check if valid RLP
if ( ! Rlp . validate ( txBytes )) {
return false
}
// Decode and check structure
const decoded = Rlp . decode ( txBytes )
if ( decoded . data . type !== 'list' ) {
return false
}
// Check field count (9 for legacy tx)
if ( decoded . data . value . length !== 9 ) {
return false
}
return true
}
const tx = new Uint8Array ([ ... ])
if ( validateTransaction ( tx )) {
// Process transaction
}
Validate API inputs:
import { Rlp } from 'tevm'
interface ApiRequest {
rlpData : string // Hex-encoded RLP
}
function handleRequest ( req : ApiRequest ) : Response {
// Convert hex to bytes
const bytes = hexToBytes ( req . rlpData )
// Validate RLP encoding
if ( ! Rlp . validate ( bytes )) {
return { error: 'Invalid RLP encoding' }
}
// Process valid RLP
const decoded = Rlp . decode ( bytes )
return { data: decoded }
}
Batch Validation
Validate multiple RLP values:
import { Rlp } from 'tevm'
function validateBatch ( items : Uint8Array []) : boolean [] {
return items . map ( item => Rlp . validate ( item ))
}
const items = [
new Uint8Array ([ 0x83 , 1 , 2 , 3 ]),
new Uint8Array ([ 0x83 , 1 ]), // Invalid
new Uint8Array ([ 0xc0 ])
]
const results = validateBatch ( items )
// => [true, false, true]
const allValid = results . every ( r => r )
console . log ( `All valid: ${ allValid } ` )
Storage Validation
Validate stored RLP data:
import { Rlp } from 'tevm'
class RlpStorage {
private store = new Map < string , Uint8Array >()
set ( key : string , rlpData : Uint8Array ) : void {
if ( ! Rlp . validate ( rlpData )) {
throw new Error ( `Invalid RLP data for key: ${ key } ` )
}
this . store . set ( key , rlpData )
}
get ( key : string ) : Uint8Array | undefined {
const data = this . store . get ( key )
if ( data && ! Rlp . validate ( data )) {
console . warn ( `Corrupted RLP data for key: ${ key } ` )
return undefined
}
return data
}
}
Validation Cost
Validation uses decode internally, so it has similar performance characteristics:
// validate() is equivalent to:
function validate ( data : Uint8Array ) : boolean {
try {
decode ( data )
return true
} catch {
return false
}
}
When to Validate
Always validate untrusted input:
Network data
User input
External APIs
File uploads
Skip validation for trusted data:
Just-encoded data
Internal processing
Cached results
import { Rlp } from 'tevm'
// Trusted: just encoded
const data = [ new Uint8Array ([ 1 ]), new Uint8Array ([ 2 ])]
const encoded = Rlp . encode ( data )
// No need to validate - we just encoded it
const decoded = Rlp . decode ( encoded )
// Untrusted: from network
const networkData = await fetchRlpData ()
if ( Rlp . validate ( networkData )) {
const decoded = Rlp . decode ( networkData )
}
Error Handling
validate never throws, always returns boolean:
import { Rlp } from 'tevm'
// Safe for any input
const result1 = Rlp . validate ( Bytes ())
// => false (no throw)
const result2 = Rlp . validate ( new Uint8Array ([ 0xff , 0xff , 0xff ]))
// => false (no throw)
// Compare to decode (throws on invalid)
try {
Rlp . decode ( Bytes ())
} catch ( error ) {
console . error ( 'Decode threw:' , error )
}
What Validation Checks
1. Length Consistency
import { Rlp } from 'tevm'
// Declared 3 bytes, provided 3 bytes
Rlp . validate ( new Uint8Array ([ 0x83 , 1 , 2 , 3 ]))
// => true
// Declared 3 bytes, provided 1 byte
Rlp . validate ( new Uint8Array ([ 0x83 , 1 ]))
// => false
2. Canonical Encoding
import { Rlp } from 'tevm'
// Canonical: single byte as-is
Rlp . validate ( new Uint8Array ([ 0x7f ]))
// => true
// Non-canonical: single byte with prefix
Rlp . validate ( new Uint8Array ([ 0x81 , 0x7f ]))
// => false
3. No Leading Zeros
import { Rlp } from 'tevm'
// Valid: minimal length encoding
Rlp . validate ( new Uint8Array ([ 0xb8 , 56 , ... Array ( 56 ). fill ( 0x42 )]))
// => true
// Invalid: leading zero in length
Rlp . validate ( new Uint8Array ([ 0xb9 , 0x00 , 0x38 , ... Array ( 56 ). fill ( 0x42 )]))
// => false
4. Depth Limits
import { Rlp } from 'tevm'
// Valid: depth 3
const shallow = [[[ new Uint8Array ([ 1 ])]]]
const encoded = Rlp . encode ( shallow )
Rlp . validate ( encoded )
// => true
// Invalid: depth > 32
const deep = Array ( 40 ). fill ( null ). reduce (
( acc ) => [ acc ],
new Uint8Array ([ 1 ])
)
const encoded = Rlp . encode ( deep )
Rlp . validate ( encoded )
// => false
5. Proper Prefix Ranges
import { Rlp } from 'tevm'
// Valid prefixes:
// 0x00-0x7f: single byte
// 0x80-0xb7: short string
// 0xb8-0xbf: long string
// 0xc0-0xf7: short list
// 0xf8-0xff: long list
Rlp . validate ( new Uint8Array ([ 0x7f ])) // true
Rlp . validate ( new Uint8Array ([ 0x80 ])) // true (empty string)
Rlp . validate ( new Uint8Array ([ 0xc0 ])) // true (empty list)
See Also