Cherry-pick minor fixes from another branch to resolve "No online accounts - not even our own?" issues

This commit is contained in:
catbref 2022-06-04 12:28:24 +01:00
parent d9b330b46a
commit 829ab1eb37
2 changed files with 35 additions and 38 deletions

View File

@ -355,7 +355,7 @@ public class Block {
long timestamp = calcTimestamp(parentBlockData, minter.getPublicKey(), minterLevel); long timestamp = calcTimestamp(parentBlockData, minter.getPublicKey(), minterLevel);
long onlineAccountsTimestamp = OnlineAccountsManager.toOnlineAccountTimestamp(timestamp); long onlineAccountsTimestamp = OnlineAccountsManager.getCurrentOnlineAccountTimestamp();
// Fetch our list of online accounts // Fetch our list of online accounts
List<OnlineAccountData> onlineAccounts = OnlineAccountsManager.getInstance().getOnlineAccounts(onlineAccountsTimestamp); List<OnlineAccountData> onlineAccounts = OnlineAccountsManager.getInstance().getOnlineAccounts(onlineAccountsTimestamp);

View File

@ -53,7 +53,7 @@ public class OnlineAccountsManager {
private static final long ONLINE_ACCOUNTS_BROADCAST_INTERVAL = 15 * 1000L; // ms private static final long ONLINE_ACCOUNTS_BROADCAST_INTERVAL = 15 * 1000L; // ms
private static final long ONLINE_ACCOUNTS_V2_PEER_VERSION = 0x0300020000L; // v3.2.0 private static final long ONLINE_ACCOUNTS_V2_PEER_VERSION = 0x0300020000L; // v3.2.0
private static final long ONLINE_ACCOUNTS_V3_PEER_VERSION = 0x03000200cbL; // v3.2.203 private static final long ONLINE_ACCOUNTS_V3_PEER_VERSION = 0x03000300cbL; // v3.3.203
private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4, new NamedThreadFactory("OnlineAccounts")); private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4, new NamedThreadFactory("OnlineAccounts"));
private volatile boolean isStopping = false; private volatile boolean isStopping = false;
@ -75,8 +75,12 @@ public class OnlineAccountsManager {
*/ */
private final SortedMap<Long, Set<OnlineAccountData>> latestBlocksOnlineAccounts = new ConcurrentSkipListMap<>(); private final SortedMap<Long, Set<OnlineAccountData>> latestBlocksOnlineAccounts = new ConcurrentSkipListMap<>();
public static long toOnlineAccountTimestamp(long timestamp) { public static Long getCurrentOnlineAccountTimestamp() {
return (timestamp / ONLINE_TIMESTAMP_MODULUS) * ONLINE_TIMESTAMP_MODULUS; Long now = NTP.getTime();
if (now == null)
return null;
return (now / ONLINE_TIMESTAMP_MODULUS) * ONLINE_TIMESTAMP_MODULUS;
} }
private OnlineAccountsManager() { private OnlineAccountsManager() {
@ -118,11 +122,10 @@ public class OnlineAccountsManager {
return; return;
} }
final Long now = NTP.getTime(); final Long onlineAccountsTimestamp = getCurrentOnlineAccountTimestamp();
if (now == null) if (onlineAccountsTimestamp == null)
return; return;
final long onlineAccountsTimestamp = toOnlineAccountTimestamp(now);
byte[] timestampBytes = Longs.toByteArray(onlineAccountsTimestamp); byte[] timestampBytes = Longs.toByteArray(onlineAccountsTimestamp);
Set<OnlineAccountData> replacementAccounts = new HashSet<>(); Set<OnlineAccountData> replacementAccounts = new HashSet<>();
@ -162,15 +165,15 @@ public class OnlineAccountsManager {
// Remove from queue // Remove from queue
onlineAccountsImportQueue.remove(onlineAccountData); onlineAccountsImportQueue.remove(onlineAccountData);
} }
LOGGER.debug("Finished validating online accounts import queue");
} catch (DataException e) { } catch (DataException e) {
LOGGER.error("Repository issue while verifying online accounts", e); LOGGER.error("Repository issue while verifying online accounts", e);
} }
if (!onlineAccountsToAdd.isEmpty()) {
LOGGER.debug("Merging {} validated online accounts from import queue", onlineAccountsToAdd.size()); LOGGER.debug("Merging {} validated online accounts from import queue", onlineAccountsToAdd.size());
addAccounts(onlineAccountsToAdd); addAccounts(onlineAccountsToAdd);
} }
}
// Utilities // Utilities
@ -224,7 +227,8 @@ public class OnlineAccountsManager {
return true; return true;
} }
private void addAccounts(Set<OnlineAccountData> onlineAccountsToAdd) { /** Adds accounts, maybe rebuilds hashes, returns whether any new accounts were added / hashes rebuilt. */
private boolean addAccounts(Collection<OnlineAccountData> onlineAccountsToAdd) {
// For keeping track of which hashes to rebuild // For keeping track of which hashes to rebuild
Map<Long, Set<Byte>> hashesToRebuild = new HashMap<>(); Map<Long, Set<Byte>> hashesToRebuild = new HashMap<>();
@ -235,6 +239,9 @@ public class OnlineAccountsManager {
hashesToRebuild.computeIfAbsent(onlineAccountData.getTimestamp(), k -> new HashSet<>()).add(onlineAccountData.getPublicKey()[0]); hashesToRebuild.computeIfAbsent(onlineAccountData.getTimestamp(), k -> new HashSet<>()).add(onlineAccountData.getPublicKey()[0]);
} }
if (hashesToRebuild.isEmpty())
return false;
for (var entry : hashesToRebuild.entrySet()) { for (var entry : hashesToRebuild.entrySet()) {
Long timestamp = entry.getKey(); Long timestamp = entry.getKey();
@ -263,6 +270,8 @@ public class OnlineAccountsManager {
)); ));
} }
} }
return true;
} }
private boolean addAccount(OnlineAccountData onlineAccountData) { private boolean addAccount(OnlineAccountData onlineAccountData) {
@ -341,10 +350,10 @@ public class OnlineAccountsManager {
* Send online accounts that are minting on this node. * Send online accounts that are minting on this node.
*/ */
private void sendOurOnlineAccountsInfo() { private void sendOurOnlineAccountsInfo() {
final Long now = NTP.getTime(); // 'current' timestamp
if (now == null) { final Long onlineAccountsTimestamp = getCurrentOnlineAccountTimestamp();
if (onlineAccountsTimestamp == null)
return; return;
}
List<MintingAccountData> mintingAccounts; List<MintingAccountData> mintingAccounts;
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
@ -378,10 +387,6 @@ public class OnlineAccountsManager {
return; return;
} }
// 'current' timestamp
final long onlineAccountsTimestamp = toOnlineAccountTimestamp(now);
boolean hasInfoChanged = false;
byte[] timestampBytes = Longs.toByteArray(onlineAccountsTimestamp); byte[] timestampBytes = Longs.toByteArray(onlineAccountsTimestamp);
List<OnlineAccountData> ourOnlineAccounts = new ArrayList<>(); List<OnlineAccountData> ourOnlineAccounts = new ArrayList<>();
@ -393,15 +398,10 @@ public class OnlineAccountsManager {
// Our account is online // Our account is online
OnlineAccountData ourOnlineAccountData = new OnlineAccountData(onlineAccountsTimestamp, signature, publicKey); OnlineAccountData ourOnlineAccountData = new OnlineAccountData(onlineAccountsTimestamp, signature, publicKey);
boolean isNewEntry = addAccount(ourOnlineAccountData);
if (isNewEntry) {
LOGGER.trace(() -> String.format("Added our online account %s with timestamp %d", Base58.encode(mintingAccount.getPublicKey()), onlineAccountsTimestamp));
ourOnlineAccounts.add(ourOnlineAccountData); ourOnlineAccounts.add(ourOnlineAccountData);
hasInfoChanged = true;
}
} }
boolean hasInfoChanged = addAccounts(ourOnlineAccounts);
if (!hasInfoChanged) if (!hasInfoChanged)
return; return;
@ -425,20 +425,18 @@ public class OnlineAccountsManager {
*/ */
// BlockMinter: only calls this to check whether returned list is empty or not, to determine whether minting is even possible or not // BlockMinter: only calls this to check whether returned list is empty or not, to determine whether minting is even possible or not
public boolean hasOnlineAccounts() { public boolean hasOnlineAccounts() {
final Long now = NTP.getTime(); // 'current' timestamp
if (now == null) final Long onlineAccountsTimestamp = getCurrentOnlineAccountTimestamp();
if (onlineAccountsTimestamp == null)
return false; return false;
final long onlineTimestamp = toOnlineAccountTimestamp(now); return this.currentOnlineAccounts.containsKey(onlineAccountsTimestamp);
return this.currentOnlineAccounts.containsKey(onlineTimestamp);
} }
/** /**
* Returns list of online accounts matching given timestamp. * Returns list of online accounts matching given timestamp.
*/ */
// Block::mint() - only wants online accounts with timestamp that matches block's timestamp so they can be added to new block // Block::mint() - only wants online accounts with (online) timestamp that matches block's (online) timestamp so they can be added to new block
// Block::areOnlineAccountsValid() - only wants online accounts with timestamp that matches block's timestamp to avoid re-verifying sigs
public List<OnlineAccountData> getOnlineAccounts(long onlineTimestamp) { public List<OnlineAccountData> getOnlineAccounts(long onlineTimestamp) {
return new ArrayList<>(Set.copyOf(this.currentOnlineAccounts.getOrDefault(onlineTimestamp, Collections.emptySet()))); return new ArrayList<>(Set.copyOf(this.currentOnlineAccounts.getOrDefault(onlineTimestamp, Collections.emptySet())));
} }
@ -448,13 +446,12 @@ public class OnlineAccountsManager {
*/ */
// API: calls this to return list of online accounts - probably expects ALL timestamps - but going to get 'current' from now on // API: calls this to return list of online accounts - probably expects ALL timestamps - but going to get 'current' from now on
public List<OnlineAccountData> getOnlineAccounts() { public List<OnlineAccountData> getOnlineAccounts() {
final Long now = NTP.getTime(); // 'current' timestamp
if (now == null) final Long onlineAccountsTimestamp = getCurrentOnlineAccountTimestamp();
if (onlineAccountsTimestamp == null)
return Collections.emptyList(); return Collections.emptyList();
final long onlineTimestamp = toOnlineAccountTimestamp(now); return getOnlineAccounts(onlineAccountsTimestamp);
return getOnlineAccounts(onlineTimestamp);
} }
// Block processing // Block processing