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
encodeArray vs encodeList
encodeArray is functionally identical to encodeList - it’s provided as an alias for semantic clarity:
import { Rlp } from 'tevm'
const items = [ new Uint8Array ([ 1 ]), new Uint8Array ([ 2 ])]
// These are equivalent
const encoded1 = Rlp . encodeArray ( items )
const encoded2 = Rlp . encodeList ( items )
// Both => Uint8Array([0xc4, 0x01, 0x02])
Use encodeArray when thinking of the input as an array of values (e.g., transaction fields, block components).
Use encodeList when thinking of the input as a list structure (e.g., nested lists, tree structures).
Usage Patterns
Transaction Encoding
Encode transaction fields as array:
import { Rlp } from 'tevm'
interface LegacyTx {
nonce : bigint
gasPrice : bigint
gasLimit : bigint
to : Uint8Array
value : bigint
data : Uint8Array
v : bigint
r : Uint8Array
s : Uint8Array
}
function encodeLegacyTx ( tx : LegacyTx ) : Uint8Array {
const fields = [
bigintToBytes ( tx . nonce ),
bigintToBytes ( tx . gasPrice ),
bigintToBytes ( tx . gasLimit ),
tx . to ,
bigintToBytes ( tx . value ),
tx . data ,
bigintToBytes ( tx . v ),
tx . r ,
tx . s
]
return Rlp . encodeArray ( fields )
}
const tx : LegacyTx = {
nonce: 0 n ,
gasPrice: 20000000000 n ,
gasLimit: 21000 n ,
to: new Uint8Array ( 20 ). fill ( 0x01 ),
value: 1000000000000000000 n ,
data: Bytes (),
v: 27 n ,
r: Bytes32 (). fill ( 0x02 ),
s: Bytes32 (). fill ( 0x03 )
}
const encoded = encodeLegacyTx ( tx )
Encode block header fields:
import { Rlp } from 'tevm'
interface BlockHeader {
parentHash : Uint8Array
uncleHash : Uint8Array
coinbase : Uint8Array
stateRoot : Uint8Array
transactionsRoot : Uint8Array
receiptsRoot : Uint8Array
logsBloom : Uint8Array
difficulty : bigint
number : bigint
gasLimit : bigint
gasUsed : bigint
timestamp : bigint
extraData : Uint8Array
}
function encodeBlockHeader ( header : BlockHeader ) : Uint8Array {
const fields = [
header . parentHash ,
header . uncleHash ,
header . coinbase ,
header . stateRoot ,
header . transactionsRoot ,
header . receiptsRoot ,
header . logsBloom ,
bigintToBytes ( header . difficulty ),
bigintToBytes ( header . number ),
bigintToBytes ( header . gasLimit ),
bigintToBytes ( header . gasUsed ),
bigintToBytes ( header . timestamp ),
header . extraData
]
return Rlp . encodeArray ( fields )
}
Log Entry Encoding
Encode event log entries:
import { Rlp } from 'tevm'
interface Log {
address : Uint8Array
topics : Uint8Array []
data : Uint8Array
}
function encodeLog ( log : Log ) : Uint8Array {
const fields = [
log . address ,
log . topics , // Nested array
log . data
]
return Rlp . encodeArray ( fields )
}
const log : Log = {
address: new Uint8Array ( 20 ). fill ( 0x01 ),
topics: [
Bytes32 (). fill ( 0x02 ),
Bytes32 (). fill ( 0x03 )
],
data: new Uint8Array ([ 0x04 , 0x05 , 0x06 ])
}
const encoded = encodeLog ( log )
Receipt Encoding
Encode transaction receipts:
import { Rlp } from 'tevm'
interface Receipt {
status : bigint
gasUsed : bigint
logsBloom : Uint8Array
logs : Log []
}
function encodeReceipt ( receipt : Receipt ) : Uint8Array {
const encodedLogs = receipt . logs . map ( log => encodeLog ( log ))
const fields = [
bigintToBytes ( receipt . status ),
bigintToBytes ( receipt . gasUsed ),
receipt . logsBloom ,
encodedLogs
]
return Rlp . encodeArray ( fields )
}
Merkle Patricia Trie Node
Encode trie nodes:
import { Rlp } from 'tevm'
type TrieNode =
| { type : 'branch' ; children : Uint8Array []; value : Uint8Array }
| { type : 'extension' ; path : Uint8Array ; child : Uint8Array }
| { type : 'leaf' ; path : Uint8Array ; value : Uint8Array }
function encodeTrieNode ( node : TrieNode ) : Uint8Array {
if ( node . type === 'branch' ) {
// Branch node: [child0, child1, ..., child15, value]
return Rlp . encodeArray ([ ... node . children , node . value ])
}
if ( node . type === 'extension' ) {
// Extension node: [path, child]
return Rlp . encodeArray ([ node . path , node . child ])
}
// Leaf node: [path, value]
return Rlp . encodeArray ([ node . path , node . value ])
}
Schema-based Encoding
Define typed schemas for RLP encoding:
import { Rlp } from 'tevm'
// Define schema
interface AccountState {
nonce : bigint
balance : bigint
storageRoot : Uint8Array
codeHash : Uint8Array
}
// Encoder function
function encodeAccountState ( account : AccountState ) : Uint8Array {
return Rlp . encodeArray ([
bigintToBytes ( account . nonce ),
bigintToBytes ( account . balance ),
account . storageRoot ,
account . codeHash
])
}
// Decoder function (see decodeArray)
function decodeAccountState ( bytes : Uint8Array ) : AccountState {
const arr = Rlp . decodeArray ( bytes )
return {
nonce: bytesToBigint ( arr [ 0 ]),
balance: bytesToBigint ( arr [ 1 ]),
storageRoot: arr [ 2 ],
codeHash: arr [ 3 ]
}
}
Pre-calculate Sizes
Calculate total size before encoding:
import { Rlp } from 'tevm'
const items = [
new Uint8Array ([ 1 , 2 , 3 ]),
new Uint8Array ([ 4 , 5 , 6 ])
]
// Calculate size first
const size = Rlp . getEncodedLength ( items )
console . log ( `Array will encode to ${ size } bytes` )
// Then encode
const encoded = Rlp . encodeArray ( items )
Batch Encoding
Encode multiple arrays efficiently:
import { Rlp } from 'tevm'
const transactions = [
[ nonce1 , gasPrice1 , ... ],
[ nonce2 , gasPrice2 , ... ],
[ nonce3 , gasPrice3 , ... ]
]
// Encode each transaction
const encodedTxs = transactions . map ( tx => Rlp . encodeArray ( tx ))
// Encode as list of transactions
const block = Rlp . encodeArray ( encodedTxs )
Reusable Buffers
For high-frequency encoding, consider pre-allocating buffers:
import { Rlp } from 'tevm'
class TxEncoder {
private buffer = new Uint8Array ( 1024 ) // Reusable buffer
encode ( tx : Transaction ) : Uint8Array {
const fields = [
bigintToBytes ( tx . nonce ),
bigintToBytes ( tx . gasPrice ),
// ...
]
return Rlp . encodeArray ( fields )
}
}
See Also