Skip to content
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

refactor: create DualBlockChain class to handle header and regular ch… #231

Merged
merged 3 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions core/src/main/java/org/bitcoinj/core/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ public void initDash(boolean liteMode, boolean allowInstantX, @Nullable EnumSet<

public void setMasternodeListManager(SimplifiedMasternodeListManager masternodeListManager) {
this.masternodeListManager = masternodeListManager;
masternodeListManager.setBlockChain(blockChain, headerChain, peerGroup, quorumManager, quorumSnapshotManager, chainLockHandler);
DualBlockChain dualBlockChain = new DualBlockChain(headerChain, blockChain);
masternodeListManager.setBlockChain(dualBlockChain, peerGroup, quorumManager, quorumSnapshotManager, chainLockHandler);
}

public void closeDash() {
Expand Down Expand Up @@ -399,15 +400,15 @@ public void setPeerGroupAndBlockChain(PeerGroup peerGroup, AbstractBlockChain bl
this.peerGroup = peerGroup;
this.blockChain = blockChain;
this.headerChain = headerChain;
DualBlockChain dualBlockChain = new DualBlockChain(headerChain, blockChain);
hashStore = new HashStore(blockChain.getBlockStore());
blockChain.addNewBestBlockListener(newBestBlockListener);
handleActivations(blockChain.getChainHead());
if (initializedObjects) {
sporkManager.setBlockChain(blockChain, peerGroup);
masternodeSync.setBlockChain(blockChain, netFullfilledRequestManager);
masternodeListManager.setBlockChain(
blockChain,
peerGroup != null ? peerGroup.headerChain : null,
dualBlockChain,
peerGroup,
quorumManager,
quorumSnapshotManager,
Expand Down
105 changes: 105 additions & 0 deletions core/src/main/java/org/bitcoinj/core/DualBlockChain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2023 Dash Core Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.bitcoinj.core;

import org.bitcoinj.store.BlockStoreException;

import javax.annotation.Nullable;

import static java.lang.Math.max;

/**
* Manages a header chain and the regular blockchain
*/
public class DualBlockChain {
private final @Nullable AbstractBlockChain headersChain;
private final AbstractBlockChain blockChain;

public DualBlockChain(@Nullable AbstractBlockChain headersChain, AbstractBlockChain blockChain) {
this.headersChain = headersChain;
this.blockChain = blockChain;
}

public AbstractBlockChain getBlockChain() {
return blockChain;
}

public AbstractBlockChain getHeadersChain() {
return headersChain;
}


public int getBlockHeight(Sha256Hash blockHash) {
try {
if (headersChain != null && headersChain.getBestChainHeight() > blockChain.getBestChainHeight()) {
return headersChain.getBlockStore().get(blockHash).getHeight();
} else return blockChain.getBlockStore().get(blockHash).getHeight();
} catch (BlockStoreException x) {
return -1;

Check warning on line 52 in core/src/main/java/org/bitcoinj/core/DualBlockChain.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/core/DualBlockChain.java#L50-L52

Added lines #L50 - L52 were not covered by tests
}
}

public int getBestChainHeight() {
int height = blockChain.getBestChainHeight();
if (headersChain != null)
height = max(headersChain.getBestChainHeight(), blockChain.getBestChainHeight());
return height;
}

public StoredBlock getBlock(Sha256Hash blockHash) {
try {
StoredBlock block = blockChain.getBlockStore().get(blockHash);
if (block == null && headersChain != null) {
block = headersChain.getBlockStore().get(blockHash);
}
return block;
} catch (BlockStoreException e) {
throw new RuntimeException(e);

Check warning on line 71 in core/src/main/java/org/bitcoinj/core/DualBlockChain.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/core/DualBlockChain.java#L70-L71

Added lines #L70 - L71 were not covered by tests
}
}

public StoredBlock getBlockAncestor(StoredBlock block, int height) {
try {
StoredBlock ancestor = block.getAncestor(blockChain.getBlockStore(), height);
if (ancestor == null && headersChain != null) {
ancestor = block.getAncestor(headersChain.getBlockStore(), height);

Check warning on line 79 in core/src/main/java/org/bitcoinj/core/DualBlockChain.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/core/DualBlockChain.java#L79

Added line #L79 was not covered by tests
}
return ancestor;
} catch (BlockStoreException e) {
throw new RuntimeException(e);

Check warning on line 83 in core/src/main/java/org/bitcoinj/core/DualBlockChain.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/core/DualBlockChain.java#L82-L83

Added lines #L82 - L83 were not covered by tests
}
}

public StoredBlock getBlock(int height) {
try {
StoredBlock block = blockChain.getBlockStore().get(height);
if (block == null && headersChain != null) {
block = headersChain.getBlockStore().get(height);
}
return block;
} catch (BlockStoreException e) {
throw new RuntimeException(e);

Check warning on line 95 in core/src/main/java/org/bitcoinj/core/DualBlockChain.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/core/DualBlockChain.java#L94-L95

Added lines #L94 - L95 were not covered by tests
}
}

public StoredBlock getChainHead() {
StoredBlock bestBlock = blockChain.getChainHead();
if (headersChain != null && headersChain.getBestChainHeight() > bestBlock.getHeight())
bestBlock = headersChain.getChainHead();
return bestBlock;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@

package org.bitcoinj.evolution;

import org.bitcoinj.core.AbstractBlockChain;
import org.bitcoinj.core.DualBlockChain;
import org.bitcoinj.core.Message;
import org.bitcoinj.core.NetworkParameters;

/**
* The abstract base class for messages that are for requesting masternode list and quorum list updates
*
* This class requires that subclasses implement {@link #toString(AbstractBlockChain)}
* This class requires that subclasses implement {@link #toString(DualBlockChain)}
*/

public abstract class AbstractQuorumRequest extends Message {
Expand All @@ -45,5 +45,5 @@ public AbstractQuorumRequest(NetworkParameters params, byte [] payload, int offs
* @param blockChain the blockChain that will convert block hashes to heights
* @return the string representation of this object with block heights next to all block hashes
*/
public abstract String toString(AbstractBlockChain blockChain);
public abstract String toString(DualBlockChain blockChain);
}
91 changes: 27 additions & 64 deletions core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.bitcoinj.core.AbstractBlockChain;
import org.bitcoinj.core.BlockQueue;
import org.bitcoinj.core.Context;
import org.bitcoinj.core.DualBlockChain;
import org.bitcoinj.core.MasternodeSync;
import org.bitcoinj.core.Message;
import org.bitcoinj.core.NetworkParameters;
Expand Down Expand Up @@ -88,11 +89,10 @@
protected final ReentrantLock lock = Threading.lock("AbstractQuorumState");

Context context;
AbstractBlockChain headerChain;
AbstractBlockChain blockChain;
DualBlockChain blockChain;
protected PeerGroup peerGroup;
protected BlockStore headerStore;
protected BlockStore blockStore;
//protected BlockStore headerStore;
//protected BlockStore blockStore;

QuorumUpdateRequest<Request> lastRequest;

Expand Down Expand Up @@ -165,13 +165,8 @@
}

// TODO: Do we need to keep track of the header chain also?
public void setBlockChain(PeerGroup peerGroup, AbstractBlockChain headerChain, AbstractBlockChain blockChain) {
public void setBlockChain(PeerGroup peerGroup, DualBlockChain blockChain) {
this.blockChain = blockChain;
this.headerChain = headerChain;
blockStore = blockChain.getBlockStore();
if (headerChain != null) {
headerStore = headerChain.getBlockStore();
}
if (peerGroup != null) {
this.peerGroup = peerGroup;
peerGroup.addMnListDownloadCompleteListener(() -> initChainTipSyncComplete = true, Threading.SAME_THREAD);
Expand Down Expand Up @@ -211,7 +206,7 @@
abstract boolean needsUpdate(StoredBlock nextBlock);

public abstract void processDiff(@Nullable Peer peer, DiffMessage difference,
AbstractBlockChain headersChain, AbstractBlockChain blockChain,
DualBlockChain blockChain,
boolean isLoadingBootStrap, PeerGroup.SyncStage syncStage)
throws VerificationException;

Expand Down Expand Up @@ -288,7 +283,7 @@
} else {
height = currentHeight;
}
StoredBlock resetBlock = blockChain.getBlockStore().get(height);
StoredBlock resetBlock = blockChain.getBlock(height);
if (resetBlock == null)
resetBlock = blockChain.getChainHead();
requestMNListDiff(resetBlock != null ? resetBlock : blockChain.getChainHead());
Expand Down Expand Up @@ -352,6 +347,7 @@

//fill up the pending list with recent blocks
if (syncOptions != MasternodeListSyncOptions.SYNC_MINIMUM) {
// TODO: update based on headers first sync
Sha256Hash tipHash = blockChain.getChainHead().getHeader().getHash();
ArrayList<StoredBlock> blocksToAdd = new ArrayList<>();
if (!getMasternodeListCache().containsKey(tipHash) && !pendingBlocks.contains(blockChain.getChainHead())) {
Expand All @@ -361,7 +357,7 @@
blocksToAdd.add(0, cursor);
} else break;
try {
cursor = cursor.getPrev(blockChain.getBlockStore());
cursor = cursor.getPrev(blockChain.getBlockChain().getBlockStore());

Check warning on line 360 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L360

Added line #L360 was not covered by tests
} catch (BlockStoreException x) {
break;
}
Expand Down Expand Up @@ -479,16 +475,13 @@
}

StoredBlock endBlock = blockChain.getChainHead();
try {
if (syncOptions == MasternodeListSyncOptions.SYNC_MINIMUM)
endBlock = blockChain.getBlockStore().get(endBlock.getHeight() - SigningManager.SIGN_HEIGHT_OFFSET);
if (getMasternodeListCache().containsKey(endBlock.getHeader().getHash()))
endBlock = blockChain.getBlockStore().get((int) getMasternodeListAtTip().getHeight() + 1);
if (endBlock == null)
endBlock = blockChain.getChainHead();
} catch (BlockStoreException x) {
throw new RuntimeException(x);
}

if (syncOptions == MasternodeListSyncOptions.SYNC_MINIMUM)
endBlock = blockChain.getBlock(endBlock.getHeight() - SigningManager.SIGN_HEIGHT_OFFSET);

Check warning on line 480 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L480

Added line #L480 was not covered by tests
if (getMasternodeListCache().containsKey(endBlock.getHeader().getHash()))
endBlock = blockChain.getBlock((int) getMasternodeListAtTip().getHeight() + 1);

Check warning on line 482 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L482

Added line #L482 was not covered by tests
if (endBlock == null)
endBlock = blockChain.getChainHead();

Check warning on line 484 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L484

Added line #L484 was not covered by tests

requestUpdate(downloadPeer, endBlock);
waitingForMNListDiff = true;
Expand All @@ -508,12 +501,13 @@
protected void fillPendingBlocksList(Sha256Hash first, Sha256Hash last) {
lock.lock();
try {
StoredBlock cursor = blockChain.getBlockStore().get(last);
// TODO: update to use DualBlockchain?
StoredBlock cursor = blockChain.getBlockChain().getBlockStore().get(last);

Check warning on line 505 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L505

Added line #L505 was not covered by tests
while (cursor != null && !cursor.getHeader().getHash().equals(first)) {
if (!pendingBlocks.contains(cursor)) {
pendingBlocks.add(cursor);
}
cursor = cursor.getPrev(blockChain.getBlockStore());
cursor = cursor.getPrev(blockChain.getBlockChain().getBlockStore());

Check warning on line 510 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L510

Added line #L510 was not covered by tests
}
} catch (BlockStoreException x) {
throw new RuntimeException(x);
Expand All @@ -535,7 +529,6 @@
}

public void addEventListeners(AbstractBlockChain blockChain, PeerGroup peerGroup) {
this.blockChain = blockChain;
blockChain.addNewBestBlockListener(Threading.SAME_THREAD, newBestBlockListener);
blockChain.addReorganizeListener(reorganizeListener);
if (peerGroup != null) {
Expand Down Expand Up @@ -569,14 +562,12 @@
if (Utils.currentTimeSeconds() - block.getHeader().getTimeSeconds() < timePeriod) {
if (syncOptions == MasternodeListSyncOptions.SYNC_MINIMUM) {
try {
StoredBlock requestBlock = getBlockHeightOffset() > 0 ? blockChain.getBlockStore().get(block.getHeight() - getBlockHeightOffset()) : block;
StoredBlock requestBlock = getBlockHeightOffset() > 0 ? blockChain.getBlock(block.getHeight() - getBlockHeightOffset()) : block;
if (getMasternodeListAtTip().getHeight() > requestBlock.getHeight())
requestBlock = blockChain.getBlockStore().get((int) getMasternodeListAtTip().getHeight() + 1);
requestBlock = blockChain.getBlock((int) getMasternodeListAtTip().getHeight() + 1);

Check warning on line 567 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L567

Added line #L567 was not covered by tests
if (requestBlock != null) {
block = requestBlock;
}
} catch (BlockStoreException x) {
throw new RuntimeException(x);
} catch (NullPointerException x) {
log.info("null pointer exception", x);
}
Expand Down Expand Up @@ -699,15 +690,11 @@
long timePeriod = syncOptions == MasternodeListSyncOptions.SYNC_SNAPSHOT_PERIOD ? SNAPSHOT_TIME_PERIOD : MAX_CACHE_SIZE * 3 * 60L;
if (Utils.currentTimeSeconds() - block.getHeader().getTimeSeconds() < timePeriod) {
if (syncOptions == MasternodeListSyncOptions.SYNC_MINIMUM) {
try {
StoredBlock requestBlock = blockChain.getBlockStore().get(block.getHeight() - getBlockHeightOffset());
if (getMasternodeListAtTip().getHeight() > requestBlock.getHeight())
requestBlock = blockChain.getBlockStore().get((int) getMasternodeListAtTip().getHeight() + 1);
if (requestBlock != null) {
block = requestBlock;
}
} catch (BlockStoreException x) {
//do nothing
StoredBlock requestBlock = blockChain.getBlock(block.getHeight() - getBlockHeightOffset());

Check warning on line 693 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L693

Added line #L693 was not covered by tests
if (getMasternodeListAtTip().getHeight() > requestBlock.getHeight())
requestBlock = blockChain.getBlock((int) getMasternodeListAtTip().getHeight() + 1);

Check warning on line 695 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L695

Added line #L695 was not covered by tests
if (requestBlock != null) {
block = requestBlock;

Check warning on line 697 in core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/AbstractQuorumState.java#L697

Added line #L697 was not covered by tests
}
}
requestMNListDiff(block);
Expand Down Expand Up @@ -837,30 +824,6 @@
}
}

protected StoredBlock getBlockFromHash(Sha256Hash blockHash) {
try {
StoredBlock block = blockChain.getBlockStore().get(blockHash);
if (block == null) {
block = headerChain.getBlockStore().get(blockHash);
}
return block;
} catch (BlockStoreException e) {
throw new RuntimeException(e);
}
}

protected StoredBlock getBlockAncestor(StoredBlock block, int height) {
try {
StoredBlock ancestor = block.getAncestor(blockStore, height);
if (ancestor == null) {
ancestor = block.getAncestor(headerStore, height);
}
return ancestor;
} catch (BlockStoreException e) {
throw new RuntimeException(e);
}
}

BLSSignature getCoinbaseChainlock(StoredBlock block) {
ChainLockSignature clsig = chainLocksHandler.getCoinbaseChainLock(block.getHeader().getHash());
if (clsig != null)
Expand All @@ -870,7 +833,7 @@

// DIP29 Random Beacon for LLMQ selection is activated with v20
Sha256Hash getHashModifier(LLMQParameters llmqParams, StoredBlock quorumBaseBlock) {
StoredBlock workBlock = getBlockAncestor(quorumBaseBlock, quorumBaseBlock.getHeight() - 8);
StoredBlock workBlock = blockChain.getBlockAncestor(quorumBaseBlock, quorumBaseBlock.getHeight() - 8);

if (params.isV20Active(workBlock.getHeight())) {
// v20 is active: calculate modifier using the new way.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package org.bitcoinj.evolution;

import org.bitcoinj.core.AbstractBlockChain;
import org.bitcoinj.core.DualBlockChain;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.ProtocolException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.store.BlockStoreException;

import java.io.IOException;
import java.io.OutputStream;
Expand Down Expand Up @@ -64,14 +63,12 @@
}

@Override
public String toString(AbstractBlockChain blockChain) {
public String toString(DualBlockChain blockChain) {
int baseHeight = -1;
int blockHeight = -1;
try {
baseHeight = blockChain.getBlockStore().get(baseBlockHash).getHeight();
blockHeight = blockChain.getBlockStore().get(blockHash).getHeight();
} catch (BlockStoreException x) {
throw new RuntimeException(x);
baseHeight = blockChain.getBlock(baseBlockHash).getHeight();
blockHeight = blockChain.getBlock(blockHash).getHeight();

Check warning on line 71 in core/src/main/java/org/bitcoinj/evolution/GetSimplifiedMasternodeListDiff.java

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/bitcoinj/evolution/GetSimplifiedMasternodeListDiff.java#L70-L71

Added lines #L70 - L71 were not covered by tests
} catch (NullPointerException x) {
// swallow
}
Expand Down
Loading
Loading