## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require amashukov/rlp-php
Ensure ext-gmp is enabled in your PHP environment (required for big integer handling).
First Use Case: Encode a simple Ethereum transaction-like structure (e.g., a nested array of byte strings):
use Amashukov\Rlp\Rlp;
$txData = [
'nonce' => '0x01',
'gasPrice' => '0x09184e72a000',
'gas' => '0x5208',
'to' => '0x0000000000000000000000000000000000000000',
'value' => '0x00',
'data' => '0x7f74657374320000000000000000000000000000000000000000000000000000',
'v' => '0x01',
'r' => '0x00',
's' => '0x00'
];
$encodedTx = Rlp::encode($txData);
Where to Look First:
Rlp::encode(): For serializing nested PHP arrays/strings to RLP format.Rlp::decode(): For parsing RLP-encoded data back into PHP structures.Rlp::encodeInt(): For encoding integers in Ethereum’s minimal big-endian convention.Rlp::decodeStream(): For parsing concatenated RLP items (e.g., blocks or transaction batches).Transaction Serialization:
Use Rlp::encode() to serialize transaction objects (arrays) into RLP format before signing or broadcasting:
$rlpTx = Rlp::encode([
hex2bin('0x01'), // nonce
hex2bin('0x09184e72a000'), // gasPrice
hex2bin('0x5208'), // gas
hex2bin('0x0000000000000000000000000000000000000000'), // to
hex2bin('0x00'), // value
hex2bin('0x7f74657374320000000000000000000000000000000000000000000000000000'), // data
hex2bin('0x01'), // v
hex2bin('0x00'), // r
hex2bin('0x00') // s
]);
Block Processing: Decode RLP-encoded blocks (e.g., from a JSON-RPC response) into PHP arrays:
$blockHex = '0xf8...'; // RLP-encoded block
$block = Rlp::decode($blockHex);
// $block[0] = block header, $block[1] = transactions, etc.
Streaming Decoding: Parse concatenated RLP items (e.g., transactions in a block) without full decoding:
$stream = $block['transactions']; // Hex string of concatenated RLP transactions
$offset = 0;
$transactions = [];
while ($offset < strlen($stream)) {
[$tx, $consumed] = Rlp::decodeStream($stream, $offset);
$transactions[] = $tx;
$offset += $consumed;
}
Integer Handling:
Encode large integers (e.g., gas limits, values) using Rlp::encodeInt():
$gasLimit = Rlp::encodeInt('1000000000000000000'); // 1e18 wei (1 ETH)
Merkle Patricia Trie: Encode trie nodes (nested arrays of hashes) for state storage:
$trieNode = [
'0x123...', // key1
'0x456...', // value1
'0x789...', // key2
'0xabc...' // value2
];
$encodedNode = Rlp::encode($trieNode);
Laravel Service Providers:
Bind the RLP encoder/decoder as a singleton in AppServiceProvider:
$this->app->singleton(Rlp::class, function () {
return new \Amashukov\Rlp\Rlp();
});
Inject it into controllers/services:
public function __construct(private Rlp $rlp) {}
Hex ↔ Binary Conversion:
Use hex2bin()/bin2hex() to convert between hex strings and binary data before/after RLP operations:
$hexData = '0x74657374';
$binaryData = hex2bin($hexData);
$encoded = Rlp::encode($binaryData);
Validation: Combine with Laravel’s validation to ensure RLP-encoded data is canonical:
$validator = Validator::make(['tx' => $txHex], [
'tx' => 'required|string|rlp_canonical', // Custom rule for RLP validation
]);
Testing: Use the package’s strict decoding to validate external RLP inputs (e.g., from JSON-RPC):
try {
$decoded = Rlp::decode($externalRlpData);
} catch (\InvalidArgumentException $e) {
// Handle malformed RLP (e.g., reject malleable transactions)
}
Strict Canonical Decoding:
Rlp::decode() throws InvalidArgumentException for non-canonical inputs (e.g., short strings encoded as long strings). Handle exceptions gracefully:
try {
$data = Rlp::decode($rlpHex);
} catch (\InvalidArgumentException $e) {
Log::error("Invalid RLP: " . $e->getMessage());
return response()->json(['error' => 'Invalid RLP'], 400);
}
Integer Encoding:
Rlp::encodeInt() expects integers as strings (e.g., '1000000000000000000'). Passing PHP integers may cause precision loss for large values:
// Correct:
$encoded = Rlp::encodeInt('1000000000000000000');
// Avoid:
$encoded = Rlp::encodeInt(1000000000000000000); // May lose precision
Binary Data Handling:
Rlp::encode() must be binary strings (not hex strings). Use hex2bin() first:
// Wrong:
Rlp::encode('0x74657374'); // Fails (treats as literal string)
// Correct:
Rlp::encode(hex2bin('0x746574')); // Encodes 'test'
Stream Decoding Offsets:
Rlp::decodeStream() returns the consumed byte count. Misusing offsets can lead to infinite loops or skipped data:
// Correct:
while ($offset < strlen($stream)) {
[$item, $consumed] = Rlp::decodeStream($stream, $offset);
$offset += $consumed;
}
// Wrong:
while (true) { // Risk of infinite loop
[$item, $consumed] = Rlp::decodeStream($stream, $offset);
$offset = 0; // Resets offset!
}
Nested Lists:
[]) are encoded as 0xc0. Ensure your data structure matches this convention:
Rlp::encode([[], []]); // 0xc2 0xc0 0xc0
Big Integer Limits:
ext-gmp handles large integers, extremely large values (e.g., > 2^256) may cause performance issuesHow can I help you explore Laravel packages today?