web3p/rlp
PHP implementation of Ethereum Recursive Length Prefix (RLP) encoding/decoding. Encode strings, integers, numeric strings, or nested arrays; decode 0x-prefixed RLP hex back to values. Simple API via Web3p\RLP\RLP with helper hex string decoding.
Installation:
composer require web3p/rlp
Ensure your composer.json has "minimum-stability": "dev" if not already set.
First Use Case: Encode a simple array of strings (e.g., Ethereum transaction data):
use Web3p\RLP\RLP;
$rlp = new RLP();
$encoded = $rlp->encode(['nonce', 'gasPrice', 'gasLimit', 'to', 'value', 'data']);
Decode the encoded data:
$decoded = $rlp->decode('0x' . $encoded);
Where to Look First:
RLP class: Core functionality for encoding/decoding.Types\Str: Helper for hex-to-string conversion (e.g., Str::decodeHex($hex)).Encoding Ethereum-Specific Data:
Encode transaction inputs (e.g., for eth_sendRawTransaction):
$txData = [
'0x123', // nonce
'0x456', // gasPrice
'0x789', // gasLimit
'0xabc', // to
'0xdef', // value
'0x0' // data (empty)
];
$encodedTx = $rlp->encode($txData);
Decoding RLP-Encoded Data: Parse raw RLP data (e.g., from blockchain nodes):
$rawRlp = '0xc483646f678365746883736f6c6964697479';
$decoded = $rlp->decode('0x' . $rawRlp);
foreach ($decoded as $item) {
echo Str::decodeHex($item) . "\n"; // Output: dog, eth, solidity
}
Handling Nested Structures: Encode arrays of arrays (e.g., multi-signature transactions):
$nestedData = [
['sig1', 'sig2'],
['addr1', 'addr2']
];
$encoded = $rlp->encode($nestedData);
Integration with Web3 Libraries: Use RLP to pre-process data before sending to Web3.js or Ethers.js:
$rlpEncoded = $rlp->encode([$to, $value, $data]);
$tx = $web3->eth.accounts.signTransaction(...);
0x to encoded strings when decoding (e.g., '0x' . $encoded).try-catch for InvalidArgumentException (e.g., unsupported types).Hex Prefix Requirement:
0x prefix (e.g., decode('c483646f67') throws an error).'0x' . $encoded for decoding.Integer Limits:
'12345678901234567890').String vs. Hex:
decode() returns hex strings, not raw bytes. Use Str::decodeHex() for human-readable output.$hex = $decoded[0]; // '646f67'
echo Str::decodeHex($hex); // 'dog'
Empty/Invalid Inputs:
encode([]) returns 0xc0 (empty list), but encode(null) throws an exception.null or empty arrays:
$rlp->encode(is_null($data) ? [] : $data);
Nested Decoding:
$decoded = $rlp->decode($rlpData);
foreach ($decoded as $item) {
if (is_array($item)) {
$item = $rlp->encode($item);
}
}
Validate Encoded Output: Use online RLP decoders (e.g., RLP Tools) to verify your encoded data matches expectations.
Log Raw Data: Log hex strings before/after encoding to spot discrepancies:
error_log('Encoded: ' . bin2hex($encoded));
Check for 0x Prefixes:
Use str_starts_with() to validate inputs:
if (!str_starts_with($hex, '0x')) {
throw new \InvalidArgumentException('Hex string must start with 0x');
}
Custom Type Handling:
Extend the RLP class to support additional types (e.g., DateTime):
class CustomRLP extends RLP {
public function encode($input) {
if ($input instanceof DateTime) {
return parent::encode($input->format('Y-m-d'));
}
return parent::encode($input);
}
}
Batch Processing:
Optimize for bulk operations by implementing a batchEncode() method:
public function batchEncode(array $data): array {
return array_map([$this, 'encode'], $data);
}
Integration with Laravel:
Bind the RLP class to the container for global access:
$app->singleton(RLP::class, function () {
return new RLP();
});
Then inject via constructor or resolve with app(RLP::class).
How can I help you explore Laravel packages today?