Theo dõi các quỹ xấu thông qua các nhóm được bảo vệ
Tôi muốn giải thích một ý tưởng điên rồ về việc theo dõi các quỹ xấu thông qua một nhóm được bảo vệ, trong khi vẫn giữ được tính riêng tư tối đa.
Dòng ghi chú
Tiến sĩ Evil đã đánh cắp một trăm tỷ đô la và đưa vào một giao thức bảo mật.
Bằng cách nào đó, vụ trộm và khoản tiền gửi đã không bị phát hiện trong một thời gian, và thời hạn trì hoãn gửi tiền đã qua. Tiền đã nằm trong hệ thống. Các giao dịch chuyển tiền riêng tư diễn ra. Không ai phân biệt được tiền tốt và tiền xấu. Thời buổi khó khăn.
Cuối cùng, có người phát hiện ra vụ trộm và báo động.
Làm thế nào để người dùng xác định các khoản tiền bị nhiễm bẩn trong số dư của họ? Làm thế nào để chúng ta tối đa hóa quyền riêng tư? Làm thế nào chúng ta có thể xác định các khoản rút tiền bị nhiễm bẩn (và chúng ta có nên làm như vậy không)?
Mục tiêu tiêu đề: Cho phép chủ sở hữu tờ tiền xác định được bao nhiêu tờ tiền của họ có nguồn gốc từ các khoản tiền gửi “xấu” mà không tiết lộ bất kỳ thông tin nào khác cho bất kỳ ai .
Siêu cấp độ cao
Người dùng có một ghi chú. Ghi chú chứa thông tin được mã hóa mà họ không thể giải mã, về các khoản tiền gửi đã đóng góp vào ghi chú của họ.
notes[i][j] = {owner,amount,randomness,deposits: [{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},...],}Mọi thứ đều đẹp và riêng tư.
Nếu sau một thời gian, khoản tiền gửi bị đưa vào danh sách đen và nếu ghi chú này là hậu duệ của khoản tiền gửi "xấu" đó, thì người dùng sẽ đột nhiên biết được thông tin này:
notes[i][j] = {owner,amount,randomness,deposits: [{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},{The bad deposit_id,Some fraction to deduce how much of that 'bad' depositis contained within this note,},{ < unintelligible ciphertext > , < unintelligible ciphertext > ,},...],}Sau đó, người dùng có thể thực hiện "mạch khử nhiễm" có tên rất ấn tượng để tạo một ghi chú mới không chứa deposit_id xấu này.
Những lưu ý
Chưa có ai đọc bài này cả.
Tôi không thực sự ủng hộ cách tiếp cận này, nhưng đây là một thiết kế thú vị nhằm giải quyết một vấn đề mà tôi chưa từng thấy trước đây.
Tôi có thể nghĩ ra một số lời chỉ trích mạnh mẽ, được nêu xuyên suốt tài liệu này (và được tóm tắt ở phần cuối).
Nó có thể chỉ là tài liệu tham khảo cho thế hệ sau.
Hy vọng đây là một bài đọc thú vị 
Giới thiệu
Nếu bạn muốn có phần giới thiệu thực sự hùng hồn về chủ đề này, hãy đọc phần I và phần II của bài báo Privacy Pools .
Đây là tóm tắt của tôi:
Một số người muốn đảm bảo quyền riêng tư khi giao dịch trên blockchain, vì vậy các nhóm đang tìm cách cho phép giao dịch blockchain riêng tư . Một mô hình phổ biến như sau:
Người dùng có thể gửi token của mình vào cái gọi là "Nhóm Token Được Che Chắn". Sau một thời gian, họ có thể rút token của mình về một địa chỉ khác. Mục đích của các giao thức này là phá vỡ liên kết có thể quan sát được giữa địa chỉ gửi và địa chỉ rút.
Một số giao thức cũng cho phép chuyển giao riêng tư các token đã được gửi vào nhóm, nhờ đó người quan sát sẽ không thể suy ra ai đã gửi gì cho ai. Chính những giao thức nạp-chuyển-rút này là điều tôi thấy thú vị nhất.
Vấn đề với tất cả các nhóm này là kẻ xấu cũng có thể lợi dụng chúng, và thực tế đã có những trường hợp kẻ xấu gửi tiền bất chính vào các nhóm này. Một khi đã gửi, việc theo dõi các khoản tiền gửi bất chính trở nên khó khăn hơn, và việc phân biệt các khoản rút tiền hợp lệ với các khoản rút tiền bất hợp pháp cũng trở nên khó khăn hơn.
Và vì thế, nhiều dự án khác nhau đã tìm cách giải quyết vấn đề này.
Các cách tiếp cận bao gồm:
- Xác định khoản tiền gửi xấu trước khi chúng được đưa vào nhóm bằng cách trì hoãn việc gửi tiền.
- Giới hạn số tiền có thể gửi vào quỹ trong một khoảng thời gian nhất định.
- Chỉ cho phép gửi tiền từ những người có uy tín.
- Cho phép người dùng cung cấp bằng chứng không liên quan đến tác nhân xấu hoặc bằng chứng chỉ liên quan đến tác nhân tốt.
- Mã hóa thông tin chi tiết của mọi giao dịch cho bên thứ 3 (chẳng hạn như cơ quan quản lý, kiểm toán viên hoặc kế toán) hoặc chia sẻ khóa xem với bên thứ 3.
- Nới lỏng một số đảm bảo về quyền riêng tư để cho phép truy xuất nguồn gốc ở một mức độ nào đó của tất cả các khoản tiền thông qua nhóm.
Tất cả những cách tiếp cận này đều có những đánh đổi thú vị mà chúng tôi sẽ đề cập dưới đây.
Ý tưởng mà tôi đang cân nhắc như sau:
Khi người dùng được gửi một ghi chú, ghi chú đó sẽ chứa danh sách các mã hóa được ngẫu nhiên hóa lại của tất cả các deposit_ids ngược dòng đã đóng góp bất kỳ giá trị nào cho ghi chú đó, cùng với các mã hóa về giá trị mà mỗi khoản tiền gửi đó đóng góp cho ghi chú.
Trong những trường hợp lý tưởng, ghi chú của người dùng sẽ không phải là hậu duệ của bất kỳ khoản tiền gửi "xấu" nào và trong những trường hợp như vậy, họ sẽ có quyền riêng tư tương đương với zcash: người dùng sẽ không thể biết khoản tiền gửi nào đã đóng góp vào ghi chú của họ.
Tuy nhiên, nếu một khoản tiền gửi được công khai coi là "xấu", thì thiết kế này cho phép tất cả chủ sở hữu trái phiếu hạ nguồn biết được lượng tiền gửi xấu đó đã chảy vào trái phiếu của họ. Quan trọng là, không có thông tin nào khác bị rò rỉ cho chủ sở hữu trái phiếu ngoài trường hợp "X số tiền trong trái phiếu của tôi được coi là có nguồn gốc từ khoản tiền gửi xấu này_id". Người quan sát của nhóm sẽ không biết được bất kỳ thông tin nào.
Lý tưởng nhất là một khoản tiền gửi xấu sẽ được xác định và gắn cờ là "xấu" trước khi nó có thể vào hệ thống, ví dụ như thông qua một khoảng thời gian trì hoãn. Bằng cách này, nó sẽ không có cơ hội "làm hỏng" tiền của người dùng trung thực. Nhưng nếu khoảng thời gian trì hoãn không đủ dài thì sao? Hoặc nếu quá trình thẩm định bỏ sót điều gì đó thì sao? Tôi nghĩ sẽ rất thú vị nếu tìm hiểu cách xác định các khoản tiền xấu có thể lọt qua được lưới trì hoãn tiền gửi như vậy mà không làm rò rỉ biểu đồ giao dịch của người dùng.
Chỉnh sửa sau khi viết: Railgun thực sự đã gặp phải vấn đề này gần đây: https://x.com/dethective/status/1994397800847589736?s=20
Chúng ta sẽ gặp phải một số vấn đề về khả năng mở rộng trong quá trình này và tìm cách giảm thiểu những vấn đề đó.
Lý lịch
Sau đây là lời nhắc nhở nhanh về các giao thức bảo mật dựa trên utxo, nếu chỉ để thống nhất về thuật ngữ.
Bạn có thể bỏ qua phần tiếp theo “Tài liệu trước đó” nếu muốn.
Tiền gửi
Về mặt khái niệm, khoản tiền gửi trông giống như thế này:
Người dùng gửi một số token công khai vào hệ thống, và một tờ ghi chú chứa số tiền đã gửi và chủ sở hữu (một địa chỉ hoặc một khóa công khai nào đó) sẽ được tạo. Tờ ghi chú này đóng vai trò đại diện cho quyền sở hữu của người dùng đối với các token cơ sở, được hệ thống nắm giữ trong một nhóm cho đến khi chủ sở hữu cuối cùng quyết định rút hoặc chuyển một phần số dư.
Nếu bạn muốn biết thêm chi tiết, đây là sơ đồ minh họa chi tiết hơn về quy trình gửi tiền. Các cách triển khai khác nhau có nhiều điểm khác biệt, nhưng điểm mấu chốt là ở đây.
Chuyển khoản
Về mặt khái niệm, một chuyển nhượng trông giống như thế này:
Người gửi sử dụng (hoặc "hủy") hai ghi chú của mình, tạo một ghi chú cho người nhận chuyển khoản và tạo một ghi chú thay đổi cho chính mình. Hai ghi chú bị hủy, hai ghi chú hủy được phát ra, và hai ghi chú mới được tạo và phát ra.
Liệu tôi có đủ can đảm để không giải thích từ "nullifier" là gì không? Tôi nghĩ là có đấy!
À, thực ra, tôi cần phải nói những điều sau về các từ khóa vô hiệu vì chúng sẽ giúp tôi chỉ trích cách tiếp cận ở phần tiếp theo:
Nullifier được sử dụng trong các giao thức thanh toán riêng tư để phá vỡ liên kết giữa giao dịch đã tạo ra ghi chú và giao dịch sau đó chi tiêu ghi chú đó. Nếu không có thuộc tính "không liên kết giao dịch" mà nullifier cung cấp, toàn bộ biểu đồ giao dịch sẽ hiển thị cho người quan sát và người dùng có thể thu thập thông tin không nên bị rò rỉ.
Trong phần còn lại của tài liệu này, tôi sẽ bỏ qua các ký tự hủy trong sơ đồ, vì chúng chỉ gây rối mắt. Nếu bạn thấy một nốt nhạc được đưa vào mạch, hãy coi như nó đang bị hủy.
Ngoài ra, tôi sẽ bỏ qua ghi chú thay đổi trong sơ đồ để giảm bớt sự lộn xộn:
Đã loại bỏ: không hiển thị bất kỳ ký tự vô hiệu nào; không hiển thị ghi chú thay đổi nào.
Rút tiền
Về mặt khái niệm, việc rút tiền trông giống như thế này:
Người dùng đốt một tờ tiền có giá trị nào đó và hệ thống – nơi lưu giữ tất cả các khoản tiền gửi công khai trong khi người dùng giao dịch riêng tư trong hệ thống – sẽ chuyển giá trị đó đến địa chỉ do người dùng chỉ định.
Nghệ thuật trước đây
Theo truyền thống trong các bài báo, trước khi đi sâu vào chi tiết của ý tưởng mới, chúng ta phải phê phán gay gắt tất cả các ý tưởng hiện có để chứng minh sự tồn tại của tài liệu này.
Tuy nhiên, tôi sẽ nhẹ nhàng thôi, bởi vì:
- Những ý tưởng hiện có thực sự khá tốt và đã được chuyển thành sản phẩm thực tế với PMF thực sự. Thật tuyệt vời.
- Bạn không bao giờ biết khi nào bạn có thể làm việc với ai đó trong tương lai;
- Ý tưởng của tôi có thể có lỗi;
- Ngay cả khi ý tưởng này không có lỗi, tôi vẫn có thể nghĩ ra một số lời chỉ trích gay gắt mà tôi sẽ chia sẻ khi chúng ta thực hiện, và có thể bạn đã nghĩ đến rồi.
Ở lại với tôi.
Tất cả các sản phẩm đều yêu cầu một số hình thức token riêng tư tuân thủ. Một số là các chương trình nạp-rút đơn giản, và một số là các chương trình nạp-chuyển-rút. Về cơ bản, tất cả đều tuân theo phương pháp được nêu trong phần "Bối cảnh", nhưng có các phương pháp khác nhau để đối phó với các tác nhân xấu.
Payy
Khi bạn nói tên sản phẩm này bằng lời, bạn phải nói "Pay with two y's" (Trả bằng hai chữ "y"), nếu không bạn sẽ bị nhìn chằm chằm. Hoặc bạn phải nói "Payyyyyyy" và nhấn mạnh cách phát âm.
Payy là một giao thức gửi-chuyển-rút tiền.
Payy áp dụng cách tiếp cận rất thực tế và đơn giản để đối phó với những tác nhân xấu: họ loại bỏ các trình vô hiệu hóa khỏi giao thức của mình:
Quay trở lại những điều cơ bản của giao thức được bảo vệ, bộ hủy cung cấp "khả năng hủy liên kết giao dịch". Nếu không có bộ hủy, các ghi chú đầu vào của một giao dịch chuyển tiền sẽ được hiển thị công khai. Tức là ghi chú đầu ra của mỗi giao dịch sau đó có thể được xem là ghi chú đầu vào của một giao dịch khác. Điều này có nghĩa là trên Payy, toàn bộ biểu đồ giao dịch đều có thể quan sát được.
Nếu một khoản tiền gửi xấu được chuyển vào hệ thống, bạn có thể theo dõi chính xác dòng tiền đó chảy vào đâu và xem khoản tiền nào được rút khỏi hệ thống là hậu quả của khoản tiền đó. Người nhận giấy nợ có thể ngay lập tức xác định rằng giấy nợ đó là hậu quả của một khoản tiền gửi xấu, mặc dù họ sẽ không biết khoản tiền gửi đó đã đóng góp bao nhiêu vào giấy nợ của mình.
Vậy là Payy đã hy sinh một phần quyền riêng tư để có thể truy vết những kẻ xấu. Hãy cùng xem xét mức độ hy sinh quyền riêng tư.
Sau đây là những lỗ hổng bảo mật mà thiết kế của Payy gây ra:
Khoản chuyển tiền đầu tiên sau khi gửi tiền sẽ được công khai xác định là từ người gửi tiền. Tức là thông tin người gửi sẽ bị tiết lộ.
Giao dịch chuyển tiền cuối cùng trước khi rút tiền sẽ được công khai xác định là của người rút tiền. Tức là thông tin người nhận sẽ bị tiết lộ.
Nếu A gửi tiền, sau đó A → B (đọc là: “A chuyển cho B”), sau đó B rút tiền, thế giới sẽ thấy rằng A đã giao dịch với B. Thế giới thậm chí có thể biết được số tiền chính xác mà A đã gửi cho B nếu không có giao dịch nào khác trong biểu đồ con đó.
Nếu E → B → C → E, thì E biết được B và C đã giao dịch. E biết được B biết C. Đó là một sự rò rỉ lớn ngoài dự kiến. Chuyện tình cảm có lẽ đã bị bại lộ với lượng rò rỉ lớn như vậy.
Nếu E là một thực thể lớn như một sàn giao dịch, họ có thể suy ra một lượng đáng kể biểu đồ giao dịch từ loại rò rỉ này. Họ có thể ghép nối những thông tin không rõ ràng với nhau, và có khả năng suy ra số tiền được thanh toán giữa những người tham gia.
Đó là những lỗ hổng tôi thấy sau 5 phút suy nghĩ. Một nhóm chuyên gia cao cấp nào đó có thể suy ra nhiều hơn.
Súng điện từ
Railgun là giao thức nạp-chuyển-rút. Rất tuyệt vời.
Tất cả các khoản tiền gửi vào hệ thống sẽ bị chậm trễ một giờ để các khoản tiền gửi "xấu" có thể bị từ chối.
Khi đã vào hệ thống, tiền có thể được chuyển riêng tư giữa những người dùng.
Vấn đề - và cũng là vấn đề chính khiến tôi tìm hiểu và viết toàn bộ bài viết này - là một giờ không phải là khoảng thời gian quá dài, và về mặt kỹ thuật, kẻ xấu hoàn toàn có thể "lọt lưới" và gửi tiền "xấu" vào "hồ". Một khi đã vào "hồ", sẽ không có cách nào để bắt chúng.
Chỉnh sửa sau khi viết xong: Chuyện đó đã xảy ra!!!
https://x.com/dethective/status/1994397800847589736?s=20
Giá mà tôi hoàn thành bộ phim tài liệu này trước khi nó xảy ra. Tôi đã được coi là người có tầm nhìn xa.
Dù sao đi nữa, tôi đặt ra mục tiêu giải quyết vấn đề truy vết các khoản tiền "xấu" thông qua một nhóm cho phép chuyển khoản riêng tư , ngay cả khi chúng tôi không biết số tiền đó là "xấu" khi chúng được đưa vào nhóm, đồng thời vẫn đảm bảo quyền riêng tư tối đa cho tất cả người dùng. Tôi sẽ nghiêm ngặt hơn về các yêu cầu sau khi đề cập đến một vài dự án khác.
EYBlockchain
Trở lại năm 2019, tôi tham gia một nhóm nghiên cứu nhỏ để khám phá vấn đề này: Làm thế nào để thiết kế một nhóm riêng tư nơi có thể theo dõi các khoản tiền gửi xấu – đồng thời vẫn đảm bảo tính riêng tư tốt.
Tôi nhớ có một thời gian chúng tôi đã đi vào ngõ cụt hiển nhiên – và ngày nay đã quá quen thuộc – là gán một deposit_id cho mỗi tờ tiền mới gửi. Sau đó, với mỗi lần chuyển khoản, tờ tiền đầu ra sẽ chứa hợp của tất cả các deposit_id của tất cả các tờ tiền đầu vào. Điều này dẫn đến một danh sách tăng theo cấp số nhân, và kích thước của nó tăng gấp đôi sau mỗi lần chuyển khoản. Đây không phải là một cách tiếp cận bền vững. Tôi không nghĩ chúng tôi đã xuất bản bất cứ thứ gì.
Thực ra, tôi đã có một số buổi nói chuyện công khai vào năm 2019, giúp giải quyết vấn đề dễ dàng hơn là truy tìm NFT bị đánh cắp thông qua một nhóm NFT được bảo vệ. Tính không thể thay thế của việc chuyển nhượng NFT đồng nghĩa với việc bạn sẽ không gặp phải vấn đề danh sách tăng theo cấp số nhân.
Nhóm nhỏ đó đã có rất nhiều nghiên cứu đi trước thời đại, nhưng chúng tôi đã không công bố những ý tưởng chưa hoàn thiện, thật đáng tiếc khi nhìn lại.
Tuy nhiên… hãy xem phần sau của tài liệu này, nơi chúng tôi cố gắng giải quyết vấn đề đó bằng cách thỉnh thoảng khởi động lại danh sách đó.
Một lời chỉ trích phổ biến đối với bất kỳ phương pháp nào theo dõi deposit_ids là các ghi chú không còn có thể thay thế được: deposit_ids đóng vai trò là điểm đánh dấu trên các ghi chú. Mọi người sẽ có thể thấy các mẫu trong các ghi chú họ gửi và nhận.
Một ví dụ rò rỉ thông thường là Eve->Bob->Eve, hoặc Eve->Bob->Charlie->Eve. Hoặc thậm chí Eve->…->Eve. Eve sẽ có thể phát hiện ra deposit_id chung trong các ghi chú cô ấy đã gửi và các ghi chú cô ấy đã nhận, và cô ấy có thể suy ra thông tin từ đó. Ví dụ, trong trường hợp E->B->C->E, Eve có thể suy ra rằng Bob biết Charlie, và Bob đã gửi tiền cho Charlie.
Tài liệu này cố gắng giải quyết vấn đề này - trong đó deposit_ids đóng vai trò đánh dấu - bằng cách ngẫu nhiên hóa danh sách deposit_ids với mỗi lần chuyển khoản. Bằng cách này, Eve sẽ không thể xác định được bất kỳ điểm chung nào giữa các ghi chú cô ấy đã gửi và các ghi chú cô ấy nhận được sau đó.
Hồ bơi riêng tư
Sản phẩm Privacy Pools là giao thức gửi-rút tiền.
Lời chỉ trích đầu tiên của tôi là “Nó không hỗ trợ chuyển khoản”, nhưng bài báo Privacy Pools có đề cập đến một phương pháp cho phép chuyển khoản riêng tư.
Chỉnh sửa sau khi trao đổi với họ tại devconnect: Phiên bản 2 của Privacy Pools dường như sẽ cho phép chuyển dữ liệu riêng tư, nhưng nó khác với cách tiếp cận được giải thích trong bài báo về Privacy Pools. Dưới đây là những gì tôi hiểu về những gì họ đang xây dựng cho phiên bản 2:
Với mỗi khoản tiền gửi, ghi chú kết quả sẽ chứa một deposit_id. Việc chuyển khoản có thể diễn ra trong hệ thống, nhưng tất cả các ghi chú đầu vào phải có cùng một deposit_id , và tất cả các ghi chú đầu ra đều được cấp cùng một deposit_id đó.
Đây chắc chắn là một cách hay để tránh vấn đề "danh sách tăng theo cấp số nhân": một ghi chú sẽ luôn chứa 1 deposit_id.
Một vấn đề với cách tiếp cận này có thể như sau. Nếu người dùng cần gửi 100 ETH, họ sẽ cần hai tờ tiền có cùng deposit_id với tổng giá trị >= 100. Nhưng nếu họ không có hai tờ tiền có cùng deposit_id thì sao? Họ sẽ cần gửi nhiều giao dịch; mỗi giao dịch cho mỗi deposit_id riêng biệt của các tờ tiền mà họ định chi tiêu.
Tôi ngờ rằng với hoạt động gửi tiền đủ lớn, người dùng sẽ hiếm khi nhận được các ghi chú có cùng deposit_id. Nếu điều đó đúng, người dùng sẽ hiếm khi kết hợp hai ghi chú lại với nhau (vì chúng phải có cùng deposit_id). Và tôi ngờ rằng điều này có thể dẫn đến một hệ thống có xu hướng "bụi"; trong đó các ghi chú chứa các giá trị nhỏ và không thực tế, vì thao tác "chia tách" sẽ vượt xa thao tác "nối".
Có lẽ người dùng có thể tương tác: người nhận tiềm năng có thể yêu cầu người gửi ghi chú chứa một số deposit_id nhất định; giống như trò chơi bài Go Fish: “Bạn có deposit_id nào = 1234 không?”.
Đề xuất trong bài đăng này nhằm mục đích cho phép deposit_ids có thể được trộn lẫn với nhau.
Một điểm đáng phê bình khác đối với phương pháp v2 này – như đã đề cập trong tiểu mục trước – là deposit_ids đóng vai trò là các dấu hiệu làm hỏng tính thay thế. Tài liệu này tìm cách giải quyết vấn đề này bằng cách ngẫu nhiên hóa lại deposit_ids với mỗi lần chuyển giao.
Lời chỉ trích thứ hai (yếu hơn) của tôi về các nhóm riêng tư là có một khoảng thời gian trễ nhất định trước khi khoản tiền gửi được chấp nhận vào nhóm. Có lẽ điều đó cũng ổn, nhưng vì tôi muốn tìm hiểu điều gì sẽ xảy ra nếu tiền xấu được đưa vào nhóm, tôi không muốn câu trả lời là "cứ chờ thêm một thời gian nữa rồi mới thực hiện thẩm định". Tôi cho rằng có thể quy trình thẩm định có thể mắc sai sót, và chúng tôi muốn có thể đánh dấu các khoản tiền gửi xấu là xấu một cách hồi tố ngay cả khi chúng vô tình được đưa vào.
Cách tiếp cận được mô tả trong tài liệu về nhóm riêng tư như sau:
Một lời chỉ trích có thể là việc rò rỉ thông tin quá nhiều; thông tin mà các nhóm bảo vệ thông thường muốn giữ kín. Rất nhiều dữ liệu riêng tư đang được chia sẻ giữa người dùng tại đây, cho đến khi các khoản tiền gửi cuối cùng được đưa vào danh sách trắng.
Blanksquare
Có lẽ bạn sẽ không tin tôi, nhưng tôi bắt đầu viết ý tưởng cho bài đăng này vào tháng 9/tháng 10. Tôi hơi bận rộn với những việc khác, như công việc hàng ngày, kỳ nghỉ gia đình vui vẻ, và devconnect.
Sau đó, khi tôi là +1 tại một đám cưới vào thứ bảy (cuối tháng 11), tôi nhận được liên kết này trong một nhóm Signal:
Nó gợi ý mã hóa deposit_ids – một ý tưởng cũng được đề cập trong tài liệu này. Thật tuyệt vời!
Dù sao thì, tôi không sao chép đâu; chúng là những hiện thực hóa độc lập của cùng một thứ. Tôi có đóng dấu thời gian trên biên lai đấy!
Tài liệu này sẽ mở rộng ý tưởng đó hơn nữa, vì vậy tôi hy vọng bạn sẽ thấy nó thú vị. Nó cũng nêu ra một số lời chỉ trích về ý tưởng đó, mà chúng ta sẽ đề cập đến ngay bây giờ.
Tóm lại, ý tưởng là một thực thể nào đó tạo ra một cặp khóa mới cho mỗi khoản tiền gửi vào hệ thống. Mỗi deposit_id sau đó có thể được mã hóa bằng khóa công khai tương ứng. Bất kỳ khoản rút tiền tương ứng nào sau đó khỏi hệ thống sẽ buộc phải gửi tín hiệu deposit_id đã mã hóa tương tự (sẽ được thêm muối để tín hiệu rút tiền trông không liên quan đến khoản tiền gửi). Theo cách tốt nhất, người quan sát sẽ không bao giờ biết được rằng khoản tiền rút liên quan đến khoản tiền gửi. Nhưng nếu khoản tiền gửi sau đó bị coi là "xấu", khóa bí mật có thể được tiết lộ bởi người nắm giữ khóa giải mã, điều này sẽ cho phép tất cả người quan sát giải mã deposit_id đã mã hóa của cả giao dịch gửi và rút tiền, và cuối cùng liên kết giao dịch rút tiền với khoản tiền gửi.
Các vấn đề với cách tiếp cận này:
Người nắm giữ khóa giải mã là một điểm yếu của hệ thống. Nếu khóa bị rò rỉ (cố ý hoặc vô tình), người dùng sẽ có thể liên kết tất cả các giao dịch gửi và rút tiền của tất cả người dùng. Có những đề xuất sử dụng TEE hoặc chia sẻ bí mật khóa giải mã thông qua một tập hợp các nút MPC. Chắc chắn, việc chia sẻ bí mật khóa giải mã (và các bí mật khác) là một phương pháp phổ biến mà bạn sẽ thấy trong các thiết lập FHE và CoSnark, vì vậy một số người có thể coi đây là điều chấp nhận được.
Vitalik chắc chắn không thích khái niệm “quyền riêng tư bị xâm phạm”:
Phương pháp tôi đề xuất trong bài đăng này vẫn có một nhóm MPC gây tranh cãi tạo ra các khóa, nhưng tôi cố gắng ngăn chặn tối đa tình huống rò rỉ tồi tệ nhất trong trường hợp tất cả các khóa giải mã bị rò rỉ.
Với phương pháp Blanksquare:
- Trong trường hợp xấu nhất, điều gì sẽ bị rò rỉ?
- Mọi giao dịch rút tiền đều có thể liên kết với mọi giao dịch gửi tiền.
- Thông tin này bị rò rỉ cho ai?
- Mọi người trên thế giới (mọi người quan sát blockchain).
Với cách tiếp cận trong tài liệu này:
- Trong trường hợp xấu nhất, điều gì sẽ bị rò rỉ?
- deposit_ids đóng góp vào ghi chú của một người dùng nhất định.
- Số tiền của mỗi deposit_id “góp phần” vào ghi chú.
- Thông tin này bị rò rỉ cho ai?
- Chỉ dành cho chủ sở hữu của tờ giấy.
Sự rò rỉ chỉ xảy ra cục bộ.
Không tệ phải không?
Ít nhất thì chúng ta không xâm phạm quyền riêng tư đến mức khiến Vitalik buồn (tôi hy vọng vậy).
Trong trường hợp xấu nhất, giao thức trong tài liệu này sẽ sụp đổ thành phương pháp mà chủ sở hữu ghi chú có thể xem deposit_ids đã đóng góp vào ghi chú của họ. Phương pháp này không lý tưởng (xem các phần trước đã phàn nàn về việc deposit_ids đóng vai trò là "dấu hiệu" không thể thay thế trên ghi chú), nhưng nó mang lại cảm giác như một tiến bộ đáng để mô tả cho tất cả các bạn.
Trong trường hợp may mắn, quyền riêng tư thực sự khá tốt.
Ý tưởng
Cuối cùng chúng ta có thể thảo luận về ý tưởng này.
Yêu cầu
Nó đang tìm kiếm những tính năng gì:
- Hồ bơi có mái che hỗ trợ việc di chuyển riêng tư.
- Trên con đường may mắn, deposit_ids (trong ghi chú) được sắp xếp ngẫu nhiên để ngăn những người sở hữu ghi chú nâng cao sử dụng chúng làm "dấu hiệu" để phát hiện các mô hình trong hoạt động.
- Nếu một khoản tiền gửi xấu vô tình được đưa vào nhóm, sau đó có thể đánh dấu là 'xấu' và tất cả người dùng trong nhóm có thể xác định: liệu tờ tiền của họ có chứa bất kỳ giá trị 'xấu' nào không và bao nhiêu phần giá trị tờ tiền của họ được coi là 'xấu'.
- Ngay cả trong trường hợp xấu nhất (rò rỉ khóa giải mã của giao thức này), người quan sát blockchain cũng không biết được ghi chú nào chứa giá trị 'xấu'.
- Tránh việc xâm phạm quyền riêng tư có hiệu lực hồi tố đối với các lần rút tiền trong quá khứ: Hệ thống này có thể được thiết kế để không làm rò rỉ thông tin về các lần rút tiền đã diễn ra, ngay cả trong trường hợp xấu nhất là khóa giải mã của hệ thống bị rò rỉ.
- Khi thực hiện giao dịch chuyển tiền hoặc rút tiền, người dùng có thể chứng minh rằng các ghi chú đầu vào của họ không phải là tiền gửi 'xấu'.
- Nếu tờ tiền của người dùng có nguồn gốc từ một khoản tiền gửi xấu, người dùng có thể 'khử nhiễm' tờ tiền của mình bằng cách chia nó thành các tờ tiền 'tốt' và 'xấu'.
- Tôi không đưa ra bất kỳ lời hứa nào liên quan đến số lượng ràng buộc

Cấp độ cao
Phần cấp thấp là tiếp theo
Cơ sở là một giao thức gửi-chuyển-rút đơn giản.
Một số Người duy trì danh sách đen sẽ quản lý danh sách đen các deposit_id xấu.
Có thể có một khoảng thời gian trì hoãn trước khi các chất lắng đọng có thể đi vào bộ lọc, nhưng chúng tôi quan tâm đến máy móc để thu thập các chất lắng đọng lọt qua khoảng thời gian trì hoãn như vậy.
Trong bước tiền xử lý lớn, một danh sách dài các cặp khóa deposit_id được tạo ra: một cặp cho mỗi lần gửi tiền trong tương lai vào giao thức.
[(x_1, Y_1), (x_2, Y_2), ..., (x_{1000000}, Y_{1000000})] [ ( x 1 , Y 1 ) , ( x 2 , Y 2 ) , . . . , ( x 1000000 , Y 1000000 ) ]
trong đó x_i x i là khóa bí mật và Y_i Y i là khóa công khai.
Danh sách này có thể được bổ sung định kỳ khi sắp hết.
Danh sách này có thể được tạo ra bởi một tác nhân duy nhất, nhưng có lẽ bạn sẽ không thích điều đó lắm, vì vậy hãy giả sử danh sách được tạo ra bởi một nhóm MPC lớn. Hãy gọi họ là Người Giữ Chìa Khóa. Người Giữ Chìa Khóa có thể là Người Duy Trì Danh Sách Đen, hoặc có thể là những thực thể khác nhau. Chúng ta sẽ sớm quay lại chủ đề đáng lo ngại này.
Khi khoản tiền gửi mới i i được thực hiện, khoản tiền gửi đó sẽ được liên kết công khai với khóa công khai Y_i Y i .
Danh sách được tạo trước cho phép người dùng gửi thông tin không tương tác vào giao thức mà không cần chờ Người giữ khóa tạo và công bố khóa công khai mới.
Chúng tôi sẽ mã hóa thông tin bằng khóa công khai Y_i Y i . Cụ thể, mỗi ghi chú "xuôi dòng" của khoản tiền gửi này sẽ chứa:
- Mã hóa deposit_id i i , được mã hóa thành Y_i Y i ;
- Mã hóa một phần tiền gửi góp vào khoản ghi chú này, được mã hóa thành Y_i Y i .
Chúng tôi sẽ đi sâu vào các chi tiết kỹ thuật ở phần sau.
Vì hệ thống này hỗ trợ chuyển khoản , một tờ tiền có thể là hậu duệ của nhiều khoản tiền gửi. Không sao cả: tờ tiền sẽ chứa danh sách tất cả các khoản tiền gửi ngược dòng. Độc giả tinh ý sẽ nhận thấy rằng danh sách như vậy sẽ tăng theo cấp số nhân và không bền vững - tăng gấp đôi sau mỗi lần chuyển khoản. Chúng ta sẽ quay lại vấn đề này sau.
Trong những trường hợp bình thường, chủ sở hữu của một tờ tiền hạ nguồn sẽ không thể giải mã thông tin tiền gửi được mã hóa chứa trong tờ tiền của họ, vì không ai (hy vọng là ngay cả tập thể Người giữ Khóa) biết khóa giải mã x_i x i , và do đó họ sẽ không biết khoản tiền gửi nào đã chảy vào tờ tiền của mình. Mục tiêu là để tính riêng tư của hệ thống càng gần với zcash càng tốt, trong đó người quan sát không biết điều gì đang xảy ra bên trong nhóm, biểu đồ giao dịch không được biết, giá trị có thể thay thế được, và chủ sở hữu của các tờ tiền không thể truy tìm nguồn gốc của các tờ tiền của họ.
Nếu khoản tiền gửi i i sau đó bị coi là "xấu", thì Người duy trì Danh sách đen sẽ đánh dấu khoản tiền gửi i i trên chuỗi. Khi thấy i i bị đưa vào danh sách đen, Người giữ Khóa có nhiệm vụ tiết lộ khóa bí mật tương ứng x_i x i trên chuỗi. Nếu Người giữ Khóa là một tập thể MPC, họ sẽ cần phải làm việc cùng nhau để tìm hiểu x_i x i thực sự là gì, ví dụ thông qua một số sơ đồ ngưỡng.
Việc công bố i i và x_i x i này sẽ kích hoạt một loạt hoạt động: Tất cả chủ sở hữu ghi chú trong toàn bộ hệ thống có thể thử giải mã tất cả các deposit_id đã mã hóa có trong ghi chú của họ. Nếu ghi chú của họ là con cháu của deposit i i , thì họ sẽ giải mã thành công một trong các trường deposit_id đã mã hóa của ghi chú để tạo ra i i .
Giả sử tờ tiền của họ có chứa số tiền "xấu" từ khoản tiền gửi i i . Ôi trời. Để biết số tiền đó là bao nhiêu, x_i x i được tiết lộ cũng có thể được sử dụng để giải mã "phần mã hóa" tương ứng tồn tại trong tờ tiền của họ. Điều này sẽ tiết lộ phần nào của khoản tiền gửi ban đầu được coi là có trong tờ tiền của họ.
Một “mạch khử nhiễm” mới có tên gọi ấn tượng sẽ cho phép người dùng “rút” tiền xấu ra khỏi tờ tiền của họ.
Điều quan trọng cần lưu ý là chủ sở hữu ghi chú sẽ không thể giải mã bất kỳ trường deposit_id nào khác đã được mã hóa trong ghi chú của họ. Tất cả những gì sẽ bị rò rỉ cho chủ sở hữu ghi chú là:
“Tờ tiền của tôi là 'xuôi dòng' của khoản tiền gửi i i ; giao thức coi tờ tiền của tôi chứa số tiền X từ khoản tiền gửi xấu đó”.
Hoặc nói ngắn gọn hơn:
“Số tiền X trong tờ giấy nợ của tôi được coi là có nguồn gốc từ khoản tiền gửi xấu i i ”.
Người sở hữu ghi chú sẽ không biết bất kỳ thông tin nào khác về nguồn gốc ghi chú của họ, bao gồm cả việc giá trị đã được truyền qua ai trước khi đến tay họ.
Người quan sát bên ngoài sẽ không biết được nốt nhạc nào bị nhiễm bẩn và sẽ không biết được thông tin có ý nghĩa về biểu đồ giao dịch.
Đến lúc này, có lẽ bạn đang có một vài lời chỉ trích gay gắt trong đầu. Hãy cùng liệt kê một số nhé:
- Nếu những Người giữ chìa khóa thông đồng với nhau, họ có thể biết được x_i x i .
- Người duy trì danh sách đen có thể trở nên độc ác và kiểm duyệt mọi người bằng cách thêm họ vào danh sách đen.
- Người giữ chìa khóa có thể không thực hiện nhiệm vụ tiết lộ x_i x i khi i i đã bị đưa vào danh sách đen.
- Có vẻ không công bằng khi một người dùng trung thực nhận được một ghi chú mà không thể biết khoản tiền gửi nào đã đóng góp vào đó, chỉ để sau đó phát hiện ra (khi bị đưa vào danh sách đen) rằng ghi chú của họ thực sự bị nhiễm một số giá trị "xấu".
- Giao thức này xác định tỷ lệ tiền gửi chảy vào từng tờ tiền như thế nào?
- Nếu bạn theo dõi danh sách tiền gửi, thì danh sách này sẽ tăng gấp đôi sau mỗi giao dịch 'chuyển khoản'. Điều đó không bền vững.
Chúng ta sẽ sớm nói về điều đó thôi.
từng bước một
Cài đặt
Trong bước tiền xử lý lớn, một danh sách dài các cặp khóa deposit_id được tạo ra: một cặp cho mỗi lần gửi tiền trong tương lai vào giao thức.
[(x_1, Y_1), (x_2, Y_2), ..., (x_{1000000}, Y_{1000000})] [ ( x 1 , Y 1 ) , ( x 2 , Y 2 ) , . . . , ( x 1000000 , Y 1000000 ) ]
trong đó x_i x i là khóa bí mật và Y_i Y i là khóa công khai.
Danh sách này có thể được bổ sung định kỳ khi sắp hết.
Trang trọng hơn một chút (nhưng vẫn khá thoải mái về ký hiệu):
G \in \mathbb{G} G ∈ G là điểm sinh.
x_i \in \mathbb{F} x i ∈ F là khóa bí mật cho deposit_id i i , trong trường vô hướng của nhóm \mathbb{G} G .
Y_i := x_i \cdot G Y i : = x i ⋅ G là khóa công khai tương ứng cho deposit_id i i .
Tiền gửi
Người dùng gửi một số tiền nhất định dưới dạng khoản tiền gửi i i . Khoản tiền gửi này được liên kết với khóa công khai Y_i Y i .
Một ghi chú mới được tạo, chứa dữ liệu sau:
notes[i][1] = {owner,amount,randomness,deposits: [{encrypted_deposit_id = "i" ,encrypted_fraction = "1" ,},{},...{}],}Ở đâu:
đôi khi chúng ta sử dụng ký hiệu "x" để ngụ ý một cách lười biếng rằng "mã hóa giá trị x ".
encrypted_deposit_id = "i" = \text{enc}_{Y_i}(i) enc Y i ( i ) , một mã hóa của deposit_id i i , được mã hóa thành khóa công khai Y_i Y i .
Sơ đồ mã hóa này phải hỗ trợ việc ngẫu nhiên hóa lại các bản mã. Elgamal là một lựa chọn tốt (xem Phụ lục).
encrypted_fraction = "1" = \text{enc}_{Y_i}(1) enc Y i ( 1 ) , một mã hóa của phần tiền gửi này đã chảy vào tờ tiền này, ban đầu là mã hóa của 1 1 .
Sơ đồ mã hóa này phải hỗ trợ phép nhân vô hướng của một bản mã với một vô hướng đã biết. Chúng tôi sẽ giải thích lý do ngay sau đây. Mã hóa Paillier là một lựa chọn hay, nhưng lại khá kém hiệu quả trong mạch snark (xem Phụ lục).
Đến giờ vẽ sơ đồ rồi!
enc_dep_id_i_jlà “tiền gửi được mã hóa_id” của khoản tiền gửiisau bước nhảyjth(chuyển khoản) từ khoản tiền gửi.
enc_frac_i_jlà “phần được mã hóa” của giá trị khoản tiền gửiiđã đóng góp vào ghi chú này (sau bước nhảyjth(chuyển khoản) từ khoản tiền gửi).
Người dùng thực sự sẽ không nhìn thấyj; nó chỉ giúp người đọc sơ đồ dễ hiểu hơn.
Mã hóa Paillier không phải là phương pháp bất di bất dịch; rõ ràng có nhiều phương pháp thay thế hiệu quả hơn để nhân một văn bản mã hóa với một số vô hướng đã biết.
Xin nhắc lại, tôi sử dụng dấu ngoặc kép để dễ đọc và không gây nhàm chán:"x"có nghĩa là "mã hóa củax".
Chuyển khoản
Ví dụ
Chuyển khoản riêng sẽ hủy hai ghi chú và tạo một ghi chú cho người nhận và một ghi chú thay đổi cho người gửi. (Chúng tôi sẽ bỏ qua ghi chú thay đổi để ngắn gọn).
Giả sử người gửi tiền ban đầu của chúng ta là 5 ETH muốn gửi 1,5 ETH cho ai đó.
Giả sử – cùng với tờ tiền 5 ETH – họ có một tờ tiền 10 ETH.
Họ có thể hủy hai tờ tiền đó – tổng giá trị là 15 ETH – và tạo ra một tờ tiền mới có giá trị là 1,5 ETH.
Bao nhiêu trong số tiền gửi 5 ETH và bao nhiêu trong số tiền gửi 10 ETH đã nằm trong tờ tiền 1,5 ETH mới?
Thực ra, rất khó để nói chính xác khoản tiền gửi nào đóng góp bao nhiêu vào một khoản tiền lãi, xét đến tính lưu động của tiền tệ. Giống như việc cố gắng tính toán xem một quả cà chua đóng góp bao nhiêu vào một thìa súp cụ thể.
Nhưng có một cách tiếp cận toán học tự nhiên mà người ta có thể áp dụng, đó là coi những đóng góp là tương xứng với các ghi chú đầu vào.
Trong ví dụ của chúng tôi, chúng ta có thể coi rằng 5 * \frac{1.5}{15} = 0.5 5 ∗ 1.5 15 = 0,5 đến từ khoản tiền gửi 5-ETH và 10 * \frac{1.5}{15} = 1 10 ∗ 1.5 15 = 1 đến từ khoản tiền gửi 10 ETH. Nói cách khác, chúng ta có thể áp dụng một phần của \frac{15}{150} 15 150 cho cả hai khoản tiền gửi đầu vào.
Về lý thuyết, người dùng có thể phân bổ các khoản đóng góp theo cách khác nhau: ví dụ: phân bổ toàn bộ deposit_id cụ thể vào phiếu chi của họ, và không phân bổ bất kỳ phần nào vào phiếu của người nhận dự định. Nhưng vì giao thức của chúng tôi ẩn đi các deposit_id nào nằm trong phiếu (trong trường hợp deposit_id là "tốt"), nên việc này thực sự vô ích; người dùng thậm chí sẽ không biết họ đang phân bổ những deposit_id nào! Và trong trường hợp một deposit_id được nhận dạng là "xấu", sẽ có một mạch khử nhiễm riêng biệt có thể tách giá trị "xấu".
Sơ đồ này minh họa cách áp dụng phân số cho deposit_ids góp phần tạo nên một ghi chú cụ thể:
Xin nhắc lại, tôi sử dụng dấu ngoặc kép để dễ đọc và không gây nhàm chán:
"x"có nghĩa là "mã hóa củax".
Chúng ta có thể xem xét một giao dịch tiếp theo sử dụng tờ tiền 1,5 ETH này làm đầu vào. Giả sử chúng ta đang chuyển 20 ETH và tờ tiền đầu vào còn lại có giá trị 100 ETH.
Sau đó, phân số tiếp theo áp dụng cho tất cả các khoản tiền gửi đóng góp vào ghi chú đầu ra 20-ETH là: \frac{200}{1015} 200 1015 .
Ký hiệu trong sơ đồ luôn phức tạp.
Bạn có thể thấy tôi hơi lười với ký hiệu trong tờ 100 ETH đó. Ví dụ:
enc_frac_3_j = "prod(f_3_j)"là ký hiệu có nghĩa là "mã hóa phần tiền gửi thứ 3 đã đóng góp vào tờ tiền này". Và chúng ta sẽ nói một cách lười biếng rằng đã cójgiao dịch được thực hiện kể từ lần gửi thứ 3 để đến được tờ tiền này".
Nếu bạn nhìn vào tờ tiền 20 ETH, bạn sẽ thấy mô hình dữ liệu tiền gửi mà chúng tôi đang theo dõi.
Dữ liệu được theo dõi cho khoản tiền gửi 5 ETH là:
deposits: [(enc_dep_id = "1" enc_frac_1_3 = "1 * (15/150) * (200/1015)" ,), Hiện tại, chủ sở hữu của tờ tiền 20 ETH này thực sự không thể giải mã các bản mã enc_dep_id_1_3 và enc_frac_1_3 này vì họ không biết khóa giải mã x_1 x 1 .
Nhưng nếu Người duy trì danh sách đen đột nhiên đưa khoản tiền gửi 1 1 vào danh sách đen và nếu Người giữ khóa thực hiện công việc của họ là suy ra và công bố x_1 x 1 , thì người giữ tờ tiền 20 ETH này sẽ có thể giải mã các bản mã enc_dep_id_1_3 và enc_frac_1_3 . (Lưu ý: họ vẫn không thể giải mã các bản mã khác được lưu trữ trong tờ tiền của họ, vì mỗi bản mã được mã hóa bằng các khóa công khai khác nhau).
Chủ sở hữu ghi chú sẽ biết “Ồ nhìn kìa, tôi đã có thể sử dụng x_1 x 1 mới được công bố để giải mã enc_dep_id_1_3 để tạo ra 1 1 , ngụ ý rằng ghi chú của tôi bị 'nhiễm' một số giá trị từ khoản tiền gửi 1 1 . Bây giờ tôi sẽ giải mã enc_frac_1_3 để tạo ra phân số 1 * (15/150) * (200/1015) . Tôi biết có bao nhiêu đã được gửi như một phần của khoản tiền gửi 1 (vì số tiền gửi là công khai): đó là 5 ETH. Vì vậy, tôi sẽ tính 5 * (1 * (15/150) * (200/1015)) = 0.098522 ETH . Do đó, giao thức coi 0.098522 ETH trong ghi chú của tôi là từ khoản tiền gửi 'xấu' 1 1 .”
Bỏ qua mọi lời chỉ trích trong đầu: điều đó thật tuyệt, phải không? Một khối dữ liệu vô nghĩa, khó hiểu, được mã hóa có thể tồn tại trong hàng trăm tờ tiền trên mạng mà không làm rò rỉ biểu đồ giao dịch, và rồi đột nhiên việc đưa một khoản tiền gửi vào danh sách đen có thể tiết lộ một phần rất nhỏ thông tin hữu ích, và chỉ dành cho chủ sở hữu của các tờ tiền tiếp theo.
Paillier
Chúng ta có thể mã hóa phân số bằng mã hóa Paillier, do đó có thể nhân nhiều lần bản mã kết quả với một phân số mới trong mỗi giao dịch chuyển tiền trong tương lai mà không cần biết phân số kết quả là gì.
Tức là nếu tôi đưa cho bạn enc(m) e n c ( m ) , bạn có thể tính enc(km) e n c ( k m ) cho một số vô hướng k k đã biết mà không cần biết m m là gì.
Xem Phụ lục để biết giải thích chi tiết về mã hóa Paillier. Độc lập với phần còn lại của tài liệu này, nó thực sự rất hay. Rõ ràng có nhiều cách tiếp cận hiệu quả hơn nhiều để đạt được tính chất "nhân vô hướng" này trong một snark bằng cách sử dụng các lược đồ FHE. Độc giả quan tâm có thể khám phá những cách đó 
Nhìn lại ví dụ đang thực hiện, chúng tôi bắt đầu với:
enc(1) e n c ( 1 )
Mạch chuyển tiếp tiếp theo nhân vô hướng bản mã này với một vô hướng đã biết 15/150 15 / 150 (được biểu diễn dưới dạng số nguyên làm tròn đến 6d.p. là 15/150 * 10^6 = 100.000 15 / 150 ∗ 10 6 = 100 , 000 ). Nếu sử dụng Paillier, phép toán sẽ là enc(1)^{100000} = enc(1 * 100000) e n c ( 1 ) 100000 = e n c ( 1 ∗ 100000 ) . Người nhận ghi chú sẽ không biết deposit_id(s) nào đã chảy vào ghi chú, họ cũng sẽ không biết được phần nào của mỗi deposit_id đã đóng góp vào ghi chú của họ: họ sẽ chỉ thấy bản mã mới được tính toán.
Mạch chuyển tiếp tiếp theo nhân vô hướng bản mã này với một vô hướng đã biết 200/1015 200 / 1015 (được biểu diễn dưới dạng số nguyên làm tròn đến 6d.p. là 200/1015 * 10^6 = 197,044 200 / 1015 ∗ 10 6 = 197 , 044. Nếu sử dụng Paillier, phép toán sẽ là enc(1 * 100000)^{197044} = enc(1 * 100000 * 197044) e n c ( 1 ∗ 100000 ) 197044 = e n c ( 1 ∗ 100000 ∗ 197044 ) .
Khi giải mã, phân số thực có thể được suy ra là 1 * 100000 * 197044 / (10^6)^2 = 0,0197044 1 ∗ 100000 ∗ 197044 / ( 10 6 ) 2 = 0,0197044
Nếu khóa giải mã được tiết lộ, người dùng sẽ có thể giải mã phân số này và áp dụng vào số tiền gửi ban đầu (trong ví dụ của chúng tôi là 5 ETH) để phát hiện ra rằng tờ tiền của họ được cho là chứa 0,0197044 * 5 = 0,098522 0,0197044 ∗ 5 = 0,098522 ETH.
Một số bình luận về Ví dụ
Một số bình luận trước khi chúng ta đi sâu hơn.
Phân số → Số thập phân
Trong sơ đồ, chúng tôi đã theo dõi các phân số được mã hóa, nhưng thực tế chúng tôi không muốn làm như vậy vì hai lý do:
Việc mã hóa một phân số và nhân lặp lại các phân số mới sẽ yêu cầu cả tử số và mẫu số phải được mã hóa riêng biệt (ít nhất là với các lược đồ mã hóa mà tôi quen thuộc) và điều này gây lãng phí các ràng buộc.
Tử số và mẫu số của một phân số bị rò rỉ:
Tử số có thể được phân tích thành nhân tử để suy ra số tiền có thể đã được chuyển với mỗi giao dịch 'chuyển' kể từ khi gửi tiền. Mẫu số có thể được phân tích thành nhân tử để suy ra quy mô của các tờ tiền mà mỗi chủ sở hữu tờ tiền trung gian nắm giữ kể từ khi gửi tiền.
Thay vào đó, chúng ta có thể chuyển đổi mỗi phân số thành số thập phân, có thể ( quan trọng và cần thiết ) được làm tròn đến một số chữ số thập phân nhất định. Việc làm tròn này làm giảm số lượng có thể suy ra thông qua việc phân tích thành nhân tử (đặc biệt nếu người dùng đưa ra những lựa chọn thú vị về số lượng chuyển đổi, khiến phân số kết quả phải làm tròn).
Tại sao deposit_ids lại được mã hóa?
Giả sử Eve gửi cho Bob, Bob gửi cho Eve (E → B → E). Nếu deposit_id không được mã hóa, Eve sẽ nhận thấy deposit_id chung giữa ghi chú cô ấy đã gửi và ghi chú cô ấy đã nhận.
Có thể tệ hơn, giả sử Eve gửi cho Bob, Bob gửi cho Charlie, Charlie gửi cho Eve (E → B → C → E). Nếu deposit_id không được mã hóa, Eve sẽ nhận thấy deposit_id chung của ghi chú cô ấy đã gửi cho Bob và ghi chú Charlie đã gửi cho cô ấy. Eve có thể suy ra những điều như "Bob biết Charlie" và "Bob đã gửi tiền cho Charlie", và thậm chí có thể cả số tiền họ đã gửi cho nhau. Đó là sự rò rỉ mà chúng ta có thể tránh bằng cách mã hóa lại deposit_id.
Nhưng nếu deposit_ids được mã hóa không thay đổi giữa các lần chuyển tiền thì các văn bản mã hóa đó thực sự trở thành mã định danh thay thế cho các khoản tiền gửi.
Đó là lý do tại sao chúng tôi ngẫu nhiên hóa deposit_ids đã mã hóa với mỗi lần chuyển khoản. Bằng cách này, danh sách deposit_ids là một danh sách khác nhau gồm các số trông ngẫu nhiên trong mỗi tờ tiền! Đó là lý do tại sao Elgamal là một lựa chọn tốt về lược đồ mã hóa. Xem Phụ lục để biết Elgamal và cơ chế ngẫu nhiên hóa hoạt động như thế nào.
Tại sao các phân số (hoặc số thập phân) lại được mã hóa?
Tương tự như lý do tại sao deposit_ids được mã hóa.
Một thực thể xuất hiện nhiều lần trong biểu đồ tx có thể phát hiện ra các mẫu trong các phân số có trong ghi chú của họ và ghép lại biểu đồ tx hoặc đưa ra suy luận tương tự như các phần trên.
Thật tệ khi người dùng nhận được 0,098522 ETH trong ví dụ
Trong ví dụ này, một phần 0,098522 ETH trong tờ tiền của người dùng được coi là "xấu", một thời gian sau khi người dùng nhận được tờ tiền. Người dùng này trung thực và không hề biết về "sự xấu" của tờ tiền khi họ nhận được nó.
Lý tưởng nhất là việc đưa vào danh sách đen sẽ được thực hiện trước khi bất kỳ giao dịch chuyển tiền nào diễn ra trong hệ thống, ví dụ như trong thời gian trì hoãn gửi tiền. Trong những trường hợp như vậy, khóa bí mật x_i x i của khoản tiền gửi xấu sẽ được tất cả người dùng biết trước khi bất kỳ giao dịch chuyển tiền nào diễn ra. Nếu kẻ xấu cố gắng chuyển tiền cho một người dùng trung thực, người dùng đó sẽ có thể phát hiện ra ngay lập tức.
Ngoài ra, còn có một hang thỏ thú vị về những gì sẽ xảy ra trong thế giới thực tương tự như th













