-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: address several sync issues and remove a potential deadlock #247
Changes from all commits
6224302
18fb28b
b3e0660
ac8f7f9
4fb46e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,6 @@ | |
import org.bitcoinj.quorums.QuorumRotationInfo; | ||
import org.bitcoinj.quorums.SigningManager; | ||
import org.bitcoinj.quorums.SimplifiedQuorumList; | ||
import org.bitcoinj.store.BlockStore; | ||
import org.bitcoinj.store.BlockStoreException; | ||
import org.bitcoinj.utils.Threading; | ||
import org.slf4j.Logger; | ||
|
@@ -155,7 +154,7 @@ public void setBootstrap(String bootstrapFilePath, InputStream bootstrapStream, | |
this.bootstrapStream = bootstrapStream; | ||
this.bootStrapFileFormat = bootStrapFileFormat; | ||
if (bootStrapFileFormat == SimplifiedMasternodeListManager.SMLE_VERSION_FORMAT_VERSION) { | ||
protocolVersion = NetworkParameters.ProtocolVersion.SMNLE_VERSIONED.getBitcoinProtocolVersion(); | ||
protocolVersion = NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion(); | ||
} else if (bootStrapFileFormat == SimplifiedMasternodeListManager.BLS_SCHEME_FORMAT_VERSION) { | ||
protocolVersion = NetworkParameters.ProtocolVersion.DMN_TYPE.getBitcoinProtocolVersion(); | ||
} else if (bootStrapFileFormat == SimplifiedMasternodeListManager.QUORUM_ROTATION_FORMAT_VERSION) { | ||
|
@@ -170,7 +169,6 @@ public void setBlockChain(PeerGroup peerGroup, DualBlockChain blockChain) { | |
this.blockChain = blockChain; | ||
if (peerGroup != null) { | ||
this.peerGroup = peerGroup; | ||
// peerGroup.addMnListDownloadCompleteListener(() -> initChainTipSyncComplete = true, Threading.SAME_THREAD); | ||
} | ||
} | ||
|
||
|
@@ -336,9 +334,9 @@ void requestNextMNListDiff() { | |
if (!shouldProcessMNListDiff()) | ||
return; | ||
|
||
log.info("download peer = {}", downloadPeer); | ||
log.info("download peer = {}, but obtaining backup from peerGroup downloadPeer", downloadPeer); | ||
Peer downloadPeerBackup = downloadPeer == null ? context.peerGroup.getDownloadPeer() : downloadPeer; | ||
|
||
log.info("backup download peer = {}", downloadPeerBackup); | ||
lock.lock(); | ||
try { | ||
if (waitingForMNListDiff) | ||
|
@@ -408,9 +406,6 @@ void requestNextMNListDiff() { | |
waitingForMNListDiff = true; | ||
} else { | ||
log.info("there are no pending blocks to process"); | ||
//if (!initChainTipSyncComplete) { | ||
// initChainTipSyncComplete = true; | ||
//} | ||
} | ||
} else { | ||
log.warn("downloadPeer is null, not requesting update"); | ||
|
@@ -425,7 +420,9 @@ void maybeGetMNListDiffFresh() { | |
return; | ||
|
||
if (downloadPeer == null) { | ||
log.info("using peerGroup downloadPeer in maybeGetMNListDiffFresh "); | ||
downloadPeer = context.peerGroup.getDownloadPeer(); | ||
log.info("using peerGroup downloadPeer in maybeGetMNListDiffFresh {}", downloadPeer); | ||
} | ||
|
||
lock.lock(); | ||
|
@@ -530,7 +527,7 @@ public boolean isDeterministicMNsSporkActive() { | |
} | ||
|
||
public void addEventListeners(AbstractBlockChain blockChain, PeerGroup peerGroup) { | ||
blockChain.addNewBestBlockListener(Threading.SAME_THREAD, newBestBlockListener); | ||
blockChain.addNewBestBlockListener(newBestBlockListener); | ||
Comment on lines
-533
to
+530
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If This is the only listener running in the same thread. |
||
blockChain.addReorganizeListener(reorganizeListener); | ||
if (peerGroup != null) { | ||
peerGroup.addConnectedEventListener(peerConnectedEventListener); | ||
|
@@ -588,24 +585,21 @@ public void notifyNewBestBlock(StoredBlock block) throws VerificationException { | |
public final PeerConnectedEventListener peerConnectedEventListener = new PeerConnectedEventListener() { | ||
@Override | ||
public void onPeerConnected(Peer peer, int peerCount) { | ||
lock.lock(); | ||
try { | ||
if (downloadPeer == null) | ||
downloadPeer = peer; | ||
} finally { | ||
lock.unlock(); | ||
} | ||
downloadPeer = context.peerGroup.getDownloadPeer(); | ||
log.info("peer connected and setting download peer to {} with onPeerConnected", downloadPeer); | ||
} | ||
}; | ||
|
||
final PeerDisconnectedEventListener peerDisconnectedEventListener = new PeerDisconnectedEventListener() { | ||
@Override | ||
public void onPeerDisconnected(Peer peer, int peerCount) { | ||
if (downloadPeer == peer) { | ||
downloadPeer = null; | ||
chooseRandomDownloadPeer(); | ||
downloadPeer = context.peerGroup.getDownloadPeer(); | ||
log.info("setting download peer to {} with onPeerDisconnected, previously was {}", downloadPeer, peer); | ||
if (downloadPeer == null) | ||
chooseRandomDownloadPeer(); | ||
} | ||
if (peer.getAddress().equals(lastRequest.getPeerAddress())) { | ||
if (peer.getAddress().equals(lastRequest.getPeerAddress()) && lastRequest.isFullfilled()) { | ||
log.warn("Disconnecting from peer {} before processing mnlistdiff", peer.getAddress()); | ||
// TODO: what else should we do? | ||
// request again? | ||
|
@@ -650,6 +644,7 @@ void chooseRandomDownloadPeer() { | |
List<Peer> peers = context.peerGroup.getConnectedPeers(); | ||
if (peers != null && !peers.isEmpty()) { | ||
downloadPeer = peers.get(new Random().nextInt(peers.size())); | ||
log.info("setting download peer with chooseRandomDownloadPeer: {}", downloadPeer); | ||
} | ||
} | ||
|
||
|
@@ -659,6 +654,7 @@ public void onChainDownloadStarted(Peer peer, int blocksLeft) { | |
lock.lock(); | ||
try { | ||
downloadPeer = peer; | ||
log.info("setting download peer with onChainDownloadStarted {}", peer); | ||
// perhaps this is not required with headers first sync | ||
// does this need to be in the next listener? | ||
if (stateManager.isLoadedFromFile()) | ||
|
@@ -675,6 +671,7 @@ public void onChainDownloadStarted(Peer peer, int blocksLeft) { | |
public void onHeadersDownloadStarted(Peer peer, int blocksLeft) { | ||
lock.lock(); | ||
try { | ||
log.info("setting download peer with onHeadersDownloadStarted: {}", peer); | ||
downloadPeer = peer; | ||
} finally { | ||
lock.unlock(); | ||
|
@@ -716,14 +713,14 @@ public void run() { | |
} catch (ExecutionException e) { | ||
// send the message again | ||
try { | ||
log.info("Exception when sending {}", lastRequest.getRequestMessage().getClass().getSimpleName(), e); | ||
log.info("Exception when sending {} to {}", lastRequest.getRequestMessage().getClass().getSimpleName(), peer, e); | ||
|
||
// use tryLock to avoid deadlocks | ||
boolean isLocked = context.peerGroup.getLock().tryLock(500, TimeUnit.MILLISECONDS); | ||
try { | ||
if (isLocked) { | ||
log.info(Thread.currentThread().getName() + ": lock acquired"); | ||
downloadPeer = context.peerGroup.getDownloadPeer(); | ||
log.info(Thread.currentThread().getName() + ": lock acquired, obtaining downloadPeer from peerGroup: {}", downloadPeer); | ||
if (downloadPeer == null) { | ||
chooseRandomDownloadPeer(); | ||
} | ||
|
@@ -735,12 +732,12 @@ public void run() { | |
} | ||
} | ||
} catch (InterruptedException x) { | ||
x.printStackTrace(); | ||
log.info("sendMessageFuture interrupted", x); | ||
} catch (NullPointerException x) { | ||
log.info("peergroup is not initialized", x); | ||
} | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
log.info("sendMessageFuture interrupted", e); | ||
} | ||
} | ||
}, Threading.THREAD_POOL); | ||
|
@@ -839,7 +836,6 @@ Sha256Hash getHashModifier(LLMQParameters llmqParams, StoredBlock quorumBaseBloc | |
if (params.isV20Active(workBlock.getHeight())) { | ||
// v20 is active: calculate modifier using the new way. | ||
BLSSignature bestCLSignature = getCoinbaseChainlock(workBlock); | ||
log.info("getHashModifier(..., {})\n work: {}\n sig: {}", quorumBaseBlock.getHeader().getHash(), workBlock.getHeader().getHash(), bestCLSignature); | ||
if (bestCLSignature != null) { | ||
// We have a non-null CL signature: calculate modifier using this CL signature | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -167,14 +167,12 @@ public void applyDiff(Peer peer, DualBlockChain blockChain, | |
StoredBlock blockMinus3C; | ||
StoredBlock blockMinus4C = null; | ||
long newHeight = ((CoinbaseTx) quorumRotationInfo.getMnListDiffAtH().coinBaseTx.getExtraPayloadObject()).getHeight(); | ||
if (peer != null) | ||
peer.queueMasternodeListDownloadedListeners(MasternodeListDownloadedListener.Stage.Received, quorumRotationInfo.getMnListDiffTip()); | ||
|
||
boolean isSyncingHeadersFirst = context.peerGroup != null && context.peerGroup.getSyncStage() == PeerGroup.SyncStage.MNLIST; | ||
|
||
log.info("processing {} qrinfo between (atH): {} & {}; {}", | ||
log.info("processing {} qrinfo between (atH): {} & {}; {} from {}", | ||
isLoadingBootStrap ? "bootstrap" : "requested", | ||
mnListAtH.getHeight(), newHeight, quorumRotationInfo.toString(blockChain)); | ||
mnListAtH.getHeight(), newHeight, quorumRotationInfo.toString(blockChain), peer); | ||
|
||
blockAtTip = blockChain.getBlock(quorumRotationInfo.getMnListDiffTip().blockHash); | ||
blockAtH = blockChain.getBlock(quorumRotationInfo.getMnListDiffAtH().blockHash); | ||
|
@@ -1237,8 +1235,13 @@ public String toString() { | |
public void processDiff(@Nullable Peer peer, QuorumRotationInfo quorumRotationInfo, DualBlockChain blockChain, | ||
boolean isLoadingBootStrap, PeerGroup.SyncStage syncStage) throws VerificationException { | ||
long newHeight = ((CoinbaseTx) quorumRotationInfo.getMnListDiffTip().coinBaseTx.getExtraPayloadObject()).getHeight(); | ||
if (peer != null) | ||
if (peer != null) { | ||
peer.queueMasternodeListDownloadedListeners(MasternodeListDownloadedListener.Stage.Received, quorumRotationInfo.getMnListDiffTip()); | ||
peer.queueMasternodeListDownloadedListeners(MasternodeListDownloadedListener.Stage.Received, quorumRotationInfo.getMnListDiffAtH()); | ||
peer.queueMasternodeListDownloadedListeners(MasternodeListDownloadedListener.Stage.Received, quorumRotationInfo.getMnListDiffAtHMinusC()); | ||
peer.queueMasternodeListDownloadedListeners(MasternodeListDownloadedListener.Stage.Received, quorumRotationInfo.getMnListDiffAtHMinus2C()); | ||
peer.queueMasternodeListDownloadedListeners(MasternodeListDownloadedListener.Stage.Received, quorumRotationInfo.getMnListDiffAtHMinus3C()); | ||
} | ||
Comment on lines
+1238
to
+1244
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the goal here is to count qrinfo messages in the bandwidth calculations. |
||
Stopwatch watch = Stopwatch.createStarted(); | ||
boolean isSyncingHeadersFirst = syncStage == PeerGroup.SyncStage.MNLIST; | ||
|
||
|
@@ -1251,6 +1254,7 @@ public void processDiff(@Nullable Peer peer, QuorumRotationInfo quorumRotationIn | |
|
||
unCache(); | ||
failedAttempts = 0; | ||
lastRequest.setFulfilled(); | ||
|
||
if (!pendingBlocks.isEmpty()) { | ||
pendingBlocks.pop(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes a problem where v20 bootstrap files cannot be loaded.