Просмотр исходного кода

research/dkg: Add more comments and complaint challenge handling.

parazyd 3 лет назад
Родитель
Сommit
6c5dbf4f92
1 измененных файлов с 41 добавлено и 20 удалено
  1. 41 20
      script/research/dkg/dkg.sage

+ 41 - 20
script/research/dkg/dkg.sage

@@ -1,8 +1,8 @@
-# Distributed Key Generation
-# A naive approach.
+# Distributed Key Generation scheme
 
-t = 4  # Threshold
+t = 4   # Threshold
 n = 10  # Participants
+assert t <= n
 
 # Pallas
 p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
@@ -24,49 +24,70 @@ shares = {}
 public_values = []
 broadcast_values = {}
 
+# The participants create their random polynomials and broadcast shares.
 for i in range(n):
+    # Pick a random secret
+    coeffs = [Fq.random_element()]
     # Generate random polynomial of degree t
-    coeffs = [Fq.random_element() for _ in range(t+1)]
-    # Set a_0 as a random secret
-    coeffs[0] = Fq.random_element()
+    for _ in range(t):
+        coeffs.append(Fq.random_element())
     polynomials.append(coeffs)
 
     # Compute and send secret shares
-    shares[i+1] = [sum([coeffs[j] * (i+1)**j for j in range(t+1)]) for i in range(n)]
+    shares[i+1] = [sum([coeffs[j] * (k**j) for j in range(t+1)]) for k in range(1, n+1)]
     # Compute public value
     public_values.append(coeffs[0] * G)
-    # Broadcast f_i(1)*G, f_i(2)*G, ..., f_i(n)*G
-    broadcast_values[i+1] = [sum([coeffs[j] * k**j for j in range(t+1)]) * G for k in range(1, n+1)]
+    # Broadcast evaluations of the polynomial at public points
+    broadcast_values[i+1] = [sum([coeffs[j] * (k**j) for j in range(t+1)]) * G for k in range(1, n+1)]
 
 # ====================
 # Step 2: Verification
 # ====================
+
+# In real-world, it is important to ensure that malicious participants
+# cannot raise false complaints to disqualify honest participants.
+# Having a robust mechanism to protect against Sybil attacks or malicious
+# complaint flodding is essential.
 complaints = {}
-for j in range(1, n+1):  # For each participant P_j
-    complaints[j] = []
-    for i in range(1, n+1):  # From each participant P_i
+
+# Initial check against broadcasted values
+for i in range(1, n+1):
+    for j in range(1, n+1):
         if shares[i][j-1] * G != broadcast_values[i][j-1]:
-            complaints[j].append(i)  # P_j complains against P_i
+            if j not in complaints:
+                complaints[j] = []
+            complaints[j].append(i)
+
+# Handle complaints
+for complainant, offenders in complaints.items():
+    for offender in list(offenders):  # Using list() to avoid runtime modification issues
+        # The offender proves they sent a correct share to the complainant
+        revealed_share = sum([polynomials[offender-1][k] * complainant**k for k in range(t+1)])
+        if revealed_share * G == broadcast_values[offender][complainant-1]:
+            complaints[complainant].remove(offender)
+
+# Disqualification step
+disqualified = {i for i, comp in complaints.items() if len(comp) > 0}
 
 # ===================================
 # Step 3: Secret Share Reconstruction
 # ===================================
-disqualified = {i for i, comp in complaints.items() if len(comp) > t}
 
-# Sum the shares of qualified participants to get the group's secret share
-# This is assuming a single party holds enough shares.
-qualified_shares = [shares[i][i-1] for i in range(1, n+1) if i not in disqualified]
+# Sum the secrets of qualified participants to get the group's secret share
+# In a real-world application, this isn't safe and measures should be in
+# place to prevent this scenario.
+qualified_shares = [polynomials[i][0] for i in range(n) if i+1 not in disqualified]
 if len(qualified_shares) < t+1:
-    raise Exception("Too many disqualifications. DKG failed.")
+    raise ValueError("Too many disqualifications. DKG failed.")
 
 group_secret = sum(qualified_shares)
 group_public_0 = group_secret * G
 
 # However we can also do this without ever giving a single party enough
 # shares to reconstruct the secret:
-participant_pubkeys = [shares[i][i-1] * G for i in range(1, n+1) if i not in disqualified]
+participant_pubkeys = [polynomials[i][0] * G for i in range(n) if i+1 not in disqualified]
 if len(participant_pubkeys) < t+1:
-    raise Exception("Too many disqualifications. DKG failed.")
+    raise ValueError("Too many disqualifications. DKG failed.")
 
 group_public_1 = sum(participant_pubkeys)
 assert group_public_0 == group_public_1