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;
|
||||
}
|
||||
|
||||
// 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();
|
||||
BlockData lastBlockData = blockRepository.getLastBlock();
|
||||
|
||||
@ -109,11 +118,6 @@ public class BlockGenerator extends Thread {
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
// 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 long ARBITRARY_REQUEST_TIMEOUT = 5 * 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 volatile boolean isStopping = false;
|
||||
@ -103,7 +103,9 @@ public class Controller extends Thread {
|
||||
private final long buildTimestamp; // seconds
|
||||
|
||||
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. */
|
||||
private byte[] inferiorChainPeerBlockSignature = null;
|
||||
@ -202,6 +204,10 @@ public class Controller extends Thread {
|
||||
return this.blockchainLock;
|
||||
}
|
||||
|
||||
public boolean isGenerationAllowed() {
|
||||
return this.isGenerationAllowed;
|
||||
}
|
||||
|
||||
// Entry point
|
||||
|
||||
public static void main(String args[]) {
|
||||
@ -321,9 +327,13 @@ public class Controller extends Thread {
|
||||
}
|
||||
|
||||
// Potentially nag end-user about NTP
|
||||
if (System.currentTimeMillis() >= ntpNagTimestamp) {
|
||||
ntpNagTimestamp += NTP_NAG_PERIOD;
|
||||
ntpNag();
|
||||
if (System.currentTimeMillis() >= ntpCheckTimestamp) {
|
||||
ntpCheckTimestamp += NTP_CHECK_PERIOD;
|
||||
Boolean isClockAccurate = ntpCheck();
|
||||
if (isClockAccurate != null) {
|
||||
isGenerationAllowed = isClockAccurate;
|
||||
updateSysTray();
|
||||
}
|
||||
}
|
||||
|
||||
// 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).
|
||||
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 (Math.abs(meanOffset) < MAX_NTP_OFFSET && isNtpActive == true)
|
||||
return;
|
||||
if (meanOffset != null && Math.abs(meanOffset) < MAX_NTP_OFFSET && isNtpActive == true)
|
||||
return true;
|
||||
|
||||
// Time to nag
|
||||
String caption = Translator.INSTANCE.translate("SysTray", "NTP_NAG_CAPTION");
|
||||
String text = Translator.INSTANCE.translate("SysTray", isWindows ? "NTP_NAG_TEXT_WINDOWS" : "NTP_NAG_TEXT_UNIX");
|
||||
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() {
|
||||
@ -475,7 +496,9 @@ public class Controller extends Thread {
|
||||
|
||||
String connectionsText = Translator.INSTANCE.translate("SysTray", numberOfPeers != 1 ? "CONNECTIONS" : "CONNECTION");
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,16 @@ BLOCK_HEIGHT = height
|
||||
|
||||
CHECK_TIME_ACCURACY = Check time accuracy
|
||||
|
||||
CONNECTION = block
|
||||
CONNECTION = connection
|
||||
|
||||
CONNECTIONS = connections
|
||||
|
||||
EXIT = Exit
|
||||
|
||||
GENERATING_DISABLED = NOT minting
|
||||
|
||||
GENERATING_ENABLED = \u2714 Minting
|
||||
|
||||
# Nagging about lack of NTP time sync
|
||||
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
|
||||
|
||||
CONNECTION = \u4E2A\u8FDE\u63A5
|
||||
|
||||
CONNECTIONS = \u4E2A\u8FDE\u63A5
|
||||
|
||||
EXIT = \u9000\u51FA\u8F6F\u4EF6
|
||||
|
||||
GENERATING_DISABLED = \u6CA1\u6709\u94F8\u5E01
|
||||
|
||||
GENERATING_ENABLED = \u2714 \u94F8\u5E01
|
||||
|
||||
# Nagging about lack of NTP time sync
|
||||
NTP_NAG_CAPTION = \u7535\u8111\u7684\u65F6\u949F\u4E0D\u51C6\u786E\uFF01
|
||||
|
||||
|
@ -19,9 +19,7 @@ public class GuiTests {
|
||||
public void testSysTray() throws InterruptedException {
|
||||
SysTray.getInstance();
|
||||
|
||||
while(true) {
|
||||
Thread.sleep(2000L);
|
||||
}
|
||||
Thread.sleep(10_000L);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user