Compare commits

..

7 Commits

Author SHA1 Message Date
CalDescent
fecfac5ad9 Keep existing findCommonBlocksWithPeers() and comparePeers() behaviour prior to consensus switchover, to reduce the number of variables. 2022-06-16 18:38:27 +01:00
CalDescent
5ed1ec8809 Merge remote-tracking branch 'catbref/sync-long-tip' into sync-long-tip 2022-06-16 18:35:16 +01:00
CalDescent
af792dfc06 Updated AdvancedInstaller project for v3.3.5 2022-06-15 21:11:12 +01:00
CalDescent
d3b6c5f052 Bump version to 3.3.5 2022-06-14 23:18:46 +01:00
CalDescent
f48eb27f00 Revert "Temporarily limit block minter as first stage of multipart minting fix. This will be reverted almost immediately after release."
This reverts commit 0eebfe4a8c.
2022-06-14 22:42:44 +01:00
CalDescent
b02ac2561f Revert "Safety check - also to be removed shortly."
This reverts commit 8b3f9db497.
2022-06-14 22:42:38 +01:00
catbref
8a76c6c0de Sync behaviour changes:
* Prefer longer chains
* Compare chain tips
* Skip pre-sync all-peer sorting (for now)
2022-06-04 10:23:31 +01:00
7 changed files with 91 additions and 33 deletions

View File

@@ -17,10 +17,10 @@
<ROW Property="Manufacturer" Value="Qortal"/>
<ROW Property="MsiLogging" MultiBuildValue="DefaultBuild:vp"/>
<ROW Property="NTP_GOOD" Value="false"/>
<ROW Property="ProductCode" Value="1033:{4FED6490-EFD9-4670-A497-4E0778B72720} 1049:{059E82DD-E2D3-40EC-AF0C-259FB68F7BEE} 2052:{0571ADAA-B818-4AA9-9320-57267B44E5C7} 2057:{92A305F9-3C4A-4800-9977-10DBB6B8F30A} " Type="16"/>
<ROW Property="ProductCode" Value="1033:{7DED0630-60A3-438A-B857-D95BD16213F1} 1049:{4A7BAAA1-E9EC-4E92-8963-34420EC1E3F4} 2052:{F3448469-4E4F-4600-AE05-DF7669B267E3} 2057:{0B980BC5-4C80-4A98-A4D2-B32D134AA276} " Type="16"/>
<ROW Property="ProductLanguage" Value="2057"/>
<ROW Property="ProductName" Value="Qortal"/>
<ROW Property="ProductVersion" Value="3.3.3" Type="32"/>
<ROW Property="ProductVersion" Value="3.3.5" Type="32"/>
<ROW Property="RECONFIG_NTP" Value="true"/>
<ROW Property="REMOVE_BLOCKCHAIN" Value="YES" Type="4"/>
<ROW Property="REPAIR_BLOCKCHAIN" Value="YES" Type="4"/>
@@ -212,7 +212,7 @@
<ROW Component="ADDITIONAL_LICENSE_INFO_71" ComponentId="{12A3ADBE-BB7A-496C-8869-410681E6232F}" Directory_="jdk.zipfs_Dir" Attributes="0" KeyPath="ADDITIONAL_LICENSE_INFO_71" Type="0"/>
<ROW Component="ADDITIONAL_LICENSE_INFO_8" ComponentId="{D53AD95E-CF96-4999-80FC-5812277A7456}" Directory_="java.naming_Dir" Attributes="0" KeyPath="ADDITIONAL_LICENSE_INFO_8" Type="0"/>
<ROW Component="ADDITIONAL_LICENSE_INFO_9" ComponentId="{6B7EA9B0-5D17-47A8-B78C-FACE86D15E01}" Directory_="java.net.http_Dir" Attributes="0" KeyPath="ADDITIONAL_LICENSE_INFO_9" Type="0"/>
<ROW Component="AI_CustomARPName" ComponentId="{28DC06DF-3CBA-4275-A907-3BD3F8E6AD61}" Directory_="APPDIR" Attributes="260" KeyPath="DisplayName" Options="1"/>
<ROW Component="AI_CustomARPName" ComponentId="{191AD445-72DF-4850-BB4A-FE92D4B62BCF}" Directory_="APPDIR" Attributes="260" KeyPath="DisplayName" Options="1"/>
<ROW Component="AI_ExePath" ComponentId="{3644948D-AE0B-41BB-9FAF-A79E70490A08}" Directory_="APPDIR" Attributes="260" KeyPath="AI_ExePath"/>
<ROW Component="APPDIR" ComponentId="{680DFDDE-3FB4-47A5-8FF5-934F576C6F91}" Directory_="APPDIR" Attributes="0"/>
<ROW Component="AccessBridgeCallbacks.h" ComponentId="{288055D1-1062-47A3-AA44-5601B4E38AED}" Directory_="bridge_Dir" Attributes="0" KeyPath="AccessBridgeCallbacks.h" Type="0"/>

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.qortal</groupId>
<artifactId>qortal</artifactId>
<version>3.3.4</version>
<version>3.3.5</version>
<packaging>jar</packaging>
<properties>
<skipTests>true</skipTests>

View File

@@ -378,10 +378,6 @@ public class Block {
// Online account (reward-share) with current timestamp but reward-share cancelled
continue;
if (accountIndex >= 7850)
// Temporary limitation as first stage of multipart minting fix
continue;
indexedOnlineAccounts.put(accountIndex, onlineAccountData);
}
List<Integer> accountIndexes = new ArrayList<>(indexedOnlineAccounts.keySet());
@@ -393,10 +389,6 @@ public class Block {
byte[] encodedOnlineAccounts = BlockTransformer.encodeOnlineAccounts(onlineAccountsSet);
int onlineAccountsCount = onlineAccountsSet.size();
if (encodedOnlineAccounts.length > 1024)
// Safety check - to be removed along with above temporary limitation
return null;
// Concatenate online account timestamp signatures (in correct order)
byte[] onlineAccountsSignatures = new byte[onlineAccountsCount * Transformer.SIGNATURE_LENGTH];
for (int i = 0; i < onlineAccountsCount; ++i) {

View File

@@ -69,6 +69,7 @@ public class BlockChain {
newBlockSigHeight,
shareBinFix,
calcChainWeightTimestamp,
newConsensusTimestamp,
transactionV5Timestamp,
transactionV6Timestamp,
disableReferenceTimestamp
@@ -403,6 +404,10 @@ public class BlockChain {
return this.featureTriggers.get(FeatureTrigger.calcChainWeightTimestamp.name()).longValue();
}
public long getNewConsensusTimestamp() {
return this.featureTriggers.get(FeatureTrigger.newConsensusTimestamp.name()).longValue();
}
public long getTransactionV5Timestamp() {
return this.featureTriggers.get(FeatureTrigger.transactionV5Timestamp.name()).longValue();
}

View File

@@ -715,6 +715,24 @@ public class Controller extends Thread {
return lastMisbehaved != null && lastMisbehaved > NTP.getTime() - MISBEHAVIOUR_COOLOFF;
};
/** True if peer has unknown height or lower height. */
public static final Predicate<Peer> hasShorterBlockchain = peer -> {
BlockData ourLatestBlockData = getInstance().getChainTip();
int ourHeight = ourLatestBlockData.getHeight();
final PeerChainTipData peerChainTipData = peer.getChainTipData();
// Ensure we have chain tip data for this peer
if (peerChainTipData == null)
return true;
// Remove if peer is at a lower height than us
Integer peerHeight = peerChainTipData.getLastHeight();
if (peerHeight == null || peerHeight < ourHeight)
return true;
return false;
};
public static final Predicate<Peer> hasNoRecentBlock = peer -> {
final Long minLatestBlockTimestamp = getMinimumLatestBlockTimestamp();
final PeerChainTipData peerChainTipData = peer.getChainTipData();

View File

@@ -199,6 +199,8 @@ public class Synchronizer extends Thread {
if (this.isSynchronizing)
return true;
boolean isNewConsensusActive = NTP.getTime() >= BlockChain.getInstance().getNewConsensusTimestamp();
// Needs a mutable copy of the unmodifiableList
List<Peer> peers = new ArrayList<>(Network.getInstance().getImmutableHandshakedPeers());
@@ -227,6 +229,10 @@ public class Synchronizer extends Thread {
if (peers.size() < Settings.getInstance().getMinBlockchainPeers())
return true;
if (isNewConsensusActive)
// Disregard peers with a shorter chain
peers.removeIf(Controller.hasShorterBlockchain);
// Disregard peers that have no block signature or the same block signature as us
peers.removeIf(Controller.hasNoOrSameBlock);
@@ -235,11 +241,13 @@ public class Synchronizer extends Thread {
final int peersBeforeComparison = peers.size();
// Request recent block summaries from the remaining peers, and locate our common block with each
Synchronizer.getInstance().findCommonBlocksWithPeers(peers);
if (!isNewConsensusActive) {
// Request recent block summaries from the remaining peers, and locate our common block with each
Synchronizer.getInstance().findCommonBlocksWithPeers(peers);
// Compare the peers against each other, and against our chain, which will return an updated list excluding those without common blocks
peers = Synchronizer.getInstance().comparePeers(peers);
// Compare the peers against each other, and against our chain, which will return an updated list excluding those without common blocks
peers = Synchronizer.getInstance().comparePeers(peers);
}
// We may have added more inferior chain tips when comparing peers, so remove any peers that are currently on those chains
peers.removeIf(Controller.hasInferiorChainTip);
@@ -985,8 +993,13 @@ public class Synchronizer extends Thread {
return SynchronizationResult.NOTHING_TO_DO;
}
boolean isNewConsensusActive = NTP.getTime() >= BlockChain.getInstance().getNewConsensusTimestamp();
// Unless we're doing a forced sync, we might need to compare blocks after common block
if (!force && ourInitialHeight > commonBlockHeight) {
boolean isBlockComparisonNeeded = isNewConsensusActive
? ourInitialHeight == peerHeight
: ourInitialHeight > commonBlockHeight;
if (!force && isBlockComparisonNeeded) {
SynchronizationResult chainCompareResult = compareChains(repository, commonBlockData, ourLatestBlockData, peer, peerHeight, peerBlockSummaries);
if (chainCompareResult != SynchronizationResult.OK)
return chainCompareResult;
@@ -1187,27 +1200,56 @@ public class Synchronizer extends Thread {
peerBlockSummaries.addAll(moreBlockSummaries);
}
// Fetch our corresponding block summaries
List<BlockSummaryData> ourBlockSummaries = repository.getBlockRepository().getBlockSummaries(commonBlockHeight + 1, ourLatestBlockData.getHeight());
boolean isNewConsensusActive = NTP.getTime() >= BlockChain.getInstance().getNewConsensusTimestamp();
if (isNewConsensusActive) {
int parentHeight = ourLatestBlockData.getHeight() - 1;
// Populate minter account levels for both lists of block summaries
populateBlockSummariesMinterLevels(repository, ourBlockSummaries);
populateBlockSummariesMinterLevels(repository, peerBlockSummaries);
BlockSummaryData ourLatestBlockSummary = new BlockSummaryData(ourLatestBlockData);
byte[] ourParentBlockSignature = ourLatestBlockData.getReference();
final int mutualHeight = commonBlockHeight + Math.min(ourBlockSummaries.size(), peerBlockSummaries.size());
BlockSummaryData peersLatestBlockSummary = peerBlockSummaries.get(peerBlockSummaries.size() - 1);
byte[] peersParentBlockSignature = peerBlockSummaries.size() > 1
? peerBlockSummaries.get(peerBlockSummaries.size() - 1 - 1).getSignature()
: commonBlockSig;
// Calculate cumulative chain weights of both blockchain subsets, from common block to highest mutual block.
BigInteger ourChainWeight = Block.calcChainWeight(commonBlockHeight, commonBlockSig, ourBlockSummaries, mutualHeight);
BigInteger peerChainWeight = Block.calcChainWeight(commonBlockHeight, commonBlockSig, peerBlockSummaries, mutualHeight);
// Populate minter account levels for both lists of block summaries
populateBlockSummariesMinterLevels(repository, Collections.singletonList(ourLatestBlockSummary));
populateBlockSummariesMinterLevels(repository, Collections.singletonList(peersLatestBlockSummary));
NumberFormat accurateFormatter = new DecimalFormat("0.################E0");
LOGGER.debug(String.format("commonBlockHeight: %d, commonBlockSig: %.8s, ourBlockSummaries.size(): %d, peerBlockSummaries.size(): %d", commonBlockHeight, Base58.encode(commonBlockSig), ourBlockSummaries.size(), peerBlockSummaries.size()));
LOGGER.debug(String.format("Our chain weight: %s, peer's chain weight: %s (higher is better)", accurateFormatter.format(ourChainWeight), accurateFormatter.format(peerChainWeight)));
BigInteger ourChainWeight = Block.calcBlockWeight(parentHeight, ourParentBlockSignature, ourLatestBlockSummary);
BigInteger peerChainWeight = Block.calcBlockWeight(parentHeight, peersParentBlockSignature, peersLatestBlockSummary);
// If our blockchain has greater weight then don't synchronize with peer
if (ourChainWeight.compareTo(peerChainWeight) >= 0) {
LOGGER.debug(String.format("Not synchronizing with peer %s as we have better blockchain", peer));
return SynchronizationResult.INFERIOR_CHAIN;
NumberFormat accurateFormatter = new DecimalFormat("0.################E0");
LOGGER.debug(String.format("Our chain weight: %s, peer's chain weight: %s (higher is better)", accurateFormatter.format(ourChainWeight), accurateFormatter.format(peerChainWeight)));
// If our blockchain has greater weight then don't synchronize with peer
if (ourChainWeight.compareTo(peerChainWeight) >= 0) {
LOGGER.debug(String.format("Not synchronizing with peer %s as we have better blockchain", peer));
return SynchronizationResult.INFERIOR_CHAIN;
}
} else {
// Fetch our corresponding block summaries
List<BlockSummaryData> ourBlockSummaries = repository.getBlockRepository().getBlockSummaries(commonBlockHeight + 1, ourLatestBlockData.getHeight());
// Populate minter account levels for both lists of block summaries
populateBlockSummariesMinterLevels(repository, ourBlockSummaries);
populateBlockSummariesMinterLevels(repository, peerBlockSummaries);
final int mutualHeight = commonBlockHeight + Math.min(ourBlockSummaries.size(), peerBlockSummaries.size());
// Calculate cumulative chain weights of both blockchain subsets, from common block to highest mutual block.
BigInteger ourChainWeight = Block.calcChainWeight(commonBlockHeight, commonBlockSig, ourBlockSummaries, mutualHeight);
BigInteger peerChainWeight = Block.calcChainWeight(commonBlockHeight, commonBlockSig, peerBlockSummaries, mutualHeight);
NumberFormat accurateFormatter = new DecimalFormat("0.################E0");
LOGGER.debug(String.format("commonBlockHeight: %d, commonBlockSig: %.8s, ourBlockSummaries.size(): %d, peerBlockSummaries.size(): %d", commonBlockHeight, Base58.encode(commonBlockSig), ourBlockSummaries.size(), peerBlockSummaries.size()));
LOGGER.debug(String.format("Our chain weight: %s, peer's chain weight: %s (higher is better)", accurateFormatter.format(ourChainWeight), accurateFormatter.format(peerChainWeight)));
// If our blockchain has greater weight then don't synchronize with peer
if (ourChainWeight.compareTo(peerChainWeight) >= 0) {
LOGGER.debug(String.format("Not synchronizing with peer %s as we have better blockchain", peer));
return SynchronizationResult.INFERIOR_CHAIN;
}
}
}

View File

@@ -58,6 +58,7 @@
"newBlockSigHeight": 320000,
"shareBinFix": 399000,
"calcChainWeightTimestamp": 1620579600000,
"newConsensusTimestamp": 9999999999999,
"transactionV5Timestamp": 1642176000000,
"transactionV6Timestamp": 9999999999999,
"disableReferenceTimestamp": 1655222400000