Skip to content
This repository has been archived by the owner on Feb 15, 2024. It is now read-only.

Commit

Permalink
Version 541. Improvements to join process.
Browse files Browse the repository at this point in the history
  • Loading branch information
n-y-z-o committed Aug 13, 2019
1 parent e6d5f73 commit 36666ca
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 56 deletions.
16 changes: 7 additions & 9 deletions src/main/java/co/nyzo/verifier/Block.java
Expand Up @@ -675,7 +675,7 @@ public long chainScore(long zeroBlockHeight) {


// This score is always relative to a provided block height. The zero block height has a score of zero, and // This score is always relative to a provided block height. The zero block height has a score of zero, and
// each subsequent block affects the score as follows: // each subsequent block affects the score as follows:
// - a new verifier subtracts 2 but adds 4 times the verifier's position in the new-verifier queue // - the preferred new verifier subtracts 2; all others add 10,000
// - an existing verifier adds the difference in cycle length between the previous block and this block, // - an existing verifier adds the difference in cycle length between the previous block and this block,
// multiplied by 4 // multiplied by 4
// - an existing verifier that is no longer in the mesh or shares an IP with another verifier adds 5 // - an existing verifier that is no longer in the mesh or shares an IP with another verifier adds 5
Expand All @@ -698,15 +698,13 @@ public long chainScore(long zeroBlockHeight) {
score = (Math.abs(HashUtil.longSHA256(block.getVerifierIdentifier())) % 9000) * -1L - 1000L; score = (Math.abs(HashUtil.longSHA256(block.getVerifierIdentifier())) % 9000) * -1L - 1000L;


} else { } else {
score -= 2L; // Only allow the top new verifier to join.

ByteBuffer topNewVerifier = NewVerifierVoteManager.topVerifier();
List<ByteBuffer> topNewVerifiers = NewVerifierVoteManager.topVerifiers(); if (topNewVerifier != null &&
ByteBuffer verifierIdentifier = ByteBuffer.wrap(block.getVerifierIdentifier()); ByteUtil.arraysAreEqual(topNewVerifier.array(), block.getVerifierIdentifier())) {
int indexInQueue = topNewVerifiers.indexOf(verifierIdentifier); score -= 2L;
if (indexInQueue < 0 || indexInQueue > 2) {
score += 12L; // maximum of three new in queue; this is behind the queue
} else { } else {
score += indexInQueue * 4L; score += 10000L;
} }


// Penalize for each balance-list spam transaction. // Penalize for each balance-list spam transaction.
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/co/nyzo/verifier/BlockManager.java
Expand Up @@ -656,7 +656,10 @@ private static synchronized void updateVerifiersInCurrentCycle(Block block,
// Build the cycle-and-near set. // Build the cycle-and-near set.
Set<ByteBuffer> currentAndNearCycleSet = ConcurrentHashMap.newKeySet(); Set<ByteBuffer> currentAndNearCycleSet = ConcurrentHashMap.newKeySet();
currentAndNearCycleSet.addAll(currentCycleList); currentAndNearCycleSet.addAll(currentCycleList);
currentAndNearCycleSet.addAll(NewVerifierVoteManager.topVerifiers()); ByteBuffer topNewVerifier = NewVerifierVoteManager.topVerifier();
if (topNewVerifier != null) {
currentAndNearCycleSet.add(topNewVerifier);
}
BlockManager.currentAndNearCycleSet = currentAndNearCycleSet; BlockManager.currentAndNearCycleSet = currentAndNearCycleSet;


// Build the cycle-and-near node set. // Build the cycle-and-near node set.
Expand Down
16 changes: 5 additions & 11 deletions src/main/java/co/nyzo/verifier/BlockVoteManager.java
Expand Up @@ -44,7 +44,7 @@ public static synchronized void registerVote(Message message) {
// Get the map for the height. // Get the map for the height.
Map<ByteBuffer, BlockVote> votesForHeight = voteMap.get(height); Map<ByteBuffer, BlockVote> votesForHeight = voteMap.get(height);
if (votesForHeight == null) { if (votesForHeight == null) {
votesForHeight = new HashMap<>(); votesForHeight = new ConcurrentHashMap<>();
voteMap.put(height, votesForHeight); voteMap.put(height, votesForHeight);
} }


Expand All @@ -62,7 +62,7 @@ public static synchronized void registerVote(Message message) {
// Get the flip map for the height. // Get the flip map for the height.
Map<ByteBuffer, BlockVote> flipVotesForHeight = flipVoteMap.get(height); Map<ByteBuffer, BlockVote> flipVotesForHeight = flipVoteMap.get(height);
if (flipVotesForHeight == null) { if (flipVotesForHeight == null) {
flipVotesForHeight = new HashMap<>(); flipVotesForHeight = new ConcurrentHashMap<>();
flipVoteMap.put(height, flipVotesForHeight); flipVoteMap.put(height, flipVotesForHeight);
} }


Expand Down Expand Up @@ -104,7 +104,7 @@ public static synchronized void removeOldVotes() {
} }
} }


public static synchronized String votesAtHeight(long height) { public static String votesAtHeight(long height) {


int numberOfVotes = 0; int numberOfVotes = 0;
int maximumVotes = 0; int maximumVotes = 0;
Expand All @@ -115,12 +115,7 @@ public static synchronized String votesAtHeight(long height) {
Map<ByteBuffer, Integer> voteCounts = new HashMap<>(); Map<ByteBuffer, Integer> voteCounts = new HashMap<>();
for (BlockVote vote : votesForHeight.values()) { for (BlockVote vote : votesForHeight.values()) {
ByteBuffer hash = ByteBuffer.wrap(vote.getHash()); ByteBuffer hash = ByteBuffer.wrap(vote.getHash());
Integer count = voteCounts.get(hash); int count = voteCounts.getOrDefault(hash, 0) + 1;
if (count == null) {
count = 1;
} else {
count++;
}
voteCounts.put(hash, count); voteCounts.put(hash, count);
maximumVotes = Math.max(maximumVotes, count); maximumVotes = Math.max(maximumVotes, count);
} }
Expand All @@ -131,8 +126,7 @@ public static synchronized String votesAtHeight(long height) {


public static Map<ByteBuffer, BlockVote> votesForHeight(long height) { public static Map<ByteBuffer, BlockVote> votesForHeight(long height) {


Map<ByteBuffer, BlockVote> votesForHeight = voteMap.get(height); return voteMap.get(height);
return votesForHeight == null ? null : new HashMap<>(votesForHeight);
} }


public static byte[] voteForIdentifierAtHeight(byte[] identifier, long height) { public static byte[] voteForIdentifierAtHeight(byte[] identifier, long height) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/co/nyzo/verifier/LockedAccountManager.java
Expand Up @@ -564,7 +564,8 @@ public static void main(String[] args) {


public static boolean isSubjectToLock(Transaction transaction) { public static boolean isSubjectToLock(Transaction transaction) {


return transaction.getType() != Transaction.typeSeed && return transaction.getType() != Transaction.typeCoinGeneration &&
transaction.getType() != Transaction.typeSeed &&
lockedAccounts.contains(ByteBuffer.wrap(transaction.getSenderIdentifier())) && lockedAccounts.contains(ByteBuffer.wrap(transaction.getSenderIdentifier())) &&
!ByteUtil.arraysAreEqual(transaction.getReceiverIdentifier(), BalanceListItem.cycleAccountIdentifier); !ByteUtil.arraysAreEqual(transaction.getReceiverIdentifier(), BalanceListItem.cycleAccountIdentifier);
} }
Expand Down
43 changes: 20 additions & 23 deletions src/main/java/co/nyzo/verifier/NewVerifierVoteManager.java
@@ -1,6 +1,8 @@
package co.nyzo.verifier; package co.nyzo.verifier;


import co.nyzo.verifier.messages.NewVerifierVote; import co.nyzo.verifier.messages.NewVerifierVote;
import co.nyzo.verifier.util.LogUtil;
import co.nyzo.verifier.util.PrintUtil;


import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
Expand Down Expand Up @@ -74,35 +76,30 @@ public static Map<ByteBuffer, Integer> voteTotals() {
return voteTotals; return voteTotals;
} }


public static List<ByteBuffer> topVerifiers() { public static ByteBuffer topVerifier() {


// Make and sort the list descending on votes. // Find the verifier with the most votes. The top vote count is initially at least half of the cycle length,
// which means that the top verifier will remain null if no verifier has the mojority of votes.
ByteBuffer topVerifier = null;
int topVoteCount = (BlockManager.currentCycleLength() + 1) / 2;
Map<ByteBuffer, Integer> voteTotals = voteTotals(); Map<ByteBuffer, Integer> voteTotals = voteTotals();
List<ByteBuffer> topVerifiers = new ArrayList<>(voteTotals.keySet()); for (ByteBuffer verifier : voteTotals.keySet()) {
Collections.sort(topVerifiers, new Comparator<ByteBuffer>() { int voteCount = voteTotals.get(verifier);
@Override if (voteCount > topVoteCount) {
public int compare(ByteBuffer verifierVote1, ByteBuffer verifierVote2) { topVoteCount = voteCount;
Integer voteCount1 = voteTotals.get(verifierVote1); topVerifier = verifier;
Integer voteCount2 = voteTotals.get(verifierVote2);
return voteCount2.compareTo(voteCount1);
} }
});

// Limit the list to three verifiers. We do not consider ties, as they are inconsequential and do not
// justify additional logic complexity.
while (topVerifiers.size() > 3) {
topVerifiers.remove(topVerifiers.size() - 1);
} }

if (topVerifier == null) {
// If the verifiers list is empty and this is a new verifier, add it to the list now. LogUtil.println("top verifier is null");
if (topVerifiers.isEmpty()) { } else {
ByteBuffer verifierIdentifier = ByteBuffer.wrap(Verifier.getIdentifier()); int cycleLength = BlockManager.currentCycleLength();
if (!BlockManager.verifierInCurrentCycle(verifierIdentifier)) { LogUtil.println(String.format("top verifier %s has %d votes with a cycle length of %d (%.1f%%)",
topVerifiers.add(verifierIdentifier); PrintUtil.compactPrintByteArray(topVerifier.array()), topVoteCount, cycleLength,
} topVoteCount * 100.0 / cycleLength));
} }


return topVerifiers; return topVerifier;
} }


public static NewVerifierVote getLocalVote() { public static NewVerifierVote getLocalVote() {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/co/nyzo/verifier/Version.java
Expand Up @@ -2,7 +2,7 @@


public class Version { public class Version {


private static final int version = 540; private static final int version = 541;


public static int getVersion() { public static int getVersion() {


Expand Down
Expand Up @@ -16,8 +16,9 @@ public class BootstrapResponseV2 implements MessageObject {


public BootstrapResponseV2() { public BootstrapResponseV2() {


this.frozenEdgeHeight = BlockManager.getFrozenEdgeHeight(); Block frozenEdge = BlockManager.getFrozenEdge();
this.frozenEdgeHash = BlockManager.frozenBlockForHeight(this.frozenEdgeHeight).getHash(); this.frozenEdgeHeight = frozenEdge == null ? -1 : frozenEdge.getBlockHeight();
this.frozenEdgeHash = frozenEdge == null ? new byte[FieldByteSize.hash] : frozenEdge.getHash();
this.cycleVerifiers = BlockManager.verifiersInCurrentCycleList(); this.cycleVerifiers = BlockManager.verifiersInCurrentCycleList();
} }


Expand Down
Expand Up @@ -32,24 +32,19 @@ public int compare(Node node1, Node node2) {
} }
}); });


// TODO: timestamp in-cycle verifiers with current timestamp to prevent promotion to top of queue when
// TODO: dropping out
// TODO: persist join timestamps to file -- this should be done based on identifier, and they should be
// TODO: reloaded when the verifier is restarted

ByteBuffer currentNewVerifierVote = NewVerifierQueueManager.getCurrentVote(); ByteBuffer currentNewVerifierVote = NewVerifierQueueManager.getCurrentVote();
List<ByteBuffer> topVerifiers = NewVerifierVoteManager.topVerifiers(); ByteBuffer topVerifier = NewVerifierVoteManager.topVerifier();


List<String> lines = new ArrayList<>(); List<String> lines = new ArrayList<>();
for (int i = 0; i < nodes.size() && lines.size() < maximumNumberOfLines; i++) { for (int i = 0; i < nodes.size() && lines.size() < maximumNumberOfLines; i++) {
Node node = nodes.get(i); Node node = nodes.get(i);
byte[] identifier = node.getIdentifier(); byte[] identifier = node.getIdentifier();
int topVerifierIndex = topVerifiers.indexOf(ByteBuffer.wrap(identifier)); boolean isTopVerifier = topVerifier != null && ByteUtil.arraysAreEqual(identifier, topVerifier.array());
boolean isCurrentVote = ByteBuffer.wrap(identifier).equals(currentNewVerifierVote); boolean isCurrentVote = ByteBuffer.wrap(identifier).equals(currentNewVerifierVote);


lines.add((BlockManager.verifierInCurrentCycle(ByteBuffer.wrap(identifier)) ? "C, " : " , ") + lines.add((BlockManager.verifierInCurrentCycle(ByteBuffer.wrap(identifier)) ? "C, " : " , ") +
PrintUtil.compactPrintByteArray(identifier) + ", " + node.getQueueTimestamp() + ", " + PrintUtil.compactPrintByteArray(identifier) + ", " + node.getQueueTimestamp() + ", " +
(topVerifierIndex < 0 ? "-" : topVerifierIndex + "") + ", " + (isCurrentVote ? "*" : "-") + (isTopVerifier ? "*" : "-") + ", " + (isCurrentVote ? "*" : "-") +
", " + NicknameManager.get(identifier)); ", " + NicknameManager.get(identifier));
} }


Expand Down

0 comments on commit 36666ca

Please sign in to comment.