diff --git a/WindowsInstaller/Qortal.aip b/WindowsInstaller/Qortal.aip
index e922943d..33e5d5c0 100755
--- a/WindowsInstaller/Qortal.aip
+++ b/WindowsInstaller/Qortal.aip
@@ -17,10 +17,10 @@
-
+
-
+
@@ -212,7 +212,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 2a4fb61c..8bf092e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.qortal
qortal
- 3.3.0
+ 3.3.1
jar
true
diff --git a/src/main/java/org/qortal/controller/TransactionImporter.java b/src/main/java/org/qortal/controller/TransactionImporter.java
index 39f45a14..5a2dab19 100644
--- a/src/main/java/org/qortal/controller/TransactionImporter.java
+++ b/src/main/java/org/qortal/controller/TransactionImporter.java
@@ -3,6 +3,7 @@ package org.qortal.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.data.transaction.TransactionData;
+import org.qortal.network.Network;
import org.qortal.network.Peer;
import org.qortal.network.message.GetTransactionMessage;
import org.qortal.network.message.Message;
@@ -18,7 +19,6 @@ import org.qortal.utils.Base58;
import org.qortal.utils.NTP;
import java.util.*;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@@ -61,7 +61,7 @@ public class TransactionImporter extends Thread {
try {
while (!Controller.isStopping()) {
- Thread.sleep(1000L);
+ Thread.sleep(500L);
// Process incoming transactions queue
validateTransactionsInQueue();
@@ -127,8 +127,12 @@ public class TransactionImporter extends Thread {
LOGGER.debug("Validating signatures in incoming transactions queue (size {})...", unvalidatedCount);
}
+ // A list of all currently pending transactions that have valid signatures
List sigValidTransactions = new ArrayList<>();
+ // A list of signatures that became valid in this round
+ List newlyValidSignatures = new ArrayList<>();
+
boolean isLiteNode = Settings.getInstance().isLite();
// Signature validation round - does not require blockchain lock
@@ -147,6 +151,7 @@ public class TransactionImporter extends Thread {
if (isLiteNode) {
// Lite nodes can't easily validate transactions, so for now we will have to assume that everything is valid
sigValidTransactions.add(transaction);
+ newlyValidSignatures.add(transactionData.getSignature());
// Add mark signature as valid if transaction still exists in import queue
incomingTransactions.computeIfPresent(transactionData, (k, v) -> Boolean.TRUE);
continue;
@@ -167,15 +172,19 @@ public class TransactionImporter extends Thread {
invalidUnconfirmedTransactions.put(signature58, expiry);
}
+ // We're done with this transaction
continue;
}
- else {
- // Count the number that were validated in this round, for logging purposes
- validatedCount++;
- }
+
+ // Count the number that were validated in this round, for logging purposes
+ validatedCount++;
// Add mark signature as valid if transaction still exists in import queue
incomingTransactions.computeIfPresent(transactionData, (k, v) -> Boolean.TRUE);
+
+ // Signature validated in this round
+ newlyValidSignatures.add(transactionData.getSignature());
+
} else {
LOGGER.trace(() -> String.format("Transaction %s known to have valid signature", Base58.encode(transactionData.getSignature())));
}
@@ -188,6 +197,12 @@ public class TransactionImporter extends Thread {
LOGGER.debug("Finished validating signatures in incoming transactions queue (valid this round: {}, total pending import: {})...", validatedCount, sigValidTransactions.size());
}
+ if (!newlyValidSignatures.isEmpty()) {
+ LOGGER.debug("Broadcasting {} newly valid signatures ahead of import", newlyValidSignatures.size());
+ Message newTransactionSignatureMessage = new TransactionSignaturesMessage(newlyValidSignatures);
+ Network.getInstance().broadcast(broadcastPeer -> newTransactionSignatureMessage);
+ }
+
} catch (DataException e) {
LOGGER.error("Repository issue while processing incoming transactions", e);
}
@@ -210,14 +225,9 @@ public class TransactionImporter extends Thread {
return;
}
- try {
- ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
- if (!blockchainLock.tryLock(2, TimeUnit.SECONDS)) {
- LOGGER.debug("Too busy to import incoming transactions queue");
- return;
- }
- } catch (InterruptedException e) {
- LOGGER.debug("Interrupted when trying to acquire blockchain lock");
+ ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
+ if (!blockchainLock.tryLock()) {
+ LOGGER.debug("Too busy to import incoming transactions queue");
return;
}
@@ -288,7 +298,6 @@ public class TransactionImporter extends Thread {
}
} finally {
LOGGER.debug("Finished importing {} incoming transaction{}", processedCount, (processedCount == 1 ? "" : "s"));
- ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
blockchainLock.unlock();
}
} catch (DataException e) {
@@ -325,8 +334,18 @@ public class TransactionImporter extends Thread {
byte[] signature = getTransactionMessage.getSignature();
try (final Repository repository = RepositoryManager.getRepository()) {
- TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
+ // Firstly check the sig-valid transactions that are currently queued for import
+ TransactionData transactionData = this.getCachedSigValidTransactions().stream()
+ .filter(t -> Arrays.equals(signature, t.getSignature()))
+ .findFirst().orElse(null);
+
if (transactionData == null) {
+ // Not found in import queue, so try the database
+ transactionData = repository.getTransactionRepository().fromSignature(signature);
+ }
+
+ if (transactionData == null) {
+ // Still not found - so we don't have this transaction
LOGGER.debug(() -> String.format("Ignoring GET_TRANSACTION request from peer %s for unknown transaction %s", peer, Base58.encode(signature)));
// Send no response at all???
return;