mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-18 21:32:35 +01:00
Peer, PeerGroup: migrate fastCatchupTime
field to java.time
API
This commit is contained in:
parent
838b12c046
commit
310b93be4e
@ -123,7 +123,7 @@ public class Peer extends PeerSocketHandler {
|
||||
// Each wallet added to the peer will be notified of downloaded transaction data.
|
||||
private final CopyOnWriteArrayList<Wallet> wallets;
|
||||
// A time before which we only download block headers, after that point we download block bodies.
|
||||
@GuardedBy("lock") private long fastCatchupTimeSecs;
|
||||
@GuardedBy("lock") private Instant fastCatchupTime;
|
||||
// Whether we are currently downloading headers only or block bodies. Starts at true. If the fast catchup time is
|
||||
// set AND our best block is before that date, switch to false until block headers beyond that point have been
|
||||
// received at which point it gets set to true again. This isn't relevant unless vDownloadData is true.
|
||||
@ -239,7 +239,7 @@ public class Peer extends PeerSocketHandler {
|
||||
this.vDownloadData = chain != null;
|
||||
this.getDataFutures = new ConcurrentLinkedQueue<>();
|
||||
this.getAddrFutures = new LinkedList<>();
|
||||
this.fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds();
|
||||
this.fastCatchupTime = params.getGenesisBlock().getTimeInstant();
|
||||
this.pendingPings = new CopyOnWriteArrayList<>();
|
||||
this.vMinProtocolVersion = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.PONG);
|
||||
this.wallets = new CopyOnWriteArrayList<>();
|
||||
@ -617,7 +617,7 @@ public class Peer extends PeerSocketHandler {
|
||||
// the chain if it pre-dates the fast catchup time. If we go past it, we can stop processing the headers and
|
||||
// request the full blocks from that point on instead.
|
||||
boolean downloadBlockBodies;
|
||||
long fastCatchupTimeSecs;
|
||||
Instant fastCatchupTime;
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
@ -626,7 +626,7 @@ public class Peer extends PeerSocketHandler {
|
||||
log.warn("Received headers when Peer is not configured with a chain.");
|
||||
return;
|
||||
}
|
||||
fastCatchupTimeSecs = this.fastCatchupTimeSecs;
|
||||
fastCatchupTime = this.fastCatchupTime;
|
||||
downloadBlockBodies = this.downloadBlockBodies;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
@ -639,7 +639,7 @@ public class Peer extends PeerSocketHandler {
|
||||
// Process headers until we pass the fast catchup time, or are about to catch up with the head
|
||||
// of the chain - always process the last block as a full/filtered block to kick us out of the
|
||||
// fast catchup mode (in which we ignore new blocks).
|
||||
boolean passedTime = header.getTimeSeconds() >= fastCatchupTimeSecs;
|
||||
boolean passedTime = header.getTimeInstant().compareTo(fastCatchupTime) >= 0;
|
||||
boolean reachedTop = blockChain.getBestChainHeight() >= vPeerVersionMessage.bestHeight;
|
||||
if (!passedTime && !reachedTop) {
|
||||
if (!vDownloadData) {
|
||||
@ -661,7 +661,7 @@ public class Peer extends PeerSocketHandler {
|
||||
try {
|
||||
log.info(
|
||||
"Passed the fast catchup time ({}) at height {}, discarding {} headers and requesting full blocks",
|
||||
TimeUtils.dateTimeFormat(fastCatchupTimeSecs * 1000), blockChain.getBestChainHeight() + 1,
|
||||
TimeUtils.dateTimeFormat(fastCatchupTime.toEpochMilli()), blockChain.getBestChainHeight() + 1,
|
||||
m.getBlockHeaders().size() - i);
|
||||
this.downloadBlockBodies = true;
|
||||
// Prevent this request being seen as a duplicate.
|
||||
@ -1313,27 +1313,47 @@ public class Peer extends PeerSocketHandler {
|
||||
* isn't known until their headers are available and they are requested in chunks, so some headers may be downloaded
|
||||
* twice using this scheme, but this optimization can still be a large win for newly created wallets.
|
||||
*
|
||||
* @param secondsSinceEpoch Time in seconds since the epoch or 0 to reset to always downloading block bodies.
|
||||
* @param useFilteredBlocks whether to request filtered blocks if the protocol version allows for them
|
||||
* @param fastCatchupTime time before which block bodies are skipped
|
||||
*/
|
||||
public void setDownloadParameters(long secondsSinceEpoch, boolean useFilteredBlocks) {
|
||||
public void setFastDownloadParameters(boolean useFilteredBlocks, Instant fastCatchupTime) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (secondsSinceEpoch == 0) {
|
||||
fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds();
|
||||
downloadBlockBodies = true;
|
||||
} else {
|
||||
fastCatchupTimeSecs = secondsSinceEpoch;
|
||||
// If the given time is before the current chains head block time, then this has no effect (we already
|
||||
// downloaded everything we need).
|
||||
if (blockChain != null && fastCatchupTimeSecs > blockChain.getChainHead().getHeader().getTimeSeconds())
|
||||
downloadBlockBodies = false;
|
||||
}
|
||||
this.fastCatchupTime = fastCatchupTime;
|
||||
// If the given time is before the current chains head block time, then this has no effect (we already
|
||||
// downloaded everything we need).
|
||||
if (blockChain != null && this.fastCatchupTime.isAfter(blockChain.getChainHead().getHeader().getTimeInstant()))
|
||||
downloadBlockBodies = false;
|
||||
this.useFilteredBlocks = useFilteredBlocks;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always download full blocks.
|
||||
* @param useFilteredBlocks whether to request filtered blocks if the protocol version allows for them
|
||||
*/
|
||||
public void setDownloadParameters(boolean useFilteredBlocks) {
|
||||
lock.lock();
|
||||
try {
|
||||
this.fastCatchupTime = params.getGenesisBlock().getTimeInstant();
|
||||
downloadBlockBodies = true;
|
||||
this.useFilteredBlocks = useFilteredBlocks;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #setDownloadParameters(boolean)} or {@link #setFastDownloadParameters(boolean, Instant)} */
|
||||
@Deprecated
|
||||
public void setDownloadParameters(long fastCatchupTimeSecs, boolean useFilteredBlocks) {
|
||||
if (fastCatchupTimeSecs > 0)
|
||||
setFastDownloadParameters(useFilteredBlocks, Instant.ofEpochSecond(fastCatchupTimeSecs));
|
||||
else
|
||||
setDownloadParameters(useFilteredBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Links the given wallet to this peer. If you have multiple peers, you should use a {@link PeerGroup} to manage
|
||||
* them and use the {@link PeerGroup#addWallet(Wallet)} method instead of registering the wallet with each peer
|
||||
|
@ -213,7 +213,7 @@ public class PeerGroup implements TransactionBroadcaster {
|
||||
@GuardedBy("lock") private boolean useLocalhostPeerWhenPossible = true;
|
||||
@GuardedBy("lock") private boolean ipv6Unreachable = false;
|
||||
|
||||
@GuardedBy("lock") private long fastCatchupTimeSecs;
|
||||
@GuardedBy("lock") private Instant fastCatchupTime;
|
||||
private final CopyOnWriteArrayList<Wallet> wallets;
|
||||
private final CopyOnWriteArrayList<PeerFilterProvider> peerFilterProviders;
|
||||
|
||||
@ -424,7 +424,7 @@ public class PeerGroup implements TransactionBroadcaster {
|
||||
Context.getOrCreate(); // create a context for convenience
|
||||
this.params = params;
|
||||
this.chain = chain;
|
||||
fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds();
|
||||
fastCatchupTime = params.getGenesisBlock().getTimeInstant();
|
||||
wallets = new CopyOnWriteArrayList<>();
|
||||
peerFilterProviders = new CopyOnWriteArrayList<>();
|
||||
|
||||
@ -1711,7 +1711,7 @@ public class PeerGroup implements TransactionBroadcaster {
|
||||
}
|
||||
downloadPeer.setDownloadData(true);
|
||||
if (chain != null)
|
||||
downloadPeer.setDownloadParameters(fastCatchupTimeSecs, bloomFilterMerger.getLastFilter() != null);
|
||||
downloadPeer.setFastDownloadParameters(bloomFilterMerger.getLastFilter() != null, fastCatchupTime);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
@ -1729,34 +1729,46 @@ public class PeerGroup implements TransactionBroadcaster {
|
||||
* before starting block chain download.
|
||||
* Do not use a {@code time > NOW - 1} block, as it will break some block download logic.
|
||||
*/
|
||||
public void setFastCatchupTimeSecs(long secondsSinceEpoch) {
|
||||
public void setFastCatchupTime(Instant fastCatchupTime) {
|
||||
lock.lock();
|
||||
try {
|
||||
checkState(chain == null || !chain.shouldVerifyTransactions(), "Fast catchup is incompatible with fully verifying");
|
||||
fastCatchupTimeSecs = secondsSinceEpoch;
|
||||
this.fastCatchupTime = fastCatchupTime;
|
||||
if (downloadPeer != null) {
|
||||
downloadPeer.setDownloadParameters(secondsSinceEpoch, bloomFilterMerger.getLastFilter() != null);
|
||||
downloadPeer.setFastDownloadParameters(bloomFilterMerger.getLastFilter() != null, fastCatchupTime);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #setFastCatchupTime(Instant)} */
|
||||
@Deprecated
|
||||
public void setFastCatchupTimeSecs(long fastCatchupTimeSecs) {
|
||||
setFastCatchupTime(Instant.ofEpochSecond(fastCatchupTimeSecs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current fast catchup time. The contents of blocks before this time won't be downloaded as they
|
||||
* cannot contain any interesting transactions. If you use {@link PeerGroup#addWallet(Wallet)} this just returns
|
||||
* the min of the wallets earliest key times.
|
||||
* @return a time in seconds since the epoch
|
||||
*/
|
||||
public long getFastCatchupTimeSecs() {
|
||||
public Instant getFastCatchupTime() {
|
||||
lock.lock();
|
||||
try {
|
||||
return fastCatchupTimeSecs;
|
||||
return fastCatchupTime;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #getFastCatchupTime()} */
|
||||
@Deprecated
|
||||
public long getFastCatchupTimeSecs() {
|
||||
return getFastCatchupTime().getEpochSecond();
|
||||
}
|
||||
|
||||
protected void handlePeerDeath(final Peer peer, @Nullable Throwable exception) {
|
||||
// Peer deaths can occur during startup if a connect attempt after peer discovery aborts immediately.
|
||||
if (!isRunning()) return;
|
||||
|
@ -3576,7 +3576,7 @@ public class Wallet extends BaseTaggableObject
|
||||
* of {@link ECKey#getCreationTimeSeconds()}. This can return zero if at least one key does
|
||||
* not have that data (was created before key timestamping was implemented). <p>
|
||||
*
|
||||
* This method is most often used in conjunction with {@link PeerGroup#setFastCatchupTimeSecs(long)} in order to
|
||||
* This method is most often used in conjunction with {@link PeerGroup#setFastCatchupTime(Instant)} in order to
|
||||
* optimize chain download for new users of wallet apps. Backwards compatibility notice: if you get zero from this
|
||||
* method, you can instead use the time of the first release of your software, as it's guaranteed no users will
|
||||
* have wallets pre-dating this time. <p>
|
||||
|
@ -43,6 +43,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -113,7 +114,7 @@ public class BitcoindComparisonTool {
|
||||
}
|
||||
log.info("bitcoind connected");
|
||||
// Make sure bitcoind has no blocks
|
||||
bitcoind.setDownloadParameters(0, false);
|
||||
bitcoind.setDownloadParameters(false);
|
||||
bitcoind.startBlockChainDownload();
|
||||
connectedFuture.complete(null);
|
||||
});
|
||||
|
@ -49,6 +49,7 @@ import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -430,23 +431,23 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
// Check the fast catchup time was initialized to something around the current runtime minus a week.
|
||||
// The wallet was already added to the peer in setup.
|
||||
final int WEEK = 86400 * 7;
|
||||
final long now = TimeUtils.currentTimeSeconds();
|
||||
final Instant now = TimeUtils.currentTime().truncatedTo(ChronoUnit.SECONDS);
|
||||
peerGroup.start();
|
||||
assertTrue(peerGroup.getFastCatchupTimeSecs() > now - WEEK - 10000);
|
||||
assertTrue(peerGroup.getFastCatchupTime().isAfter(now.minusSeconds(WEEK).minusSeconds(10000)));
|
||||
Wallet w2 = Wallet.createDeterministic(UNITTEST, ScriptType.P2PKH);
|
||||
ECKey key1 = new ECKey();
|
||||
key1.setCreationTimeSeconds(now - 86400); // One day ago.
|
||||
key1.setCreationTimeSeconds(now.getEpochSecond() - 86400); // One day ago.
|
||||
w2.importKey(key1);
|
||||
peerGroup.addWallet(w2);
|
||||
peerGroup.waitForJobQueue();
|
||||
assertEquals(peerGroup.getFastCatchupTimeSecs(), now - 86400 - WEEK);
|
||||
assertEquals(peerGroup.getFastCatchupTime(), now.minusSeconds(86400).minusSeconds(WEEK));
|
||||
// Adding a key to the wallet should update the fast catchup time, but asynchronously and in the background
|
||||
// due to the need to avoid complicated lock inversions.
|
||||
ECKey key2 = new ECKey();
|
||||
key2.setCreationTimeSeconds(now - 100000);
|
||||
key2.setCreationTimeSeconds(now.getEpochSecond() - 100000);
|
||||
w2.importKey(key2);
|
||||
peerGroup.waitForJobQueue();
|
||||
assertEquals(peerGroup.getFastCatchupTimeSecs(), now - WEEK - 100000);
|
||||
assertEquals(peerGroup.getFastCatchupTime(),now.minusSeconds(WEEK).minusSeconds(100000));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -466,7 +466,9 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
b4.solve();
|
||||
|
||||
// Request headers until the last 2 blocks.
|
||||
peer.setDownloadParameters(TimeUtils.currentTimeSeconds() - (600*2) + 1, false);
|
||||
peer.setFastDownloadParameters(
|
||||
false, TimeUtils.currentTime().minusSeconds(600 * 2).plusSeconds(1)
|
||||
);
|
||||
peer.startBlockChainDownload();
|
||||
GetHeadersMessage getheaders = (GetHeadersMessage) outbound(writeTarget);
|
||||
BlockLocator expectedLocator = new BlockLocator();
|
||||
|
Loading…
Reference in New Issue
Block a user