Hand-rolled RLP (Recursive Length Prefix) encoder for Ethereum legacy (type-0) transaction serialization.
This module implements only the encoding side — there is no decoder. The set of inputs we encode is narrow: bytes, non-negative integers, and lists of already-encoded items. That's enough for legacy EIP-155 transactions and pure RLP test vectors.
Encoding rules (per the Ethereum spec)
Bytes / strings:
- Empty:
0x80. - Single byte
bwhere0x00 <= b <= 0x7f: encoded as itself (single byte, no length prefix). - Other byte strings of length
len:1 <= len <= 55:<<0x80 + len, ...bytes>>.len > 55:<<0xb7 + size_of_len, ...len_bytes, ...bytes>>wherelen_bytesis the minimal big-endian encoding oflen.
Lists with combined-payload size len:
0 <= len <= 55:<<0xc0 + len, ...payload>>.len > 55:<<0xf7 + size_of_len, ...len_bytes, ...payload>>.
Non-negative integers are encoded as their minimal-byte big-endian
representation, then RLP-encoded as a byte string. Zero collapses to
the empty string 0x80 — the integer 0 does NOT encode as
<<0x00>>.
Output is byte-for-byte verified against ethers.encodeRlp in
test/fixtures/tx.json § rlp_primitives.
Summary
Functions
Encodes a binary as an RLP string.
Encodes a non-negative integer as an RLP byte string carrying the
minimal big-endian representation. Zero encodes as 0x80 (empty
string), matching the canonical Ethereum/RLP convention.
Encodes a list of already-RLP-encoded items as an RLP list.
Hex-encodes raw RLP output for human display or fixture comparison.
Always lowercase, always 0x-prefixed.
Functions
Encodes a binary as an RLP string.
@spec encode_integer(non_neg_integer()) :: binary()
Encodes a non-negative integer as an RLP byte string carrying the
minimal big-endian representation. Zero encodes as 0x80 (empty
string), matching the canonical Ethereum/RLP convention.
Encodes a list of already-RLP-encoded items as an RLP list.
The caller is responsible for encoding each element first
(encode_bytes/1, encode_integer/1, or a nested encode_list/1).
This module deliberately keeps element-encoding decisions in the
caller — there is no value tagging that would let one function
decide between "string" and "integer" interpretations of arbitrary
Elixir terms.
Hex-encodes raw RLP output for human display or fixture comparison.
Always lowercase, always 0x-prefixed.