forked from Qortal/qortal
Don't allow block generation unless system clock is accurate.
Controller performs NTP check on startup (and every 5 minutes) which determines whether block generation is allowed. System Tray tooltip updated to reflect generating status. Plus new translations. Improved GuiTests. BlockGenerator fetches forging accounts first, and sleeps if none configured, which is less work than processing peer lists.
This commit is contained in:
parent
73e53120a9
commit
671dc5995a
@ -79,6 +79,15 @@ public class BlockGenerator extends Thread {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If Controller says we can't generate, then don't...
|
||||||
|
if (!Controller.getInstance().isGenerationAllowed())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<ForgingAccountData> forgingAccountsData = repository.getAccountRepository().getForgingAccounts();
|
||||||
|
// No forging accounts?
|
||||||
|
if (forgingAccountsData.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
List<Peer> peers = Network.getInstance().getUniqueHandshakedPeers();
|
List<Peer> peers = Network.getInstance().getUniqueHandshakedPeers();
|
||||||
BlockData lastBlockData = blockRepository.getLastBlock();
|
BlockData lastBlockData = blockRepository.getLastBlock();
|
||||||
|
|
||||||
@ -109,11 +118,6 @@ public class BlockGenerator extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do we need to build any potential new blocks?
|
// Do we need to build any potential new blocks?
|
||||||
List<ForgingAccountData> forgingAccountsData = repository.getAccountRepository().getForgingAccounts();
|
|
||||||
// No forging accounts?
|
|
||||||
if (forgingAccountsData.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
List<PrivateKeyAccount> forgingAccounts = forgingAccountsData.stream().map(accountData -> new PrivateKeyAccount(repository, accountData.getSeed())).collect(Collectors.toList());
|
List<PrivateKeyAccount> forgingAccounts = forgingAccountsData.stream().map(accountData -> new PrivateKeyAccount(repository, accountData.getSeed())).collect(Collectors.toList());
|
||||||
|
|
||||||
// Discard accounts we have blocks for
|
// Discard accounts we have blocks for
|
||||||
|
@ -91,7 +91,7 @@ public class Controller extends Thread {
|
|||||||
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 * 1000; // ms
|
||||||
private static final long REPOSITORY_BACKUP_PERIOD = 123 * 60 * 1000; // ms
|
private static final long REPOSITORY_BACKUP_PERIOD = 123 * 60 * 1000; // ms
|
||||||
private static final long NTP_NAG_PERIOD = 5 * 60 * 1000; // ms
|
private static final long NTP_CHECK_PERIOD = 5 * 60 * 1000; // ms
|
||||||
private static final long MAX_NTP_OFFSET = 500; // ms
|
private static final long MAX_NTP_OFFSET = 500; // ms
|
||||||
|
|
||||||
private static volatile boolean isStopping = false;
|
private static volatile boolean isStopping = false;
|
||||||
@ -103,7 +103,9 @@ public class Controller extends Thread {
|
|||||||
private final long buildTimestamp; // seconds
|
private final long buildTimestamp; // seconds
|
||||||
|
|
||||||
private long repositoryBackupTimestamp = startTime + REPOSITORY_BACKUP_PERIOD;
|
private long repositoryBackupTimestamp = startTime + REPOSITORY_BACKUP_PERIOD;
|
||||||
private long ntpNagTimestamp = startTime + NTP_NAG_PERIOD;
|
private long ntpCheckTimestamp = startTime; // ms
|
||||||
|
/** Whether BlockGenerator is allowed to generate blocks. Mostly determined by system clock accuracy. */
|
||||||
|
private boolean isGenerationAllowed = false;
|
||||||
|
|
||||||
/** Signature of peer's latest block when we tried to sync but peer had inferior chain. */
|
/** Signature of peer's latest block when we tried to sync but peer had inferior chain. */
|
||||||
private byte[] inferiorChainPeerBlockSignature = null;
|
private byte[] inferiorChainPeerBlockSignature = null;
|
||||||
@ -202,6 +204,10 @@ public class Controller extends Thread {
|
|||||||
return this.blockchainLock;
|
return this.blockchainLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGenerationAllowed() {
|
||||||
|
return this.isGenerationAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
// Entry point
|
// Entry point
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
@ -321,9 +327,13 @@ public class Controller extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Potentially nag end-user about NTP
|
// Potentially nag end-user about NTP
|
||||||
if (System.currentTimeMillis() >= ntpNagTimestamp) {
|
if (System.currentTimeMillis() >= ntpCheckTimestamp) {
|
||||||
ntpNagTimestamp += NTP_NAG_PERIOD;
|
ntpCheckTimestamp += NTP_CHECK_PERIOD;
|
||||||
ntpNag();
|
Boolean isClockAccurate = ntpCheck();
|
||||||
|
if (isClockAccurate != null) {
|
||||||
|
isGenerationAllowed = isClockAccurate;
|
||||||
|
updateSysTray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune stuck/slow/old peers
|
// Prune stuck/slow/old peers
|
||||||
@ -422,8 +432,12 @@ public class Controller extends Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Nag if we detect system clock is too far from internet time. */
|
/**
|
||||||
private void ntpNag() {
|
* Nag if we detect system clock is too far from internet time.
|
||||||
|
*
|
||||||
|
* @return <tt>true</tt> if clock is accurate, <tt>false</tt> if inaccurate, <tt>null</tt> if we don't know.
|
||||||
|
*/
|
||||||
|
private Boolean ntpCheck() {
|
||||||
// Fetch mean offset from internet time (ms).
|
// Fetch mean offset from internet time (ms).
|
||||||
Long meanOffset = NTP.getOffset();
|
Long meanOffset = NTP.getOffset();
|
||||||
|
|
||||||
@ -459,13 +473,20 @@ public class Controller extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If offset is good and ntp is active then we're good
|
// If offset is good and ntp is active then we're good
|
||||||
if (Math.abs(meanOffset) < MAX_NTP_OFFSET && isNtpActive == true)
|
if (meanOffset != null && Math.abs(meanOffset) < MAX_NTP_OFFSET && isNtpActive == true)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
// Time to nag
|
// Time to nag
|
||||||
String caption = Translator.INSTANCE.translate("SysTray", "NTP_NAG_CAPTION");
|
String caption = Translator.INSTANCE.translate("SysTray", "NTP_NAG_CAPTION");
|
||||||
String text = Translator.INSTANCE.translate("SysTray", isWindows ? "NTP_NAG_TEXT_WINDOWS" : "NTP_NAG_TEXT_UNIX");
|
String text = Translator.INSTANCE.translate("SysTray", isWindows ? "NTP_NAG_TEXT_WINDOWS" : "NTP_NAG_TEXT_UNIX");
|
||||||
SysTray.getInstance().showMessage(caption, text, MessageType.WARNING);
|
SysTray.getInstance().showMessage(caption, text, MessageType.WARNING);
|
||||||
|
|
||||||
|
if (meanOffset == null)
|
||||||
|
// We don't know if we're inaccurate
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Return whether we're accurate (disregarding whether NTP service is active)
|
||||||
|
return Math.abs(meanOffset) < MAX_NTP_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSysTray() {
|
public void updateSysTray() {
|
||||||
@ -475,7 +496,9 @@ public class Controller extends Thread {
|
|||||||
|
|
||||||
String connectionsText = Translator.INSTANCE.translate("SysTray", numberOfPeers != 1 ? "CONNECTIONS" : "CONNECTION");
|
String connectionsText = Translator.INSTANCE.translate("SysTray", numberOfPeers != 1 ? "CONNECTIONS" : "CONNECTION");
|
||||||
String heightText = Translator.INSTANCE.translate("SysTray", "BLOCK_HEIGHT");
|
String heightText = Translator.INSTANCE.translate("SysTray", "BLOCK_HEIGHT");
|
||||||
String tooltip = String.format("qora-core - %d %s - %s %d", numberOfPeers, connectionsText, heightText, height);
|
String generatingText = Translator.INSTANCE.translate("SysTray", isGenerationAllowed ? "GENERATING_ENABLED" : "GENERATING_DISABLED");
|
||||||
|
|
||||||
|
String tooltip = String.format("%s - %d %s - %s %d", generatingText, numberOfPeers, connectionsText, heightText, height);
|
||||||
SysTray.getInstance().setToolTipText(tooltip);
|
SysTray.getInstance().setToolTipText(tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,16 @@ BLOCK_HEIGHT = height
|
|||||||
|
|
||||||
CHECK_TIME_ACCURACY = Check time accuracy
|
CHECK_TIME_ACCURACY = Check time accuracy
|
||||||
|
|
||||||
CONNECTION = block
|
CONNECTION = connection
|
||||||
|
|
||||||
CONNECTIONS = connections
|
CONNECTIONS = connections
|
||||||
|
|
||||||
EXIT = Exit
|
EXIT = Exit
|
||||||
|
|
||||||
|
GENERATING_DISABLED = NOT minting
|
||||||
|
|
||||||
|
GENERATING_ENABLED = \u2714 Minting
|
||||||
|
|
||||||
# Nagging about lack of NTP time sync
|
# Nagging about lack of NTP time sync
|
||||||
NTP_NAG_CAPTION = Computer's clock is inaccurate!
|
NTP_NAG_CAPTION = Computer's clock is inaccurate!
|
||||||
|
|
||||||
|
@ -5,10 +5,16 @@ BLOCK_HEIGHT = \u5757\u9AD8\u5EA6
|
|||||||
|
|
||||||
CHECK_TIME_ACCURACY = \u68C0\u67E5\u65F6\u95F4\u51C6\u786E\u6027
|
CHECK_TIME_ACCURACY = \u68C0\u67E5\u65F6\u95F4\u51C6\u786E\u6027
|
||||||
|
|
||||||
|
CONNECTION = \u4E2A\u8FDE\u63A5
|
||||||
|
|
||||||
CONNECTIONS = \u4E2A\u8FDE\u63A5
|
CONNECTIONS = \u4E2A\u8FDE\u63A5
|
||||||
|
|
||||||
EXIT = \u9000\u51FA\u8F6F\u4EF6
|
EXIT = \u9000\u51FA\u8F6F\u4EF6
|
||||||
|
|
||||||
|
GENERATING_DISABLED = \u6CA1\u6709\u94F8\u5E01
|
||||||
|
|
||||||
|
GENERATING_ENABLED = \u2714 \u94F8\u5E01
|
||||||
|
|
||||||
# Nagging about lack of NTP time sync
|
# Nagging about lack of NTP time sync
|
||||||
NTP_NAG_CAPTION = \u7535\u8111\u7684\u65F6\u949F\u4E0D\u51C6\u786E\uFF01
|
NTP_NAG_CAPTION = \u7535\u8111\u7684\u65F6\u949F\u4E0D\u51C6\u786E\uFF01
|
||||||
|
|
||||||
|
@ -19,9 +19,7 @@ public class GuiTests {
|
|||||||
public void testSysTray() throws InterruptedException {
|
public void testSysTray() throws InterruptedException {
|
||||||
SysTray.getInstance();
|
SysTray.getInstance();
|
||||||
|
|
||||||
while(true) {
|
Thread.sleep(10_000L);
|
||||||
Thread.sleep(2000L);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user