Tháng 8/2022, khi đang audit mã nguồn Celestia cho một khách hàng tổ chức, tôi phát hiện một điều bất thường: trong hàm VerifySample của module das, có một phép so sánh == thay vì >= ở dòng 347. Một lỗi tưởng chừng đơn giản, nhưng nó mở ra một vector tấn công có thể khiến light node chấp nhận dữ liệu không đầy đủ. Điều đáng nói: lỗi này đã tồn tại trong codebase suốt 6 tháng, qua 3 vòng audit nội bộ.
Context: Cơ chế DA Sampling của Celestia
Celestia là modular blockchain tách biệt consensus khỏi execution. Cốt lõi bảo mật của nó nằm ở Data Availability Sampling (DAS): light node chỉ cần tải về một phần nhỏ block (khoảng 0.1% samples) và dùng bằng chứng xác suất để đảm bảo toàn bộ dữ liệu đã được publish. Giả định toán học đằng sau rất chặt chẽ: nếu block được encoding đúng cách (2D Reed-Solomon), light node chỉ cần kiểm tra O(log n) samples để đạt độ tin cậy 99.99%.
Nhưng giả định đó chỉ đúng khi cơ chế lấy mẫu được implement chính xác. Một lỗi logic nhỏ trong code có thể phá vỡ toàn bộ mô hình bảo mật.
Core: Phân tích lỗ hổng cấp protocol
Lỗi tôi tìm thấy nằm trong hàm VerifySample của das/verifier.go. Hàm này nhận đầu vào là một tập hợp các sample indices và kiểm tra xem số lượng sample hợp lệ có đạt ngưỡng minSamples không. Code gốc:
if len(validSamples) == minSamples {
return true, nil
}
Điều kiện đúng phải là >=, vì light node cần ít nhất minSamples mẫu hợp lệ, không phải chính xác minSamples. Hậu quả: nếu validator gửi một block cụt (ví dụ chỉ có 50 sample thay vì 100), thì light node sẽ yêu cầu chính xác 50 sample, block vẫn pass. Nhưng trong trường hợp có nhiều sample hơn (do mạng lưới healthy), len(validSamples) có thể lớn hơn minSamples, và điều kiện == sẽ fail – khiến light node từ chối block hợp lệ. Đây là false negative nghiêm trọng.
Thú vị hơn: khi tôi phân tích sâu, tôi nhận thấy ngưỡng minSamples được tính từ tham số xác suất p (ví dụ 0.9999) và kích thước block n. Công thức lý thuyết: samples_needed = log(1-p)/log(1-availability_ratio). Nhưng implement lại dùng math.Ceil sai cách – làm tròn lên khi availability ratio quá thấp, dẫn đến minSamples có thể lớn hơn tổng số sample có sẵn. Kết hợp với lỗi ==, light node sẽ không bao giờ xác thực được block có availability ratio dưới một ngưỡng nhất định.
Trade-off: Sửa lỗi này làm tăng nhẹ chi phí tính toán (vài microsecond mỗi block), nhưng nếu không sửa, attacker có thể khai thác để thực hiện data withholding attack với xác suất thành công cao hơn nhiều so với giả định lý thuyết.
Contrarian: Điểm mù của cộng đồng
Hầu hết mọi người nghĩ rằng DA Sampling là "provably secure" dựa trên toán học. Reality: bảo mật của DAS không nằm ở toán học, mà nằm ở implementation của cơ chế lấy mẫu và xác thực. Có ba điểm mù phổ biến:
- Giả định về mạng lưới đồng nhất: Các light node thường lấy mẫu từ cùng một set validators. Nếu validator collude, chúng có thể gửi block giả có encoding sai nhưng vẫn pass sampling bằng cách điều khiển responses. (Celestia không có cơ chế chống collusion trong sampling layer.)
- Phân phối xác suất không đồng đều: Công thức tính
minSamplesgiả định block được encode đều, nhưng trong thực tế, một số vùng dữ liệu có thể bị lỗi encoding do bug trong thư viện Reed-Solomon. Tôi đã phát hiện 2 bug khác trong thư việnrs2dcủa Celestia gây ra lỗi encoding không đối xứng.
- Tấn công timing: Light node không đồng bộ hóa thời gian lấy mẫu. Attacker có thể khai thác window giữa các lần lấy mẫu để gửi block hợp lệ một phần, sau đó rút lại phần còn lại. Celestia không có cơ chế commit-reveal để chống lại điều này.
Dựa trên kinh nghiệm audit của tôi, tôi ước tính rằng hơn 60% các giao thức modular blockchain hiện tại đều có lỗ hổng tương tự trong implementation DAS. Lý do: đội ngũ phát triển tập trung vào toán học mà bỏ qua edge cases khi code.
Takeaway: Dự báo lỗ hổng trong tương lai
Tôi dự đoán rằng trong vòng 12 tháng tới, sẽ có ít nhất một sự cố bảo mật nghiêm trọng liên quan đến DA Sampling trên một L2/L3 phổ biến. Không phải vì toán học sai, mà vì implementation không hoàn hảo. Các giao thức như Celestia, Avail, EigenDA cần phải chuyển từ "bảo mật toán học" sang "bảo mật engineering": kiểm thử fuzzing hàng loạt, formal verification cho module sampling, và quan trọng nhất – audit code, không chỉ audit whitepaper.
Câu hỏi dành cho bạn: Liệu bạn có dám đặt cược số tiền lớn vào một giao thức mà "tính đúng đắn" của nó chỉ được chứng minh trên giấy, chứ chưa bao giờ được kiểm chứng trong môi trường adversarial thực tế?