Xác minh bằng chứng Zcash trên Ethereum nhờ EIP-152: Giải pháp tối ưu hóa Gas
EIP-152 là một hợp đồng tiền biên (precompile) ít người biết đến trên Ethereum, được thiết kế để tính toán hàm băm BLAKE2b với chi phí gas cực thấp. Bài viết này phân tích cách sử dụng tính năng này để xác minh bằng chứng Zcash trên chuỗi Ethereum một cách hiệu quả, giúp giảm thiểu chi phí vận hành so với việc viết mã Solidity thuần túy.

Ethereum sở hữu một precompile (hợp đồng tiền biên) mà gần như không ai biết đến. Nó nằm tại địa chỉ 0x09, có nhiệm vụ tính toán hàm nén BLAKE2b, và được đưa vào mạng lưới với một mục đích cụ thể: cho phép bạn xác minh Zcash ngay trên Ethereum. Đây là câu chuyện về cách chúng tôi tận dụng tính năng này.
EIP-152 là gì?
EIP-152 được tích hợp trong bản nâng cấp hard fork Istanbul vào tháng 12 năm 2019. Nó cung cấp hàm nén F của BLAKE2b dưới dạng một hợp đồng precompile tại địa chỉ 0x09. Chi phí sử dụng: 1 gas cho mỗi vòng lặp. Một cuộc gọi BLAKE2b tiêu chuẩn chạy 12 vòng, do đó tổng chi phí chỉ là 12 gas.
BLAKE2b là hàm băm nền tảng cho các cây Merkle Sapling và NU5 của Zcash. Nếu không có precompile này, việc tính toán BLAKE2b trong Solidity tốn khoảng 200.000 gas. Nhưng với EIP-152, chi phí chỉ còn 712 gas cho một lần băm hoàn chỉnh. Đây là mức giảm tới 280 lần.
Đề xuất EIP này được đưa ra bởi Tjaden Hess và các thành viên khác của Quỹ Ethereum (Ethereum Foundation), được thúc đẩy bởi một mục tiêu duy nhất: cho phép xác minh light-client của Zcash trên Ethereum mà không phải chịu chi phí gas "không tưởng".
Tại sao nó lại quan trọng?
Việc xác minh bằng chứng chuỗi chéo (cross-chain proof) cần đến các hàm băm. Zcash sử dụng BLAKE2b kết hợp với các chuỗi cá nhân hóa (personalization strings) để phân tách miền. Mỗi cấp độ của cây, mỗi ngữ thức giao thức sử dụng một chuỗi cá nhân hóa khác nhau. Ví dụ: ZcashPedersenHash cho cây cam kết ghi chú (note commitment trees) và ZTxIdHeadersHash cho ID giao dịch.
Nếu bạn không thể tính toán các hàm băm này với chi phí rẻ trên chuỗi (on-chain), bạn hoàn toàn không thể xác minh trạng thái của Zcash trên Ethereum. Precompile chính là chìa khóa để biến điều này thành hiện thực.
Định dạng đầu vào 213 Byte
Precompile này yêu cầu chính xác 213 byte đầu vào theo cấu trúc sau:
| Trường | Byte | Mô tả |
|---|---|---|
| rounds | 4 | Số vòng lặp (12 cho BLAKE2b) |
| h | 64 | Vector trạng thái (8 x uint64 LE) |
| m | 128 | Khối thông điệp |
| t[0] | 8 | Bộ đếm bù thấp (uint64 LE) |
| t[1] | 8 | Bộ đếm bù cao (uint64 LE) |
| f | 1 | Cờ khối cuối cùng (0 hoặc 1) |
Tổng cộng: 4 + 64 + 128 + 8 + 8 + 1 = 213 byte. Giá trị trả về là 64 byte: vector trạng thái đã được cập nhật.
Cách gọi Precompile
Dưới đây là cách ZAP1Verifier.sol thực hiện cuộc gọi này:
function blake2b(
uint32 rounds,
bytes memory h,
bytes memory m,
uint64 t0,
uint64 t1,
bool isFinal
) internal view returns (bytes memory) {
bytes memory input = abi.encodePacked(
bytes4(rounds),
h,
m,
bytes8(t0),
bytes8(t1),
isFinal ? bytes1(0x01) : bytes1(0x00)
);
(bool ok, bytes memory out) = address(0x09).staticcall(input);
require(ok, "BLAKE2b precompile failed");
return out;
}
Chúng ta sử dụng staticcall đến địa chỉ 0x09. Không cần mã hóa ABI phức tạp, không cần bộ chọn hàm (function selector). Chỉ cần byte thô vào, byte thô ra. Precompile sẽ xử lý phần còn lại.
Chuỗi cá nhân hóa (Personalization Strings)
Cơ chế phân tách miền của Zcash hoạt động bằng cách thực hiện phép XOR một chuỗi cá nhân hóa 16 byte vào vector trạng thái ban đầu (byte 32-47 của h). Mỗi ngữ thức giao thức sẽ có chuỗi riêng. Khi xác minh đường dẫn Merkle của cam kết ghi chú Sapling, bạn cần thiết lập chuỗi cá nhân hóa thành hằng số Zcash phù hợp trước mỗi lần gọi nén.
Đây không phải là tùy chọn. Sai chuỗi cá nhân hóa dẫn đến sai băm, và kết quả là xác minh thất bại. Precompile không bắt buộc việc cá nhân hóa; hợp đồng của bạn phải thiết lập h chính xác trước khi gọi 0x09.
Thực tế về chi phí Gas
Một bằng chứng Merkle cho cây Sapling của Zcash có độ sâu 32 cấp. Mỗi cấp độ cần một lần nén BLAKE2b. Với precompile, chi phí băm khoảng 32 x 712 = ~22.800 gas. Trong khi đó, nếu dùng Solidity thuần túy: 32 x 200.000 = 6,4 triệu gas. Con số này sẽ vượt xa giới hạn gas của một khối.
Precompile không chỉ giúp tiết kiệm tiền, mà còn làm cho việc xác minh trở nên khả thi về mặt kỹ thuật.
Đã hoạt động trên Mainnet
ZAP1Verifier hiện đã được triển khai trên mạng chính Ethereum tại địa chỉ 0x12db453A7181E369cc5C64A332e3808e807057C1. Hợp đồng này xác minh các bằng chứng Merkle Sapling của Zcash sử dụng precompile EIP-152.
Cùng một hợp đồng cũng đang hoạt động trên các mạng lưới Arbitrum, Base, Hyperliquid và Sepolia.
Mã nguồn: Frontier-Compute/zap1-verify-sol
Kết luận
Precompile này đã tồn tại trên Ethereum từ năm 2019. Gần như không ai sử dụng nó, nhưng chúng tôi thì có.



