Code clean-up thanks to SonarLint & bugfix for ByteArray::compareTo!

This commit is contained in:
catbref 2019-10-15 17:10:13 +01:00
parent a3751823eb
commit 5798c69449
86 changed files with 347 additions and 401 deletions

View File

@ -3,7 +3,6 @@ package org.hsqldb.jdbc;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import org.hsqldb.jdbc.JDBCPool;
import org.hsqldb.jdbc.pool.JDBCPooledConnection; import org.hsqldb.jdbc.pool.JDBCPooledConnection;
public class HSQLDBPool extends JDBCPool { public class HSQLDBPool extends JDBCPool {

View File

@ -34,10 +34,10 @@ public class ApplyUpdate {
private static final String NEW_JAR_FILENAME = AutoUpdate.NEW_JAR_FILENAME; private static final String NEW_JAR_FILENAME = AutoUpdate.NEW_JAR_FILENAME;
private static final String WINDOWS_EXE_LAUNCHER = "qora-core.exe"; private static final String WINDOWS_EXE_LAUNCHER = "qora-core.exe";
private static final long CHECK_INTERVAL = 5 * 1000; // ms private static final long CHECK_INTERVAL = 5 * 1000L; // ms
private static final int MAX_ATTEMPTS = 5; private static final int MAX_ATTEMPTS = 5;
public static void main(String args[]) { public static void main(String[] args) {
Security.insertProviderAt(new BouncyCastleProvider(), 0); Security.insertProviderAt(new BouncyCastleProvider(), 0);
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1); Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);
@ -114,6 +114,7 @@ public class ApplyUpdate {
try { try {
Thread.sleep(CHECK_INTERVAL); Thread.sleep(CHECK_INTERVAL);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// Doggedly retry
} }
} }

View File

@ -1,6 +1,5 @@
package org.qora; package org.qora;
import java.io.IOException;
import java.security.Security; import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
@ -17,15 +16,15 @@ public class ProxyKeys {
System.exit(1); System.exit(1);
} }
public static void main(String argv[]) throws IOException { public static void main(String[] args) {
if (argv.length != 2) if (args.length != 2)
usage(); usage();
Security.insertProviderAt(new BouncyCastleProvider(), 0); Security.insertProviderAt(new BouncyCastleProvider(), 0);
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1); Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);
PrivateKeyAccount privateAccount = new PrivateKeyAccount(null, Base58.decode(argv[0])); PrivateKeyAccount privateAccount = new PrivateKeyAccount(null, Base58.decode(args[0]));
PublicKeyAccount publicAccount = new PublicKeyAccount(null, Base58.decode(argv[1])); PublicKeyAccount publicAccount = new PublicKeyAccount(null, Base58.decode(args[1]));
byte[] proxyPrivateKey = privateAccount.getProxyPrivateKey(publicAccount.getPublicKey()); byte[] proxyPrivateKey = privateAccount.getProxyPrivateKey(publicAccount.getPublicKey());

View File

@ -1,6 +1,5 @@
package org.qora; package org.qora;
import java.io.IOException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import java.util.Random; import java.util.Random;
@ -59,22 +58,22 @@ public class VanityGen {
} }
} }
public static void main(String argv[]) throws IOException { public static void main(String[] args) {
if (argv.length == 0) if (args.length == 0)
usage(); usage();
int threadCount = 1; int threadCount = 1;
int argIndex = 0; int argIndex = 0;
while (argIndex < argv.length) { while (argIndex < args.length) {
String arg = argv[argIndex++]; String arg = args[argIndex++];
if (arg.equals("-t")) { if (arg.equals("-t")) {
if (argIndex >= argv.length) if (argIndex >= args.length)
usage(); usage();
try { try {
threadCount = Integer.parseInt(argv[argIndex++]); threadCount = Integer.parseInt(args[argIndex++]);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
usage(); usage();
} }

View File

@ -13,7 +13,7 @@ public class XorUpdate {
private static final byte XOR_VALUE = AutoUpdate.XOR_VALUE; private static final byte XOR_VALUE = AutoUpdate.XOR_VALUE;
public static void main(String args[]) { public static void main(String[] args) {
if (args.length != 2) { if (args.length != 2) {
System.err.println("usage: XorUpdate <input-file> <output-file>"); System.err.println("usage: XorUpdate <input-file> <output-file>");
System.exit(1); System.exit(1);

View File

@ -142,9 +142,9 @@ public class Account {
byte[] reference = null; byte[] reference = null;
for (TransactionData transactionData : unconfirmedTransactions) { for (TransactionData transactionData : unconfirmedTransactions) {
String address = PublicKeyAccount.getAddress(transactionData.getCreatorPublicKey()); String unconfirmedTransactionAddress = PublicKeyAccount.getAddress(transactionData.getCreatorPublicKey());
if (address.equals(this.address)) if (unconfirmedTransactionAddress.equals(this.address))
reference = transactionData.getSignature(); reference = transactionData.getSignature();
} }

View File

@ -118,7 +118,7 @@ public enum ApiError {
// Groups // Groups
GROUP_UNKNOWN(1101, 404); GROUP_UNKNOWN(1101, 404);
private final static Map<Integer, ApiError> map = stream(ApiError.values()).collect(toMap(apiError -> apiError.code, apiError -> apiError)); private static final Map<Integer, ApiError> map = stream(ApiError.values()).collect(toMap(apiError -> apiError.code, apiError -> apiError));
private final int code; // API error code private final int code; // API error code
private final int status; // HTTP status code private final int status; // HTTP status code

View File

@ -10,12 +10,12 @@ public class ApiException extends WebApplicationException {
private static final long serialVersionUID = 4619299036312089050L; private static final long serialVersionUID = 4619299036312089050L;
// HTTP status code // HTTP status code
public int status; public final int status;
// API error code // API error code
public int error; public final int error;
public String message; public final String message;
public ApiException(int status, int error, String message) { public ApiException(int status, int error, String message) {
this(status, error, message, null); this(status, error, message, null);

View File

@ -47,7 +47,6 @@ public class ApiService {
} }
public Iterable<Class<?>> getResources() { public Iterable<Class<?>> getResources() {
// return resources;
return this.config.getClasses(); return this.config.getClasses();
} }

View File

@ -1,7 +1,7 @@
package org.qora.api; package org.qora.api;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -17,7 +17,7 @@ public class TransactionCountMapXmlAdapter extends XmlAdapter<TransactionCountMa
public static class StringIntegerMap { public static class StringIntegerMap {
@XmlVariableNode("key") @XmlVariableNode("key")
List<MapEntry> entries = new ArrayList<MapEntry>(); List<MapEntry> entries = new ArrayList<>();
} }
public static class MapEntry { public static class MapEntry {
@ -30,7 +30,7 @@ public class TransactionCountMapXmlAdapter extends XmlAdapter<TransactionCountMa
@Override @Override
public Map<TransactionType, Integer> unmarshal(StringIntegerMap stringIntegerMap) throws Exception { public Map<TransactionType, Integer> unmarshal(StringIntegerMap stringIntegerMap) throws Exception {
Map<TransactionType, Integer> map = new HashMap<>(stringIntegerMap.entries.size()); Map<TransactionType, Integer> map = new EnumMap<>(TransactionType.class);
for (MapEntry entry : stringIntegerMap.entries) for (MapEntry entry : stringIntegerMap.entries)
map.put(TransactionType.valueOf(entry.key), entry.value); map.put(TransactionType.valueOf(entry.key), entry.value);

View File

@ -1,6 +1,6 @@
package org.qora.api.model; package org.qora.api.model;
import java.util.HashMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
@ -20,9 +20,10 @@ public class ActivitySummary {
// Assuming TransactionType values are contiguous so 'length' equals count // Assuming TransactionType values are contiguous so 'length' equals count
@XmlJavaTypeAdapter(TransactionCountMapXmlAdapter.class) @XmlJavaTypeAdapter(TransactionCountMapXmlAdapter.class)
public Map<TransactionType, Integer> transactionCountByType = new HashMap<>(); public Map<TransactionType, Integer> transactionCountByType = new EnumMap<>(TransactionType.class);
public ActivitySummary() { public ActivitySummary() {
// Needed for JAXB
} }
} }

View File

@ -30,7 +30,6 @@ import org.qora.api.ApiException;
import org.qora.api.ApiExceptionFactory; import org.qora.api.ApiExceptionFactory;
import org.qora.api.model.ApiOnlineAccount; import org.qora.api.model.ApiOnlineAccount;
import org.qora.api.model.ProxyKeyRequest; import org.qora.api.model.ProxyKeyRequest;
import org.qora.api.resource.TransactionsResource;
import org.qora.asset.Asset; import org.qora.asset.Asset;
import org.qora.controller.Controller; import org.qora.controller.Controller;
import org.qora.crypto.Crypto; import org.qora.crypto.Crypto;

View File

@ -134,18 +134,15 @@ public class AdminResource {
public String shutdown() { public String shutdown() {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
new Thread(new Runnable() { new Thread(() -> {
@Override // Short sleep to allow HTTP response body to be emitted
public void run() { try {
// Short sleep to allow HTTP response body to be emitted Thread.sleep(1000);
try { } catch (InterruptedException e) {
Thread.sleep(1000); // Not important
} catch (InterruptedException e) {
// Not important
}
Controller.getInstance().shutdownAndExit();
} }
Controller.getInstance().shutdownAndExit();
}).start(); }).start();
return "true"; return "true";

View File

@ -66,7 +66,7 @@ public class AnnotationPostProcessor implements ReaderListener {
if (apiErrors == null) if (apiErrors == null)
continue; continue;
LOGGER.trace("Found @ApiErrors annotation on " + clazz.getSimpleName() + "." + method.getName()); LOGGER.trace(() -> String.format("Found @ApiErrors annotation on %s.%s", clazz.getSimpleName(), method.getName()));
PathItem pathItem = getPathItemFromMethod(openAPI, classPathString, method); PathItem pathItem = getPathItemFromMethod(openAPI, classPathString, method);
if (pathItem == null) { if (pathItem == null) {

View File

@ -282,7 +282,7 @@ public class AssetsResource {
List<OrderData> orders = repository.getAssetRepository().getAggregatedOpenOrders(assetId, otherAssetId, limit, offset, reverse); List<OrderData> orders = repository.getAssetRepository().getAggregatedOpenOrders(assetId, otherAssetId, limit, offset, reverse);
// Map to aggregated form // Map to aggregated form
return orders.stream().map(orderData -> new AggregatedOrder(orderData)).collect(Collectors.toList()); return orders.stream().map(AggregatedOrder::new).collect(Collectors.toList());
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }

View File

@ -98,9 +98,7 @@ public class GroupsResource {
ref = "reverse" ref = "reverse"
) @QueryParam("reverse") Boolean reverse) { ) @QueryParam("reverse") Boolean reverse) {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<GroupData> groups = repository.getGroupRepository().getAllGroups(limit, offset, reverse); return repository.getGroupRepository().getAllGroups(limit, offset, reverse);
return groups;
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
@ -126,9 +124,7 @@ public class GroupsResource {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<GroupData> groups = repository.getGroupRepository().getGroupsByOwner(owner); return repository.getGroupRepository().getGroupsByOwner(owner);
return groups;
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
@ -154,9 +150,7 @@ public class GroupsResource {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<GroupData> groups = repository.getGroupRepository().getGroupsWithMember(member); return repository.getGroupRepository().getGroupsWithMember(member);
return groups;
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }

View File

@ -73,7 +73,7 @@ public class NamesResource {
List<NameData> names = repository.getNameRepository().getAllNames(limit, offset, reverse); List<NameData> names = repository.getNameRepository().getAllNames(limit, offset, reverse);
// Convert to summary // Convert to summary
return names.stream().map(nameData -> new NameSummary(nameData)).collect(Collectors.toList()); return names.stream().map(NameSummary::new).collect(Collectors.toList());
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }
@ -102,7 +102,7 @@ public class NamesResource {
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<NameData> names = repository.getNameRepository().getNamesByOwner(address, limit, offset, reverse); List<NameData> names = repository.getNameRepository().getNamesByOwner(address, limit, offset, reverse);
return names.stream().map(nameData -> new NameSummary(nameData)).collect(Collectors.toList()); return names.stream().map(NameSummary::new).collect(Collectors.toList());
} catch (DataException e) { } catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
} }

View File

@ -56,7 +56,7 @@ public class PeersResource {
} }
) )
public List<ConnectedPeer> getPeers() { public List<ConnectedPeer> getPeers() {
return Network.getInstance().getConnectedPeers().stream().map(peer -> new ConnectedPeer(peer)).collect(Collectors.toList()); return Network.getInstance().getConnectedPeers().stream().map(ConnectedPeer::new).collect(Collectors.toList());
} }
@GET @GET

View File

@ -311,7 +311,7 @@ public class TransactionsResource {
txTypes, null, address, confirmationStatus, limit, offset, reverse); txTypes, null, address, confirmationStatus, limit, offset, reverse);
// Expand signatures to transactions // Expand signatures to transactions
List<TransactionData> transactions = new ArrayList<TransactionData>(signatures.size()); List<TransactionData> transactions = new ArrayList<>(signatures.size());
for (byte[] signature : signatures) for (byte[] signature : signatures)
transactions.add(repository.getTransactionRepository().fromSignature(signature)); transactions.add(repository.getTransactionRepository().fromSignature(signature));

View File

@ -229,14 +229,15 @@ public class Order {
final boolean isOrderNewAssetPricing = orderData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp(); final boolean isOrderNewAssetPricing = orderData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp();
final long haveAssetId = orderData.getHaveAssetId(); // Cached for readability
final long wantAssetId = orderData.getWantAssetId(); final long _haveAssetId = orderData.getHaveAssetId();
final long _wantAssetId = orderData.getWantAssetId();
final AssetData haveAssetData = this.repository.getAssetRepository().fromAssetId(haveAssetId); final AssetData haveAssetData = this.repository.getAssetRepository().fromAssetId(_haveAssetId);
final AssetData wantAssetData = this.repository.getAssetRepository().fromAssetId(wantAssetId); final AssetData wantAssetData = this.repository.getAssetRepository().fromAssetId(_wantAssetId);
final long amountAssetId = (isOurOrderNewPricing && wantAssetId > haveAssetId) ? wantAssetId : haveAssetId; final long amountAssetId = (isOurOrderNewPricing && _wantAssetId > _haveAssetId) ? _wantAssetId : _haveAssetId;
final long returnAssetId = (isOurOrderNewPricing && haveAssetId < wantAssetId) ? haveAssetId : wantAssetId; final long returnAssetId = (isOurOrderNewPricing && _haveAssetId < _wantAssetId) ? _haveAssetId : _wantAssetId;
final AssetData amountAssetData = this.repository.getAssetRepository().fromAssetId(amountAssetId); final AssetData amountAssetData = this.repository.getAssetRepository().fromAssetId(amountAssetId);
final AssetData returnAssetData = this.repository.getAssetRepository().fromAssetId(returnAssetId); final AssetData returnAssetData = this.repository.getAssetRepository().fromAssetId(returnAssetId);

View File

@ -45,7 +45,7 @@ public class AT {
byte[] creationBytes = deployATTransactionData.getCreationBytes(); byte[] creationBytes = deployATTransactionData.getCreationBytes();
long assetId = deployATTransactionData.getAssetId(); long assetId = deployATTransactionData.getAssetId();
short version = (short) (creationBytes[0] | (creationBytes[1] << 8)); // Little-endian short version = (short) ((creationBytes[0] & 0xff) | (creationBytes[1] << 8)); // Little-endian
if (version >= 2) { if (version >= 2) {
MachineState machineState = new MachineState(deployATTransactionData.getCreationBytes()); MachineState machineState = new MachineState(deployATTransactionData.getCreationBytes());
@ -78,7 +78,7 @@ public class AT {
// Extract actual code length, stored in minimal-size form (byte, short or int) // Extract actual code length, stored in minimal-size form (byte, short or int)
if (numCodePages * 256 < 257) { if (numCodePages * 256 < 257) {
codeLen = (int) (byteBuffer.get() & 0xff); codeLen = byteBuffer.get() & 0xff;
} else if (numCodePages * 256 < Short.MAX_VALUE + 1) { } else if (numCodePages * 256 < Short.MAX_VALUE + 1) {
codeLen = byteBuffer.getShort() & 0xffff; codeLen = byteBuffer.getShort() & 0xffff;
} else if (numCodePages * 256 <= Integer.MAX_VALUE) { } else if (numCodePages * 256 <= Integer.MAX_VALUE) {
@ -135,14 +135,14 @@ public class AT {
byte[] codeBytes = this.atData.getCodeBytes(); byte[] codeBytes = this.atData.getCodeBytes();
// Fetch latest ATStateData for this AT (if any) // Fetch latest ATStateData for this AT (if any)
ATStateData atStateData = this.repository.getATRepository().getLatestATState(atAddress); ATStateData latestAtStateData = this.repository.getATRepository().getLatestATState(atAddress);
// There should be at least initial AT state data // There should be at least initial AT state data
if (atStateData == null) if (latestAtStateData == null)
throw new IllegalStateException("No initial AT state data found"); throw new IllegalStateException("No initial AT state data found");
// [Re]create AT machine state using AT state data or from scratch as applicable // [Re]create AT machine state using AT state data or from scratch as applicable
MachineState state = MachineState.fromBytes(api, logger, atStateData.getStateData(), codeBytes); MachineState state = MachineState.fromBytes(api, logger, latestAtStateData.getStateData(), codeBytes);
state.execute(); state.execute();
int height = this.repository.getBlockRepository().getBlockchainHeight() + 1; int height = this.repository.getBlockRepository().getBlockchainHeight() + 1;

View File

@ -115,7 +115,7 @@ public enum BlockchainAPI {
public final int value; public final int value;
private final static Map<Integer, BlockchainAPI> map = stream(BlockchainAPI.values()).collect(toMap(type -> type.value, type -> type)); private static final Map<Integer, BlockchainAPI> map = stream(BlockchainAPI.values()).collect(toMap(type -> type.value, type -> type));
BlockchainAPI(int value) { BlockchainAPI(int value) {
this.value = value; this.value = value;

View File

@ -52,7 +52,7 @@ public class QoraATAPI extends API {
public QoraATAPI(Repository repository, ATData atData, long blockTimestamp) { public QoraATAPI(Repository repository, ATData atData, long blockTimestamp) {
this.repository = repository; this.repository = repository;
this.atData = atData; this.atData = atData;
this.transactions = new ArrayList<AtTransaction>(); this.transactions = new ArrayList<>();
this.blockTimestamp = blockTimestamp; this.blockTimestamp = blockTimestamp;
} }

View File

@ -2,7 +2,6 @@ package org.qora.at;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qora.at.AT;
public class QoraATLogger implements org.ciyam.at.LoggerInterface { public class QoraATLogger implements org.ciyam.at.LoggerInterface {

View File

@ -1,6 +1,6 @@
package org.qora.at; package org.qora.at;
import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -37,14 +37,10 @@ public enum QoraFunctionCode {
protected void postCheckExecute(FunctionData functionData, MachineState state, short rawFunctionCode) throws ExecutionException { protected void postCheckExecute(FunctionData functionData, MachineState state, short rawFunctionCode) throws ExecutionException {
Timestamp timestamp = new Timestamp(functionData.value2); Timestamp timestamp = new Timestamp(functionData.value2);
try { String recipient = new String(state.getB(), StandardCharsets.UTF_8);
String recipient = new String(state.getB(), "UTF-8");
BlockchainAPI blockchainAPI = BlockchainAPI.valueOf(timestamp.blockchainId); BlockchainAPI blockchainAPI = BlockchainAPI.valueOf(timestamp.blockchainId);
blockchainAPI.putTransactionFromRecipientAfterTimestampInA(recipient, timestamp, state); blockchainAPI.putTransactionFromRecipientAfterTimestampInA(recipient, timestamp, state);
} catch (UnsupportedEncodingException e) {
throw new ExecutionException("Couldn't parse recipient from B", e);
}
} }
}; };
@ -102,6 +98,6 @@ public enum QoraFunctionCode {
} }
/** Actually execute function */ /** Actually execute function */
abstract protected void postCheckExecute(FunctionData functionData, MachineState state, short rawFunctionCode) throws ExecutionException; protected abstract void postCheckExecute(FunctionData functionData, MachineState state, short rawFunctionCode) throws ExecutionException;
} }

View File

@ -2,6 +2,7 @@ package org.qora.block;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -204,7 +205,7 @@ public class BlockGenerator extends Thread {
ValidationResult validationResult = newBlock.isValid(); ValidationResult validationResult = newBlock.isValid();
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(String.format("Valid, generated block now invalid '%s' after adding unconfirmed transactions?", validationResult.name()));
// Rebuild block candidates, just to be sure // Rebuild block candidates, just to be sure
newBlocks.clear(); newBlocks.clear();
@ -215,7 +216,7 @@ public class BlockGenerator extends Thread {
try { try {
newBlock.process(); newBlock.process();
LOGGER.info("Generated new block: " + newBlock.getBlockData().getHeight()); LOGGER.info(String.format("Generated new block: %d", newBlock.getBlockData().getHeight()));
repository.saveChanges(); repository.saveChanges();
ProxyForgerData proxyForgerData = repository.getAccountRepository().getProxyForgeData(newBlock.getBlockData().getGeneratorPublicKey()); ProxyForgerData proxyForgerData = repository.getAccountRepository().getProxyForgeData(newBlock.getBlockData().getGeneratorPublicKey());
@ -292,24 +293,15 @@ public class BlockGenerator extends Thread {
// Grab all valid unconfirmed transactions (already sorted) // Grab all valid unconfirmed transactions (already sorted)
List<TransactionData> unconfirmedTransactions = Transaction.getUnconfirmedTransactions(repository); List<TransactionData> unconfirmedTransactions = Transaction.getUnconfirmedTransactions(repository);
for (int i = 0; i < unconfirmedTransactions.size(); ++i) { Iterator<TransactionData> unconfirmedTransactionsIterator = unconfirmedTransactions.iterator();
TransactionData transactionData = unconfirmedTransactions.get(i); final long newBlockTimestamp = newBlock.getBlockData().getTimestamp();
while (unconfirmedTransactionsIterator.hasNext()) {
TransactionData transactionData = unconfirmedTransactionsIterator.next();
// Ignore transactions that have timestamp later than block's timestamp (not yet valid) // Ignore transactions that have timestamp later than block's timestamp (not yet valid)
if (transactionData.getTimestamp() > newBlock.getBlockData().getTimestamp()) {
unconfirmedTransactions.remove(i);
--i;
continue;
}
Transaction transaction = Transaction.fromData(repository, transactionData);
// Ignore transactions that have expired before this block - they will be cleaned up later // Ignore transactions that have expired before this block - they will be cleaned up later
if (transaction.getDeadline() <= newBlock.getBlockData().getTimestamp()) { if (transactionData.getTimestamp() > newBlockTimestamp || Transaction.getDeadline(transactionData) <= newBlockTimestamp)
unconfirmedTransactions.remove(i); unconfirmedTransactionsIterator.remove();
--i;
continue;
}
} }
// Sign to create block's signature, needed by Block.isValid() // Sign to create block's signature, needed by Block.isValid()
@ -324,7 +316,7 @@ public class BlockGenerator extends Thread {
// If newBlock is no longer valid then we can't use transaction // If newBlock is no longer valid then we can't use transaction
ValidationResult validationResult = newBlock.isValid(); ValidationResult validationResult = newBlock.isValid();
if (validationResult != ValidationResult.OK) { if (validationResult != ValidationResult.OK) {
LOGGER.debug("Skipping invalid transaction " + Base58.encode(transactionData.getSignature()) + " during block generation"); LOGGER.debug(() -> String.format("Skipping invalid transaction %s during block generation", Base58.encode(transactionData.getSignature())));
newBlock.deleteTransaction(transactionData); newBlock.deleteTransaction(transactionData);
} }
} }

View File

@ -54,7 +54,7 @@ public class GenesisBlock extends Block {
} }
// Properties // Properties
private static BlockData blockData; private static BlockData genesisBlockData;
private static List<TransactionData> transactionsData; private static List<TransactionData> transactionsData;
private static List<AssetData> initialAssets; private static List<AssetData> initialAssets;
@ -65,7 +65,7 @@ public class GenesisBlock extends Block {
} }
public static GenesisBlock getInstance(Repository repository) throws DataException { public static GenesisBlock getInstance(Repository repository) throws DataException {
return new GenesisBlock(repository, blockData, transactionsData); return new GenesisBlock(repository, genesisBlockData, transactionsData);
} }
// Construction from JSON // Construction from JSON
@ -73,7 +73,7 @@ public class GenesisBlock extends Block {
/** Construct block data from blockchain config */ /** Construct block data from blockchain config */
public static void newInstance(GenesisInfo info) { public static void newInstance(GenesisInfo info) {
// Should be safe to make this call as BlockChain's instance is set // Should be safe to make this call as BlockChain's instance is set
// so we won't be blocked trying to re-enter synchronzied Settings.getInstance() // so we won't be blocked trying to re-enter synchronized Settings.getInstance()
BlockChain blockchain = BlockChain.getInstance(); BlockChain blockchain = BlockChain.getInstance();
// Timestamp of zero means "now" but only valid for test nets! // Timestamp of zero means "now" but only valid for test nets!
@ -87,7 +87,7 @@ public class GenesisBlock extends Block {
info.timestamp = System.currentTimeMillis(); info.timestamp = System.currentTimeMillis();
} }
transactionsData = new ArrayList<TransactionData>(Arrays.asList(info.transactions)); transactionsData = new ArrayList<>(Arrays.asList(info.transactions));
// Add default values to transactions // Add default values to transactions
transactionsData.stream().forEach(transactionData -> { transactionsData.stream().forEach(transactionData -> {
@ -133,7 +133,7 @@ public class GenesisBlock extends Block {
int atCount = 0; int atCount = 0;
BigDecimal atFees = BigDecimal.ZERO.setScale(8); BigDecimal atFees = BigDecimal.ZERO.setScale(8);
blockData = new BlockData(info.version, reference, transactionCount, totalFees, transactionsSignature, height, info.timestamp, genesisBlockData = new BlockData(info.version, reference, transactionCount, totalFees, transactionsSignature, height, info.timestamp,
generatorPublicKey, generatorSignature, atCount, atFees); generatorPublicKey, generatorSignature, atCount, atFees);
} }
@ -246,14 +246,14 @@ public class GenesisBlock extends Block {
@Override @Override
public boolean isSignatureValid() { public boolean isSignatureValid() {
byte[] signature = calcSignature(this.getBlockData()); byte[] signature = calcSignature(this.blockData);
// Validate block signature // Validate block signature
if (!Arrays.equals(signature, this.getBlockData().getGeneratorSignature())) if (!Arrays.equals(signature, this.blockData.getGeneratorSignature()))
return false; return false;
// Validate transactions signature // Validate transactions signature
if (!Arrays.equals(signature, this.getBlockData().getTransactionsSignature())) if (!Arrays.equals(signature, this.blockData.getTransactionsSignature()))
return false; return false;
return true; return true;
@ -275,10 +275,10 @@ public class GenesisBlock extends Block {
@Override @Override
public void process() throws DataException { public void process() throws DataException {
LOGGER.info(String.format("Using genesis block timestamp of %d", blockData.getTimestamp())); LOGGER.info(String.format("Using genesis block timestamp of %d", this.blockData.getTimestamp()));
// If we're a version 1 genesis block, create assets now // If we're a version 1 genesis block, create assets now
if (blockData.getVersion() == 1) if (this.blockData.getVersion() == 1)
for (AssetData assetData : initialAssets) for (AssetData assetData : initialAssets)
repository.getAssetRepository().save(assetData); repository.getAssetRepository().save(assetData);

View File

@ -6,7 +6,7 @@ import com.google.common.hash.HashCode;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class brokenmd160 { public class brokenmd160 {
public static void main(String args[]) { public static void main(String[] args) {
if (args.length == 0) { if (args.length == 0) {
System.err.println("usage: broken-md160 <hex>\noutputs: hex"); System.err.println("usage: broken-md160 <hex>\noutputs: hex");
System.exit(1); System.exit(1);

View File

@ -64,7 +64,7 @@ public class ArbitraryDataManager extends Thread {
} }
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
return; // Fall-through to exit thread...
} }
} }
@ -76,7 +76,7 @@ public class ArbitraryDataManager extends Thread {
private boolean hasLocalData(final Repository repository, final byte[] signature) { private boolean hasLocalData(final Repository repository, final byte[] signature) {
try { try {
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature); TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
if (transactionData == null || !(transactionData instanceof ArbitraryTransactionData)) if (!(transactionData instanceof ArbitraryTransactionData))
return true; return true;
ArbitraryTransaction arbitraryTransaction = new ArbitraryTransaction(repository, transactionData); ArbitraryTransaction arbitraryTransaction = new ArbitraryTransaction(repository, transactionData);

View File

@ -39,7 +39,7 @@ public class AutoUpdate extends Thread {
public static final String NEW_JAR_FILENAME = "new-" + JAR_FILENAME; public static final String NEW_JAR_FILENAME = "new-" + JAR_FILENAME;
private static final Logger LOGGER = LogManager.getLogger(AutoUpdate.class); private static final Logger LOGGER = LogManager.getLogger(AutoUpdate.class);
private static final long CHECK_INTERVAL = 5 * 60 * 1000; // ms private static final long CHECK_INTERVAL = 5 * 60 * 1000L; // ms
private static final int DEV_GROUP_ID = 1; private static final int DEV_GROUP_ID = 1;
private static final int UPDATE_SERVICE = 1; private static final int UPDATE_SERVICE = 1;
@ -65,6 +65,7 @@ public class AutoUpdate extends Thread {
return instance; return instance;
} }
@Override
public void run() { public void run() {
Thread.currentThread().setName("Auto-update"); Thread.currentThread().setName("Auto-update");
@ -94,7 +95,7 @@ public class AutoUpdate extends Thread {
continue; continue;
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signatures.get(0)); TransactionData transactionData = repository.getTransactionRepository().fromSignature(signatures.get(0));
if (transactionData == null || !(transactionData instanceof ArbitraryTransactionData)) if (!(transactionData instanceof ArbitraryTransactionData))
continue; continue;
// Transaction needs to be newer than this build // Transaction needs to be newer than this build

View File

@ -97,21 +97,21 @@ public class Controller extends Thread {
public static final String VERSION_PREFIX = "qora-core-"; public static final String VERSION_PREFIX = "qora-core-";
private static final Logger LOGGER = LogManager.getLogger(Controller.class); private static final Logger LOGGER = LogManager.getLogger(Controller.class);
private static final long MISBEHAVIOUR_COOLOFF = 10 * 60 * 1000; // ms private static final long MISBEHAVIOUR_COOLOFF = 10 * 60 * 1000L; // ms
private static final int MAX_BLOCKCHAIN_TIP_AGE = 5; // blocks private static final int MAX_BLOCKCHAIN_TIP_AGE = 5; // blocks
private static final Object shutdownLock = new Object(); private static final Object shutdownLock = new Object();
private static final String repositoryUrlTemplate = "jdbc:hsqldb:file:%s/blockchain;create=true;hsqldb.full_log_replay=true"; private static final String repositoryUrlTemplate = "jdbc:hsqldb:file:%s/blockchain;create=true;hsqldb.full_log_replay=true";
private static final long ARBITRARY_REQUEST_TIMEOUT = 5 * 1000; // ms private static final long ARBITRARY_REQUEST_TIMEOUT = 5 * 1000L; // ms
private static final long REPOSITORY_BACKUP_PERIOD = 123 * 60 * 1000; // ms private static final long REPOSITORY_BACKUP_PERIOD = 123 * 60 * 1000L; // ms
private static final long NTP_PRE_SYNC_CHECK_PERIOD = 5 * 1000; // ms private static final long NTP_PRE_SYNC_CHECK_PERIOD = 5 * 1000L; // ms
private static final long NTP_POST_SYNC_CHECK_PERIOD = 5 * 60 * 1000; // ms private static final long NTP_POST_SYNC_CHECK_PERIOD = 5 * 60 * 1000L; // ms
private static final long DELETE_EXPIRED_INTERVAL = 5 * 60 * 1000; // ms private static final long DELETE_EXPIRED_INTERVAL = 5 * 60 * 1000L; // ms
// To do with online accounts list // To do with online accounts list
private static final long ONLINE_ACCOUNTS_TASKS_INTERVAL = 10 * 1000; // ms private static final long ONLINE_ACCOUNTS_TASKS_INTERVAL = 10 * 1000L; // ms
private static final long ONLINE_ACCOUNTS_BROADCAST_INTERVAL = 1 * 60 * 1000; // ms private static final long ONLINE_ACCOUNTS_BROADCAST_INTERVAL = 1 * 60 * 1000L; // ms
private static final long ONLINE_TIMESTAMP_MODULUS = 5 * 60 * 1000; private static final long ONLINE_TIMESTAMP_MODULUS = 5 * 60 * 1000L;
private static final long LAST_SEEN_EXPIRY_PERIOD = (ONLINE_TIMESTAMP_MODULUS * 2) + (1 * 60 * 1000); private static final long LAST_SEEN_EXPIRY_PERIOD = (ONLINE_TIMESTAMP_MODULUS * 2) + (1 * 60 * 1000L);
private static volatile boolean isStopping = false; private static volatile boolean isStopping = false;
private static BlockGenerator blockGenerator = null; private static BlockGenerator blockGenerator = null;
@ -170,18 +170,18 @@ public class Controller extends Thread {
throw new RuntimeException("Can't read build.properties resource", e); throw new RuntimeException("Can't read build.properties resource", e);
} }
String buildTimestamp = properties.getProperty("build.timestamp"); String buildTimestampProperty = properties.getProperty("build.timestamp");
if (buildTimestamp == null) if (buildTimestampProperty == null)
throw new RuntimeException("Can't read build.timestamp from build.properties resource"); throw new RuntimeException("Can't read build.timestamp from build.properties resource");
this.buildTimestamp = LocalDateTime.parse(buildTimestamp, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")).toEpochSecond(ZoneOffset.UTC); this.buildTimestamp = LocalDateTime.parse(buildTimestampProperty, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")).toEpochSecond(ZoneOffset.UTC);
LOGGER.info(String.format("Build timestamp: %s", buildTimestamp)); LOGGER.info(String.format("Build timestamp: %s", buildTimestampProperty));
String buildVersion = properties.getProperty("build.version"); String buildVersionProperty = properties.getProperty("build.version");
if (buildVersion == null) if (buildVersionProperty == null)
throw new RuntimeException("Can't read build.version from build.properties resource"); throw new RuntimeException("Can't read build.version from build.properties resource");
this.buildVersion = VERSION_PREFIX + buildVersion; this.buildVersion = VERSION_PREFIX + buildVersionProperty;
LOGGER.info(String.format("Build version: %s", this.buildVersion)); LOGGER.info(String.format("Build version: %s", this.buildVersion));
} }
@ -231,7 +231,7 @@ public class Controller extends Thread {
// Entry point // Entry point
public static void main(String args[]) { public static void main(String[] args) {
LOGGER.info("Starting up..."); LOGGER.info("Starting up...");
// Potential GUI startup with splash screen, etc. // Potential GUI startup with splash screen, etc.
@ -282,7 +282,7 @@ public class Controller extends Thread {
LOGGER.info("Starting controller"); LOGGER.info("Starting controller");
Controller.getInstance().start(); Controller.getInstance().start();
LOGGER.info("Starting networking on port " + Settings.getInstance().getListenPort()); LOGGER.info(String.format("Starting networking on port %d", Settings.getInstance().getListenPort()));
try { try {
Network network = Network.getInstance(); Network network = Network.getInstance();
network.start(); network.start();
@ -312,7 +312,7 @@ public class Controller extends Thread {
LOGGER.info("Starting auto-update"); LOGGER.info("Starting auto-update");
AutoUpdate.getInstance().start(); AutoUpdate.getInstance().start();
LOGGER.info("Starting API on port " + Settings.getInstance().getApiPort()); LOGGER.info(String.format("Starting API on port %d", Settings.getInstance().getApiPort()));
try { try {
ApiService apiService = ApiService.getInstance(); ApiService apiService = ApiService.getInstance();
apiService.start(); apiService.start();
@ -321,7 +321,7 @@ public class Controller extends Thread {
System.exit(1); System.exit(1);
} }
LOGGER.info("Starting node management UI on port " + Settings.getInstance().getUiPort()); LOGGER.info(String.format("Starting node management UI on port %d", Settings.getInstance().getUiPort()));
try { try {
UiService uiService = UiService.getInstance(); UiService uiService = UiService.getInstance();
uiService.start(); uiService.start();
@ -335,7 +335,7 @@ public class Controller extends Thread {
} }
/** Called by AdvancedInstaller's launch EXE in single-instance mode, when an instance is already running. */ /** Called by AdvancedInstaller's launch EXE in single-instance mode, when an instance is already running. */
public static void secondaryMain(String args[]) { public static void secondaryMain(String[] args) {
// Return as we don't want to run more than one instance // Return as we don't want to run more than one instance
} }
@ -670,7 +670,7 @@ public class Controller extends Thread {
network.broadcast(peer -> network.buildHeightMessage(peer, latestBlockData)); network.broadcast(peer -> network.buildHeightMessage(peer, latestBlockData));
// Send (if outbound) / Request unconfirmed transaction signatures // Send (if outbound) / Request unconfirmed transaction signatures
network.broadcast(peer -> network.buildGetUnconfirmedTransactionsMessage(peer)); network.broadcast(network::buildGetUnconfirmedTransactionsMessage);
} }
public void onGenerationPossibleChange(boolean isGenerationPossible) { public void onGenerationPossibleChange(boolean isGenerationPossible) {
@ -1002,7 +1002,7 @@ public class Controller extends Thread {
// Fetch actual transaction data from peer // Fetch actual transaction data from peer
Message getTransactionMessage = new GetTransactionMessage(signature); Message getTransactionMessage = new GetTransactionMessage(signature);
Message responseMessage = peer.getResponse(getTransactionMessage); Message responseMessage = peer.getResponse(getTransactionMessage);
if (responseMessage == null || !(responseMessage instanceof TransactionMessage)) { if (!(responseMessage instanceof TransactionMessage)) {
// Maybe peer no longer has this transaction // Maybe peer no longer has this transaction
LOGGER.trace(() -> String.format("Peer %s didn't send transaction %s", peer, Base58.encode(signature))); LOGGER.trace(() -> String.format("Peer %s didn't send transaction %s", peer, Base58.encode(signature)));
continue; continue;
@ -1158,7 +1158,7 @@ public class Controller extends Thread {
// Check transaction exists and payload hash is correct // Check transaction exists and payload hash is correct
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature); TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
if (transactionData == null || !(transactionData instanceof ArbitraryTransactionData)) if (!(transactionData instanceof ArbitraryTransactionData))
break; break;
ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData; ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData;
@ -1231,10 +1231,10 @@ public class Controller extends Thread {
case ONLINE_ACCOUNTS: { case ONLINE_ACCOUNTS: {
OnlineAccountsMessage onlineAccountsMessage = (OnlineAccountsMessage) message; OnlineAccountsMessage onlineAccountsMessage = (OnlineAccountsMessage) message;
List<OnlineAccountData> onlineAccounts = onlineAccountsMessage.getOnlineAccounts(); List<OnlineAccountData> peersOnlineAccounts = onlineAccountsMessage.getOnlineAccounts();
LOGGER.trace(() -> String.format("Received %d online accounts from %s", onlineAccounts.size(), peer)); LOGGER.trace(() -> String.format("Received %d online accounts from %s", peersOnlineAccounts.size(), peer));
for (OnlineAccountData onlineAccountData : onlineAccounts) for (OnlineAccountData onlineAccountData : peersOnlineAccounts)
this.verifyAndAddAccount(onlineAccountData); this.verifyAndAddAccount(onlineAccountData);
break; break;
@ -1309,7 +1309,7 @@ public class Controller extends Thread {
synchronized (this.onlineAccounts) { synchronized (this.onlineAccounts) {
message = new GetOnlineAccountsMessage(this.onlineAccounts); message = new GetOnlineAccountsMessage(this.onlineAccounts);
} }
Network.getInstance().broadcast((peer) -> message); Network.getInstance().broadcast(peer -> message);
} }
// Refresh our online accounts signatures? // Refresh our online accounts signatures?
@ -1341,7 +1341,7 @@ public class Controller extends Thread {
iterator.remove(); iterator.remove();
} }
} catch (DataException e) { } catch (DataException e) {
LOGGER.warn("Repository issue trying to fetch forging accounts: " + e.getMessage()); LOGGER.warn(String.format("Repository issue trying to fetch forging accounts: %s", e.getMessage()));
return; return;
} }
@ -1389,7 +1389,7 @@ public class Controller extends Thread {
return; return;
Message message = new OnlineAccountsMessage(ourOnlineAccounts); Message message = new OnlineAccountsMessage(ourOnlineAccounts);
Network.getInstance().broadcast((peer) -> message); Network.getInstance().broadcast(peer -> message);
LOGGER.trace(()-> String.format("Broadcasted %d online account%s with timestamp %d", ourOnlineAccounts.size(), (ourOnlineAccounts.size() != 1 ? "s" : ""), onlineAccountsTimestamp)); LOGGER.trace(()-> String.format("Broadcasted %d online account%s with timestamp %d", ourOnlineAccounts.size(), (ourOnlineAccounts.size() != 1 ? "s" : ""), onlineAccountsTimestamp));
} }

View File

@ -214,7 +214,7 @@ public class Synchronizer {
--ourHeight; --ourHeight;
} }
LOGGER.debug(String.format("Orphaned blocks back to height %d, sig %.8s - fetching blocks from peer", commonBlockHeight, commonBlockSig58, peer)); LOGGER.debug(String.format("Orphaned blocks back to height %d, sig %.8s - fetching blocks from peer %s", commonBlockHeight, commonBlockSig58, peer));
} else { } else {
LOGGER.debug(String.format("Fetching new blocks from peer %s", peer)); LOGGER.debug(String.format("Fetching new blocks from peer %s", peer));
} }
@ -224,7 +224,7 @@ public class Synchronizer {
int maxBatchHeight = commonBlockHeight + SYNC_BATCH_SIZE; int maxBatchHeight = commonBlockHeight + SYNC_BATCH_SIZE;
// Convert any block summaries from above into signatures to request from peer // Convert any block summaries from above into signatures to request from peer
List<byte[]> peerBlockSignatures = peerBlockSummaries.stream().map(blockSummaryData -> blockSummaryData.getSignature()).collect(Collectors.toList()); List<byte[]> peerBlockSignatures = peerBlockSummaries.stream().map(BlockSummaryData::getSignature).collect(Collectors.toList());
while (ourHeight < peerHeight && ourHeight < maxBatchHeight) { while (ourHeight < peerHeight && ourHeight < maxBatchHeight) {
// Do we need more signatures? // Do we need more signatures?

View File

@ -196,12 +196,9 @@ public class BTC {
peerGroup.start(); peerGroup.start();
} }
public static BTC getInstance() { public static synchronized BTC getInstance() {
if (instance == null) if (instance == null)
synchronized (instanceLock) { instance = new BTC();
if (instance == null)
instance = new BTC();
}
return instance; return instance;
} }

View File

@ -6,8 +6,8 @@ package org.qora.crypto;
* <b>DO NOT USE in future code</b> as this implementation is BROKEN and returns incorrect digests for some inputs. * <b>DO NOT USE in future code</b> as this implementation is BROKEN and returns incorrect digests for some inputs.
* <p> * <p>
* It is only "grand-fathered" here to produce correct QORA addresses. * It is only "grand-fathered" here to produce correct QORA addresses.
* @deprecated
*/ */
@Deprecated @Deprecated
public class BrokenMD160 { public class BrokenMD160 {

View File

@ -2,8 +2,6 @@ package org.qora.data.voting;
import java.util.List; import java.util.List;
import org.qora.data.voting.PollOptionData;
public class PollData { public class PollData {
// Properties // Properties

View File

@ -33,13 +33,13 @@ public enum BIP39WordList {
try (InputStream inputStream = loader.getResourceAsStream("BIP39/wordlist_" + lang + ".txt")) { try (InputStream inputStream = loader.getResourceAsStream("BIP39/wordlist_" + lang + ".txt")) {
if (inputStream == null) { if (inputStream == null) {
LOGGER.warn("Can't locate '" + lang + "' BIP39 wordlist"); LOGGER.warn(String.format("Can't locate '%s' BIP39 wordlist", lang));
return null; return null;
} }
wordList = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.toList()); wordList = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.toList());
} catch (IOException e) { } catch (IOException e) {
LOGGER.warn("Error reading '" + lang + "' BIP39 wordlist", e); LOGGER.warn(String.format("Error reading '%s' BIP39 wordlist", lang), e);
return null; return null;
} }

View File

@ -46,7 +46,7 @@ public class Group {
public final int value; public final int value;
public final boolean isPercentage; public final boolean isPercentage;
private final static Map<Integer, ApprovalThreshold> map = stream(ApprovalThreshold.values()) private static final Map<Integer, ApprovalThreshold> map = stream(ApprovalThreshold.values())
.collect(toMap(threshold -> threshold.value, threshold -> threshold)); .collect(toMap(threshold -> threshold.value, threshold -> threshold));
ApprovalThreshold(int value, boolean isPercentage) { ApprovalThreshold(int value, boolean isPercentage) {

View File

@ -41,7 +41,7 @@ public class SplashFrame {
private SplashFrame() { private SplashFrame() {
this.splashDialog = new JDialog(); this.splashDialog = new JDialog();
List<Image> icons = new ArrayList<Image>(); List<Image> icons = new ArrayList<>();
icons.add(Gui.loadImage("icons/icon16.png")); icons.add(Gui.loadImage("icons/icon16.png"));
icons.add(Gui.loadImage("icons/icon32.png")); icons.add(Gui.loadImage("icons/icon32.png"));
icons.add(Gui.loadImage("icons/icon64.png")); icons.add(Gui.loadImage("icons/icon64.png"));

View File

@ -4,8 +4,6 @@ import java.awt.AWTError;
import java.awt.AWTException; import java.awt.AWTException;
import java.awt.SystemTray; import java.awt.SystemTray;
import java.awt.TrayIcon; import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
@ -37,7 +35,7 @@ import org.qora.utils.URLViewer;
public class SysTray { public class SysTray {
protected static final Logger LOGGER = LogManager.getLogger(SplashFrame.class); protected static final Logger LOGGER = LogManager.getLogger(SysTray.class);
private static final String NTP_SCRIPT = "ntpcfg.bat"; private static final String NTP_SCRIPT = "ntpcfg.bat";
private static SysTray instance; private static SysTray instance;
@ -147,31 +145,25 @@ public class SysTray {
}); });
JMenuItem openUi = new JMenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI")); JMenuItem openUi = new JMenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI"));
openUi.addActionListener(new ActionListener() { openUi.addActionListener(actionEvent -> {
@Override destroyHiddenDialog();
public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
try { try {
URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort())); URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort()));
} catch (Exception e1) { } catch (Exception e) {
LOGGER.error("Unable to open node UI in browser"); LOGGER.error("Unable to open node UI in browser");
}
} }
}); });
menu.add(openUi); menu.add(openUi);
JMenuItem openTimeCheck = new JMenuItem(Translator.INSTANCE.translate("SysTray", "CHECK_TIME_ACCURACY")); JMenuItem openTimeCheck = new JMenuItem(Translator.INSTANCE.translate("SysTray", "CHECK_TIME_ACCURACY"));
openTimeCheck.addActionListener(new ActionListener() { openTimeCheck.addActionListener(actionEvent -> {
@Override destroyHiddenDialog();
public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
try { try {
URLViewer.openWebpage(new URL("https://time.is")); URLViewer.openWebpage(new URL("https://time.is"));
} catch (Exception e1) { } catch (Exception e) {
LOGGER.error("Unable to open time-check website in browser"); LOGGER.error("Unable to open time-check website in browser");
}
} }
}); });
menu.add(openTimeCheck); menu.add(openTimeCheck);
@ -179,25 +171,19 @@ public class SysTray {
// Only for Windows users // Only for Windows users
if (System.getProperty("os.name").toLowerCase().contains("win")) { if (System.getProperty("os.name").toLowerCase().contains("win")) {
JMenuItem syncTime = new JMenuItem(Translator.INSTANCE.translate("SysTray", "SYNCHRONIZE_CLOCK")); JMenuItem syncTime = new JMenuItem(Translator.INSTANCE.translate("SysTray", "SYNCHRONIZE_CLOCK"));
syncTime.addActionListener(new ActionListener() { syncTime.addActionListener(actionEvent -> {
@Override destroyHiddenDialog();
public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
new SynchronizeWorker().execute(); new SynchronizeWorker().execute();
}
}); });
menu.add(syncTime); menu.add(syncTime);
} }
JMenuItem exit = new JMenuItem(Translator.INSTANCE.translate("SysTray", "EXIT")); JMenuItem exit = new JMenuItem(Translator.INSTANCE.translate("SysTray", "EXIT"));
exit.addActionListener(new ActionListener() { exit.addActionListener(actionEvent -> {
@Override destroyHiddenDialog();
public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
new ClosingWorker().execute(); new ClosingWorker().execute();
}
}); });
menu.add(exit); menu.add(exit);

View File

@ -44,7 +44,7 @@ public class mintsim {
} }
} }
public static void main(String args[]) { public static void main(String[] args) {
if (args.length < 2 || (args.length % 2) != 0) { if (args.length < 2 || (args.length % 2) != 0) {
System.err.println("usage: mintsim <tier1-min-blocks> <number-tier1-accounts> [<tier2-min-blocks> <max-tier2-per-tier1> [...]]"); System.err.println("usage: mintsim <tier1-min-blocks> <number-tier1-accounts> [<tier2-min-blocks> <max-tier2-per-tier1> [...]]");
System.exit(1); System.exit(1);
@ -53,8 +53,8 @@ public class mintsim {
try { try {
int argIndex = 0; int argIndex = 0;
do { do {
int minBlocks = Integer.valueOf(args[argIndex++]); int minBlocks = Integer.parseInt(args[argIndex++]);
int maxAccounts = Integer.valueOf(args[argIndex++]); int maxAccounts = Integer.parseInt(args[argIndex++]);
tiers.add(new TierInfo(maxAccounts, minBlocks)); tiers.add(new TierInfo(maxAccounts, minBlocks));
} while (argIndex < args.length); } while (argIndex < args.length);

View File

@ -201,7 +201,7 @@ public enum Handshake {
private static final Logger LOGGER = LogManager.getLogger(Handshake.class); private static final Logger LOGGER = LogManager.getLogger(Handshake.class);
/** Maximum allowed difference between peer's reported timestamp and when they connected, in milliseconds. */ /** Maximum allowed difference between peer's reported timestamp and when they connected, in milliseconds. */
private static final long MAX_TIMESTAMP_DELTA = 30 * 1000; // ms private static final long MAX_TIMESTAMP_DELTA = 30 * 1000L; // ms
public final MessageType expectedMessageType; public final MessageType expectedMessageType;

View File

@ -59,22 +59,22 @@ import org.qora.utils.ExecuteProduceConsume;
import org.qora.utils.NTP; import org.qora.utils.NTP;
// For managing peers // For managing peers
public class Network extends Thread { public class Network {
private static final Logger LOGGER = LogManager.getLogger(Network.class); private static final Logger LOGGER = LogManager.getLogger(Network.class);
private static Network instance; private static Network instance;
private static final int LISTEN_BACKLOG = 10; private static final int LISTEN_BACKLOG = 10;
/** How long before retrying after a connection failure, in milliseconds. */ /** How long before retrying after a connection failure, in milliseconds. */
private static final int CONNECT_FAILURE_BACKOFF = 5 * 60 * 1000; // ms private static final long CONNECT_FAILURE_BACKOFF = 5 * 60 * 1000L; // ms
/** How long between informational broadcasts to all connected peers, in milliseconds. */ /** How long between informational broadcasts to all connected peers, in milliseconds. */
private static final int BROADCAST_INTERVAL = 60 * 1000; // ms private static final long BROADCAST_INTERVAL = 60 * 1000L; // ms
/** Maximum time since last successful connection for peer info to be propagated, in milliseconds. */ /** Maximum time since last successful connection for peer info to be propagated, in milliseconds. */
private static final long RECENT_CONNECTION_THRESHOLD = 24 * 60 * 60 * 1000; // ms private static final long RECENT_CONNECTION_THRESHOLD = 24 * 60 * 60 * 1000L; // ms
/** Maximum time since last connection attempt before a peer is potentially considered "old", in milliseconds. */ /** Maximum time since last connection attempt before a peer is potentially considered "old", in milliseconds. */
private static final long OLD_PEER_ATTEMPTED_PERIOD = 24 * 60 * 60 * 1000; // ms private static final long OLD_PEER_ATTEMPTED_PERIOD = 24 * 60 * 60 * 1000L; // ms
/** Maximum time since last successful connection before a peer is potentially considered "old", in milliseconds. */ /** Maximum time since last successful connection before a peer is potentially considered "old", in milliseconds. */
private static final long OLD_PEER_CONNECTION_PERIOD = 7 * 24 * 60 * 60 * 1000; // ms private static final long OLD_PEER_CONNECTION_PERIOD = 7 * 24 * 60 * 60 * 1000L; // ms
/** Maximum time allowed for handshake to complete, in milliseconds. */ /** Maximum time allowed for handshake to complete, in milliseconds. */
private static final long HANDSHAKE_TIMEOUT = 60 * 1000; // ms private static final long HANDSHAKE_TIMEOUT = 60 * 1000; // ms
@ -135,7 +135,7 @@ public class Network extends Thread {
serverChannel.bind(endpoint, LISTEN_BACKLOG); serverChannel.bind(endpoint, LISTEN_BACKLOG);
serverChannel.register(channelSelector, SelectionKey.OP_ACCEPT); serverChannel.register(channelSelector, SelectionKey.OP_ACCEPT);
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
LOGGER.error("Can't bind listen socket to address " + Settings.getInstance().getBindAddress()); LOGGER.error(String.format("Can't bind listen socket to address %s", Settings.getInstance().getBindAddress()));
throw new RuntimeException("Can't bind listen socket to address"); throw new RuntimeException("Can't bind listen socket to address");
} catch (IOException e) { } catch (IOException e) {
LOGGER.error("Can't create listen socket"); LOGGER.error("Can't create listen socket");
@ -167,7 +167,9 @@ public class Network extends Thread {
10L, TimeUnit.SECONDS, 10L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>()); new SynchronousQueue<Runnable>());
networkEPC = new NetworkProcessor(networkExecutor); networkEPC = new NetworkProcessor(networkExecutor);
}
public void start() {
// Start up first networking thread // Start up first networking thread
networkEPC.start(); networkEPC.start();
} }
@ -244,14 +246,9 @@ public class Network extends Thread {
/** Returns list of peers we connected to that have completed handshaking. */ /** Returns list of peers we connected to that have completed handshaking. */
public List<Peer> getOutboundHandshakedPeers() { public List<Peer> getOutboundHandshakedPeers() {
List<Peer> peers = new ArrayList<>();
synchronized (this.connectedPeers) { synchronized (this.connectedPeers) {
peers = this.connectedPeers.stream().filter(peer -> peer.isOutbound() && peer.getHandshakeStatus() == Handshake.COMPLETED) return this.connectedPeers.stream().filter(peer -> peer.isOutbound() && peer.getHandshakeStatus() == Handshake.COMPLETED).collect(Collectors.toList());
.collect(Collectors.toList());
} }
return peers;
} }
/** Returns Peer with inbound connection and matching ID, or null if none found. */ /** Returns Peer with inbound connection and matching ID, or null if none found. */
@ -359,9 +356,7 @@ public class Network extends Thread {
LOGGER.trace(() -> String.format("Network thread %s encountered I/O error: %s", Thread.currentThread().getId(), e.getMessage()), e); LOGGER.trace(() -> String.format("Network thread %s encountered I/O error: %s", Thread.currentThread().getId(), e.getMessage()), e);
peer.disconnect("I/O error"); peer.disconnect("I/O error");
return;
} }
} }
} }
@ -664,7 +659,7 @@ public class Network extends Thread {
if (socketChannel == null) if (socketChannel == null)
return; return;
if (this.isInterrupted()) if (Thread.currentThread().isInterrupted())
return; return;
synchronized (this.connectedPeers) { synchronized (this.connectedPeers) {
@ -839,7 +834,7 @@ public class Network extends Thread {
// If inbound peer, use listen port and socket address to recreate first entry // If inbound peer, use listen port and socket address to recreate first entry
if (!peer.isOutbound()) { if (!peer.isOutbound()) {
PeerAddress sendingPeerAddress = PeerAddress.fromString(peer.getPeerData().getAddress().getHost() + ":" + peerPort); PeerAddress sendingPeerAddress = PeerAddress.fromString(peer.getPeerData().getAddress().getHost() + ":" + peerPort);
LOGGER.trace("PEERS_V2 sending peer's listen address: " + sendingPeerAddress.toString()); LOGGER.trace(() -> String.format("PEERS_V2 sending peer's listen address: %s", sendingPeerAddress.toString()));
peerV2Addresses.add(0, sendingPeerAddress); peerV2Addresses.add(0, sendingPeerAddress);
} }
@ -1100,10 +1095,7 @@ public class Network extends Thread {
List<PeerData> knownPeers = repository.getNetworkRepository().getAllPeers(); List<PeerData> knownPeers = repository.getNetworkRepository().getAllPeers();
// Filter out duplicates // Filter out duplicates
Predicate<PeerAddress> isKnownAddress = peerAddress -> { Predicate<PeerAddress> isKnownAddress = peerAddress -> knownPeers.stream().anyMatch(knownPeerData -> knownPeerData.getAddress().equals(peerAddress));
return knownPeers.stream().anyMatch(knownPeerData -> knownPeerData.getAddress().equals(peerAddress));
};
peerAddresses.removeIf(isKnownAddress); peerAddresses.removeIf(isKnownAddress);
repository.discardChanges(); repository.discardChanges();
@ -1126,6 +1118,8 @@ public class Network extends Thread {
public void broadcast(Function<Peer, Message> peerMessageBuilder) { public void broadcast(Function<Peer, Message> peerMessageBuilder) {
class Broadcaster implements Runnable { class Broadcaster implements Runnable {
private final Random random = new Random();
private List<Peer> targetPeers; private List<Peer> targetPeers;
private Function<Peer, Message> peerMessageBuilder; private Function<Peer, Message> peerMessageBuilder;
@ -1138,12 +1132,10 @@ public class Network extends Thread {
public void run() { public void run() {
Thread.currentThread().setName("Network Broadcast"); Thread.currentThread().setName("Network Broadcast");
Random random = new Random();
for (Peer peer : targetPeers) { for (Peer peer : targetPeers) {
// Very short sleep to reduce strain, improve multi-threading and catch interrupts // Very short sleep to reduce strain, improve multi-threading and catch interrupts
try { try {
Thread.sleep(random.nextInt(20) + 20); Thread.sleep(random.nextInt(20) + 20L);
} catch (InterruptedException e) { } catch (InterruptedException e) {
break; break;
} }

View File

@ -256,7 +256,7 @@ public class Peer {
this.socketChannel.configureBlocking(false); this.socketChannel.configureBlocking(false);
this.byteBuffer = ByteBuffer.allocate(Network.getInstance().getMaxMessageSize()); this.byteBuffer = ByteBuffer.allocate(Network.getInstance().getMaxMessageSize());
this.replyQueues = Collections.synchronizedMap(new HashMap<Integer, BlockingQueue<Message>>()); this.replyQueues = Collections.synchronizedMap(new HashMap<Integer, BlockingQueue<Message>>());
this.pendingMessages = new LinkedBlockingQueue<Message>(); this.pendingMessages = new LinkedBlockingQueue<>();
} }
public SocketChannel connect() { public SocketChannel connect() {
@ -394,7 +394,7 @@ public class Peer {
if (bytesWritten == 0) if (bytesWritten == 0)
// Underlying socket's internal buffer probably full, // Underlying socket's internal buffer probably full,
// so wait a short while for bytes to actually be transmitted over the wire // so wait a short while for bytes to actually be transmitted over the wire
Thread.sleep(1L); this.socketChannel.wait(1L);
} }
} }
} catch (MessageException e) { } catch (MessageException e) {
@ -424,7 +424,7 @@ public class Peer {
* @throws InterruptedException * @throws InterruptedException
*/ */
public Message getResponse(Message message) throws InterruptedException { public Message getResponse(Message message) throws InterruptedException {
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<Message>(1); BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<>(1);
// Assign random ID to this message // Assign random ID to this message
int id; int id;
@ -443,8 +443,7 @@ public class Peer {
} }
try { try {
Message response = blockingQueue.poll(RESPONSE_TIMEOUT, TimeUnit.MILLISECONDS); return blockingQueue.poll(RESPONSE_TIMEOUT, TimeUnit.MILLISECONDS);
return response;
} finally { } finally {
this.replyQueues.remove(id); this.replyQueues.remove(id);
} }

View File

@ -73,7 +73,7 @@ public abstract class Message {
ONLINE_ACCOUNTS(26); ONLINE_ACCOUNTS(26);
public final int value; public final int value;
public final Method fromByteBuffer; public final Method fromByteBufferMethod;
private static final Map<Integer, MessageType> map = stream(MessageType.values()) private static final Map<Integer, MessageType> map = stream(MessageType.values())
.collect(toMap(messageType -> messageType.value, messageType -> messageType)); .collect(toMap(messageType -> messageType.value, messageType -> messageType));
@ -88,16 +88,16 @@ public abstract class Message {
String className = String.join("", classNameParts); String className = String.join("", classNameParts);
Method fromByteBuffer; Method method;
try { try {
Class<?> subclass = Class.forName(String.join("", Message.class.getPackage().getName(), ".", className, "Message")); Class<?> subclass = Class.forName(String.join("", Message.class.getPackage().getName(), ".", className, "Message"));
fromByteBuffer = subclass.getDeclaredMethod("fromByteBuffer", int.class, ByteBuffer.class); method = subclass.getDeclaredMethod("fromByteBuffer", int.class, ByteBuffer.class);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
fromByteBuffer = null; method = null;
} }
this.fromByteBuffer = fromByteBuffer; this.fromByteBufferMethod = method;
} }
public static MessageType valueOf(int value) { public static MessageType valueOf(int value) {
@ -105,11 +105,11 @@ public abstract class Message {
} }
public Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { public Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException {
if (this.fromByteBuffer == null) if (this.fromByteBufferMethod == null)
throw new MessageException("Unsupported message type [" + value + "] during conversion from bytes"); throw new MessageException("Unsupported message type [" + value + "] during conversion from bytes");
try { try {
return (Message) this.fromByteBuffer.invoke(null, id, byteBuffer); return (Message) this.fromByteBufferMethod.invoke(null, id, byteBuffer);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
if (e.getCause() instanceof BufferUnderflowException) if (e.getCause() instanceof BufferUnderflowException)
throw new MessageException("Byte data too short for " + name() + " message"); throw new MessageException("Byte data too short for " + name() + " message");

View File

@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -42,7 +43,7 @@ public class PeersV2Message extends Message {
byte[] addressBytes = new byte[addressSize & 0xff]; byte[] addressBytes = new byte[addressSize & 0xff];
byteBuffer.get(addressBytes); byteBuffer.get(addressBytes);
String addressString = new String(addressBytes, "UTF-8"); String addressString = new String(addressBytes, StandardCharsets.UTF_8);
try { try {
PeerAddress peerAddress = PeerAddress.fromString(addressString); PeerAddress peerAddress = PeerAddress.fromString(addressString);
@ -63,10 +64,10 @@ public class PeersV2Message extends Message {
List<byte[]> addresses = new ArrayList<>(); List<byte[]> addresses = new ArrayList<>();
// First entry represents sending node but contains only port number with empty address. // First entry represents sending node but contains only port number with empty address.
addresses.add(new String("0.0.0.0:" + Settings.getInstance().getListenPort()).getBytes("UTF-8")); addresses.add(("0.0.0.0:" + Settings.getInstance().getListenPort()).getBytes(StandardCharsets.UTF_8));
for (PeerAddress peerAddress : this.peerAddresses) for (PeerAddress peerAddress : this.peerAddresses)
addresses.add(peerAddress.toString().getBytes("UTF-8")); addresses.add(peerAddress.toString().getBytes(StandardCharsets.UTF_8));
// We can't send addresses that are longer than 255 bytes as length itself is encoded in one byte. // We can't send addresses that are longer than 255 bytes as length itself is encoded in one byte.
addresses.removeIf(addressString -> addressString.length > 255); addresses.removeIf(addressString -> addressString.length > 255);

View File

@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
@ -44,7 +45,7 @@ public class VersionMessage extends Message {
byte[] versionBytes = new byte[versionStringLength]; byte[] versionBytes = new byte[versionStringLength];
bytes.get(versionBytes); bytes.get(versionBytes);
String versionString = new String(versionBytes, "UTF-8"); String versionString = new String(versionBytes, StandardCharsets.UTF_8);
return new VersionMessage(id, buildTimestamp, versionString); return new VersionMessage(id, buildTimestamp, versionString);
} }

View File

@ -45,7 +45,7 @@ public class Payment {
return ValidationResult.NEGATIVE_FEE; return ValidationResult.NEGATIVE_FEE;
// Total up payment amounts by assetId // Total up payment amounts by assetId
Map<Long, BigDecimal> amountsByAssetId = new HashMap<Long, BigDecimal>(); Map<Long, BigDecimal> amountsByAssetId = new HashMap<>();
// Add transaction fee to start with // Add transaction fee to start with
amountsByAssetId.put(Asset.QORT, fee); amountsByAssetId.put(Asset.QORT, fee);

View File

@ -188,7 +188,7 @@ public class HSQLDBATRepository implements ATRepository {
@Override @Override
public List<ATStateData> getBlockATStatesAtHeight(int height) throws DataException { public List<ATStateData> getBlockATStatesAtHeight(int height) throws DataException {
List<ATStateData> atStates = new ArrayList<ATStateData>(); List<ATStateData> atStates = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute("SELECT AT_address, state_hash, fees FROM ATStates WHERE height = ? ORDER BY creation ASC", try (ResultSet resultSet = this.repository.checkedExecute("SELECT AT_address, state_hash, fees FROM ATStates WHERE height = ? ORDER BY creation ASC",
height)) { height)) {

View File

@ -321,7 +321,7 @@ public class HSQLDBAccountRepository implements AccountRepository {
} }
// For no-address queries, or unless specifically requested, only return accounts with non-zero balance // For no-address queries, or unless specifically requested, only return accounts with non-zero balance
if (addresses.isEmpty() || (excludeZero != null && excludeZero == true)) { if (addresses.isEmpty() || (excludeZero != null && excludeZero)) {
sql.append(assetIds.isEmpty() ? " WHERE " : " AND "); sql.append(assetIds.isEmpty() ? " WHERE " : " AND ");
sql.append("balance != 0 "); sql.append("balance != 0 ");
} }

View File

@ -104,7 +104,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<AssetData> assets = new ArrayList<AssetData>(); List<AssetData> assets = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) {
if (resultSet == null) if (resultSet == null)
@ -228,7 +228,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
@Override @Override
public List<OrderData> getOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset, public List<OrderData> getOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset,
Boolean reverse) throws DataException { Boolean reverse) throws DataException {
List<OrderData> orders = new ArrayList<OrderData>(); List<OrderData> orders = new ArrayList<>();
// Cache have & want asset names for later use, which also saves a table join // Cache have & want asset names for later use, which also saves a table join
AssetData haveAssetData = this.fromAssetId(haveAssetId); AssetData haveAssetData = this.fromAssetId(haveAssetId);
@ -305,7 +305,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
sql.append(", ordered"); sql.append(", ordered");
List<OrderData> orders = new ArrayList<OrderData>(); List<OrderData> orders = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), bindParams.toArray())) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), bindParams.toArray())) {
if (resultSet == null) if (resultSet == null)
@ -336,7 +336,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
@Override @Override
public List<OrderData> getAggregatedOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset, public List<OrderData> getAggregatedOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset,
Boolean reverse) throws DataException { Boolean reverse) throws DataException {
List<OrderData> orders = new ArrayList<OrderData>(); List<OrderData> orders = new ArrayList<>();
// Cache have & want asset names for later use, which also saves a table join // Cache have & want asset names for later use, which also saves a table join
AssetData haveAssetData = this.fromAssetId(haveAssetId); AssetData haveAssetData = this.fromAssetId(haveAssetId);
@ -404,7 +404,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<OrderData> orders = new ArrayList<OrderData>(); List<OrderData> orders = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), publicKey)) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), publicKey)) {
if (resultSet == null) if (resultSet == null)
@ -437,7 +437,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
@Override @Override
public List<OrderData> getAccountsOrders(byte[] publicKey, long haveAssetId, long wantAssetId, Boolean optIsClosed, public List<OrderData> getAccountsOrders(byte[] publicKey, long haveAssetId, long wantAssetId, Boolean optIsClosed,
Boolean optIsFulfilled, Integer limit, Integer offset, Boolean reverse) throws DataException { Boolean optIsFulfilled, Integer limit, Integer offset, Boolean reverse) throws DataException {
List<OrderData> orders = new ArrayList<OrderData>(); List<OrderData> orders = new ArrayList<>();
// Cache have & want asset names for later use, which also saves a table join // Cache have & want asset names for later use, which also saves a table join
AssetData haveAssetData = this.fromAssetId(haveAssetId); AssetData haveAssetData = this.fromAssetId(haveAssetId);
@ -524,7 +524,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
@Override @Override
public List<TradeData> getTrades(long haveAssetId, long wantAssetId, Integer limit, Integer offset, Boolean reverse) public List<TradeData> getTrades(long haveAssetId, long wantAssetId, Integer limit, Integer offset, Boolean reverse)
throws DataException { throws DataException {
List<TradeData> trades = new ArrayList<TradeData>(); List<TradeData> trades = new ArrayList<>();
// Cache have & want asset names for later use, which also saves a table join // Cache have & want asset names for later use, which also saves a table join
AssetData haveAssetData = this.fromAssetId(haveAssetId); AssetData haveAssetData = this.fromAssetId(haveAssetId);
@ -677,7 +677,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<TradeData> trades = new ArrayList<TradeData>(); List<TradeData> trades = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), orderId)) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), orderId)) {
if (resultSet == null) if (resultSet == null)

View File

@ -153,7 +153,7 @@ public class HSQLDBBlockRepository implements BlockRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), signature)) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), signature)) {
if (resultSet == null) if (resultSet == null)

View File

@ -29,8 +29,10 @@ public class HSQLDBDatabaseUpdates {
* @throws SQLException * @throws SQLException
*/ */
private static void incrementDatabaseVersion(Connection connection) throws SQLException { private static void incrementDatabaseVersion(Connection connection) throws SQLException {
connection.createStatement().execute("UPDATE DatabaseInfo SET version = version + 1"); try (Statement stmt = connection.createStatement()) {
connection.commit(); stmt.execute("UPDATE DatabaseInfo SET version = version + 1");
connection.commit();
}
} }
/** /**

View File

@ -308,9 +308,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
if (resultSet == null) if (resultSet == null)
return null; return null;
String owner = resultSet.getString(1); return resultSet.getString(1);
return owner;
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch group owner from repository", e); throw new DataException("Unable to fetch group owner from repository", e);
} }

View File

@ -63,7 +63,7 @@ public class HSQLDBRepository implements Repository {
this.slowQueryThreshold = Settings.getInstance().getSlowQueryThreshold(); this.slowQueryThreshold = Settings.getInstance().getSlowQueryThreshold();
if (this.slowQueryThreshold != null) if (this.slowQueryThreshold != null)
this.sqlStatements = new ArrayList<String>(); this.sqlStatements = new ArrayList<>();
// Find out our session ID // Find out our session ID
try (Statement stmt = this.connection.createStatement()) { try (Statement stmt = this.connection.createStatement()) {
@ -237,13 +237,13 @@ public class HSQLDBRepository implements Repository {
@Override @Override
public void backup(boolean quick) throws DataException { public void backup(boolean quick) throws DataException {
// First perform a CHECKPOINT if (!quick)
try { // First perform a CHECKPOINT
if (!quick) try (Statement stmt = this.connection.createStatement()) {
this.connection.createStatement().execute("CHECKPOINT DEFRAG"); stmt.execute("CHECKPOINT DEFRAG");
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to prepare repository for backup"); throw new DataException("Unable to prepare repository for backup");
} }
// Clean out any previous backup // Clean out any previous backup
try { try {
@ -272,8 +272,8 @@ public class HSQLDBRepository implements Repository {
} }
// Actually create backup // Actually create backup
try { try (Statement stmt = this.connection.createStatement()) {
this.connection.createStatement().execute("BACKUP DATABASE TO 'backup/' NOT BLOCKING AS FILES"); stmt.execute("BACKUP DATABASE TO 'backup/' NOT BLOCKING AS FILES");
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to backup repository"); throw new DataException("Unable to backup repository");
} }
@ -287,8 +287,7 @@ public class HSQLDBRepository implements Repository {
if (!matcher.find()) if (!matcher.find())
return null; return null;
String pathname = matcher.group(1); return matcher.group(1);
return pathname;
} }
private static String buildBackupUrl(String dbPathname) { private static String buildBackupUrl(String dbPathname) {
@ -298,8 +297,7 @@ public class HSQLDBRepository implements Repository {
// Try to open backup. We need to remove "create=true" and insert "backup" dir before final filename. // Try to open backup. We need to remove "create=true" and insert "backup" dir before final filename.
String backupUrlTemplate = "jdbc:hsqldb:file:%s/backup/%s;create=false;hsqldb.full_log_replay=true"; String backupUrlTemplate = "jdbc:hsqldb:file:%s/backup/%s;create=false;hsqldb.full_log_replay=true";
String backupUrl = String.format(backupUrlTemplate, oldRepoDirPath.toString(), oldRepoFilePath.toString()); return String.format(backupUrlTemplate, oldRepoDirPath.toString(), oldRepoFilePath.toString());
return backupUrl;
} }
/* package */ static void attemptRecovery(String connectionUrl) throws DataException { /* package */ static void attemptRecovery(String connectionUrl) throws DataException {
@ -321,11 +319,11 @@ public class HSQLDBRepository implements Repository {
.filter(file -> file.getPath().startsWith(dbPathname)) .filter(file -> file.getPath().startsWith(dbPathname))
.forEach(File::delete); .forEach(File::delete);
try { try (Statement stmt = connection.createStatement()) {
// Now "backup" the backup back to original repository location (the parent) // Now "backup" the backup back to original repository location (the parent)
// NOTE: trailing / is OK because HSQLDB checks for both / and O/S-specific separator // NOTE: trailing / is OK because HSQLDB checks for both / and O/S-specific separator
// textdb.allow_full_path connection property is required to be able to use '..' // textdb.allow_full_path connection property is required to be able to use '..'
connection.createStatement().execute("BACKUP DATABASE TO '../' BLOCKING AS FILES"); stmt.execute("BACKUP DATABASE TO '../' BLOCKING AS FILES");
} catch (SQLException e) { } catch (SQLException e) {
// We really failed // We really failed
throw new DataException("Failed to recover repository to original location"); throw new DataException("Failed to recover repository to original location");
@ -357,9 +355,7 @@ public class HSQLDBRepository implements Repository {
if (this.sqlStatements != null) if (this.sqlStatements != null)
this.sqlStatements.add(sql); this.sqlStatements.add(sql);
PreparedStatement preparedStatement = this.connection.prepareStatement(sql); return this.connection.prepareStatement(sql);
return preparedStatement;
} }
/** /**
@ -594,7 +590,7 @@ public class HSQLDBRepository implements Repository {
return e; return e;
do { do {
long sessionId = resultSet.getLong(1); long systemSessionId = resultSet.getLong(1);
boolean inTransaction = resultSet.getBoolean(2); boolean inTransaction = resultSet.getBoolean(2);
long transactionSize = resultSet.getLong(3); long transactionSize = resultSet.getLong(3);
String waitingForThis = resultSet.getString(4); String waitingForThis = resultSet.getString(4);
@ -602,7 +598,7 @@ public class HSQLDBRepository implements Repository {
String currentStatement = resultSet.getString(6); String currentStatement = resultSet.getString(6);
LOGGER.error(String.format("Session %d, %s transaction (size %d), waiting for this '%s', this waiting for '%s', current statement: %s", LOGGER.error(String.format("Session %d, %s transaction (size %d), waiting for this '%s', this waiting for '%s', current statement: %s",
sessionId, (inTransaction ? "in" : "not in"), transactionSize, waitingForThis, thisWaitingFor, currentStatement)); systemSessionId, (inTransaction ? "in" : "not in"), transactionSize, waitingForThis, thisWaitingFor, currentStatement));
} while (resultSet.next()); } while (resultSet.next());
} catch (SQLException de) { } catch (SQLException de) {
// Throw original exception instead // Throw original exception instead
@ -619,8 +615,10 @@ public class HSQLDBRepository implements Repository {
throw new DataException("Unable to check repository status after " + context); throw new DataException("Unable to check repository status after " + context);
try (ResultSet resultSet = stmt.getResultSet()) { try (ResultSet resultSet = stmt.getResultSet()) {
if (resultSet == null || !resultSet.next()) if (resultSet == null || !resultSet.next()) {
LOGGER.warn("Unable to check repository status after " + context); LOGGER.warn(String.format("Unable to check repository status after %s", context));
return;
}
boolean inTransaction = resultSet.getBoolean(1); boolean inTransaction = resultSet.getBoolean(1);
int transactionCount = resultSet.getInt(2); int transactionCount = resultSet.getInt(2);

View File

@ -3,6 +3,7 @@ package org.qora.repository.hsqldb;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; import java.util.Properties;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -31,9 +32,10 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
// Check no-one else is accessing database // Check no-one else is accessing database
try (Connection connection = DriverManager.getConnection(this.connectionUrl)) { try (Connection connection = DriverManager.getConnection(this.connectionUrl)) {
// We only need to check we can obtain connection. It will be auto-closed.
} catch (SQLException e) { } catch (SQLException e) {
Throwable cause = e.getCause(); Throwable cause = e.getCause();
if (cause == null || !(cause instanceof HsqlException)) if (!(cause instanceof HsqlException))
throw new DataException("Unable to open repository: " + e.getMessage()); throw new DataException("Unable to open repository: " + e.getMessage());
HsqlException he = (HsqlException) cause; HsqlException he = (HsqlException) cause;
@ -84,7 +86,7 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
if (delay > SLOW_CONNECTION_THRESHOLD) if (delay > SLOW_CONNECTION_THRESHOLD)
// This could be an indication of excessive repository use, or insufficient pool size // This could be an indication of excessive repository use, or insufficient pool size
LOGGER.warn(String.format("Fetching repository connection from pool took %dms (threshold: %dms)"), delay, SLOW_CONNECTION_THRESHOLD); LOGGER.warn(() -> String.format("Fetching repository connection from pool took %dms (threshold: %dms)", delay, SLOW_CONNECTION_THRESHOLD));
setupConnection(connection); setupConnection(connection);
return connection; return connection;
@ -112,8 +114,9 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
this.connectionPool.close(0); this.connectionPool.close(0);
// Now that all connections are closed, create a dedicated connection to shut down repository // Now that all connections are closed, create a dedicated connection to shut down repository
try (Connection connection = DriverManager.getConnection(this.connectionUrl)) { try (Connection connection = DriverManager.getConnection(this.connectionUrl);
connection.createStatement().execute("SHUTDOWN"); Statement stmt = connection.createStatement()) {
stmt.execute("SHUTDOWN");
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Error during repository shutdown", e); throw new DataException("Error during repository shutdown", e);

View File

@ -22,8 +22,8 @@ public class HSQLDBSaver {
private String table; private String table;
private List<String> columns = new ArrayList<String>(); private List<String> columns = new ArrayList<>();
private List<Object> objects = new ArrayList<Object>(); private List<Object> objects = new ArrayList<>();
/** /**
* Construct a SaveHelper, using SQL Connection and table name. * Construct a SaveHelper, using SQL Connection and table name.

View File

@ -41,7 +41,7 @@ public class HSQLDBVotingRepository implements VotingRepository {
if (optionsResultSet == null) if (optionsResultSet == null)
return null; return null;
List<PollOptionData> pollOptions = new ArrayList<PollOptionData>(); List<PollOptionData> pollOptions = new ArrayList<>();
// NOTE: do-while because checkedExecute() above has already called rs.next() for us // NOTE: do-while because checkedExecute() above has already called rs.next() for us
do { do {
@ -112,7 +112,7 @@ public class HSQLDBVotingRepository implements VotingRepository {
@Override @Override
public List<VoteOnPollData> getVotes(String pollName) throws DataException { public List<VoteOnPollData> getVotes(String pollName) throws DataException {
String sql = "SELECT voter, option_index FROM PollVotes WHERE poll_name = ?"; String sql = "SELECT voter, option_index FROM PollVotes WHERE poll_name = ?";
List<VoteOnPollData> votes = new ArrayList<VoteOnPollData>(); List<VoteOnPollData> votes = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql, pollName)) { try (ResultSet resultSet = this.repository.checkedExecute(sql, pollName)) {
if (resultSet == null) if (resultSet == null)

View File

@ -65,6 +65,7 @@ public class HSQLDBArbitraryTransactionRepository extends HSQLDBTransactionRepos
this.savePayments(transactionData.getSignature(), arbitraryTransactionData.getPayments()); this.savePayments(transactionData.getSignature(), arbitraryTransactionData.getPayments());
} }
@Override
public void delete(TransactionData transactionData) throws DataException { public void delete(TransactionData transactionData) throws DataException {
ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData; ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData;

View File

@ -36,7 +36,7 @@ public class HSQLDBCreatePollTransactionRepository extends HSQLDBTransactionRepo
if (optionsResultSet == null) if (optionsResultSet == null)
return null; return null;
List<PollOptionData> pollOptions = new ArrayList<PollOptionData>(); List<PollOptionData> pollOptions = new ArrayList<>();
// NOTE: do-while because checkedExecute() above has already called rs.next() for us // NOTE: do-while because checkedExecute() above has already called rs.next() for us
do { do {

View File

@ -9,7 +9,7 @@ import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -105,16 +105,13 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
for (TransactionType txType : TransactionType.values()) { for (TransactionType txType : TransactionType.values()) {
RepositorySubclassInfo subclassInfo = subclassInfos[txType.value]; RepositorySubclassInfo subclassInfo = subclassInfos[txType.value];
if (subclassInfo == null) if (subclassInfo == null || subclassInfo.constructor == null)
continue;
if (subclassInfo.constructor == null)
continue; continue;
try { try {
this.repositoryByTxType[txType.value] = (HSQLDBTransactionRepository) subclassInfo.constructor.newInstance(repository); this.repositoryByTxType[txType.value] = (HSQLDBTransactionRepository) subclassInfo.constructor.newInstance(repository);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) { } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) {
continue; LOGGER.debug(String.format("HSQLDBTransactionRepository subclass constructor failed for transaction type \"%s\"", txType.name()));
} }
} }
} }
@ -152,9 +149,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
approvalHeight = null; approvalHeight = null;
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, creatorPublicKey, fee, approvalStatus, blockHeight, approvalHeight, signature); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, creatorPublicKey, fee, approvalStatus, blockHeight, approvalHeight, signature);
TransactionData transactionData = this.fromBase(type, baseTransactionData); return this.fromBase(type, baseTransactionData);
return transactionData;
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch transaction from repository", e); throw new DataException("Unable to fetch transaction from repository", e);
} }
@ -187,9 +182,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
approvalHeight = null; approvalHeight = null;
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, creatorPublicKey, fee, approvalStatus, blockHeight, approvalHeight, signature); BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, creatorPublicKey, fee, approvalStatus, blockHeight, approvalHeight, signature);
TransactionData transactionData = this.fromBase(type, baseTransactionData); return this.fromBase(type, baseTransactionData);
return transactionData;
} catch (SQLException e) { } catch (SQLException e) {
throw new DataException("Unable to fetch transaction from repository", e); throw new DataException("Unable to fetch transaction from repository", e);
} }
@ -242,7 +235,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
protected List<PaymentData> getPaymentsFromSignature(byte[] signature) throws DataException { protected List<PaymentData> getPaymentsFromSignature(byte[] signature) throws DataException {
String sql = "SELECT recipient, amount, asset_id FROM SharedTransactionPayments WHERE signature = ?"; String sql = "SELECT recipient, amount, asset_id FROM SharedTransactionPayments WHERE signature = ?";
List<PaymentData> payments = new ArrayList<PaymentData>(); List<PaymentData> payments = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) { try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) {
if (resultSet == null) if (resultSet == null)
@ -314,7 +307,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
public List<byte[]> getSignaturesInvolvingAddress(String address) throws DataException { public List<byte[]> getSignaturesInvolvingAddress(String address) throws DataException {
String sql = "SELECT signature FROM TransactionRecipients WHERE participant = ?"; String sql = "SELECT signature FROM TransactionRecipients WHERE participant = ?";
List<byte[]> signatures = new ArrayList<byte[]>(); List<byte[]> signatures = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql, address)) { try (ResultSet resultSet = this.repository.checkedExecute(sql, address)) {
if (resultSet == null) if (resultSet == null)
@ -366,7 +359,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
+ "WHERE block_height BETWEEN ? AND ? " + "WHERE block_height BETWEEN ? AND ? "
+ "GROUP BY type"; + "GROUP BY type";
Map<TransactionType, Integer> transactionCounts = new HashMap<>(); Map<TransactionType, Integer> transactionCounts = new EnumMap<>(TransactionType.class);
try (ResultSet resultSet = this.repository.checkedExecute(sql, startHeight, endHeight)) { try (ResultSet resultSet = this.repository.checkedExecute(sql, startHeight, endHeight)) {
if (resultSet == null) if (resultSet == null)
@ -389,7 +382,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
public List<byte[]> getSignaturesMatchingCriteria(Integer startBlock, Integer blockLimit, Integer txGroupId, public List<byte[]> getSignaturesMatchingCriteria(Integer startBlock, Integer blockLimit, Integer txGroupId,
List<TransactionType> txTypes, Integer service, String address, List<TransactionType> txTypes, Integer service, String address,
ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) throws DataException { ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) throws DataException {
List<byte[]> signatures = new ArrayList<byte[]>(); List<byte[]> signatures = new ArrayList<>();
boolean hasAddress = address != null && !address.isEmpty(); boolean hasAddress = address != null && !address.isEmpty();
boolean hasTxTypes = txTypes != null && !txTypes.isEmpty(); boolean hasTxTypes = txTypes != null && !txTypes.isEmpty();
@ -399,9 +392,9 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
startBlock = (reverse == null || !reverse) ? 1 : this.repository.getBlockRepository().getBlockchainHeight() - blockLimit; startBlock = (reverse == null || !reverse) ? 1 : this.repository.getBlockRepository().getBlockchainHeight() - blockLimit;
String signatureColumn = "Transactions.signature"; String signatureColumn = "Transactions.signature";
List<String> whereClauses = new ArrayList<String>(); List<String> whereClauses = new ArrayList<>();
String groupBy = null; String groupBy = null;
List<Object> bindParams = new ArrayList<Object>(); List<Object> bindParams = new ArrayList<>();
// Tables, starting with Transactions // Tables, starting with Transactions
StringBuilder tables = new StringBuilder(256); StringBuilder tables = new StringBuilder(256);
@ -579,7 +572,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) {
if (resultSet == null) if (resultSet == null)
@ -693,7 +686,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
// Find transactions with no corresponding row in BlockTransactions // Find transactions with no corresponding row in BlockTransactions
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), bindParams)) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), bindParams)) {
@ -729,7 +722,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
sql.append(" AND Transactions.block_height < ? - Groups.min_block_delay"); sql.append(" AND Transactions.block_height < ? - Groups.min_block_delay");
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), blockHeight)) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), blockHeight)) {
if (resultSet == null) if (resultSet == null)
@ -764,7 +757,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
sql.append(" AND Transactions.block_height < ? - Groups.max_block_delay"); sql.append(" AND Transactions.block_height < ? - Groups.max_block_delay");
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), blockHeight)) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString(), blockHeight)) {
if (resultSet == null) if (resultSet == null)
@ -925,7 +918,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
HSQLDBRepository.limitOffsetSql(sql, limit, offset); HSQLDBRepository.limitOffsetSql(sql, limit, offset);
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
// Find transactions with no corresponding row in BlockTransactions // Find transactions with no corresponding row in BlockTransactions
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) { try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) {

View File

@ -94,8 +94,8 @@ public class Settings {
// Auto-update sources // Auto-update sources
private String[] autoUpdateRepos = new String[] { private String[] autoUpdateRepos = new String[] {
"https://github.com/catbref/qora-core/raw/%s/qora-core.jar", "https://github.com/QORT/qortal/raw/%s/qora-core.jar",
"https://raw.githubusercontent.com@151.101.16.133/catbref/qora-core/%s/qora-core.jar" "https://raw.githubusercontent.com@151.101.16.133/QORT/qortal/%s/qora-core.jar"
}; };
/** Array of NTP server hostnames. */ /** Array of NTP server hostnames. */
@ -171,7 +171,7 @@ public class Settings {
String path = ""; String path = "";
do { do {
LOGGER.info("Using settings file: " + path + filename); LOGGER.info(String.format("Using settings file: %s%s", path, filename));
// Create the StreamSource by creating Reader to the JSON input // Create the StreamSource by creating Reader to the JSON input
try (Reader settingsReader = new FileReader(path + filename)) { try (Reader settingsReader = new FileReader(path + filename)) {

View File

@ -35,7 +35,7 @@ public class ArbitraryTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() throws DataException { public List<Account> getRecipientAccounts() throws DataException {
List<Account> recipients = new ArrayList<Account>(); List<Account> recipients = new ArrayList<>();
if (arbitraryTransactionData.getVersion() != 1) if (arbitraryTransactionData.getVersion() != 1)
for (PaymentData paymentData : arbitraryTransactionData.getPayments()) for (PaymentData paymentData : arbitraryTransactionData.getPayments())
@ -92,7 +92,7 @@ public class ArbitraryTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
// Are arbitrary transactions even allowed at this point? // Are arbitrary transactions even allowed at this point?
if (arbitraryTransactionData.getVersion() != ArbitraryTransaction.getVersionByTimestamp(arbitraryTransactionData.getTimestamp())) if (arbitraryTransactionData.getVersion() != Transaction.getVersionByTimestamp(arbitraryTransactionData.getTimestamp()))
return ValidationResult.NOT_YET_RELEASED; return ValidationResult.NOT_YET_RELEASED;
if (this.arbitraryTransactionData.getTimestamp() < BlockChain.getInstance().getArbitraryReleaseTimestamp()) if (this.arbitraryTransactionData.getTimestamp() < BlockChain.getInstance().getArbitraryReleaseTimestamp())

View File

@ -57,7 +57,7 @@ public class AtTransaction extends Transaction {
/** For AT-Transactions, the use the AT address instead of transaction creator (which is genesis account) */ /** For AT-Transactions, the use the AT address instead of transaction creator (which is genesis account) */
@Override @Override
public List<Account> getInvolvedAccounts() throws DataException { public List<Account> getInvolvedAccounts() throws DataException {
List<Account> participants = new ArrayList<Account>(getRecipientAccounts()); List<Account> participants = new ArrayList<>(getRecipientAccounts());
participants.add(getATAccount()); participants.add(getATAccount());
return participants; return participants;
} }

View File

@ -33,7 +33,7 @@ public class CancelAssetOrderTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() { public List<Account> getRecipientAccounts() {
return new ArrayList<Account>(); return new ArrayList<>();
} }
@Override @Override

View File

@ -33,7 +33,7 @@ public class CancelSellNameTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() { public List<Account> getRecipientAccounts() {
return new ArrayList<Account>(); return new ArrayList<>();
} }
@Override @Override

View File

@ -35,7 +35,7 @@ public class CreateAssetOrderTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() { public List<Account> getRecipientAccounts() {
return new ArrayList<Account>(); return new ArrayList<>();
} }
@Override @Override

View File

@ -1,9 +1,9 @@
package org.qora.transaction; package org.qora.transaction;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -46,7 +46,7 @@ public class DeployAtTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() throws DataException { public List<Account> getRecipientAccounts() throws DataException {
return new ArrayList<Account>(); return new ArrayList<>();
} }
@Override @Override
@ -79,8 +79,7 @@ public class DeployAtTransaction extends Transaction {
/** Returns AT version from the header bytes */ /** Returns AT version from the header bytes */
private short getVersion() { private short getVersion() {
byte[] creationBytes = deployATTransactionData.getCreationBytes(); byte[] creationBytes = deployATTransactionData.getCreationBytes();
short version = (short) (creationBytes[0] | (creationBytes[1] << 8)); // Little-endian return (short) ((creationBytes[0] & 0xff) | (creationBytes[1] << 8)); // Little-endian
return version;
} }
/** Make sure deployATTransactionData has an ATAddress */ /** Make sure deployATTransactionData has an ATAddress */
@ -92,29 +91,25 @@ public class DeployAtTransaction extends Transaction {
if (blockHeight == 0) if (blockHeight == 0)
blockHeight = this.repository.getBlockRepository().getBlockchainHeight() + 1; blockHeight = this.repository.getBlockRepository().getBlockchainHeight() + 1;
try { byte[] name = this.deployATTransactionData.getName().getBytes(StandardCharsets.UTF_8);
byte[] name = this.deployATTransactionData.getName().getBytes("UTF-8"); byte[] description = this.deployATTransactionData.getDescription().replaceAll("\\s", "").getBytes(StandardCharsets.UTF_8);
byte[] description = this.deployATTransactionData.getDescription().replaceAll("\\s", "").getBytes("UTF-8"); byte[] creatorPublicKey = this.deployATTransactionData.getCreatorPublicKey();
byte[] creatorPublicKey = this.deployATTransactionData.getCreatorPublicKey(); byte[] creationBytes = this.deployATTransactionData.getCreationBytes();
byte[] creationBytes = this.deployATTransactionData.getCreationBytes();
ByteBuffer byteBuffer = ByteBuffer ByteBuffer byteBuffer = ByteBuffer
.allocate(name.length + description.length + creatorPublicKey.length + creationBytes.length + Transformer.INT_LENGTH); .allocate(name.length + description.length + creatorPublicKey.length + creationBytes.length + Transformer.INT_LENGTH);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN); byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.put(name); byteBuffer.put(name);
byteBuffer.put(description); byteBuffer.put(description);
byteBuffer.put(creatorPublicKey); byteBuffer.put(creatorPublicKey);
byteBuffer.put(creationBytes); byteBuffer.put(creationBytes);
byteBuffer.putInt(blockHeight); byteBuffer.putInt(blockHeight);
String atAddress = Crypto.toATAddress(byteBuffer.array()); String atAddress = Crypto.toATAddress(byteBuffer.array());
this.deployATTransactionData.setAtAddress(atAddress); this.deployATTransactionData.setAtAddress(atAddress);
} catch (UnsupportedEncodingException e) {
throw new DataException("Unable to generate AT account from Deploy AT transaction data", e);
}
} }
// Navigation // Navigation

View File

@ -90,7 +90,7 @@ public class MessageTransaction extends Transaction {
@Override @Override
public ValidationResult isValid() throws DataException { public ValidationResult isValid() throws DataException {
// Are message transactions even allowed at this point? // Are message transactions even allowed at this point?
if (messageTransactionData.getVersion() != MessageTransaction.getVersionByTimestamp(messageTransactionData.getTimestamp())) if (messageTransactionData.getVersion() != Transaction.getVersionByTimestamp(messageTransactionData.getTimestamp()))
return ValidationResult.NOT_YET_RELEASED; return ValidationResult.NOT_YET_RELEASED;
if (this.repository.getBlockRepository().getBlockchainHeight() < BlockChain.getInstance().getMessageReleaseHeight()) if (this.repository.getBlockRepository().getBlockchainHeight() < BlockChain.getInstance().getMessageReleaseHeight())

View File

@ -35,7 +35,7 @@ public class MultiPaymentTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() throws DataException { public List<Account> getRecipientAccounts() throws DataException {
List<Account> recipients = new ArrayList<Account>(); List<Account> recipients = new ArrayList<>();
for (PaymentData paymentData : multiPaymentTransactionData.getPayments()) for (PaymentData paymentData : multiPaymentTransactionData.getPayments())
recipients.add(new Account(this.repository, paymentData.getRecipient())); recipients.add(new Account(this.repository, paymentData.getRecipient()));
@ -95,7 +95,7 @@ public class MultiPaymentTransaction extends Transaction {
return ValidationResult.NOT_YET_RELEASED; return ValidationResult.NOT_YET_RELEASED;
// Check number of payments // Check number of payments
if (payments.size() < 1 || payments.size() > MAX_PAYMENTS_COUNT) if (payments.isEmpty() || payments.size() > MAX_PAYMENTS_COUNT)
return ValidationResult.INVALID_PAYMENTS_COUNT; return ValidationResult.INVALID_PAYMENTS_COUNT;
// Check reference is correct // Check reference is correct

View File

@ -36,7 +36,7 @@ public class SellNameTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() { public List<Account> getRecipientAccounts() {
return new ArrayList<Account>(); return new ArrayList<>();
} }
@Override @Override

View File

@ -7,6 +7,7 @@ import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -91,7 +92,7 @@ public abstract class Transaction {
public final Class<?> clazz; public final Class<?> clazz;
public final Constructor<?> constructor; public final Constructor<?> constructor;
private final static Map<Integer, TransactionType> map = stream(TransactionType.values()).collect(toMap(type -> type.value, type -> type)); private static final Map<Integer, TransactionType> map = stream(TransactionType.values()).collect(toMap(type -> type.value, type -> type));
TransactionType(int value, boolean needsApproval) { TransactionType(int value, boolean needsApproval) {
this.value = value; this.value = value;
@ -105,14 +106,14 @@ public abstract class Transaction {
this.className = String.join("", classNameParts); this.className = String.join("", classNameParts);
Class<?> clazz = null; Class<?> subClazz = null;
Constructor<?> constructor = null; Constructor<?> subConstructor = null;
try { try {
clazz = Class.forName(String.join("", Transaction.class.getPackage().getName(), ".", this.className, "Transaction")); subClazz = Class.forName(String.join("", Transaction.class.getPackage().getName(), ".", this.className, "Transaction"));
try { try {
constructor = clazz.getConstructor(Repository.class, TransactionData.class); subConstructor = subClazz.getConstructor(Repository.class, TransactionData.class);
} catch (NoSuchMethodException | SecurityException e) { } catch (NoSuchMethodException | SecurityException e) {
LOGGER.debug(String.format("Transaction subclass constructor not found for transaction type \"%s\"", this.name())); LOGGER.debug(String.format("Transaction subclass constructor not found for transaction type \"%s\"", this.name()));
} }
@ -120,8 +121,8 @@ public abstract class Transaction {
LOGGER.debug(String.format("Transaction subclass not found for transaction type \"%s\"", this.name())); LOGGER.debug(String.format("Transaction subclass not found for transaction type \"%s\"", this.name()));
} }
this.clazz = clazz; this.clazz = subClazz;
this.constructor = constructor; this.constructor = subConstructor;
} }
public static TransactionType valueOf(int value) { public static TransactionType valueOf(int value) {
@ -140,7 +141,7 @@ public abstract class Transaction {
public final int value; public final int value;
private final static Map<Integer, ApprovalStatus> map = stream(ApprovalStatus.values()).collect(toMap(result -> result.value, result -> result)); private static final Map<Integer, ApprovalStatus> map = stream(ApprovalStatus.values()).collect(toMap(result -> result.value, result -> result));
ApprovalStatus(int value) { ApprovalStatus(int value) {
this.value = value; this.value = value;
@ -244,7 +245,7 @@ public abstract class Transaction {
public final int value; public final int value;
private final static Map<Integer, ValidationResult> map = stream(ValidationResult.values()).collect(toMap(result -> result.value, result -> result)); private static final Map<Integer, ValidationResult> map = stream(ValidationResult.values()).collect(toMap(result -> result.value, result -> result));
ValidationResult(int value) { ValidationResult(int value) {
this.value = value; this.value = value;
@ -417,7 +418,7 @@ public abstract class Transaction {
*/ */
public List<Account> getInvolvedAccounts() throws DataException { public List<Account> getInvolvedAccounts() throws DataException {
// Typically this is all the recipients plus the transaction creator/sender // Typically this is all the recipients plus the transaction creator/sender
List<Account> participants = new ArrayList<Account>(getRecipientAccounts()); List<Account> participants = new ArrayList<>(getRecipientAccounts());
participants.add(getCreator()); participants.add(getCreator());
return participants; return participants;
} }
@ -622,8 +623,8 @@ public abstract class Transaction {
List<TransactionData> unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions(); List<TransactionData> unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions();
int count = 0; int count = 0;
for (TransactionData transactionData : unconfirmedTransactions) { for (TransactionData unconfirmedTransactionData : unconfirmedTransactions) {
Transaction transaction = Transaction.fromData(repository, transactionData); Transaction transaction = Transaction.fromData(repository, unconfirmedTransactionData);
PublicKeyAccount otherCreator = transaction.getCreator(); PublicKeyAccount otherCreator = transaction.getCreator();
if (Arrays.equals(creator.getPublicKey(), otherCreator.getPublicKey())) if (Arrays.equals(creator.getPublicKey(), otherCreator.getPublicKey()))
@ -662,14 +663,14 @@ public abstract class Transaction {
repository.discardChanges(); repository.discardChanges();
try { try {
for (int i = 0; i < unconfirmedTransactions.size(); ++i) { Iterator<TransactionData> unconfirmedTransactionsIterator = unconfirmedTransactions.iterator();
TransactionData transactionData = unconfirmedTransactions.get(i); while (unconfirmedTransactionsIterator.hasNext()) {
TransactionData transactionData = unconfirmedTransactionsIterator.next();
if (!isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp())) { if (isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp()))
unconfirmedTransactions.remove(i);
--i;
continue; continue;
}
unconfirmedTransactionsIterator.remove();
} }
} finally { } finally {
// Throw away temporary updates to account lastReference // Throw away temporary updates to account lastReference
@ -713,16 +714,15 @@ public abstract class Transaction {
repository.discardChanges(); repository.discardChanges();
try { try {
for (int i = 0; i < unconfirmedTransactions.size(); ++i) { Iterator<TransactionData> unconfirmedTransactionsIterator = unconfirmedTransactions.iterator();
TransactionData transactionData = unconfirmedTransactions.get(i); while (unconfirmedTransactionsIterator.hasNext()) {
TransactionData transactionData = unconfirmedTransactionsIterator.next();
if (!isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp())) { if (isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp()))
invalidTransactions.add(transactionData);
unconfirmedTransactions.remove(i);
--i;
continue; continue;
}
invalidTransactions.add(transactionData);
unconfirmedTransactionsIterator.remove();
} }
} finally { } finally {
// Throw away temporary updates to account lastReference // Throw away temporary updates to account lastReference
@ -927,7 +927,7 @@ public abstract class Transaction {
*/ */
public ValidationResult isProcessable() throws DataException { public ValidationResult isProcessable() throws DataException {
return ValidationResult.OK; return ValidationResult.OK;
}; }
/** /**
* Actually process a transaction, updating the blockchain. * Actually process a transaction, updating the blockchain.

View File

@ -41,7 +41,7 @@ public class VoteOnPollTransaction extends Transaction {
@Override @Override
public List<Account> getRecipientAccounts() { public List<Account> getRecipientAccounts() {
return new ArrayList<Account>(); return new ArrayList<>();
} }
@Override @Override
@ -151,15 +151,13 @@ public class VoteOnPollTransaction extends Transaction {
Integer previousOptionIndex = voteOnPollTransactionData.getPreviousOptionIndex(); Integer previousOptionIndex = voteOnPollTransactionData.getPreviousOptionIndex();
if (previousOptionIndex != null) { if (previousOptionIndex != null) {
// Reinstate previous vote // Reinstate previous vote
LOGGER.trace("Reinstating previous vote by " + voter.getAddress() + " on poll \"" + voteOnPollTransactionData.getPollName() LOGGER.trace(() -> String.format("Reinstating previous vote by %s on poll \"%s\" with option index %d", voter.getAddress(), voteOnPollTransactionData.getPollName(), previousOptionIndex));
+ "\" with option index " + previousOptionIndex);
VoteOnPollData previousVoteOnPollData = new VoteOnPollData(voteOnPollTransactionData.getPollName(), voteOnPollTransactionData.getVoterPublicKey(), VoteOnPollData previousVoteOnPollData = new VoteOnPollData(voteOnPollTransactionData.getPollName(), voteOnPollTransactionData.getVoterPublicKey(),
previousOptionIndex); previousOptionIndex);
votingRepository.save(previousVoteOnPollData); votingRepository.save(previousVoteOnPollData);
} else { } else {
// Delete vote // Delete vote
LOGGER.trace("Deleting vote by " + voter.getAddress() + " on poll \"" + voteOnPollTransactionData.getPollName() + "\" with option index " LOGGER.trace(() -> String.format("Deleting vote by %s on poll \"%s\" with option index %d", voter.getAddress(), voteOnPollTransactionData.getPollName(), voteOnPollTransactionData.getOptionIndex()));
+ voteOnPollTransactionData.getOptionIndex());
votingRepository.delete(voteOnPollTransactionData.getPollName(), voteOnPollTransactionData.getVoterPublicKey()); votingRepository.delete(voteOnPollTransactionData.getPollName(), voteOnPollTransactionData.getVoterPublicKey());
} }

View File

@ -7,7 +7,6 @@ import java.nio.ByteBuffer;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.qora.data.PaymentData; import org.qora.data.PaymentData;
import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;

View File

@ -109,7 +109,7 @@ public class BlockTransformer extends Transformer {
int atCount = 0; int atCount = 0;
BigDecimal atFees = BigDecimal.ZERO.setScale(8); BigDecimal atFees = BigDecimal.ZERO.setScale(8);
List<ATStateData> atStates = new ArrayList<ATStateData>(); List<ATStateData> atStates = new ArrayList<>();
if (version >= 2) { if (version >= 2) {
int atBytesLength = byteBuffer.getInt(); int atBytesLength = byteBuffer.getInt();
@ -172,7 +172,7 @@ public class BlockTransformer extends Transformer {
int transactionCount = byteBuffer.getInt(); int transactionCount = byteBuffer.getInt();
// Parse transactions now, compared to deferred parsing in Gen1, so we can throw ParseException if need be. // Parse transactions now, compared to deferred parsing in Gen1, so we can throw ParseException if need be.
List<TransactionData> transactions = new ArrayList<TransactionData>(); List<TransactionData> transactions = new ArrayList<>();
for (int t = 0; t < transactionCount; ++t) { for (int t = 0; t < transactionCount; ++t) {
if (byteBuffer.remaining() < TRANSACTION_SIZE_LENGTH) if (byteBuffer.remaining() < TRANSACTION_SIZE_LENGTH)
@ -244,7 +244,7 @@ public class BlockTransformer extends Transformer {
BlockData blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, BlockData blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp,
generatorPublicKey, generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures); generatorPublicKey, generatorSignature, atCount, atFees, encodedOnlineAccounts, onlineAccountsCount, onlineAccountsTimestamp, onlineAccountsSignatures);
return new Triple<BlockData, List<TransactionData>, List<ATStateData>>(blockData, transactions, atStates); return new Triple<>(blockData, transactions, atStates);
} }
public static int getDataLength(Block block) throws TransformationException { public static int getDataLength(Block block) throws TransformationException {

View File

@ -16,6 +16,7 @@ import org.qora.data.transaction.BaseTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.data.transaction.ArbitraryTransactionData.DataType; import org.qora.data.transaction.ArbitraryTransactionData.DataType;
import org.qora.transaction.ArbitraryTransaction; import org.qora.transaction.ArbitraryTransaction;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.TransactionType; import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.PaymentTransformer; import org.qora.transform.PaymentTransformer;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
@ -59,7 +60,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
int version = ArbitraryTransaction.getVersionByTimestamp(timestamp); int version = Transaction.getVersionByTimestamp(timestamp);
int txGroupId = 0; int txGroupId = 0;
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
@ -71,7 +72,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
byte[] senderPublicKey = Serialization.deserializePublicKey(byteBuffer); byte[] senderPublicKey = Serialization.deserializePublicKey(byteBuffer);
// V3+ allows payments but always return a list of payments, even if empty // V3+ allows payments but always return a list of payments, even if empty
List<PaymentData> payments = new ArrayList<PaymentData>(); List<PaymentData> payments = new ArrayList<>();
if (version != 1) { if (version != 1) {
int paymentsCount = byteBuffer.getInt(); int paymentsCount = byteBuffer.getInt();
@ -182,7 +183,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
// In v1, a coding error means that all bytes prior to final payment entry are lost! // In v1, a coding error means that all bytes prior to final payment entry are lost!
// If there are no payments then we can skip mangling // If there are no payments then we can skip mangling
if (arbitraryTransactionData.getPayments().size() == 0) if (arbitraryTransactionData.getPayments().isEmpty())
return bytes; return bytes;
// So we're left with: final payment entry, service, data size, data, fee // So we're left with: final payment entry, service, data size, data, fee

View File

@ -72,7 +72,7 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
if (optionsCount < 1 || optionsCount > Poll.MAX_OPTIONS) if (optionsCount < 1 || optionsCount > Poll.MAX_OPTIONS)
throw new TransformationException("Invalid number of options for CreatePollTransaction"); throw new TransformationException("Invalid number of options for CreatePollTransaction");
List<PollOptionData> pollOptions = new ArrayList<PollOptionData>(); List<PollOptionData> pollOptions = new ArrayList<>();
for (int optionIndex = 0; optionIndex < optionsCount; ++optionIndex) { for (int optionIndex = 0; optionIndex < optionsCount; ++optionIndex) {
String optionName = Serialization.deserializeSizedString(byteBuffer, Poll.MAX_NAME_SIZE); String optionName = Serialization.deserializeSizedString(byteBuffer, Poll.MAX_NAME_SIZE);

View File

@ -11,6 +11,7 @@ import org.qora.data.transaction.BaseTransactionData;
import org.qora.data.transaction.DeployAtTransactionData; import org.qora.data.transaction.DeployAtTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.transaction.DeployAtTransaction; import org.qora.transaction.DeployAtTransaction;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.TransactionType; import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
@ -59,7 +60,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
int version = DeployAtTransaction.getVersionByTimestamp(timestamp); int version = Transaction.getVersionByTimestamp(timestamp);
int txGroupId = 0; int txGroupId = 0;
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
@ -106,7 +107,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH; int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH;
int version = DeployAtTransaction.getVersionByTimestamp(transactionData.getTimestamp()); int version = Transaction.getVersionByTimestamp(transactionData.getTimestamp());
// V4+ have assetId too // V4+ have assetId too
if (version >= 4) if (version >= 4)
@ -123,7 +124,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
try { try {
DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData; DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData;
int version = DeployAtTransaction.getVersionByTimestamp(transactionData.getTimestamp()); int version = Transaction.getVersionByTimestamp(transactionData.getTimestamp());
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ByteArrayOutputStream bytes = new ByteArrayOutputStream();

View File

@ -11,6 +11,7 @@ import org.qora.data.transaction.BaseTransactionData;
import org.qora.data.transaction.MessageTransactionData; import org.qora.data.transaction.MessageTransactionData;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.transaction.MessageTransaction; import org.qora.transaction.MessageTransaction;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.TransactionType; import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.utils.Serialization; import org.qora.utils.Serialization;
@ -53,7 +54,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong(); long timestamp = byteBuffer.getLong();
int version = MessageTransaction.getVersionByTimestamp(timestamp); int version = Transaction.getVersionByTimestamp(timestamp);
int txGroupId = 0; int txGroupId = 0;
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())

View File

@ -58,7 +58,7 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
int paymentsCount = byteBuffer.getInt(); int paymentsCount = byteBuffer.getInt();
List<PaymentData> payments = new ArrayList<PaymentData>(); List<PaymentData> payments = new ArrayList<>();
for (int i = 0; i < paymentsCount; ++i) for (int i = 0; i < paymentsCount; ++i)
payments.add(PaymentTransformer.fromByteBuffer(byteBuffer)); payments.add(PaymentTransformer.fromByteBuffer(byteBuffer));

View File

@ -80,11 +80,9 @@ public class UpdateAssetTransactionTransformer extends TransactionTransformer {
public static int getDataLength(TransactionData transactionData) throws TransformationException { public static int getDataLength(TransactionData transactionData) throws TransformationException {
UpdateAssetTransactionData updateAssetTransactionData = (UpdateAssetTransactionData) transactionData; UpdateAssetTransactionData updateAssetTransactionData = (UpdateAssetTransactionData) transactionData;
int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH return getBaseLength(transactionData) + EXTRAS_LENGTH
+ Utf8.encodedLength(updateAssetTransactionData.getNewDescription()) + Utf8.encodedLength(updateAssetTransactionData.getNewDescription())
+ Utf8.encodedLength(updateAssetTransactionData.getNewData()); + Utf8.encodedLength(updateAssetTransactionData.getNewData());
return dataLength;
} }
public static byte[] toBytes(TransactionData transactionData) throws TransformationException { public static byte[] toBytes(TransactionData transactionData) throws TransformationException {

View File

@ -40,7 +40,7 @@ public class BIP39 {
bitShift = 0 - bitShift; bitShift = 0 - bitShift;
entropy[byteIndex++] |= (byte) (wordListIndex >> bitShift); entropy[byteIndex++] |= (byte) (wordListIndex >> bitShift);
entropy[byteIndex] |= (byte) ((wordListIndex << (8 - bitShift))); entropy[byteIndex] |= (byte) (wordListIndex << (8 - bitShift));
bitShift = bitShift + BITS_PER_WORD - 8; bitShift = bitShift + BITS_PER_WORD - 8;
} }
} }

View File

@ -27,7 +27,7 @@ public class ByteArray implements Comparable<ByteArray> {
public int hashCode() { public int hashCode() {
int h = hash; int h = hash;
if (h == 0 && value.length > 0) { if (h == 0 && value.length > 0) {
byte val[] = value; byte[] val = value;
for (int i = 0; i < val.length; ++i) for (int i = 0; i < val.length; ++i)
h = 31 * h + val[i]; h = 31 * h + val[i];
@ -56,7 +56,7 @@ public class ByteArray implements Comparable<ByteArray> {
int b = otherValue[i] & 0xFF; int b = otherValue[i] & 0xFF;
if (a < b) if (a < b)
return -1; return -1;
if (b > a) if (a > b)
return 1; return 1;
} }

View File

@ -53,7 +53,7 @@ public class NTP implements Runnable {
this.remote = remote; this.remote = remote;
} }
public boolean poll(NTPUDPClient client) { public boolean doPoll(NTPUDPClient client) {
Thread.currentThread().setName(String.format("NTP: %s", this.remote)); Thread.currentThread().setName(String.format("NTP: %s", this.remote));
try { try {
@ -161,9 +161,9 @@ public class NTP implements Runnable {
while (!isStopping) { while (!isStopping) {
Thread.sleep(1000); Thread.sleep(1000);
CompletionService<Boolean> ecs = new ExecutorCompletionService<Boolean>(serverExecutor); CompletionService<Boolean> ecs = new ExecutorCompletionService<>(serverExecutor);
for (NTPServer server : ntpServers) for (NTPServer server : ntpServers)
ecs.submit(() -> server.poll(client)); ecs.submit(() -> server.doPoll(client));
boolean hasUpdate = false; boolean hasUpdate = false;
for (int i = 0; i < ntpServers.size(); ++i) { for (int i = 0; i < ntpServers.size(); ++i) {

View File

@ -6,6 +6,7 @@ import java.io.UnsupportedEncodingException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.qora.transform.TransformationException; import org.qora.transform.TransformationException;
import org.qora.transform.Transformer; import org.qora.transform.Transformer;
@ -92,7 +93,7 @@ public class Serialization {
} }
public static void serializeSizedString(ByteArrayOutputStream bytes, String string) throws UnsupportedEncodingException, IOException { public static void serializeSizedString(ByteArrayOutputStream bytes, String string) throws UnsupportedEncodingException, IOException {
byte[] stringBytes = string.getBytes("UTF-8"); byte[] stringBytes = string.getBytes(StandardCharsets.UTF_8);
bytes.write(Ints.toByteArray(stringBytes.length)); bytes.write(Ints.toByteArray(stringBytes.length));
bytes.write(stringBytes); bytes.write(stringBytes);
} }
@ -108,11 +109,7 @@ public class Serialization {
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
byteBuffer.get(bytes); byteBuffer.get(bytes);
try { return new String(bytes, StandardCharsets.UTF_8);
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new TransformationException("UTF-8 charset unsupported during string deserialization");
}
} }
} }

View File

@ -16,7 +16,7 @@ public class StringLongMapXmlAdapter extends XmlAdapter<StringLongMapXmlAdapter.
public static class StringLongMap { public static class StringLongMap {
@XmlVariableNode("key") @XmlVariableNode("key")
List<MapEntry> entries = new ArrayList<MapEntry>(); List<MapEntry> entries = new ArrayList<>();
} }
public static class MapEntry { public static class MapEntry {

View File

@ -120,4 +120,14 @@ public class ByteArrayTests {
System.out.println(String.format("Primitive hashCode: 0x%08x", copiedValue.hashCode())); System.out.println(String.format("Primitive hashCode: 0x%08x", copiedValue.hashCode()));
} }
@Test
public void testCompareTo() {
ByteArray testValue0 = new ByteArray(new byte[] { 0x00 });
ByteArray testValue1 = new ByteArray(new byte[] { 0x01 });
assertEquals("0 should be the same as 0", 0, testValue0.compareTo(testValue0));
assertEquals("0 should be before 1", -1, testValue0.compareTo(testValue1));
assertEquals("1 should be after 0", 1, testValue1.compareTo(testValue0));
}
} }