Add a precompile that verifies multiple KZG openings (z_i, y_i) for a single EIP-4844 blob commitment, returning the same 64-byte output as the existing point-evaluation precompile.
EIP-4844 provides a point-evaluation precompile at 0x0A costing 50,000 gas per opening. Contracts needing multiple blob values (e.g., fraud proofs) must pay this cost repeatedly. A batch interface verifies k openings in one call, reducing overhead.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
| Name | Value | Comment |
|---|---|---|
MULTI_POINT_EVALUATION_PRECOMPILE_ADDRESS |
TBD |
precompile address |
MAX_MULTI_POINTS |
128 |
maximum number of evaluation points |
MULTI_POINT_EVALUATION_BASE_GAS |
TBD |
base gas cost |
MULTI_POINT_EVALUATION_PER_POINT_GAS |
TBD |
gas cost per evaluation point |
We introduce a precompile to perform multi KZG point evaluation:
It verifies multiple KZG openings (z_i, y_i) for a single EIP-4844 blob commitment in one call. The verification uses BLS12-381 pairing operations internally to check the multi-point opening proof. Gas cost is defined by MULTI_POINT_EVALUATION_BASE_GAS + MULTI_POINT_EVALUATION_PER_POINT_GAS * n where n is the number of evaluation points.
versioned_hash : Bytes32
commitment : Bytes48
n : uint32 (big-endian)
pairs : n × (z: Bytes32, y: Bytes32)
proof : Bytes48
Total length: 132 + (n × 64) bytes. All z and y MUST be strictly less than BLS_MODULUS.
On success, return 64 bytes identical to EIP-4844:
FIELD_ELEMENTS_PER_BLOB : uint256 (big-endian)
BLS_MODULUS : uint256 (big-endian)
Add a precompile at MULTI_POINT_EVALUATION_PRECOMPILE_ADDRESS that verifies multiple KZG openings (z_i, y_i) for a single EIP-4844 blob commitment.
The precompile executes the following logic:
def multi_point_evaluation_precompile(input: Bytes) -> Bytes:
versioned_hash = input[:32]
commitment = input[32:80]
n = int.from_bytes(input[80:84], 'big')
assert 1 <= n <= MAX_MULTI_POINTS
assert len(input) == 132 + n * 64
z_values, y_values = [], []
for i in range(n):
offset = 84 + i * 64
z_i = int.from_bytes(input[offset:offset+32], 'big')
y_i = int.from_bytes(input[offset+32:offset+64], 'big')
assert z_i < BLS_MODULUS and y_i < BLS_MODULUS
z_values.append(z_i)
y_values.append(y_i)
proof = input[84 + n*64 : 84 + n*64 + 48]
assert kzg_to_versioned_hash(commitment) == versioned_hash
assert verify_kzg_proof_multi(commitment, z_values, y_values, proof)
return U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + U256(BLS_MODULUS).to_be_bytes32()
The verify_kzg_proof_multi function performs multi-point opening verification using the EIP-4844 trusted setup and BLS12-381 pairing operations. Implementations typically use Lagrange interpolation to construct a polynomial through all (z_i, y_i) pairs, which has O(n²) complexity. When evaluation points align with roots of unity, FFT-based methods reduce this to O(n log n). The final verification step uses a single pairing check to verify all openings simultaneously.
The gas cost for multi point evaluation is:
def gas_cost(n: int) -> int:
return MULTI_POINT_EVALUATION_BASE_GAS + MULTI_POINT_EVALUATION_PER_POINT_GAS * n
Gas constants SHOULD ensure batching is cheaper than n separate 0x0A calls for n > 1. The verification internally uses BLS12-381 pairing operations, which are computationally expensive but enable efficient batch verification of multiple openings.
0x0A to avoid compatibility risks.MAX_MULTI_POINTS = 128 bounds input size while enabling meaningful savings.No changes to EIP-4844 transactions, BLOBHASH, or the existing precompile at 0x0A.
>= BLS_MODULUS).Copyright and related rights waived via CC0.