5 · Bảo mật
Bảo mật trong XChain là theo tài sản, không theo chain. Mỗi tài sản mang một security-class tối thiểu, và tài sản giá trị cao đơn giản không thể tồn tại trong Miền dữ liệu. Điều này khiến tấn công "hạ cấp" bất khả về cấu trúc, và đặt an toàn của giá trị lên mật mã và vốn, thay vì lên lòng tin ở số ít validator.
Ba lớp cho giá trị cao
Với giá trị cao (T0–T1), ba lớp kết hợp:
- ZK validity proof — dù một ủy ban bị chiếm 100% cũng không tạo được trạng thái sai; nó mất liveness, không mất safety.
- Global restaking — gian lận trên bất kỳ chain nào cắt vốn toàn cục.
- Watcher / fraud proof — phát hiện và thách thức.
Dữ liệu giá trị thấp (T3–T4) chỉ dựa proof-of-publication. Ba security-class của chain trải khắp dải, và pessimistic proof phủ thêm một lớp cách ly lỗi: một chain hỏng chỉ mất phần của chính nó.
| Security-class | Áp cho | Dựa vào gì | Được mang giá trị cao? |
|---|---|---|---|
| SOVEREIGN | T3–T4 · Miền dữ liệu | Validator riêng + proof-of-publication | Không — UAC cấm về mặt cấu trúc |
| SHARED | T1–T2 · Execution | Partial Set Security — mượn tập validator | Có, trong hạn mức của class |
| ZK_SECURED | T0–T1 · Settlement / Value | Bắt buộc validity proof + global restaking + watcher | Có — class cao nhất |
Hình 5 — Bảo mật chi theo giá trị: ba lớp cộng lại cho Miền giá trị, chỉ cần bằng chứng công bố ở rìa.
Xác minh thật sự tốn bao nhiêu
"Verify, đừng chạy lại" chỉ là một lập luận cho tới khi có người đo nó — nên đây là các con số. Chúng đến từ đường verify Groth16/BN254 thật, đúng bản đã merge vào master và chứng minh trọn vòng trên node devnet. ⚠️ Chúng KHÔNG mô tả testnet công khai, nơi vẫn chạy binary trước nâng cấp với prover MOCK; khác biệt đó được theo dõi ở Hiện trạng & Lộ trình và không được nói lướt ở đây.
| Đo được | Giá trị | Vì sao đáng kể |
|---|---|---|
| Xác minh một chứng chỉ chuyển trạng thái | ~1,19 ms (một phép pairing BN254, Go thuần, bên trong DeliverTx) | Với nhịp block 3.000 ms, có thể xác minh ~2.500 chứng chỉ mỗi block trước khi xác minh trở thành nút thắt |
Tính đầu vào công khai MiMC(prev,tx,new) | ~14 µs | Chain tự dẫn ra, nên một proof bị buộc vào đúng một chuyển trạng thái và không phát lại cho cái khác được |
Chi phí groth16.Verify so với cỡ mạch | Hằng số — không phụ thuộc số đầu vào công khai lẫn số ràng buộc của mạch | Nên con số 1,19 ms cũng đại diện cho vkey SP1 thật, không riêng mạch stand-in hiện tại |
| Sinh một proof (SP1 wrap → Groth16) | ~15,97 triệu ràng buộc, ~21,5 GB RAM | Ngoài chuỗi theo cấu trúc — không bao giờ chạy trên validator. Sinh proof cần một mạng prover hoặc máy ≥64 GB |
Chính sự bất đối xứng đó là toàn bộ ý đồ của kiến trúc. Sinh một proof nặng tới mức phải có hạ tầng chuyên dụng; kiểm một proof rẻ tới mức không ảnh hưởng gì tới nhịp block. Đây là thứ giữ cho chi phí ở Root gần như hằng số trong khi lưu lượng ở rìa lớn dần — và cũng là lý do nguồn cung prover được nêu thẳng như một bài toán kinh tế chưa giải ở Bài toán mở, thay vì cho là đã xong.
Làm cứng trong thực tế trông thế nào
Ba tính chất chịu lực, và mỗi cái đều được kiểm chứ không phải khẳng định suông:
Tính tất định. Bộ verify không dùng dấu phẩy động, không dùng ngẫu nhiên. Đây không phải chi tiết làm đẹp: nếu một validator tính ra kết quả khác thì app hash phân kỳ và chain dừng. Điều này được kiểm bằng cách lặp lại đúng phép verify nhiều lần cho kết quả giống hệt, cộng một lượt chạy trọn vòng nơi hai validator ra cùng một app hash sau khi verify một proof thật bên trong một block.
Từ chối rác một cách êm. Mọi thứ đến từ giao dịch đều là đầu vào thù địch, và bên trong DeliverTx thì panic hay treo đều là chain dừng. Fuzzing tìm ra một trường hợp thật: bộ giải mã proof đọc trường nbCommitments không kiểm rồi cấp phát theo nó, nên kẻ tấn công đặt nó cỡ bốn tỷ là kích hoạt một lệnh cấp phát ~256 GB — một đòn từ chối dịch vụ mỗi giao dịch, đủ để dừng chain. Bản vá là một chốt kiểm hình dạng tất định, áp trước khi proof tới tay thư viện mật mã (đúng độ dài kỳ vọng, số commitment bằng 0); giải pháp timeout bị loại vì nó phá tính tất định. Sau vá: 4,26 triệu lượt fuzz sạch, đầu vào từng làm treo nay thành một test hồi quy chạy dưới một giây, và trên node sống thì đầu vào độc hại bị từ chối trong khi node vẫn tiếp tục ra block.
Trả tiền cho phần việc mình gây ra. Một phát hiện tinh hơn: chênh lệch gas giữa proof thật và MOCK (~48.191 so với ~40.638) gần như hoàn toàn đến từ việc lưu một proof lớn hơn, chứ không phải từ ~1,19 ms CPU mà phép verify thật sự tốn — vì gas được tính cho thao tác lưu trữ, không tính cho tính toán thuần bên trong handler. Kẻ tấn công vì thế mua được CPU thật với giá rẻ bằng cách spam các proof đúng-định-dạng-nhưng-không-hợp-lệ. Cách sửa là tính phí cho phép verify một cách tường minh, TRƯỚC khi thực hiện nó, để phí phản ánh đúng chi phí bị áp đặt.
Không cái nào trong số này được tìm ra bằng suy luận trên bản thiết kế; chúng được tìm ra bằng cách chạy nó. Đó là lý lẽ cho một testnet công khai, gói trong một đoạn văn.
Câu chốt: gắn một security-class vào mỗi tài sản là viên đá chốt — nó biến "đừng đặt giá trị nhầm chỗ" từ lời khuyên thành một bảo đảm cấu trúc. Mọi bảo đảm đã nêu tới giờ — ranh giới Miền, tách READ/WRITE, security-class theo tài sản — phải được cưỡng chế ở một nơi đủ nhỏ để kiểm toán và tin cậy. Nơi đó là eo thắt: bảy nguyên thủy, đặc tả ở mục sau.