Skip to content
Permalink
Browse files

Version 550. Added variable per-block transaction limit for block

assembly.
  • Loading branch information...
n-y-z-o committed Oct 27, 2019
1 parent 871720a commit 2ea08c5183f6cfed97984249ae78bd1be2961245
@@ -18,7 +18,8 @@

public static final long minimumPreferredBalance = 10L * Transaction.micronyzoMultiplierRatio;

public static List<Transaction> approvedTransactionsForBlock(List<Transaction> transactions, Block previousBlock) {
public static List<Transaction> approvedTransactionsForBlock(List<Transaction> transactions, Block previousBlock,
boolean forBlockAssembly) {

// Sort the transactions in block order, then remove all duplicates.
sortTransactions(transactions);
@@ -124,6 +125,28 @@
}
}

// If this method is being used for new-block assembly and the list of approved transactions is larger than
// allowed for the block, remove the smallest transactions until the list is an acceptable size.
int maximumListSize = BlockchainMetricsManager.maximumTransactionsForBlockAssembly();
if (approvedTransactions.size() > maximumListSize && forBlockAssembly) {

// Sort the transactions on amount descending.
approvedTransactions.sort(new Comparator<Transaction>() {
@Override
public int compare(Transaction transaction1, Transaction transaction2) {
return Long.compare(transaction2.getAmount(), transaction1.getAmount());
}
});

// Remove the tail of the list until it is an appropriate size.
while (approvedTransactions.size() > maximumListSize) {
approvedTransactions.remove(approvedTransactions.size() - 1);
}

// Sort the list back to block order.
sortTransactions(approvedTransactions);
}

return approvedTransactions;
}

@@ -563,7 +563,7 @@ public static BalanceList balanceListForNextBlock(Block previousBlock, BalanceLi
// only needs to be performed on blocks past the frozen edge, as blocks that have been frozen are no
// longer subject to scrutiny.
if (previousBlock != null && blockHeight > BlockManager.getFrozenEdgeHeight()) {
transactions = BalanceManager.approvedTransactionsForBlock(transactions, previousBlock);
transactions = BalanceManager.approvedTransactionsForBlock(transactions, previousBlock, false);
}

// Add/subtract all transactions. While doing this, sum the fees, organic transaction fees, and
@@ -487,6 +487,7 @@ public static synchronized void setFrozenEdge(Block block, List<ByteBuffer> cycl
}

updateVerifiersInCurrentCycle(block, cycleVerifiers, isNewVerifier);
BlockchainMetricsManager.registerBlock(block);
}

// Always add the block to the map. This should be done after the frozen edge is set, because the map looks at
@@ -0,0 +1,71 @@
package co.nyzo.verifier;

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

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BlockchainMetricsManager {

// The baseline transaction rate is 10 transactions per second, which is 70 transactions per block.
private static final int baselineTransactionRate = 10;
private static final int baselineTransactionsPerBlock = (int) (Block.blockDuration * baselineTransactionRate /
1000L);

// Above baseline, one transaction is allowed per block for each Nyzo in organic transactions, on average, in the
// previous cycle. This ensures that transaction capacity automatically increases to support additional demand on
// the system while eliminating the possibility of cheap attacks with many small transactions. To enable this
// behavior, the sum of transactions over the previous cycle must be tracked.
private static final Map<Long, Long> blockTransactionSumMap = new ConcurrentHashMap<>();
private static long cycleTransactionSum = 0L;
private static int cycleLength = 1;

public static int maximumTransactionsForBlockAssembly() {
int additionalTransactions = (int) (cycleTransactionSum / Transaction.micronyzoMultiplierRatio / cycleLength);
return baselineTransactionsPerBlock + Math.max(additionalTransactions, 0);
}

public static void registerBlock(Block block) {

// Store the block transaction sum in the map.
long blockSum = standardTransactionSum(block.getTransactions());
blockTransactionSumMap.put(block.getBlockHeight(), blockSum);

// Calculate the cycle sum and, in the same process, remove old values from the map.
long cycleTransactionSum = 0L;
if (block.getCycleInformation() != null) {
long thresholdHeight = block.getBlockHeight() - block.getCycleInformation().getCycleLength();
for (Long height : new HashSet<>(blockTransactionSumMap.keySet())) {
if (height < thresholdHeight) {
blockTransactionSumMap.remove(height);
} else {
cycleTransactionSum += blockTransactionSumMap.get(height);
}
}

// Store the cycle length.
cycleLength = block.getCycleInformation().getCycleLength();
}

// Store the cycle sum.
BlockchainMetricsManager.cycleTransactionSum = cycleTransactionSum;
LogUtil.println("after registering block " + block + " in BlockchainMetricsManager(), cycleTransactionSum=" +
PrintUtil.printAmountWithCommas(BlockchainMetricsManager.cycleTransactionSum) + ", cycleLength=" +
cycleLength);
}

private static long standardTransactionSum(List<Transaction> transactions) {

long sum = 0L;
for (Transaction transaction : transactions) {
if (transaction.getType() == Transaction.typeStandard) {
sum += transaction.getAmount();
}
}

return sum;
}
}
@@ -96,7 +96,14 @@ public static void updateTopVerifier() {
}
}
if (topVerifier == null) {
LogUtil.println("top verifier is null");
if (Verifier.inCycle()) {
LogUtil.println("Top verifier is null. This is likely due to vote scattering, a transition period " +
"between voting windows, or recent restart of this verifier. If this continues for more than " +
"50 blocks, please check your verifier configuration.");
} else {
LogUtil.println("Unable to determine top verifier. This is normal; out-of-cycle verifiers are not " +
"typically notified about new-verifier votes.");
}
} else {
int cycleLength = BlockManager.currentCycleLength();
LogUtil.println(String.format("top verifier %s has %d votes with a cycle length of %d (%.1f%%)",
@@ -15,6 +15,7 @@ public static RunMode getRunMode() {
}

public static void setRunMode(RunMode runMode) {
System.err.println("*** setting run mode of " + runMode + " for version " + Version.getVersion() + " ***");
RunMode.runMode = runMode;
}
}
@@ -87,7 +87,7 @@ public static boolean registerBlock(Block block) {
// Get the map of blocks at this height.
Map<ByteBuffer, Block> blocksAtHeight = unfrozenBlocks.get(block.getBlockHeight());
if (blocksAtHeight == null) {
blocksAtHeight = new HashMap<>();
blocksAtHeight = new ConcurrentHashMap<>();
unfrozenBlocks.put(block.getBlockHeight(), blocksAtHeight);
}

@@ -150,7 +150,7 @@ public static boolean registerBlock(Block block) {
// to avoid having to request it later.
Map<ByteBuffer, Block> disconnectedBlocksForHeight = disconnectedBlocks.get(block.getBlockHeight());
if (disconnectedBlocksForHeight == null) {
disconnectedBlocksForHeight = new HashMap<>();
disconnectedBlocksForHeight = new ConcurrentHashMap<>();
disconnectedBlocks.put(block.getBlockHeight(), disconnectedBlocksForHeight);
}

@@ -685,7 +685,7 @@ private static Block createNextBlock(Block previousBlock, boolean upgradeBlockch

// Check the transactions list, keeping only approved transactions.
List<Transaction> approvedTransactions = BalanceManager.approvedTransactionsForBlock(transactions,
previousBlock);
previousBlock, true);

BalanceList previousBalanceList = BalanceListManager.balanceListForBlock(previousBlock);
if (previousBalanceList != null) {
@@ -2,7 +2,7 @@

public class Version {

private static final int version = 549;
private static final int version = 550;

public static int getVersion() {

@@ -790,7 +790,7 @@ private static Block createNextBlock(Block previousBlock, ManagedVerifier verifi
}

List<Transaction> approvedTransactions = BalanceManager.approvedTransactionsForBlock(transactions,
previousBlock);
previousBlock, true);

BalanceList previousBalanceList = BalanceListManager.balanceListForBlock(previousBlock);
BalanceList balanceList = Block.balanceListForNextBlock(previousBlock, previousBalanceList,
@@ -2,6 +2,9 @@

import co.nyzo.verifier.ByteUtil;
import co.nyzo.verifier.Transaction;
import co.nyzo.verifier.nyzoString.NyzoStringEncoder;
import co.nyzo.verifier.nyzoString.NyzoStringPrivateSeed;
import co.nyzo.verifier.nyzoString.NyzoStringPublicIdentifier;

import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
@@ -145,4 +148,19 @@ public static String superCompactPrintByteBufferList(List<ByteBuffer> list) {

return result.toString();
}

public static String printPublicIdentifier(byte[] identifier) {
NyzoStringPublicIdentifier identifierString = new NyzoStringPublicIdentifier(identifier);
return NyzoStringEncoder.encode(identifierString);
}

public static String printPublicIdentifierExtraWrap(byte[] identifier) {
String normalString = printPublicIdentifier(identifier);
StringBuilder stringWithExtraWrap = new StringBuilder(normalString.charAt(0) + "");
for (int i = 1; i < normalString.length(); i++) {
stringWithExtraWrap.append("&#8203;").append(normalString.charAt(i));
}

return stringWithExtraWrap.toString();
}
}
@@ -7,8 +7,9 @@

private List<HtmlElement> elements = new ArrayList<>();

public void add(HtmlElement element) {
public HtmlElement add(HtmlElement element) {
elements.add(element);
return element;
}

@Override
@@ -23,6 +23,10 @@ public HtmlTag attr(String name, String value) {
return this;
}

public String getAttr(String name) {
return attributes.get(name);
}

public HtmlTag addRaw(String rawHtml) {
elements.add(new RawHtml(rawHtml));
return this;

0 comments on commit 2ea08c5

Please sign in to comment.
You can’t perform that action at this time.