Browse Source

Don't crash, but do report, on mysterious VRF failure

Ian Goldberg 4 years ago
parent
commit
3c41577330
3 changed files with 24 additions and 5 deletions
  1. 7 3
      client.py
  2. 11 1
      relay.py
  3. 6 1
      simulator.py

+ 7 - 3
client.py

@@ -205,8 +205,8 @@ class SinglePassCreatedHandler:
                 dirauth.SNIP.verify(snip, self.channelmgr.consensus,
                         network.thenetwork.dirauthkeys()[0],
                         self.channelmgr.perfstats)
-                # TODO: compute the index, check the VRF, ensure the
-                # SNIP is the correct one
+                # Compute the index, check the VRF, ensure the SNIP is
+                # the correct one
                 pathsel_rand, next_blindkey = relay.Sphinx.client(
                         self.client_key, blinding_keys,
                         onionkey, b'pathsel',
@@ -214,10 +214,14 @@ class SinglePassCreatedHandler:
                 if nextlayer is not None:
                     blinding_keys.append(next_blindkey)
 
-                index = int.from_bytes(relay.VRF.check_output(pathselkey,
+                try:
+                    index = int.from_bytes(relay.VRF.check_output(pathselkey,
                                         pathsel_rand, vrfout,
                                         self.channelmgr.perfstats)[:4],
                                     'big', signed=False)
+                except ValueError as e:
+                    circhandler.close()
+                    raise ValueError(str(e.args) + str(lasthopd))
 
                 indexrange = snip.snipdict["range"]
                 if index < indexrange[0] or index >= indexrange[1]:

+ 11 - 1
relay.py

@@ -14,6 +14,8 @@ import nacl.bindings
 import network
 import dirauth
 
+vrftable = dict()
+
 # Simulated VRF.  The output and proof are of the correct size (32 bytes
 # for the output, 48 bytes for the proof), and we charge the right
 # number of group operations (1 keygen, 2 DH for proving, 3 DH for
@@ -36,6 +38,7 @@ class VRF:
                 encoder=nacl.encoding.RawEncoder) + bytes(16)
         perfstats.keygens += 1
         perfstats.dhs += 2
+        vrftable[proof] = (bytes(vrf_privkey), vrf_input, val, bytes(vrf_pubkey))
         return val, proof
 
     @staticmethod
@@ -48,8 +51,15 @@ class VRF:
         if nacl.hash.sha256(vrf_pubkey + val + vrf_input,
                 encoder=nacl.encoding.RawEncoder) + bytes(16) != \
                 proof:
-            raise ValueError("VRF proof did not verify")
+            t = [nacl.encoding.HexEncoder.encode(x) for x in vrftable[proof]]
+            raise ValueError("VRF proof did not verify: %s %s %s 00x16 ?= %s: %s" % \
+                    (nacl.encoding.HexEncoder.encode(vrf_pubkey),
+                     nacl.encoding.HexEncoder.encode(val),
+                     nacl.encoding.HexEncoder.encode(vrf_input),
+                     nacl.encoding.HexEncoder.encode(proof),
+                     t))
         perfstats.dhs += 3
+        del vrftable[proof]
         return val
 
 

+ 6 - 1
simulator.py

@@ -134,8 +134,13 @@ class Simulator:
 
         lastpercent = -1
         while simtime < 1.0:
-            allcircs.append(
+            try:
+                allcircs.append(
                     random.choice(self.clients).channelmgr.new_circuit())
+            except ValueError as e:
+                self.statslogger.error(str(e))
+                next
+
             simtime += random.expovariate(self.gamma * numclients)
             numcircs += 1
             percent = int(100*simtime)