Nếu bạn đang tìm hiểu về cơ chế hoạt động của zk-SNARKs, hẳn là các bạn sẽ bắt gặp một số khái niệm như: Rank-1 Constraint System (R1CS), Quadratic Arithmetic Program (QAP). Bài viết này giúp bạn hình dung chi tiết về cách hoạt động của việc chuyển đổi 1 biểu thức thành dạng R1CS cùng với một demo tương tác. Hy vọng sẽ giúp bạn dễ hình dung vấn đề một cách thấu đáo hơn.
Bài viết này sẽ dựa trên bài viết chính của Vitalik với tựa đề “Quadratic Arithmetic Programs: from Zero to Hero“
R1CS (Rank-1 Constraint System) là một biểu diễn tiêu chuẩn để mô tả các phép toán đại số phức tạp trong ngữ cảnh của zk-SNARKs. Chúng ta phải chuyển đổi sang dạng R1CS vì một số lý do sau:
Đầu tiên, zk-SNARKs cần chuyển các phép toán phức tạp thành các ràng buộc toán học dưới dạng . R1CS giúp chuyển các tính toán phức tạp thành một hệ thống các ràng buộc tuyến tính mà các thuật toán zk-SNARKs có thể dễ dàng xử lý.
R1CS là một định dạng tổng quát, có thể biểu diễn bất kỳ phép toán nào (cộng, nhân, lũy thừa, điều kiện, logic). Điều này giúp zk-SNARKs xử lý được nhiều loại vấn đề toán học và chương trình khác nhau. Một chương trình tính toán phức tạp có thể được chuyển thành hàng nghìn ràng buộc R1CS nhưng vẫn giữ được tính chính xác toán học.
Sau khi có R1CS, hệ thống có thể được chuyển thành một hệ đa thức gọi là Quadratic Arithmetic Program (QAP), đây là bước quan trọng trong zk-SNARKs để tạo và xác minh các chứng minh mật mã.
Giả sử ta có một function để tính biểu thức , đoạn code tương đương có thể là:
function evaluate(x,y) {
return x**3 + y + 5;
}
Biểu thức kiểm chứng sẽ có dạng: . Biểu thức này sẽ được phân tích thành một hệ các biểu thức ràng buộc đơn giản có dạng tích của 2 thừa số có hạng (rank) không quá 1.
Đó cũng chính là lý do tại sao nó có tên Rank-1 Constraint System. Quay lại với biểu thức trên sẽ được chia nhỏ và biểu diễn thành các biểu thức ràng buộc:
Biểu thức ràng buộc (constraint) 1:
Biểu thức ràng buộc 2:
Biểu thức ràng buộc 3:
Và ràng buộc cuối cùng:
Witness là một bộ giá trị (tuple) có dạng vector chứa tất cả các giá trị của biến, hằng số, output, … thỏa mãn tất cả các constraint được sinh ra từ biểu thức ban đầu. Với ví dụ trên, witness vector có dạng là một bộ các giá trị . Ví dụ: có một trong các witness vector như sau:
Nếu thay các giá trị của witness vector trên vào các ràng buộc ta thấy toàn bộ các contraint đều thỏa mãn:
Constraint 1:
Constraint 2:
Constraint 3:
Constraint 4:
Dạng cơ sở của các constraint là , và chúng ta có constraint, cùng với một witness vector có thành phần, chúng ta sẽ cố gắng đưa về dạng ma trận như sau:
Với là các ma trận kích thước (có dòng, cột):
là ma trận biểu diễn các biến output
là ma trận biểu diễn các biến vế trái
là ma trận biểu diễn các biến vế phải
Hãy xem một ví dụ: , witness vector . Với trường hợp này, chỉ có 1 constraint, do đó, các ma trận chỉ có 1 dòng. Các ma trận này sẽ có dạng như sau:
Trường hợp constraint là phép nhân hai biến
Để ý rằng ta có thứ tự cách biến tuần tự là . Ở đây, mỗi phần tử của ma trận thể hiện sự hiện diện của một biến ở vị trí tương ứng trong constraint ấy. Đối với constraint thì ta có:
đại diện cho sự hiện diện của biến ở vị trí cột 4
đại diện cho sự hiện diện của biến ở vị trí cột 2
đại diện cho sự hiện diện của biến ở vị trí cột 3
💡 Để ý rằng cột thứ nhất (constant) luôn được set giá trị bằng 1, và sẽ được dùng trong các trường hợp với contraints phức tạp hơn.
Trường hợp constraint chứa constant hoặc
Lúc này, cột thứ nhất sẽ được set bằng giá trị constant.
Ví dụ 1: với , thì
Ví dụ 2: với , thì
Trường hợp constraint là phép cộng
Lúc này, ta sẽ chuyển về dạng
Lúc đó, với thì
Trường hợp rút gọn
Thực ra, các trường hợp đã nếu trên là các trường hợp constraint đơn giản. Trong thực tế, một constraint miễn là thỏa tiêu chí:
Có dạng
Tất cả các thành phần đều có bậc của biến không quá 1
Ví dụ:
hoặc đều là các constraint rank 1.
không phải constraint rank 1
Giả sử có biểu thức dạng và witness vector thì ta chuyển đổi thành dạng và áp dụng tương tự phương pháp như trên để có:
Ma trận
Ma trận
Ma trận
Quay lại ví dụ ban đầu với các constraint
Và với witness vector tương ứng, các ma trận sẽ có nhiều dòng, mỗi dòng biểu diễn cho một constraint tương ứng:
Đây là một demo đơn giản để mô tả việc chuyển một biểu thức thành dạng R1CS:
Các constraints sinh ra có thể là chưa tối ưu
Chỉ cho phép các phép tính: lũy thừa (^), phép nhân (*), phép cộng (+). Các phép tính trừ và chia sẽ được hiểu là phép nhân và phép cộng với nghịch đảo trên trường hữu hạn
No comments yet. Be the first to comment!