| 
					
				 | 
			
			
				@@ -1632,6 +1632,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      "7" -- Provides keyword=integer pairs of consensus parameters 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      "8" -- Provides microdescriptor summaries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      "9" -- Provides weights for selecting flagged routers in paths 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     "10" -- Fixes edge case bugs in router flag selection weights 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    Before generating a consensus, an authority must decide which consensus 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    method to use.  To do this, it looks for the highest version number 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1694,22 +1695,25 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       Wme*E + Wee*E == E                          (aka: Wee = 1-Wme) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   We are short 2 constraints with the above set. The remaining constraints 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  come from examining different cases of network load. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  come from examining different cases of network load. The following 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  constraints are used in consensus method 10 and above. There are another 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  incorrect and obsolete set of constraints used for these same cases in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  consensus method 9. For those, see dir-spec.txt in Tor 0.2.2.10-alpha 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  to 0.2.2.16-alpha. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Case 1: E >= T/3 && G >= T/3 (Neither Exit nor Guard Scarce) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    In this case, the additional two constraints are: Wme*E == Wmd*D and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Wgd == 0, which maximizes Exit-flagged bandwidth in the middle position. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    In this case, the additional two constraints are: Wmg == Wmd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Wed == 1/3. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     This leads to the solution: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wgg = (weight_scale*(D+E+G+M))/(3*G) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wmg = weight_scale - Wgg 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wed = weight_scale - Wmd 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       Wgd = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wgd = weight_scale/3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wed = weight_scale/3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wmd = weight_scale/3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wee = (weight_scale*(E+G+M))/(3*E) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wme = weight_scale - Wee 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wmg = (weight_scale*(2*G-E-M))/(3*G) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wgg = weight_scale - Wmg 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Case 2: E < T/3 && G < T/3 (Both are scarce) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1733,25 +1737,35 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Subcase b: R+D >= S 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       In this case, if M <= T/3, we have enough bandwidth to try to achieve 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      a balancing condition, and add the constraints Wgg == 1 and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      Wme*E == Wmd*D: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      a balancing condition. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wgg = weight_scale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wgd = (weight_scale*(D + E - 2*G + M))/(3*D)      (T/3 >= G (Ok)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wmd = (weight_scale*(D + E + G - 2*M))/(6*D)      (T/3 >= M) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wme = (weight_scale*(D + E + G - 2*M))/(6*E) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E)   (2E+M >= T/3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wmg = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wed = weight_scale - Wgd - Wmd 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      Add constraints Wgg = 1, Wmd == Wgd to maximize bandwidth in the guard 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      position while still allowing exits to be used as middle nodes: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      If M >= T/3, the above solution will not be valid (one of the weights 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      will be < 0 or > 1). In this case, we use: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wee = (weight_scale*(E - G + M))/E 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wed = (weight_scale*(D - 2*E + 4*G - 2*M))/(3*D) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wme = (weight_scale*(G-M))/E 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wmg = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wgg = weight_scale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wmd = (weight_scale - Wed)/2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wgd = (weight_scale - Wed)/2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      If this system ends up with any values out of range (ie negative, or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      above weight_scale), use the constraints Wgg == 1 and Wee == 1, since 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      both those positions are scarce: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          Wgg = weight_scale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          Wee = weight_scale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wmg = Wme = Wmd = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wgd = (weight_scale*(D+E-G))/(2*D) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         Wed = weight_scale - Wgd 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wed = (weight_scale*(D - 2*E + G + M))/(3*D) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wmd = (weight_Scale*(D - 2*M + G + E))/(3*D) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wme = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wmg = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wgd = weight_scale - Wed - Wmd 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      If M > T/3, then the Wmd weight above will become negative. Set it to 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      in this case: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wmd = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         Wgd = weight_scale - Wed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Case 3: One of E < T/3 or G < T/3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1759,36 +1773,44 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Subcase a: (S+D) < T/3: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if G=S: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wgg = Wgd = weight_scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wmd = Wed = Wmg = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wme = (weight_scale*(E-M))/(2*E); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wee = weight_scale-Wme; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wgg = Wgd = weight_scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wmd = Wed = Wmg = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Minor subcase, if E is more scarce than M, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // keep its bandwidth in place. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (E < M) Wme = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else Wme = (weight_scale*(E-M))/(2*E); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wee = weight_scale-Wme; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if E=S: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wee = Wed = weight_scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wmd = Wgd = Wmg = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wmg = (weight_scale*(G-M))/(2*G); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wgg = weight_scale-Wmg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wee = Wed = weight_scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wmd = Wgd = Wme = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Minor subcase, if G is more scarce than M, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // keep its bandwidth in place. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (G < M) Wmg = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else Wmg = (weight_scale*(G-M))/(2*G); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Wgg = weight_scale-Wmg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Subcase b: (S+D) >= T/3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if G=S: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Add constraints Wmg = 0, Wme*E == Wmd*D to maximize exit bandwidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        in the middle position: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wgd = (weight_scale*(D + E - 2*G + M))/(3*D); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wmd = (weight_scale*(D + E + G - 2*M))/(6*D); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wme = (weight_scale*(D + E + G - 2*M))/(6*E); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wee = (weight_scale*(-D + 5*E - G + 2*M))/(6*E); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wgg = weight_scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wmg = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wed = weight_scale - Wgd - Wmd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Add constraints Wgg = 1, Wmd == Wed to maximize bandwidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        in the guard position, while still allowing exits to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        used as middle nodes: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wgg = weight_scale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wgd = (weight_scale*(D - 2*G + E + M))/(3*D) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wmg = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wee = (weight_scale*(E+M))/(2*E) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wme = weight_scale - Wee 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wmd = (weight_scale - Wgd)/2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wed = (weight_scale - Wgd)/2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if E=S: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Add constraints Wgd = 0, Wme*E == Wmd*D: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wgg = (weight_scale*(D + E + G + M))/(3*G); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wmd = (weight_scale*(2*D + 2*E - G - M))/(6*D); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wme = (weight_scale*(2*D + 2*E - G - M))/(6*E); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wee = (weight_scale*(-2*D + 4*E + G + M))/(6*E); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wgd = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Add constraints Wee == 1, Wmd == Wgd to maximize bandwidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        in the exit position: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wee = weight_scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wed = (weight_scale*(D - 2*E + G + M))/(3*D); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wme = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wgg = (weight_scale*(G+M))/(2*G); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           Wmg = weight_scale - Wgg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          Wed = weight_scale - Wmd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wmd = (weight_scale - Wed)/2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          Wgd = (weight_scale - Wed)/2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   To ensure consensus, all calculations are performed using integer math 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   with a fixed precision determined by the bwweightscale consensus 
			 |