Compressing read only eth_call
Project description
ethcompress
Calldata compression for eth_call. Build and execute compressed calls that return byte‑identical results, without changing your decode logic. Strategies supported:
- JIT: Generate a temporary on‑chain decompressor that reconstructs calldata and forwards the call.
- FLZ: FastLZ variant used by Solady (LZ77‑style) with a tiny forwarder.
- CD: Calldata run‑length encoding (00/FF runs) with a tiny forwarder.
The library auto‑selects when helpful and safely falls back to vanilla.
Decompressor installs are done via eth_call state override at a fixed address:
0x00000000000000000000000000000000000000e0.
Quick Start
Compress a single call (raw calldata)
from web3 import Web3
from ethcompress import compress_eth_call
# Create a Web3 client
w3 = Web3(Web3.HTTPProvider("https://your.rpc.url"))
# to: destination contract; data_hex: 0x-prefixed calldata
cc = compress_eth_call(to, data_hex, alg="auto", min_size=800)
raw = cc.execute(w3) # returns 0x-hex bytes
# Decode with your ABI
block_number, return_data = w3.codec.decode(["uint256", "bytes[]"], bytes.fromhex(raw[2:]))
Compress from a web3py ContractFunction
from ethcompress import compress_call_fn
cc = compress_call_fn(contract.functions.symbol(), alg="auto", min_size=800)
raw = cc.execute(w3) # raw output, will need to abi decode
Add middleware (Web3.py)
from ethcompress.middleware import CompressionMiddleware
w3.middleware_onion.add(CompressionMiddleware(
alg="auto", # "auto" | "jit" | "flz" | "cd"
min_size=800, # only compress above this many bytes
allow_fallback=True # fall back to uncompressed on any error
))
# Existing w3.eth.call(...) keeps working; large calls get compressed
AsyncWeb3
from ethcompress.middleware import AsyncCompressionMiddleware
aw3.middleware_onion.add(AsyncCompressionMiddleware(alg="auto", min_size=800))
Performance Tips
- For best performance with the middleware, use a dedicated
Web3instance with onlyCompressionMiddleware(clear the onion and keep only compression). You can keep usingContractFunction.call()or calleth_callon pre‑encoded data — both work.
from ethcompress.middleware import CompressionMiddleware
# Remove all middlewares
w3.middleware_onion.clear()
# Add only compression (tweak settings as needed)
w3.middleware_onion.add(CompressionMiddleware(alg="jit", min_size=0, allow_fallback=False))
Low‑level primitives
from ethcompress import cd_compress, flz_compress, jit_bytecode, flz_fwd_bytecode, rle_fwd_bytecode
cd = cd_compress(data_hex)
flz = flz_compress(data_hex)
jit_code = jit_bytecode(data_hex)
flz_fwd = flz_fwd_bytecode(target_address)
cd_fwd = rle_fwd_bytecode(target_address)
Manual override call
from ethcompress import compress_call_data
to2, data2, override, meta = compress_call_data(data_hex, target_address, alg="auto", min_size=800)
if meta["algo"] != "vanilla":
resp = w3.provider.make_request("eth_call", [{"to": to2, "data": data2}, "latest", override])
else:
resp = w3.provider.make_request("eth_call", [{"to": target_address, "data": data_hex}, "latest"])
Strategy & Selection
- Threshold: by default, skip compression if calldata < 800 bytes (
min_size). - Auto (alg="auto"):
- If original size ≥ 2096 bytes: prefer JIT (no FLZ/CD trials).
- Else: compute FLZ and CD once, pick the smaller compressed stream.
- Always validate benefit: if (code + compressed) ≥ original, use vanilla.
All strategies are transparent: the decompressor forwards to the real target and returns the same bytes as a vanilla call.
Middleware Behavior
- Intercepts only
eth_calland only whento/dataare present. - Builds compressed call and state override; merges with any existing override map.
- On failure, returns vanilla result when
allow_fallback=True.
API Reference (condensed)
compress_eth_call(to, data, *, alg="auto", min_size=800, allow_fallback=True) -> CompressedCallCompressedCall.execute(w3, block="latest") -> hex
compress_call_fn(fn, *, alg="auto", min_size=800, allow_fallback=True) -> CompressedCallcompress_call_data(data, target, *, alg="auto", min_size=800) -> (to, data, override, meta)cd_compress(data) -> hex,flz_compress(data) -> hexjit_bytecode(data) -> hex,flz_fwd_bytecode(address) -> hex,rle_fwd_bytecode(address) -> hex- Middleware:
CompressionMiddleware(...),AsyncCompressionMiddleware(...)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ethcompress-0.0.1.tar.gz.
File metadata
- Download URL: ethcompress-0.0.1.tar.gz
- Upload date:
- Size: 17.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed8140d6fe052ab8c4045dfddea6ba6f9ea27e3496ba495e3e9e8f963de5eed9
|
|
| MD5 |
80b9b4813a52ac0576a526da0560b2d3
|
|
| BLAKE2b-256 |
e803c79bd161c24c0b9802a51e17cc0b8b95c35195fa4ea1d8f086a68dfed82d
|
File details
Details for the file ethcompress-0.0.1-py3-none-any.whl.
File metadata
- Download URL: ethcompress-0.0.1-py3-none-any.whl
- Upload date:
- Size: 15.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6e106d5766e2a13aff8501932eb71fb568bbf0f6df61a29265b17139701e8db
|
|
| MD5 |
72de4b1247a874f54af8776f34066d88
|
|
| BLAKE2b-256 |
6f15783e977825c94446d4dc8e6b1fc9a0e24f336e7839c0d7ce69d932155630
|