forked from Qortal/qortal
Change to how "best block" is determined.
This commit is contained in:
parent
c559c16a4a
commit
99ffd62a6e
@ -142,12 +142,11 @@ public class BlockGenerator extends Thread {
|
|||||||
|
|
||||||
boolean newBlockGenerated = false;
|
boolean newBlockGenerated = false;
|
||||||
|
|
||||||
generation: try {
|
try {
|
||||||
// Clear repository's "in transaction" state so we don't cause a repository deadlock
|
// Clear repository's "in transaction" state so we don't cause a repository deadlock
|
||||||
repository.discardChanges();
|
repository.discardChanges();
|
||||||
|
|
||||||
List<Block> goodBlocks = new ArrayList<>();
|
List<Block> goodBlocks = new ArrayList<>();
|
||||||
|
|
||||||
for (Block testBlock : newBlocks) {
|
for (Block testBlock : newBlocks) {
|
||||||
// Is new block's timestamp valid yet?
|
// Is new block's timestamp valid yet?
|
||||||
// We do a separate check as some timestamp checks are skipped for testchains
|
// We do a separate check as some timestamp checks are skipped for testchains
|
||||||
@ -162,7 +161,7 @@ public class BlockGenerator extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (goodBlocks.isEmpty())
|
if (goodBlocks.isEmpty())
|
||||||
break generation;
|
continue;
|
||||||
|
|
||||||
// Pick random generator
|
// Pick random generator
|
||||||
int winningIndex = new Random().nextInt(goodBlocks.size());
|
int winningIndex = new Random().nextInt(goodBlocks.size());
|
||||||
@ -182,8 +181,10 @@ public class BlockGenerator extends Thread {
|
|||||||
if (validationResult != ValidationResult.OK) {
|
if (validationResult != ValidationResult.OK) {
|
||||||
// No longer valid? Report and discard
|
// No longer valid? Report and discard
|
||||||
LOGGER.error("Valid, generated block now invalid '" + validationResult.name() + "' after adding unconfirmed transactions?");
|
LOGGER.error("Valid, generated block now invalid '" + validationResult.name() + "' after adding unconfirmed transactions?");
|
||||||
|
|
||||||
|
// Rebuild block candidates, just to be sure
|
||||||
newBlocks.clear();
|
newBlocks.clear();
|
||||||
break generation;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to blockchain - something else will notice and broadcast new block to network
|
// Add to blockchain - something else will notice and broadcast new block to network
|
||||||
|
@ -29,7 +29,7 @@ import org.qora.block.BlockGenerator;
|
|||||||
import org.qora.controller.Synchronizer.SynchronizationResult;
|
import org.qora.controller.Synchronizer.SynchronizationResult;
|
||||||
import org.qora.crypto.Crypto;
|
import org.qora.crypto.Crypto;
|
||||||
import org.qora.data.block.BlockData;
|
import org.qora.data.block.BlockData;
|
||||||
import org.qora.data.network.BlockSummaryData;
|
import org.qora.data.block.BlockSummaryData;
|
||||||
import org.qora.data.network.PeerData;
|
import org.qora.data.network.PeerData;
|
||||||
import org.qora.data.transaction.ArbitraryTransactionData;
|
import org.qora.data.transaction.ArbitraryTransactionData;
|
||||||
import org.qora.data.transaction.ArbitraryTransactionData.DataType;
|
import org.qora.data.transaction.ArbitraryTransactionData.DataType;
|
||||||
|
@ -10,7 +10,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.qora.block.Block;
|
import org.qora.block.Block;
|
||||||
import org.qora.block.Block.ValidationResult;
|
import org.qora.block.Block.ValidationResult;
|
||||||
import org.qora.data.block.BlockData;
|
import org.qora.data.block.BlockData;
|
||||||
import org.qora.data.network.BlockSummaryData;
|
import org.qora.data.block.BlockSummaryData;
|
||||||
import org.qora.data.transaction.TransactionData;
|
import org.qora.data.transaction.TransactionData;
|
||||||
import org.qora.network.Peer;
|
import org.qora.network.Peer;
|
||||||
import org.qora.network.message.BlockMessage;
|
import org.qora.network.message.BlockMessage;
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
package org.qora.data.network;
|
package org.qora.data.block;
|
||||||
|
|
||||||
import org.qora.data.block.BlockData;
|
|
||||||
|
|
||||||
public class BlockSummaryData {
|
public class BlockSummaryData {
|
||||||
|
|
@ -7,7 +7,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.qora.data.network.BlockSummaryData;
|
import org.qora.data.block.BlockSummaryData;
|
||||||
import org.qora.transform.Transformer;
|
import org.qora.transform.Transformer;
|
||||||
import org.qora.transform.block.BlockTransformer;
|
import org.qora.transform.block.BlockTransformer;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.qora.api.model.BlockForgerSummary;
|
import org.qora.api.model.BlockForgerSummary;
|
||||||
import org.qora.data.block.BlockData;
|
import org.qora.data.block.BlockData;
|
||||||
|
import org.qora.data.block.BlockSummaryData;
|
||||||
import org.qora.data.block.BlockTransactionData;
|
import org.qora.data.block.BlockTransactionData;
|
||||||
import org.qora.data.transaction.TransactionData;
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
|
||||||
@ -117,6 +118,11 @@ public interface BlockRepository {
|
|||||||
*/
|
*/
|
||||||
public List<BlockData> getBlocks(int firstBlockHeight, int lastBlockHeight) throws DataException;
|
public List<BlockData> getBlocks(int firstBlockHeight, int lastBlockHeight) throws DataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns block summaries for the passed height range.
|
||||||
|
*/
|
||||||
|
public List<BlockSummaryData> getBlockSummaries(int firstBlockHeight, int lastBlockHeight) throws DataException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves block into repository.
|
* Saves block into repository.
|
||||||
*
|
*
|
||||||
|
@ -9,6 +9,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.qora.api.model.BlockForgerSummary;
|
import org.qora.api.model.BlockForgerSummary;
|
||||||
import org.qora.data.block.BlockData;
|
import org.qora.data.block.BlockData;
|
||||||
|
import org.qora.data.block.BlockSummaryData;
|
||||||
import org.qora.data.block.BlockTransactionData;
|
import org.qora.data.block.BlockTransactionData;
|
||||||
import org.qora.data.transaction.TransactionData;
|
import org.qora.data.transaction.TransactionData;
|
||||||
import org.qora.repository.BlockRepository;
|
import org.qora.repository.BlockRepository;
|
||||||
@ -265,6 +266,31 @@ public class HSQLDBBlockRepository implements BlockRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BlockSummaryData> getBlockSummaries(int firstBlockHeight, int lastBlockHeight) throws DataException {
|
||||||
|
String sql = "SELECT signature, height, generator FROM Blocks WHERE height BETWEEN ? AND ?";
|
||||||
|
|
||||||
|
List<BlockSummaryData> blockSummaries = new ArrayList<>();
|
||||||
|
|
||||||
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, firstBlockHeight, lastBlockHeight)) {
|
||||||
|
if (resultSet == null)
|
||||||
|
return blockSummaries;
|
||||||
|
|
||||||
|
do {
|
||||||
|
byte[] signature = resultSet.getBytes(1);
|
||||||
|
int height = resultSet.getInt(2);
|
||||||
|
byte[] generatorPublicKey = resultSet.getBytes(3);
|
||||||
|
|
||||||
|
BlockSummaryData blockSummary = new BlockSummaryData(height, signature, generatorPublicKey);
|
||||||
|
blockSummaries.add(blockSummary);
|
||||||
|
} while (resultSet.next());
|
||||||
|
|
||||||
|
return blockSummaries;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to fetch height-ranged block summaries from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(BlockData blockData) throws DataException {
|
public void save(BlockData blockData) throws DataException {
|
||||||
HSQLDBSaver saveHelper = new HSQLDBSaver("Blocks");
|
HSQLDBSaver saveHelper = new HSQLDBSaver("Blocks");
|
||||||
|
46
src/main/java/org/qora/utils/ByteArray.java
Normal file
46
src/main/java/org/qora/utils/ByteArray.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package org.qora.utils;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
|
||||||
|
public class ByteArray implements Comparable<ByteArray> {
|
||||||
|
|
||||||
|
private static final Comparator<ByteArray> COMPARATOR;
|
||||||
|
static {
|
||||||
|
COMPARATOR = Comparator.comparing(byteArray -> byteArray.comparable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String comparable;
|
||||||
|
|
||||||
|
public final byte[] raw;
|
||||||
|
|
||||||
|
public ByteArray(byte[] content) {
|
||||||
|
this.comparable = HashCode.fromBytes(content).toString();
|
||||||
|
this.raw = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (this == other)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!(other instanceof ByteArray))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ByteArray otherByteArray = (ByteArray) other;
|
||||||
|
|
||||||
|
return this.comparable.equals(otherByteArray.comparable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.comparable.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(ByteArray other) {
|
||||||
|
return COMPARATOR.compare(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
src/test/java/org/qora/test/ByteArrayTests.java
Normal file
66
src/test/java/org/qora/test/ByteArrayTests.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package org.qora.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.qora.utils.ByteArray;
|
||||||
|
|
||||||
|
public class ByteArrayTests {
|
||||||
|
|
||||||
|
private static List<byte[]> testValues;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createTestValues() {
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
testValues = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
byte[] testValue = new byte[32];
|
||||||
|
random.nextBytes(testValue);
|
||||||
|
testValues.add(testValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fillMap(Map<ByteArray, String> map) {
|
||||||
|
for (byte[] testValue : testValues)
|
||||||
|
map.put(new ByteArray(testValue), String.valueOf(map.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testByteArray() {
|
||||||
|
// Create two objects, which will have different references, but same content.
|
||||||
|
byte[] testValue = testValues.get(0);
|
||||||
|
ByteArray ba1 = new ByteArray(testValue);
|
||||||
|
ByteArray ba2 = new ByteArray(testValue);
|
||||||
|
|
||||||
|
// Confirm JVM-assigned references are different
|
||||||
|
assertNotSame(ba1, ba2);
|
||||||
|
|
||||||
|
// Confirm "equals" works as intended
|
||||||
|
assertTrue("equals did not return true", ba1.equals(ba2));
|
||||||
|
assertEquals("ba1 not equal to ba2", ba1, ba2);
|
||||||
|
|
||||||
|
// Confirm "hashCode" results match
|
||||||
|
assertEquals("hashCodes do not match", ba1.hashCode(), ba2.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testByteArrayMap() {
|
||||||
|
Map<ByteArray, String> testMap = new HashMap<>();
|
||||||
|
fillMap(testMap);
|
||||||
|
|
||||||
|
// Create new ByteArray object with an existing value.
|
||||||
|
ByteArray ba = new ByteArray(testValues.get(3));
|
||||||
|
|
||||||
|
// Confirm object can be found in map
|
||||||
|
assertTrue("ByteArray not found in map", testMap.containsKey(ba));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user