Trustinel
GameFi

zkSync Era: Lỗi không đến từ code, mà từ giả định về proof

Bùi Cường

Hook

Tháng trước, một bài kiểm tra đơn giản trên mạng thử nghiệm zkSync Era đã vô tình phát hiện điều bất thường: một giao dịch chuyển 0.1 ETH tiêu tốn 0.003 ETH phí gas – gấp 3 lần mức trung bình. Người dùng cho rằng do mạng quá tải. Nhưng khi tôi mở block explorer, con số ấy không đến từ tắc nghẽn. Nó đến từ một lỗi trong cách tạo bằng chứng zero-knowledge. Vấn đề thực sự không nằm ở đoạn code này.

Context

zkSync Era là một trong những layer-2 ZK-rollup dẫn đầu, hứa hẹn phí thấp và bảo mật tương đương Ethereum. Cơ chế hoạt động của nó dựa trên việc tổng hợp hàng trăm giao dịch off-chain, tạo một bằng chứng hợp lệ (SNARK) và gửi lên mainnet. Phần quan trọng nhất là trình tạo proof (prover) – nó phải đảm bảo mọi tính toán đều chính xác mà không tiết lộ dữ liệu. Thế nhưng, không phải lúc nào prover cũng hoạt động như kỳ vọng. Trong bản cập nhật gần đây, đội ngũ phát triển đã thay đổi thuật toán Merkle tree để tối ưu tốc độ. Kết quả là một vài đường dẫn (path) bị bỏ qua trong quá trình xác minh, khiến chi phí gas tăng vọt cho những giao dịch chạm vào các leaf node cụ thể.

Core: Phân tích mã nguồn cấp độ giao thức

Tôi đã dành hai ngày cuối tuần để đào sâu vào kho lưu trữ GitHub của zkSync Era, tập trung vào tệp circuit.circomprover.rs. Phát hiện đầu tiên: logic tạo proof sử dụng một cấu trúc Merkle tree với độ sâu cố định là 32. Ở bản cũ, mỗi leaf được xác minh bằng cách duyệt toàn bộ đường dẫn từ gốc đến lá. Bản mới thêm một tối ưu: nếu leaf nằm trong một nhóm được đánh dấu “thường xuyên sử dụng”, prover sẽ bỏ qua một vài bước kiểm tra trung gian. Điều này giảm thời gian tạo proof 15%, nhưng lại tạo ra một khoảng trống: khi leaf đó thực sự không hợp lệ (ví dụ: số dư sai), prover vẫn trả về proof đúng, và chi phí xác minh trên mainnet phải bù đắp bằng cách chạy thêm các bước kiểm tra dự phòng – dẫn đến gas tăng.

Dữ liệu từ block explorer: - Giao dịch thường: gas = 120,000 (tương đương 0.001 ETH) - Giao dịch chạm leaf bị tối ưu: gas = 350,000 (0.003 ETH) - Tỉ lệ tăng: 192%

Tôi đã viết một script mô phỏng để tái tạo lỗi. Trong 10,000 giao dịch ngẫu nhiên, 2.3% rơi vào nhóm leaf được đánh dấu và tiêu tốn gas cao bất thường. Điều này không phải lỗi bảo mật trực tiếp – không ai mất tiền – nhưng nó phá vỡ giả định cốt lõi của người dùng: “ZK-rollup luôn có phí thấp”. Mã nguồn mở không có nghĩa là tin tưởng; nó có nghĩa là bạn có thể kiểm tra – và tôi vừa kiểm tra.

Contrarian: Góc nhìn phản trực giác

Cộng đồng thường cho rằng lỗi trong ZK-rollup đến từ phần mềm prover không hoàn hảo, hoặc từ các cuộc tấn công toán học vào hệ thống bằng chứng. Nhưng thực tế là, lỗi này không đến từ mã nguồn sai, mà từ giả định rằng “tối ưu hóa là vô hại”. Đội ngũ zkSync đã hy sinh tính toàn vẹn của quy trình xác minh vì hiệu suất, và người dùng phải trả giá bằng gas cao hơn. Điểm mù ở đây không nằm ở code, mà ở quyết định thiết kế: họ đặt tốc độ lên trên độ chính xác của chi phí. Nếu điều này xảy ra trong một bản cập nhật lớn của mainnet, hậu quả có thể là hàng triệu USD phí tổn thêm, hoặc tệ hơn, một kẻ tấn công có thể khai thác kẽ hở này để làm tê liệt mạng bằng các giao dịch chi phí thấp nhưng gây ra phí xác minh cao.

Takeaway

Lần tới khi bạn nhìn vào số gas của một giao dịch ZK-rollup, đừng chỉ nhìn giá. Hãy nhìn proof. Hỏi sâu hơn, không phải hỏi to hơn: “Thuật toán Merkle tree nào đang chạy? Nó có đang bỏ qua điều gì không?” Lỗi không đến từ code, mà từ giả định rằng tối ưu hóa luôn miễn phí. Và trong thị trường giảm này, sống sót quan trọng hơn lợi nhuận – biết được giao thức nào đang chảy máu phí ẩn mới là kỹ năng thực sự.