zk-SNARK'lar, hem blockchain hem de blockchain tabanlı olmayan uygulamaların giderek daha önemli bir parçası haline gelen güçlü bir şifreleme aracıdır. Karmaşıklıkları hem nasıl işlediklerinin anlaşılmasında hem de nasıl etkili bir şekilde kullanılabileceğinin anlaşılmasında açıkça görülmektedir. Bu makalede, zk-SNARK'ların mevcut uygulamalara nasıl uyum sağladığı ele alınmakta, neyi başarabilecekleri ve neyi başaramayacaklarına dair örnekler verilmekte ve zk-SNARK'ların belirli uygulamalar için ne zaman uygun olduğuna ilişkin genel yönergeler sunulmaktadır. Mahremiyetin sağlanmasındaki rollerine özel bir vurgu yapılacaktır.
Genel bir giriş x, özel bir giriş w ve girişleri doğrulayan bir (genel) fonksiyon f(x,w) → {True,False} olduğunu hayal edin. zk-SNARK'larla, w'nin gerçekte ne olduğunu açıklamadan, belirli bir f ve x için f(x,w) = Doğru olacak şekilde aw'yi bildikleri kanıtlanabilir. Dahası, doğrulayıcılar w'yi bilseler bile f(x,w)'yi hesaplayabileceklerinden çok daha hızlı bir şekilde ispatı doğrulayabilirler.
Bu, zk-SNARK'lara iki özellik kazandırır: gizlilik ve ölçeklenebilirlik. Belirtildiği gibi, bu makaledeki örneklerimiz esas olarak gizlilik yönüne odaklanacaktır.
Diyelim ki bir Ethereum cüzdanınız var ve kayıtlı kişinin gerçekte kim olduğunu açıklamadan, bu cüzdanın bir insanlık kanıtı sistemi altında kayıtlı olduğunu kanıtlamak istiyorsunuz. Bu fonksiyon matematiksel olarak şu şekilde tanımlanabilir:
Özel giriş (w): A adresiniz, k adresiniz özel anahtarı
Genel giriş (x): Doğrulanmış tüm insanlık kanıtı profillerinin adres kümesi {H1…Hn}
Doğrulama fonksiyonu f(x,w):
w'yi bir çift (A, σ) olarak ve x'i geçerli bir profil listesi olarak yorumlayın {H1…Hn}
A'nın {H1…Hn}içindeki adreslerden biri olduğunu doğrulayın
privtoaddr(k) = A'yı doğrulayın
Her iki doğrulama da başarılı olursa True değerini döndürün. Bunlardan herhangi biri başarısız olursa False değerini döndürün.
Kanıtlayıcı, f için özel girdi olarak w=(A,k) sağlayarak A adresini ve ilgili k anahtarını üretir. Zincirden, mevcut doğrulanmış insanlık kanıtı profilleri {H1…Hn} kümesi olan genel girdiyi alırlar. Daha sonra (girişin doğru olduğu varsayılarak) bir kanıt üreten zk-SNARK kanıt algoritmasını çalıştırırlar. Bu kanıt, doğrulayıcıya, doğrulanmış profil listesini getirdikleri blok yüksekliğiyle birlikte gönderilir.
Doğrulayıcı ayrıca, kanıtlayıcı tarafından belirtilen yükseklikten {H1…Hn} listesini alarak zinciri okur ve kanıtı kontrol eder. Doğrulama başarılı olursa, doğrulayıcı, kanıtlayıcının doğrulanmış bir insanlık kanıtı profiline sahip olduğuna inanır.
Daha karmaşık örneklere dalmadan önce yukarıdaki örneği tam olarak anlamanızı şiddetle tavsiye ederim.
Yukarıda bahsedilen kanıt sisteminin bir dezavantajı, doğrulayıcının {H1…Hn} profil kümesinin tamamından haberdar olmasının gerekmesidir; bu, bu kümeyi zk-SNARK mekanizmasına "girmek" için O(n) zamanını gerektirir. Bu sorun, tüm profilleri kapsayan zincir içi Merkle kökünün genel giriş (potansiyel olarak yalnızca durum kökü) olarak kullanılmasıyla çözülebilir. Kanıtlayıcının A hesabının ağacın ilgili bölümünde olduğunu doğrulayan bir Merkle kanıtı M olan başka bir özel girdi ekliyoruz.
ZK üyelik kanıtları için Merkle kanıtlarına son derece yeni ve daha etkili bir alternatif Caulk'tur. Gelecekte bu kullanım örneklerinden bazıları Caulk'a benzer çözümlere dönüşebilir.
Zcash ve Tornado.cash gibi projeler gizliliği koruyan para birimlerine sahip olmamızı sağlıyor. Şimdi, bahsi geçen “ZK insan kanıtlarından” faydalanabilecekleri düşünülebilir, ancak mesele insan profili kanıtlarına erişimi kanıtlamak değil; madeni paralara erişimi kanıtlamakla ilgili. Burada bir sorun yatıyor: Hem mahremiyete hem de çifte harcamaya aynı anda değinmeliyiz. Yani aynı parayı iki kere harcamamalıyız.
Bunu şu şekilde çözüyoruz: Coin sahibi olan herkesin özel bir sırrı “s” vardır. Yerel olarak bir "yaprak" L=hash(s,1) hesaplarlar, bu zincirde yayınlanır ve N=hash(s,2) durumunun bir parçası haline gelir, buna da nullifier adını veririz. Durum Merkle ağacında saklanır.
Bir jeton harcamak için gönderenin bir ZK-SNARK üretmesi gerekir; bu durumda:
Genel girdiler arasında bir geçersizleştirici N, geçerli veya güncel Merkle kökü R ve yeni bir yaprak L' (gönderene L'=hash(s',1) olarak iletilen gizli bir s'ye sahip olan alıcıya yöneliktir) bulunur.
Özel girdiler bir gizli s, bir yaprak L ve bir Merkle dalı M'den oluşur.
Doğrulama işlevi şunları kontrol eder:
M geçerli bir Merkle dalıdır ve L'nin R'ye kök salmış bir ağacın yaprağı olduğunu kanıtlar; burada R, mevcut durumun Merkle köküdür.
hash(s,1)=L ve hash(s,2)=N.
İşlem, geçersiz kılıcı N'yi ve yeni yaprak L''yi içerir. Aslında L' hakkında hiçbir şey kanıtlamıyoruz, ancak işlem sırasında üçüncü şahıslar tarafından değişiklik yapılmasını önlemek için kanıtın içine "karıştırılmıştır". İşlemi doğrulamak için zincir, ZK-SNARK'ı doğrular ve önceki işlemlerde N'nin kullanılıp kullanılmadığını kontrol eder. Başarılı olursa, harcanan etkisizleştiriciler kümesine N eklenir ve tekrar kullanılamaz hale gelir. L' Merkle ağacına eklenir.
ZK-SNARK'ları kullanarak iki değeri birbirine bağlarız: L (para basıldığında zincirde görünür) ve N (harcandığında görünür), hangi L'nin hangi N'ye bağlandığını açıklamadan. L ve N arasındaki bağlantı yalnızca onları yaratan sırları biliyorum. Basılan her madeni para bir kez kullanılabilir (çünkü her L için yalnızca bir geçerli N vardır), ancak herhangi bir zamanda kullanılan belirli madeni para gizli kalır.
Bu anlaşılması gereken çok önemli bir ilkeldir. Aşağıda açıkladığımız birçok mekanizma, farklı amaçlarla da olsa buna dayanmaktadır.
Yukarıdakiler, keyfi bakiyelere sahip madeni paralara kolayca genişletilebilir. Biz “coin” kavramını sürdürüyoruz ancak her bir coin (özel) bir bakiye taşıyor. Bunu başarmanın basit bir yolu, her bir madalyonun sadece L yaprağıyla değil, aynı zamanda şifreli bir bakiyeyle de zincir depolamaya sahip olmasıdır. Her işlemde iki koin tüketilecek ve iki yeni koin oluşturularak duruma iki çift (yaprak, şifreli bakiye) eklenecektir. ZK-SNARK ayrıca girdi bakiyeleri toplamının çıktı bakiyelerinin toplamına eşit olduğunu ve her iki çıktı bakiyesinin de negatif olmadığını doğrular.
İlgi çekici bir DOS karşıtı araç: Kolayca oluşturulamayan bir zincir içi kimliğiniz olduğunu hayal edin; bu, insan geçirmez bir profil veya 32 ETH doğrulayıcı ya da yalnızca sıfır olmayan ETH bakiyesine sahip bir hesap olabilir. Yalnızca gönderenin bir profile sahip olduğunu kanıtlayan mesajları kabul ederek DOS'a daha dayanıklı bir eşler arası ağ oluşturabiliriz. Her profile saatte en fazla 1000 mesaja izin verilecek. Gönderen hile yaparsa profili listeden kaldırılır. Peki gizliliği nasıl sağlayacağız?
İlk olarak kurulum: k kullanıcının özel anahtarı olsun ve A=privtoaddr(k) karşılık gelen adres olsun. Geçerli adreslerin listesi herkese açıktır (örneğin, zincir üstü bir kayıt defteri). Şu ana kadar bu, insanların kanıtladığı örneği yansıtıyor: Hangi adres olduğunu açıklamadan, bir adresin özel anahtarını elinizde tuttuğunuzu kanıtlamalısınız. Ancak sadece listede olduğunuzun kanıtını istemiyoruz. Listede olduğunuzu kanıtlamanıza olanak tanıyan ancak kanıtlarınızı sınırlayan bir protokole ihtiyacımız var.
Zamanı dönemlere ayıracağız: her biri 3,6 saniye sürecek (saatte 1000 dönem). Amacımız her kullanıcının dönem başına yalnızca bir mesaj göndermesine olanak sağlamaktır; Aynı dönemde iki tane gönderirlerse yakalanırlar. Ara sıra meydana gelen patlamalara izin vermek için yakın dönemleri kullanabilirler. Yani bir kullanıcının 500 kullanılmayan dönemi varsa, aynı anda 500 mesajın tamamını gönderebilir.
Geçersizleştiricileri kullanan temel bir sürümle başlayalım. Bir kullanıcı (N = \text{hash}(k, e)) ile (k) kendi anahtarı ve (e) bir dönem numarası olan bir nullifier oluşturur ve bunu (m) mesajıyla yayınlar. ZK-SNARK daha sonra (\text{hash}(m))'yi gizler. Bu süreçte (m) ile ilgili hiçbir şey doğrulanmaz, dolayısıyla kanıt tek bir mesaja bağlanır. Bir kullanıcı aynı geçersizleştiriciyi kullanarak iki kanıtı iki farklı mesaja bağlarsa yakalanma riskiyle karşı karşıya kalır.
Şimdi daha karmaşık bir versiyona geçiyoruz. Bu senaryoda, sonraki protokol, yalnızca birinin aynı dönemi iki kez kullanıp kullanmadığını doğrulamak yerine, özel anahtarını ortaya çıkarır. Temel tekniğimiz “iki noktanın bir doğruyu belirlemesi” ilkesine dayanıyor. Bir çizgi üzerindeki bir noktayı ortaya çıkarmak çok az şeyi açığa çıkarır, ancak iki noktayı açığa çıkarmak tüm çizgiyi ortaya çıkarır.
Her (e) dönemi için bir çizgi seçeriz (L_e(x) = \text{hash}(k, e) \times x + k). Doğrunun eğimi (\text{hash}(k, e)) ve y-kesme noktası (k)'dır; bunların ikisi de herkes tarafından bilinmemektedir. (m) mesajına yönelik bir sertifika oluşturmak için gönderen şunu sağlar: (y = L_e(\text{hash}(m)) = \text{hash}(k, e) \times \text{hash}(m) + k ), (y) hesaplamasının doğru olduğuna dair ZK-SNARK kanıtıyla birlikte.
Özetle ZK-SNARK şu şekildedir:
({A_1…A_n}): Geçerli hesapların listesi
(M): Sertifika tarafından doğrulanan mesaj
(E): Sertifikanın dönem numarası
(Y): Hat fonksiyonunun değerlendirilmesi
(\text{privtoaddr}(k))'nin ({A_1…A_n}) içinde olup olmadığını kontrol edin
Onayla (y = \text{hash}(k, e) \times \text{hash}(m) + k)
Peki ya birisi bir dönemi iki kez kullanırsa? Sertifika değerleriyle birlikte (m_1) ve (m_2) iki değerini (y_1 = \text{hash}(k, e) \times \text{hash}(m_1) + k) ve (y_2 = \text{hash} ortaya çıkarırlardı. (k, e) \times \text{hash}(m_2) + k). Daha sonra bu iki noktayı çizgiyi ve ardından özel anahtar olan y kesim noktasını kurtarmak için kullanabiliriz.
Yani eğer birisi bir dönemi yeniden kullanırsa, özel anahtarını istemeden herkese açıklamış olur. Bağlama bağlı olarak bu, fon hırsızlığına veya yalnızca özel anahtarın yayınlanmasına ve akıllı bir sözleşmeye entegre edilmesine yol açarak ilgili adresin kaldırılmasına yol açabilir.
Blockchain eşler arası ağlar, sohbet uygulamaları ve benzer sistemler için uygun, zincir dışı anonim hizmet reddi önleme sistemi, herhangi bir çalışma kanıtı gerektirmez. RLN projesi, küçük değişikliklerle (yani, hem sıfırlayıcıları hem de iki nokta çizgisi tekniğini kullanarak, bir çağın yeniden kullanıldığı örnekleri tespit etmeyi daha basit hale getirerek) esasen bu konsepte odaklanmaktadır.
Tam bir anonimlik sunan (kalıcı adınız bile yok), ancak daha yüksek kaliteli içeriği teşvik eden bir itibar sistemine sahip, 4chan gibi çevrimiçi bir forum olan 0chan'ı kurduğunuzu hayal edin. Böyle bir sistem, sistem kurallarını ihlal eden gönderileri işaretleyecek ve üç vuruşlu bir mekanizmayı devreye sokacak bir yönetişim DAO'suna sahip olabilir.
İtibar sistemi olumlu veya olumsuz itibara hitap edebilir; ancak olumsuz itibara uyum sağlamak ek altyapı gerektirir. Bu, kullanıcıların olumsuz olsa bile tüm itibar verilerini kanıtlarına dahil etmelerini gerektirir. Unirep Social'ın uygulamayı amaçladığı şeye benzer şekilde öncelikle bu zorlu kullanım senaryosuna odaklanacağız.
Herkes, gönderiyi içeren zincire ZK-SNARK eşliğinde bir mesaj göndererek gönderi paylaşabilir. Bu ZK-SNARK, (i) size hesap oluşturma izni veren benzersiz bir harici kimliğe sahip olduğunuzun veya (ii) daha önce belirli gönderiler yayınladığınızın bir kanıtı olarak hizmet eder. ZK-SNARK spesifik olarak şu şekilde çalışır:
Sıfırlayıcı, N
En yeni blockchain durum kökü, R
Gönderi içeriği (üzerinde herhangi bir hesaplama yapılmadan, gönderiye bağlanmak için kanıtın içine 'karışık')
Özel anahtarınız, k
Önceki gönderide kullanılan harici kimlik (adres A) veya geçersizleştirici Nprev
Zincirin A veya Nprev içerdiğine dair Merkle kanıtı M
Bu hesabı kullanarak yayınladığınız i. gönderi
M'nin geçerli bir Merkle dalı olduğunu doğrulayın ve (A veya Nprev, hangisi sağlanırsa) kökü R olan bir ağacın yaprağı olduğunu kanıtlayın.
N = enc(i, k)'yi doğrulayın; burada enc bir şifreleme işlevidir (örneğin, AES).
i=0 ise A=privtoaddr(k)'yi doğrulayın, aksi takdirde Nprev=enc(i−1,k)'yi doğrulayın.
Kanıt doğrulamanın yanı sıra, zincir ayrıca (i) R'nin gerçekten yeni bir durum kökü olup olmadığını ve (ii) N geçersizleştiricisinin daha önce kullanılmadığını da kontrol eder. Bu noktaya kadar, daha önce açıklanan gizliliği koruyan madeni paralara benziyor, ancak yeni hesaplar 'basmak' için bir süreç ekledik ve hesabınızı farklı anahtarlara 'gönderme' özelliğini kaldırdık. Bunun yerine, tüm nullifier'lar orijinal anahtar kullanılarak oluşturulur. Sıfırlayıcıyı tersine çevrilebilir hale getirmek için burada enc kullanıyoruz. Eğer k anahtarınız varsa, zincirdeki herhangi bir geçersizleştiricinin şifresini çözebilirsiniz; sonuç rastgele anlamsız ifadeler yerine geçerli bir dizinse (örneğin, dec(N) < 2^64'ü kontrol edebiliriz), geçersiz kılıcının k anahtarı kullanılarak oluşturulduğunu bilirsiniz.
Bu şemada itibar zincir üzerindedir ve açıktır. Bazı akıllı sözleşmeler, bir gönderiyle birlikte yayımlanan geçersiz kılıcıyı ve girdi olarak eklenecek veya çıkarılacak itibar birimlerinin sayısını alan addReputation adı verilen bir yönteme sahiptir.
Her gönderi için zincirde depolanan verileri genişlettik. Yalnızca N geçersizleştiricisini depolamak yerine, {N, h¯, u¯} ı burada saklıyoruz:
h¯ = karma(h, r) burada h, kanıtta başvurulan durum kökünün blok yüksekliğini temsil eder.
u¯ = karma(u, r) burada u, hesabın itibar puanıdır (yeni hesaplar için 0'dan başlar).
Burada R, h ve u'nun kaba kuvvet araması yoluyla bulunmasını önlemek için eklenen rastgele bir değerdir. Kriptografik açıdan R'nin eklenmesi hash'i gizli bir taahhüt haline getirir.
Bir gönderinin root R kullandığını ve {N, h¯, u¯} dosyasını depoladığını varsayalım. Kanıtı kapsamında, {Nprev, h¯prev, u¯prev} verilerini depolayan önceki bir gönderiye bağlantı verir. Gönderinin kanıtı aynı zamanda hprev ve h arasında gönderilen tüm itibar girişlerini de kapsamalıdır. Her N nullifier için, doğrulama fonksiyonu kullanıcının k anahtarını kullanarak N'nin şifresini çözer. Şifre çözme işlemi geçerli bir dizin üretirse itibar güncellemesini uygular. Tüm itibar güncellemelerinin toplamı δ'ye eşitse, u = artış + δ kanıtlanır.
Eğer “üç vuruş yaparsan oyundan çıkarsın” kuralını uygulamak istiyorsak, ZK-SNARK u > -3'ü de garantileyecektir. Temsilcisi ≥ 100 olan bir gönderinin özel bir "yüksek itibarlı gönderi" etiketi alacağı bir kural istiyorsak, bu da yapılabilir.
Bu sistemin ölçeklenebilirliğini arttırmak için onu iki tür mesaja ayırabiliriz: Mesajlar ve RCA'lar. Geçtiğimiz hafta yapılan bir RCA'ya işaret etmeyi gerektirse de, bir gönderi zincir dışı olacaktır. RCA'lar zincir üzerinde olacak ve yayıncının önceki RCA'sından bu yana tüm itibar güncellemelerini kapsayacak. Bu şekilde zincir üzerindeki yük, haftada posta başına bir işleme ve ayrıca her itibar mesajı için bir işleme düşürülür.
Bazen merkezi bir "operatöre" sahip bir sistem tasarlamaya ihtiyaç duyulur. Bunun nedenleri farklılık gösterebilir: Bazen ölçeklenebilirlik, bazen de gizlilik, özellikle de operatör tarafından tutulan verilerin gizliliği içindir. Örneğin, MACI zorlayıcı oylama sistemi, seçmenlerin oylarını merkezi bir operatör tarafından tutulan bir anahtarla şifrelenmiş olarak zincir üzerinde göndermelerini gerektiriyor. Bu operatör, zincirdeki tüm oyların şifresini çözer, bunları sayar ve nihai sonucu görüntüler. Yaptıkları her şeyin doğru olduğunu kanıtlamak için ZK-SNARK'ı kullanıyorlar. Bu ilave karmaşıklık, sağlam bir gizlilik (zorlayıcı direnç olarak bilinir) sağlamak için çok önemlidir: Kullanıcılar isteseler bile, nasıl oy verdiklerini kimseye kanıtlayamazlar. Blockchain ve ZK-SNARK sayesinde operatöre olan güven seviyemiz minimum düzeyde kalıyor. Kötü niyetli operatörler zorlayıcı direnci ihlal edebilir, ancak oylar blok zincirinde yayınlandığı için oyları sansürleyerek hile yapamazlar. Ve ZK-SNARK sağlamaları gerektiğinden, sonuçları yanlış hesaplayarak hile yapamazlar.
ZK-SNARK'ların daha gelişmiş bir kullanımı, girdinin iki veya daha fazla taraf arasında dağıtıldığı ve kanıtın gerekli olduğu hesaplamalardadır ve hiçbir tarafın diğerinin girdisi hakkında bilgi sahibi olmasını istemeyiz. İki taraflı bir senaryoda, bozuk devreler gizlilik gereksinimlerini karşılayabilir; N parti için daha karmaşık çok partili hesaplama protokolleri kullanılabilir. Doğrulanabilir çok taraflı hesaplamalar için ZK-SNARK'lar bu protokollerle entegre edilebilir. Bu, birden fazla katılımcının kendi özel girdileri üzerinde ortak hesaplamalar yapmasına olanak tanıyan gelişmiş itibar sistemlerine olanak tanır. Bunu etkili bir şekilde başarmak için gereken matematik henüz başlangıç aşamasındadır.
ZK-SNARK'lar, kullanıcıların özel durumlarına sahip olduğu sistemlerin oluşturulmasında oldukça etkilidir. Ancak kimsenin bilmediği özel bir devleti sürdüremez. Bilginin kanıtlanabilmesi için kanıtlayıcının onu düz metin olarak bilmesi gerekir. Uniswap özelleştirilmesi zor bir örnek. Uniswap'te merkezi bir mantıksal “varlık” vardır; kimseye ait olmayan likidite sağlayıcı hesabı ve tüm Uniswap işlemleri bu hesapla gerçekleşir. Birisinin bunu kanıtlamak için bu durumu düz metin olarak tutması gerektiğinden ve her işlem bu kişinin aktif katılımını gerektireceğinden, bu hesabın durumunu gizleyemezsiniz. Uniswap'in merkezi, güvenli ve özel bir versiyonunu oluşturmak için ZK-SNARK'ın bozuk devrelerini kullanabilirsiniz, ancak faydaların maliyetlerden daha ağır basıp basmayacağı belli değil. Gerçek bir fayda bile sağlamayabilir: Sözleşmelerin kullanıcıları varlık fiyatları konusunda bilgilendirmesi gerekir ve blok başına fiyat değişimleri işlem etkinliğini ortaya çıkarabilir. Blok zincirleri devlet bilgilerini küreselleştirebilir ve ZK-SNARK'lar bunu özelleştirebilir, ancak devlet bilgilerini aynı anda küreselleştirmenin ve özelleştirmenin sağlam bir yöntemi yoktur.
Yukarıdaki bölümlerde, kendi başlarına güçlü olan ancak aynı zamanda diğer uygulamalar için yapı taşı görevi görebilen araç örneklerini gördük. Para birimleri için hayati öneme sahip geçersiz kılıcılar artık diğer kullanım durumlarında yeniden ortaya çıkıyor. Olumsuz itibar bölümünde kullanılan “zorlayıcı bağlantı” tekniği geniş bir uygulama alanına sahiptir. Kullanıcının "profilinin" zaman içinde karmaşık şekillerde değiştiği ve gizliliği korurken kullanıcıları sistem kurallarına uymaya zorlamak istediğiniz birçok uygulama için son derece etkilidir. Kullanıcılara, tam özel bir Merkle ağacı kullanarak dahili "durumlarını" temsil etme görevi bile verilebilir. Bahsedilen “taahhüt havuzu” aracı ZK-SNARK ile oluşturulabilir. Belirli uygulamalar zincir üzerinde tam olarak çalışamıyorsa ve merkezi bir operatör gerektiriyorsa, aynı teknikler operatörün dürüst olmasını sağlayabilir. ZK-SNARK, hesap verebilirlik ve gizlilik avantajlarını harmanlayan güçlü bir araçtır. Bazı durumlarda sınırlamaları olsa da akıllı uygulama tasarımları bu kısıtlamaları aşabilir. Gelecek yıllarda daha fazla uygulamanın ZK-SNARK'ı benimsediğini ve sonunda ZK-SNARK'ı diğer şifreleme biçimleriyle birleştiren uygulamalar geliştirdiğini görmeyi umuyorum.
zk-SNARK'lar, hem blockchain hem de blockchain tabanlı olmayan uygulamaların giderek daha önemli bir parçası haline gelen güçlü bir şifreleme aracıdır. Karmaşıklıkları hem nasıl işlediklerinin anlaşılmasında hem de nasıl etkili bir şekilde kullanılabileceğinin anlaşılmasında açıkça görülmektedir. Bu makalede, zk-SNARK'ların mevcut uygulamalara nasıl uyum sağladığı ele alınmakta, neyi başarabilecekleri ve neyi başaramayacaklarına dair örnekler verilmekte ve zk-SNARK'ların belirli uygulamalar için ne zaman uygun olduğuna ilişkin genel yönergeler sunulmaktadır. Mahremiyetin sağlanmasındaki rollerine özel bir vurgu yapılacaktır.
Genel bir giriş x, özel bir giriş w ve girişleri doğrulayan bir (genel) fonksiyon f(x,w) → {True,False} olduğunu hayal edin. zk-SNARK'larla, w'nin gerçekte ne olduğunu açıklamadan, belirli bir f ve x için f(x,w) = Doğru olacak şekilde aw'yi bildikleri kanıtlanabilir. Dahası, doğrulayıcılar w'yi bilseler bile f(x,w)'yi hesaplayabileceklerinden çok daha hızlı bir şekilde ispatı doğrulayabilirler.
Bu, zk-SNARK'lara iki özellik kazandırır: gizlilik ve ölçeklenebilirlik. Belirtildiği gibi, bu makaledeki örneklerimiz esas olarak gizlilik yönüne odaklanacaktır.
Diyelim ki bir Ethereum cüzdanınız var ve kayıtlı kişinin gerçekte kim olduğunu açıklamadan, bu cüzdanın bir insanlık kanıtı sistemi altında kayıtlı olduğunu kanıtlamak istiyorsunuz. Bu fonksiyon matematiksel olarak şu şekilde tanımlanabilir:
Özel giriş (w): A adresiniz, k adresiniz özel anahtarı
Genel giriş (x): Doğrulanmış tüm insanlık kanıtı profillerinin adres kümesi {H1…Hn}
Doğrulama fonksiyonu f(x,w):
w'yi bir çift (A, σ) olarak ve x'i geçerli bir profil listesi olarak yorumlayın {H1…Hn}
A'nın {H1…Hn}içindeki adreslerden biri olduğunu doğrulayın
privtoaddr(k) = A'yı doğrulayın
Her iki doğrulama da başarılı olursa True değerini döndürün. Bunlardan herhangi biri başarısız olursa False değerini döndürün.
Kanıtlayıcı, f için özel girdi olarak w=(A,k) sağlayarak A adresini ve ilgili k anahtarını üretir. Zincirden, mevcut doğrulanmış insanlık kanıtı profilleri {H1…Hn} kümesi olan genel girdiyi alırlar. Daha sonra (girişin doğru olduğu varsayılarak) bir kanıt üreten zk-SNARK kanıt algoritmasını çalıştırırlar. Bu kanıt, doğrulayıcıya, doğrulanmış profil listesini getirdikleri blok yüksekliğiyle birlikte gönderilir.
Doğrulayıcı ayrıca, kanıtlayıcı tarafından belirtilen yükseklikten {H1…Hn} listesini alarak zinciri okur ve kanıtı kontrol eder. Doğrulama başarılı olursa, doğrulayıcı, kanıtlayıcının doğrulanmış bir insanlık kanıtı profiline sahip olduğuna inanır.
Daha karmaşık örneklere dalmadan önce yukarıdaki örneği tam olarak anlamanızı şiddetle tavsiye ederim.
Yukarıda bahsedilen kanıt sisteminin bir dezavantajı, doğrulayıcının {H1…Hn} profil kümesinin tamamından haberdar olmasının gerekmesidir; bu, bu kümeyi zk-SNARK mekanizmasına "girmek" için O(n) zamanını gerektirir. Bu sorun, tüm profilleri kapsayan zincir içi Merkle kökünün genel giriş (potansiyel olarak yalnızca durum kökü) olarak kullanılmasıyla çözülebilir. Kanıtlayıcının A hesabının ağacın ilgili bölümünde olduğunu doğrulayan bir Merkle kanıtı M olan başka bir özel girdi ekliyoruz.
ZK üyelik kanıtları için Merkle kanıtlarına son derece yeni ve daha etkili bir alternatif Caulk'tur. Gelecekte bu kullanım örneklerinden bazıları Caulk'a benzer çözümlere dönüşebilir.
Zcash ve Tornado.cash gibi projeler gizliliği koruyan para birimlerine sahip olmamızı sağlıyor. Şimdi, bahsi geçen “ZK insan kanıtlarından” faydalanabilecekleri düşünülebilir, ancak mesele insan profili kanıtlarına erişimi kanıtlamak değil; madeni paralara erişimi kanıtlamakla ilgili. Burada bir sorun yatıyor: Hem mahremiyete hem de çifte harcamaya aynı anda değinmeliyiz. Yani aynı parayı iki kere harcamamalıyız.
Bunu şu şekilde çözüyoruz: Coin sahibi olan herkesin özel bir sırrı “s” vardır. Yerel olarak bir "yaprak" L=hash(s,1) hesaplarlar, bu zincirde yayınlanır ve N=hash(s,2) durumunun bir parçası haline gelir, buna da nullifier adını veririz. Durum Merkle ağacında saklanır.
Bir jeton harcamak için gönderenin bir ZK-SNARK üretmesi gerekir; bu durumda:
Genel girdiler arasında bir geçersizleştirici N, geçerli veya güncel Merkle kökü R ve yeni bir yaprak L' (gönderene L'=hash(s',1) olarak iletilen gizli bir s'ye sahip olan alıcıya yöneliktir) bulunur.
Özel girdiler bir gizli s, bir yaprak L ve bir Merkle dalı M'den oluşur.
Doğrulama işlevi şunları kontrol eder:
M geçerli bir Merkle dalıdır ve L'nin R'ye kök salmış bir ağacın yaprağı olduğunu kanıtlar; burada R, mevcut durumun Merkle köküdür.
hash(s,1)=L ve hash(s,2)=N.
İşlem, geçersiz kılıcı N'yi ve yeni yaprak L''yi içerir. Aslında L' hakkında hiçbir şey kanıtlamıyoruz, ancak işlem sırasında üçüncü şahıslar tarafından değişiklik yapılmasını önlemek için kanıtın içine "karıştırılmıştır". İşlemi doğrulamak için zincir, ZK-SNARK'ı doğrular ve önceki işlemlerde N'nin kullanılıp kullanılmadığını kontrol eder. Başarılı olursa, harcanan etkisizleştiriciler kümesine N eklenir ve tekrar kullanılamaz hale gelir. L' Merkle ağacına eklenir.
ZK-SNARK'ları kullanarak iki değeri birbirine bağlarız: L (para basıldığında zincirde görünür) ve N (harcandığında görünür), hangi L'nin hangi N'ye bağlandığını açıklamadan. L ve N arasındaki bağlantı yalnızca onları yaratan sırları biliyorum. Basılan her madeni para bir kez kullanılabilir (çünkü her L için yalnızca bir geçerli N vardır), ancak herhangi bir zamanda kullanılan belirli madeni para gizli kalır.
Bu anlaşılması gereken çok önemli bir ilkeldir. Aşağıda açıkladığımız birçok mekanizma, farklı amaçlarla da olsa buna dayanmaktadır.
Yukarıdakiler, keyfi bakiyelere sahip madeni paralara kolayca genişletilebilir. Biz “coin” kavramını sürdürüyoruz ancak her bir coin (özel) bir bakiye taşıyor. Bunu başarmanın basit bir yolu, her bir madalyonun sadece L yaprağıyla değil, aynı zamanda şifreli bir bakiyeyle de zincir depolamaya sahip olmasıdır. Her işlemde iki koin tüketilecek ve iki yeni koin oluşturularak duruma iki çift (yaprak, şifreli bakiye) eklenecektir. ZK-SNARK ayrıca girdi bakiyeleri toplamının çıktı bakiyelerinin toplamına eşit olduğunu ve her iki çıktı bakiyesinin de negatif olmadığını doğrular.
İlgi çekici bir DOS karşıtı araç: Kolayca oluşturulamayan bir zincir içi kimliğiniz olduğunu hayal edin; bu, insan geçirmez bir profil veya 32 ETH doğrulayıcı ya da yalnızca sıfır olmayan ETH bakiyesine sahip bir hesap olabilir. Yalnızca gönderenin bir profile sahip olduğunu kanıtlayan mesajları kabul ederek DOS'a daha dayanıklı bir eşler arası ağ oluşturabiliriz. Her profile saatte en fazla 1000 mesaja izin verilecek. Gönderen hile yaparsa profili listeden kaldırılır. Peki gizliliği nasıl sağlayacağız?
İlk olarak kurulum: k kullanıcının özel anahtarı olsun ve A=privtoaddr(k) karşılık gelen adres olsun. Geçerli adreslerin listesi herkese açıktır (örneğin, zincir üstü bir kayıt defteri). Şu ana kadar bu, insanların kanıtladığı örneği yansıtıyor: Hangi adres olduğunu açıklamadan, bir adresin özel anahtarını elinizde tuttuğunuzu kanıtlamalısınız. Ancak sadece listede olduğunuzun kanıtını istemiyoruz. Listede olduğunuzu kanıtlamanıza olanak tanıyan ancak kanıtlarınızı sınırlayan bir protokole ihtiyacımız var.
Zamanı dönemlere ayıracağız: her biri 3,6 saniye sürecek (saatte 1000 dönem). Amacımız her kullanıcının dönem başına yalnızca bir mesaj göndermesine olanak sağlamaktır; Aynı dönemde iki tane gönderirlerse yakalanırlar. Ara sıra meydana gelen patlamalara izin vermek için yakın dönemleri kullanabilirler. Yani bir kullanıcının 500 kullanılmayan dönemi varsa, aynı anda 500 mesajın tamamını gönderebilir.
Geçersizleştiricileri kullanan temel bir sürümle başlayalım. Bir kullanıcı (N = \text{hash}(k, e)) ile (k) kendi anahtarı ve (e) bir dönem numarası olan bir nullifier oluşturur ve bunu (m) mesajıyla yayınlar. ZK-SNARK daha sonra (\text{hash}(m))'yi gizler. Bu süreçte (m) ile ilgili hiçbir şey doğrulanmaz, dolayısıyla kanıt tek bir mesaja bağlanır. Bir kullanıcı aynı geçersizleştiriciyi kullanarak iki kanıtı iki farklı mesaja bağlarsa yakalanma riskiyle karşı karşıya kalır.
Şimdi daha karmaşık bir versiyona geçiyoruz. Bu senaryoda, sonraki protokol, yalnızca birinin aynı dönemi iki kez kullanıp kullanmadığını doğrulamak yerine, özel anahtarını ortaya çıkarır. Temel tekniğimiz “iki noktanın bir doğruyu belirlemesi” ilkesine dayanıyor. Bir çizgi üzerindeki bir noktayı ortaya çıkarmak çok az şeyi açığa çıkarır, ancak iki noktayı açığa çıkarmak tüm çizgiyi ortaya çıkarır.
Her (e) dönemi için bir çizgi seçeriz (L_e(x) = \text{hash}(k, e) \times x + k). Doğrunun eğimi (\text{hash}(k, e)) ve y-kesme noktası (k)'dır; bunların ikisi de herkes tarafından bilinmemektedir. (m) mesajına yönelik bir sertifika oluşturmak için gönderen şunu sağlar: (y = L_e(\text{hash}(m)) = \text{hash}(k, e) \times \text{hash}(m) + k ), (y) hesaplamasının doğru olduğuna dair ZK-SNARK kanıtıyla birlikte.
Özetle ZK-SNARK şu şekildedir:
({A_1…A_n}): Geçerli hesapların listesi
(M): Sertifika tarafından doğrulanan mesaj
(E): Sertifikanın dönem numarası
(Y): Hat fonksiyonunun değerlendirilmesi
(\text{privtoaddr}(k))'nin ({A_1…A_n}) içinde olup olmadığını kontrol edin
Onayla (y = \text{hash}(k, e) \times \text{hash}(m) + k)
Peki ya birisi bir dönemi iki kez kullanırsa? Sertifika değerleriyle birlikte (m_1) ve (m_2) iki değerini (y_1 = \text{hash}(k, e) \times \text{hash}(m_1) + k) ve (y_2 = \text{hash} ortaya çıkarırlardı. (k, e) \times \text{hash}(m_2) + k). Daha sonra bu iki noktayı çizgiyi ve ardından özel anahtar olan y kesim noktasını kurtarmak için kullanabiliriz.
Yani eğer birisi bir dönemi yeniden kullanırsa, özel anahtarını istemeden herkese açıklamış olur. Bağlama bağlı olarak bu, fon hırsızlığına veya yalnızca özel anahtarın yayınlanmasına ve akıllı bir sözleşmeye entegre edilmesine yol açarak ilgili adresin kaldırılmasına yol açabilir.
Blockchain eşler arası ağlar, sohbet uygulamaları ve benzer sistemler için uygun, zincir dışı anonim hizmet reddi önleme sistemi, herhangi bir çalışma kanıtı gerektirmez. RLN projesi, küçük değişikliklerle (yani, hem sıfırlayıcıları hem de iki nokta çizgisi tekniğini kullanarak, bir çağın yeniden kullanıldığı örnekleri tespit etmeyi daha basit hale getirerek) esasen bu konsepte odaklanmaktadır.
Tam bir anonimlik sunan (kalıcı adınız bile yok), ancak daha yüksek kaliteli içeriği teşvik eden bir itibar sistemine sahip, 4chan gibi çevrimiçi bir forum olan 0chan'ı kurduğunuzu hayal edin. Böyle bir sistem, sistem kurallarını ihlal eden gönderileri işaretleyecek ve üç vuruşlu bir mekanizmayı devreye sokacak bir yönetişim DAO'suna sahip olabilir.
İtibar sistemi olumlu veya olumsuz itibara hitap edebilir; ancak olumsuz itibara uyum sağlamak ek altyapı gerektirir. Bu, kullanıcıların olumsuz olsa bile tüm itibar verilerini kanıtlarına dahil etmelerini gerektirir. Unirep Social'ın uygulamayı amaçladığı şeye benzer şekilde öncelikle bu zorlu kullanım senaryosuna odaklanacağız.
Herkes, gönderiyi içeren zincire ZK-SNARK eşliğinde bir mesaj göndererek gönderi paylaşabilir. Bu ZK-SNARK, (i) size hesap oluşturma izni veren benzersiz bir harici kimliğe sahip olduğunuzun veya (ii) daha önce belirli gönderiler yayınladığınızın bir kanıtı olarak hizmet eder. ZK-SNARK spesifik olarak şu şekilde çalışır:
Sıfırlayıcı, N
En yeni blockchain durum kökü, R
Gönderi içeriği (üzerinde herhangi bir hesaplama yapılmadan, gönderiye bağlanmak için kanıtın içine 'karışık')
Özel anahtarınız, k
Önceki gönderide kullanılan harici kimlik (adres A) veya geçersizleştirici Nprev
Zincirin A veya Nprev içerdiğine dair Merkle kanıtı M
Bu hesabı kullanarak yayınladığınız i. gönderi
M'nin geçerli bir Merkle dalı olduğunu doğrulayın ve (A veya Nprev, hangisi sağlanırsa) kökü R olan bir ağacın yaprağı olduğunu kanıtlayın.
N = enc(i, k)'yi doğrulayın; burada enc bir şifreleme işlevidir (örneğin, AES).
i=0 ise A=privtoaddr(k)'yi doğrulayın, aksi takdirde Nprev=enc(i−1,k)'yi doğrulayın.
Kanıt doğrulamanın yanı sıra, zincir ayrıca (i) R'nin gerçekten yeni bir durum kökü olup olmadığını ve (ii) N geçersizleştiricisinin daha önce kullanılmadığını da kontrol eder. Bu noktaya kadar, daha önce açıklanan gizliliği koruyan madeni paralara benziyor, ancak yeni hesaplar 'basmak' için bir süreç ekledik ve hesabınızı farklı anahtarlara 'gönderme' özelliğini kaldırdık. Bunun yerine, tüm nullifier'lar orijinal anahtar kullanılarak oluşturulur. Sıfırlayıcıyı tersine çevrilebilir hale getirmek için burada enc kullanıyoruz. Eğer k anahtarınız varsa, zincirdeki herhangi bir geçersizleştiricinin şifresini çözebilirsiniz; sonuç rastgele anlamsız ifadeler yerine geçerli bir dizinse (örneğin, dec(N) < 2^64'ü kontrol edebiliriz), geçersiz kılıcının k anahtarı kullanılarak oluşturulduğunu bilirsiniz.
Bu şemada itibar zincir üzerindedir ve açıktır. Bazı akıllı sözleşmeler, bir gönderiyle birlikte yayımlanan geçersiz kılıcıyı ve girdi olarak eklenecek veya çıkarılacak itibar birimlerinin sayısını alan addReputation adı verilen bir yönteme sahiptir.
Her gönderi için zincirde depolanan verileri genişlettik. Yalnızca N geçersizleştiricisini depolamak yerine, {N, h¯, u¯} ı burada saklıyoruz:
h¯ = karma(h, r) burada h, kanıtta başvurulan durum kökünün blok yüksekliğini temsil eder.
u¯ = karma(u, r) burada u, hesabın itibar puanıdır (yeni hesaplar için 0'dan başlar).
Burada R, h ve u'nun kaba kuvvet araması yoluyla bulunmasını önlemek için eklenen rastgele bir değerdir. Kriptografik açıdan R'nin eklenmesi hash'i gizli bir taahhüt haline getirir.
Bir gönderinin root R kullandığını ve {N, h¯, u¯} dosyasını depoladığını varsayalım. Kanıtı kapsamında, {Nprev, h¯prev, u¯prev} verilerini depolayan önceki bir gönderiye bağlantı verir. Gönderinin kanıtı aynı zamanda hprev ve h arasında gönderilen tüm itibar girişlerini de kapsamalıdır. Her N nullifier için, doğrulama fonksiyonu kullanıcının k anahtarını kullanarak N'nin şifresini çözer. Şifre çözme işlemi geçerli bir dizin üretirse itibar güncellemesini uygular. Tüm itibar güncellemelerinin toplamı δ'ye eşitse, u = artış + δ kanıtlanır.
Eğer “üç vuruş yaparsan oyundan çıkarsın” kuralını uygulamak istiyorsak, ZK-SNARK u > -3'ü de garantileyecektir. Temsilcisi ≥ 100 olan bir gönderinin özel bir "yüksek itibarlı gönderi" etiketi alacağı bir kural istiyorsak, bu da yapılabilir.
Bu sistemin ölçeklenebilirliğini arttırmak için onu iki tür mesaja ayırabiliriz: Mesajlar ve RCA'lar. Geçtiğimiz hafta yapılan bir RCA'ya işaret etmeyi gerektirse de, bir gönderi zincir dışı olacaktır. RCA'lar zincir üzerinde olacak ve yayıncının önceki RCA'sından bu yana tüm itibar güncellemelerini kapsayacak. Bu şekilde zincir üzerindeki yük, haftada posta başına bir işleme ve ayrıca her itibar mesajı için bir işleme düşürülür.
Bazen merkezi bir "operatöre" sahip bir sistem tasarlamaya ihtiyaç duyulur. Bunun nedenleri farklılık gösterebilir: Bazen ölçeklenebilirlik, bazen de gizlilik, özellikle de operatör tarafından tutulan verilerin gizliliği içindir. Örneğin, MACI zorlayıcı oylama sistemi, seçmenlerin oylarını merkezi bir operatör tarafından tutulan bir anahtarla şifrelenmiş olarak zincir üzerinde göndermelerini gerektiriyor. Bu operatör, zincirdeki tüm oyların şifresini çözer, bunları sayar ve nihai sonucu görüntüler. Yaptıkları her şeyin doğru olduğunu kanıtlamak için ZK-SNARK'ı kullanıyorlar. Bu ilave karmaşıklık, sağlam bir gizlilik (zorlayıcı direnç olarak bilinir) sağlamak için çok önemlidir: Kullanıcılar isteseler bile, nasıl oy verdiklerini kimseye kanıtlayamazlar. Blockchain ve ZK-SNARK sayesinde operatöre olan güven seviyemiz minimum düzeyde kalıyor. Kötü niyetli operatörler zorlayıcı direnci ihlal edebilir, ancak oylar blok zincirinde yayınlandığı için oyları sansürleyerek hile yapamazlar. Ve ZK-SNARK sağlamaları gerektiğinden, sonuçları yanlış hesaplayarak hile yapamazlar.
ZK-SNARK'ların daha gelişmiş bir kullanımı, girdinin iki veya daha fazla taraf arasında dağıtıldığı ve kanıtın gerekli olduğu hesaplamalardadır ve hiçbir tarafın diğerinin girdisi hakkında bilgi sahibi olmasını istemeyiz. İki taraflı bir senaryoda, bozuk devreler gizlilik gereksinimlerini karşılayabilir; N parti için daha karmaşık çok partili hesaplama protokolleri kullanılabilir. Doğrulanabilir çok taraflı hesaplamalar için ZK-SNARK'lar bu protokollerle entegre edilebilir. Bu, birden fazla katılımcının kendi özel girdileri üzerinde ortak hesaplamalar yapmasına olanak tanıyan gelişmiş itibar sistemlerine olanak tanır. Bunu etkili bir şekilde başarmak için gereken matematik henüz başlangıç aşamasındadır.
ZK-SNARK'lar, kullanıcıların özel durumlarına sahip olduğu sistemlerin oluşturulmasında oldukça etkilidir. Ancak kimsenin bilmediği özel bir devleti sürdüremez. Bilginin kanıtlanabilmesi için kanıtlayıcının onu düz metin olarak bilmesi gerekir. Uniswap özelleştirilmesi zor bir örnek. Uniswap'te merkezi bir mantıksal “varlık” vardır; kimseye ait olmayan likidite sağlayıcı hesabı ve tüm Uniswap işlemleri bu hesapla gerçekleşir. Birisinin bunu kanıtlamak için bu durumu düz metin olarak tutması gerektiğinden ve her işlem bu kişinin aktif katılımını gerektireceğinden, bu hesabın durumunu gizleyemezsiniz. Uniswap'in merkezi, güvenli ve özel bir versiyonunu oluşturmak için ZK-SNARK'ın bozuk devrelerini kullanabilirsiniz, ancak faydaların maliyetlerden daha ağır basıp basmayacağı belli değil. Gerçek bir fayda bile sağlamayabilir: Sözleşmelerin kullanıcıları varlık fiyatları konusunda bilgilendirmesi gerekir ve blok başına fiyat değişimleri işlem etkinliğini ortaya çıkarabilir. Blok zincirleri devlet bilgilerini küreselleştirebilir ve ZK-SNARK'lar bunu özelleştirebilir, ancak devlet bilgilerini aynı anda küreselleştirmenin ve özelleştirmenin sağlam bir yöntemi yoktur.
Yukarıdaki bölümlerde, kendi başlarına güçlü olan ancak aynı zamanda diğer uygulamalar için yapı taşı görevi görebilen araç örneklerini gördük. Para birimleri için hayati öneme sahip geçersiz kılıcılar artık diğer kullanım durumlarında yeniden ortaya çıkıyor. Olumsuz itibar bölümünde kullanılan “zorlayıcı bağlantı” tekniği geniş bir uygulama alanına sahiptir. Kullanıcının "profilinin" zaman içinde karmaşık şekillerde değiştiği ve gizliliği korurken kullanıcıları sistem kurallarına uymaya zorlamak istediğiniz birçok uygulama için son derece etkilidir. Kullanıcılara, tam özel bir Merkle ağacı kullanarak dahili "durumlarını" temsil etme görevi bile verilebilir. Bahsedilen “taahhüt havuzu” aracı ZK-SNARK ile oluşturulabilir. Belirli uygulamalar zincir üzerinde tam olarak çalışamıyorsa ve merkezi bir operatör gerektiriyorsa, aynı teknikler operatörün dürüst olmasını sağlayabilir. ZK-SNARK, hesap verebilirlik ve gizlilik avantajlarını harmanlayan güçlü bir araçtır. Bazı durumlarda sınırlamaları olsa da akıllı uygulama tasarımları bu kısıtlamaları aşabilir. Gelecek yıllarda daha fazla uygulamanın ZK-SNARK'ı benimsediğini ve sonunda ZK-SNARK'ı diğer şifreleme biçimleriyle birleştiren uygulamalar geliştirdiğini görmeyi umuyorum.