Commit 110cb012 authored by Karsten Loesing's avatar Karsten Loesing
Browse files

Parse "shared-rand-.*" lines in consensuses and votes.

parent 2bcd6bb0
......@@ -16,6 +16,7 @@
- Parse "proto" lines in server descriptors, "pr" lines in status
entries, and "(recommended|required)-(client|relay)-protocols"
lines in consensuses and votes.
- Parse "shared-rand-.*" lines in consensuses and votes.
# Changes in version 1.5.0 - 2016-10-19
......
......@@ -178,6 +178,40 @@ public interface RelayNetworkStatusConsensus extends Descriptor {
*/
public SortedMap<String, Integer> getConsensusParams();
/**
* Return the number of commits used to generate the second-to-last shared
* random value, or -1 if the consensus does not contain a second-to-last
* shared random value.
*
* @since 1.6.0
*/
public int getSharedRandPreviousNumReveals();
/**
* Return the second-to-last shared random value, encoded in base64, or null
* if the consensus does not contain a second-to-last shared random value.
*
* @since 1.6.0
*/
public String getSharedRandPreviousValue();
/**
* Return the number of commits used to generate the latest shared random
* value, or -1 if the consensus does not contain the latest shared random
* value.
*
* @since 1.6.0
*/
public int getSharedRandCurrentNumReveals();
/**
* Return the latest shared random value, encoded in base64, or null if the
* consensus does not contain the latest shared random value.
*
* @since 1.6.0
*/
public String getSharedRandCurrentValue();
/**
* Return directory source entries for each directory authority that
* contributed to the consensus, with map keys being SHA-1 digests of
......
......@@ -305,6 +305,61 @@ public interface RelayNetworkStatusVote extends Descriptor {
*/
public String getContactLine();
/**
* Return whether this directory authority supports and can participate in
* the shared random protocol.
*
* @since 1.6.0
*/
public boolean isSharedRandParticipate();
/**
* Return all currently known directory authority commit lines for the shared
* randomness protocol in the original format as they are contained in this
* vote, or null if this vote does not contain any such line.
*
* <pre>
* "shared-rand-commit" SP Version SP AlgName SP Identity SP Commit
* [SP Reveal] NL
* </pre>
*
* @since 1.6.0
*/
public List<String> getSharedRandCommitLines();
/**
* Return the number of commits used to generate the second-to-last shared
* random value, or -1 if this vote does not contain a second-to-last shared
* random value.
*
* @since 1.6.0
*/
public int getSharedRandPreviousNumReveals();
/**
* Return the second-to-last shared random value, encoded in base64, or null
* if this vote does not contain a second-to-last shared random value.
*
* @since 1.6.0
*/
public String getSharedRandPreviousValue();
/**
* Return the number of commits used to generate the latest shared random
* value, or -1 if this vote does not contain the latest shared random value.
*
* @since 1.6.0
*/
public int getSharedRandCurrentNumReveals();
/**
* Return the latest shared random value, encoded in base64, or null if this
* vote does not contain the latest shared random value.
*
* @since 1.6.0
*/
public String getSharedRandCurrentValue();
/**
* Return the version of the directory key certificate used by this
* authority, which must be 3 or higher.
......
......@@ -54,8 +54,9 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
Set<String> atMostOnceKeywords = new HashSet<>(Arrays.asList((
"client-versions,server-versions,recommended-client-protocols,"
+ "recommended-relay-protocols,required-client-protocols,"
+ "required-relay-protocols,params,directory-footer,"
+ "bandwidth-weights").split(",")));
+ "required-relay-protocols,params,shared-rand-previous-value,"
+ "shared-rand-current-value,directory-footer,bandwidth-weights")
.split(",")));
this.checkAtMostOnceKeywords(atMostOnceKeywords);
this.checkFirstKeyword("network-status-version");
this.clearParsedKeywords();
......@@ -147,6 +148,12 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
case "params":
this.parseParamsLine(line, parts);
break;
case "shared-rand-previous-value":
this.parseSharedRandPreviousValueLine(line, parts);
break;
case "shared-rand-current-value":
this.parseSharedRandCurrentValueLine(line, parts);
break;
default:
if (this.failUnrecognizedDescriptorLines) {
throw new DescriptorParseException("Unrecognized line '"
......@@ -350,6 +357,36 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
parts, 1, "=");
}
private void parseSharedRandPreviousValueLine(String line, String[] parts)
throws DescriptorParseException {
if (parts.length != 3) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
try {
this.sharedRandPreviousNumReveals = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
this.sharedRandPreviousValue = parts[2];
}
private void parseSharedRandCurrentValueLine(String line, String[] parts)
throws DescriptorParseException {
if (parts.length != 3) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
try {
this.sharedRandCurrentNumReveals = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
this.sharedRandCurrentValue = parts[2];
}
private void parseBandwidthWeightsLine(String line, String[] parts)
throws DescriptorParseException {
this.bandwidthWeights = ParseHelper.parseKeyValueIntegerPairs(line,
......@@ -486,6 +523,34 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
: new TreeMap<>(this.consensusParams);
}
private int sharedRandPreviousNumReveals = -1;
@Override
public int getSharedRandPreviousNumReveals() {
return this.sharedRandPreviousNumReveals;
}
private String sharedRandPreviousValue = null;
@Override
public String getSharedRandPreviousValue() {
return this.sharedRandPreviousValue;
}
private int sharedRandCurrentNumReveals = -1;
@Override
public int getSharedRandCurrentNumReveals() {
return this.sharedRandCurrentNumReveals;
}
private String sharedRandCurrentValue = null;
@Override
public String getSharedRandCurrentValue() {
return this.sharedRandCurrentValue;
}
private SortedMap<String, Integer> bandwidthWeights;
@Override
......
......@@ -54,7 +54,8 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
"consensus-methods,client-versions,server-versions,"
+ "recommended-client-protocols,recommended-relay-protocols,"
+ "required-client-protocols,required-relay-protocols,"
+ "flag-thresholds,params,contact,"
+ "flag-thresholds,params,contact,shared-rand-participate,"
+ "shared-rand-previous-value,shared-rand-current-value,"
+ "legacy-key,dir-key-crosscert,dir-address,directory-footer")
.split(",")));
this.checkAtMostOnceKeywords(atMostOnceKeywords);
......@@ -149,6 +150,18 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
case "contact":
this.parseContactLine(line, parts);
break;
case "shared-rand-participate":
this.parseSharedRandParticipateLine(line, parts);
break;
case "shared-rand-commit":
this.parseSharedRandCommitLine(line, parts);
break;
case "shared-rand-previous-value":
this.parseSharedRandPreviousValueLine(line, parts);
break;
case "shared-rand-current-value":
this.parseSharedRandCurrentValueLine(line, parts);
break;
case "dir-key-certificate-version":
this.parseDirKeyCertificateVersionLine(line, parts);
break;
......@@ -452,6 +465,53 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
}
}
private void parseSharedRandParticipateLine(String line, String[] parts)
throws DescriptorParseException {
if (parts.length != 1) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
this.sharedRandParticipate = true;
}
private void parseSharedRandCommitLine(String line, String[] parts)
throws DescriptorParseException {
if (this.sharedRandCommitLines == null) {
this.sharedRandCommitLines = new ArrayList<>();
}
this.sharedRandCommitLines.add(line);
}
private void parseSharedRandPreviousValueLine(String line, String[] parts)
throws DescriptorParseException {
if (parts.length != 3) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
try {
this.sharedRandPreviousNumReveals = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
this.sharedRandPreviousValue = parts[2];
}
private void parseSharedRandCurrentValueLine(String line, String[] parts)
throws DescriptorParseException {
if (parts.length != 3) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
try {
this.sharedRandCurrentNumReveals = Integer.parseInt(parts[1]);
} catch (NumberFormatException e) {
throw new DescriptorParseException("Illegal line '" + line
+ "' in vote.");
}
this.sharedRandCurrentValue = parts[2];
}
private void parseDirKeyCertificateVersionLine(String line,
String[] parts) throws DescriptorParseException {
if (parts.length != 2) {
......@@ -604,6 +664,48 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
return this.contactLine;
}
private boolean sharedRandParticipate = false;
@Override
public boolean isSharedRandParticipate() {
return this.sharedRandParticipate;
}
private List<String> sharedRandCommitLines = null;
@Override
public List<String> getSharedRandCommitLines() {
return this.sharedRandCommitLines;
}
private int sharedRandPreviousNumReveals = -1;
@Override
public int getSharedRandPreviousNumReveals() {
return this.sharedRandPreviousNumReveals;
}
private String sharedRandPreviousValue = null;
@Override
public String getSharedRandPreviousValue() {
return this.sharedRandPreviousValue;
}
private int sharedRandCurrentNumReveals = -1;
@Override
public int getSharedRandCurrentNumReveals() {
return this.sharedRandCurrentNumReveals;
}
private String sharedRandCurrentValue = null;
@Override
public String getSharedRandCurrentValue() {
return this.sharedRandCurrentValue;
}
private int dirKeyCertificateVersion;
@Override
......
......@@ -188,6 +188,30 @@ public class ConsensusBuilder {
return new RelayNetworkStatusConsensusImpl(cb.buildConsensus(), true);
}
private String sharedRandPreviousValueLine =
"shared-rand-previous-value 8 "
+ "grwbnD6I40odtsdtWYxqs0DvPweCur6qG2Fo5p5ivS4=";
protected static RelayNetworkStatusConsensus
createWithSharedRandPreviousValueLine(String line)
throws DescriptorParseException {
ConsensusBuilder cb = new ConsensusBuilder();
cb.sharedRandPreviousValueLine = line;
return new RelayNetworkStatusConsensusImpl(cb.buildConsensus(), true);
}
private String sharedRandCurrentValueLine =
"shared-rand-current-value 8 "
+ "D88plxd8YeLfCIVAR9gjiFlWB1WqpC53kWr350o1pzw=";
protected static RelayNetworkStatusConsensus
createWithSharedRandCurrentValueLine(String line)
throws DescriptorParseException {
ConsensusBuilder cb = new ConsensusBuilder();
cb.sharedRandCurrentValueLine = line;
return new RelayNetworkStatusConsensusImpl(cb.buildConsensus(), true);
}
List<String> dirSources = new ArrayList<>();
List<String> statusEntries = new ArrayList<>();
......@@ -385,6 +409,12 @@ public class ConsensusBuilder {
if (this.paramsLine != null) {
sb.append(this.paramsLine).append("\n");
}
if (this.sharedRandPreviousValueLine != null) {
sb.append(this.sharedRandPreviousValueLine).append("\n");
}
if (this.sharedRandCurrentValueLine != null) {
sb.append(this.sharedRandCurrentValueLine).append("\n");
}
if (this.unrecognizedHeaderLine != null) {
sb.append(this.unrecognizedHeaderLine).append("\n");
}
......
......@@ -855,6 +855,21 @@ public class RelayNetworkStatusConsensusImplTest {
ConsensusBuilder.createWithParamsLine("params max=2147483648");
}
@Test(expected = DescriptorParseException.class)
public void testSharedRandPreviousNumRevealsOnly()
throws DescriptorParseException {
ConsensusBuilder.createWithSharedRandPreviousValueLine(
"shared-rand-previous-value 8");
}
@Test(expected = DescriptorParseException.class)
public void testSharedRandPreviousExtraArg()
throws DescriptorParseException {
ConsensusBuilder.createWithSharedRandCurrentValueLine(
"shared-rand-current-value 8 "
+ "D88plxd8YeLfCIVAR9gjiFlWB1WqpC53kWr350o1pzw= -1.0");
}
@Test()
public void testDirSourceLegacyNickname()
throws DescriptorParseException {
......
......@@ -252,6 +252,52 @@ public class RelayNetworkStatusVoteImplTest {
return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
}
private String sharedRandParticipateLine = "shared-rand-participate";
private static RelayNetworkStatusVote createWithSharedRandParticipateLine(
String line) throws DescriptorParseException {
VoteBuilder vb = new VoteBuilder();
vb.sharedRandParticipateLine = line;
return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
}
private List<String> sharedRandCommitLines = Arrays.asList(new String[] {
"shared-rand-commit 1 sha3-256 "
+ "0232AF901C31A04EE9848595AF9BB7620D4C5B2E "
+ "AAAAAFieVABh3Aauk2h31FVKaW0xIm28T7VPDkzP5nHwoMItxp7iQg==",
"shared-rand-commit 1 sha3-256 "
+ "14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
+ "AAAAAFieVAA26LuAu9z2UhalmV7zuczWauSkqp1c/bsPA3AkH85iGw==" });
private static RelayNetworkStatusVote createWithSharedRandCommitLines(
List<String> lines) throws DescriptorParseException {
VoteBuilder vb = new VoteBuilder();
vb.sharedRandCommitLines = lines;
return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
}
private String sharedRandPreviousValueLine =
"shared-rand-previous-value 8 "
+ "grwbnD6I40odtsdtWYxqs0DvPweCur6qG2Fo5p5ivS4=";
private static RelayNetworkStatusVote createWithSharedRandPreviousValueLine(
String line) throws DescriptorParseException {
VoteBuilder vb = new VoteBuilder();
vb.sharedRandPreviousValueLine = line;
return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
}
private String sharedRandCurrentValueLine =
"shared-rand-current-value 8 "
+ "D88plxd8YeLfCIVAR9gjiFlWB1WqpC53kWr350o1pzw=";
private static RelayNetworkStatusVote createWithSharedRandCurrentValueLine(
String line) throws DescriptorParseException {
VoteBuilder vb = new VoteBuilder();
vb.sharedRandCurrentValueLine = line;
return new RelayNetworkStatusVoteImpl(vb.buildVote(), true);
}
private String legacyDirKeyLine = null;
private static RelayNetworkStatusVote
......@@ -572,6 +618,20 @@ public class RelayNetworkStatusVoteImplTest {
if (this.contactLine != null) {
sb.append(this.contactLine).append("\n");
}
if (this.sharedRandParticipateLine != null) {
sb.append(this.sharedRandParticipateLine).append("\n");
}
if (this.sharedRandCommitLines != null) {
for (String line : this.sharedRandCommitLines) {
sb.append(line).append("\n");
}
}
if (this.sharedRandPreviousValueLine != null) {
sb.append(this.sharedRandPreviousValueLine).append("\n");
}
if (this.sharedRandCurrentValueLine != null) {
sb.append(this.sharedRandCurrentValueLine).append("\n");
}
if (this.legacyDirKeyLine != null) {
sb.append(this.legacyDirKeyLine).append("\n");
}
......@@ -1252,6 +1312,43 @@ public class RelayNetworkStatusVoteImplTest {
+ "Appelbaum <jacob@appelbaum.net>");
}
@Test(expected = DescriptorParseException.class)
public void testSharedRandParticipateLineDuplicate()
throws DescriptorParseException {
VoteBuilder.createWithSharedRandParticipateLine("shared-rand-participate\n"
+ "shared-rand-participate");
}
@Test(expected = DescriptorParseException.class)
public void testSharedRandParticipateLineArg()
throws DescriptorParseException {
VoteBuilder.createWithSharedRandParticipateLine(
"shared-rand-participate 1");
}
@Test()
public void testSharedRandCommitLinesEmpty() throws DescriptorParseException {
RelayNetworkStatusVote vote =
VoteBuilder.createWithSharedRandCommitLines(null);
assertNull(vote.getSharedRandCommitLines());
}
@Test(expected = DescriptorParseException.class)
public void testSharedRandPreviousValueBeforeNumReveals()
throws DescriptorParseException {
VoteBuilder.createWithSharedRandPreviousValueLine(
"shared-rand-previous-value "
+ "grwbnD6I40odtsdtWYxqs0DvPweCur6qG2Fo5p5ivS4= 8");
}
@Test(expected = DescriptorParseException.class)
public void testSharedRandCurrentNoNumReveals()
throws DescriptorParseException {
VoteBuilder.createWithSharedRandCurrentValueLine(
"shared-rand-current-value "
+ "D88plxd8YeLfCIVAR9gjiFlWB1WqpC53kWr350o1pzw=");
}
@Test()
public void testLegacyDirKeyLine() throws DescriptorParseException {
RelayNetworkStatusVote vote = VoteBuilder.createWithLegacyDirKeyLine(
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment