From 623389a156be2a118f771c8fdfe9aabea3e77fe4 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Mon, 9 Jan 2012 11:57:08 +0100 Subject: [PATCH] Address comments from Miron and Andreas: - Make GetBlocksMessage/GetHeadersMessage implement toString/hashCode - Minor comment/naming fixes - > not >= for comparing fast catchup time to block header - Return current time in Wallet.getEarliestKeyCreationTime() rather than throw an exception when there are no keys in the wallet. --- .../google/bitcoin/core/GetBlocksMessage.java | 23 +++++++++++-- .../bitcoin/core/GetHeadersMessage.java | 32 +++++++++++++++++++ src/com/google/bitcoin/core/Peer.java | 4 +-- src/com/google/bitcoin/core/PeerGroup.java | 2 +- src/com/google/bitcoin/core/Wallet.java | 6 ++-- tests/com/google/bitcoin/core/WalletTest.java | 12 +++---- 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/com/google/bitcoin/core/GetBlocksMessage.java b/src/com/google/bitcoin/core/GetBlocksMessage.java index 172541eb..466c1d9d 100644 --- a/src/com/google/bitcoin/core/GetBlocksMessage.java +++ b/src/com/google/bitcoin/core/GetBlocksMessage.java @@ -23,9 +23,9 @@ import java.util.List; public class GetBlocksMessage extends Message { private static final long serialVersionUID = 3479412877853645644L; - private long version; - private List locator; - private Sha256Hash stopHash; + protected long version; + protected List locator; + protected Sha256Hash stopHash; public GetBlocksMessage(NetworkParameters params, List locator, Sha256Hash stopHash) { super(params); @@ -83,4 +83,21 @@ public class GetBlocksMessage extends Message { // Next, a block ID to stop at. stream.write(stopHash.getBytes()); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof GetBlocksMessage)) return false; + GetBlocksMessage other = (GetBlocksMessage) o; + return (other.version == version && + locator.size() == other.locator.size() && locator.containsAll(other.locator) && + stopHash.equals(other.stopHash)); + } + + @Override + public int hashCode() { + int hashCode = (int) version ^ "getblocks".hashCode(); + for (int i = 0; i < locator.size(); i++) hashCode ^= locator.get(i).hashCode(); + hashCode ^= stopHash.hashCode(); + return hashCode; + } } diff --git a/src/com/google/bitcoin/core/GetHeadersMessage.java b/src/com/google/bitcoin/core/GetHeadersMessage.java index fca30f35..8f1c8081 100644 --- a/src/com/google/bitcoin/core/GetHeadersMessage.java +++ b/src/com/google/bitcoin/core/GetHeadersMessage.java @@ -28,4 +28,36 @@ public class GetHeadersMessage extends GetBlocksMessage { public GetHeadersMessage(NetworkParameters params, List locator, Sha256Hash stopHash) { super(params, locator, stopHash); } + + @Override + public String toString() { + StringBuffer b = new StringBuffer(); + b.append("getheaders: "); + for (Sha256Hash hash : locator) { + b.append(hash.toString()); + b.append(" "); + } + return b.toString(); + } + + /** + * Compares two getheaders messages. Note that even though they are structurally identical a GetHeadersMessage + * will not compare equal to a GetBlocksMessage containing the same data. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof GetHeadersMessage)) return false; + GetHeadersMessage other = (GetHeadersMessage) o; + return (other.version == version && + locator.size() == other.locator.size() && locator.containsAll(other.locator) && + stopHash.equals(other.stopHash)); + } + + @Override + public int hashCode() { + int hashCode = (int) version ^ "getheaders".hashCode(); + for (int i = 0; i < locator.size(); i++) hashCode ^= locator.get(i).hashCode(); + hashCode ^= stopHash.hashCode(); + return hashCode; + } } diff --git a/src/com/google/bitcoin/core/Peer.java b/src/com/google/bitcoin/core/Peer.java index 94580d5a..fc7cd249 100644 --- a/src/com/google/bitcoin/core/Peer.java +++ b/src/com/google/bitcoin/core/Peer.java @@ -356,7 +356,7 @@ public class Peer { 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 (fastCatchupTimeSecs >= blockChain.getChainHead().getHeader().getTimeSeconds()) { + if (fastCatchupTimeSecs > blockChain.getChainHead().getHeader().getTimeSeconds()) { downloadBlockBodies = false; } } @@ -483,7 +483,7 @@ public class Peer { } blockLocator.add(0, topBlock.getHash()); } - // The stopHash field is set to zero already by the constructor. + // The toHash field is set to zero already by the constructor. if (downloadBlockBodies) { GetBlocksMessage message = new GetBlocksMessage(params, blockLocator, toHash); diff --git a/src/com/google/bitcoin/core/PeerGroup.java b/src/com/google/bitcoin/core/PeerGroup.java index a7213d48..8461ede8 100644 --- a/src/com/google/bitcoin/core/PeerGroup.java +++ b/src/com/google/bitcoin/core/PeerGroup.java @@ -453,7 +453,7 @@ public class PeerGroup { /** * Tells the PeerGroup to download only block headers before a certain time and bodies after that. See - * {@link Peer#setFastCatchupTime(long)} for further explanation. + * {@link Peer#setFastCatchupTime(long)} for further explanation. Call this before starting block chain download. */ public synchronized void setFastCatchupTimeSecs(long secondsSinceEpoch) { fastCatchupTimeSecs = secondsSinceEpoch; diff --git a/src/com/google/bitcoin/core/Wallet.java b/src/com/google/bitcoin/core/Wallet.java index 212426cf..94e30a35 100644 --- a/src/com/google/bitcoin/core/Wallet.java +++ b/src/com/google/bitcoin/core/Wallet.java @@ -1030,13 +1030,13 @@ public class Wallet implements Serializable { * This method is most often used in conjunction with {@link PeerGroup#setFastCatchupTimeSecs(long)} 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. + * have wallets pre-dating this time.

* - * @throws IllegalStateException if there are no keys in the wallet. + * If there are no keys in the wallet, the current time is returned. */ public long getEarliestKeyCreationTime() { if (keychain.size() == 0) { - throw new IllegalStateException("No keys in wallet"); + return Utils.now().getTime() / 1000; } long earliestTime = Long.MAX_VALUE; for (ECKey key : keychain) { diff --git a/tests/com/google/bitcoin/core/WalletTest.java b/tests/com/google/bitcoin/core/WalletTest.java index 485f2bda..85d4e6ff 100644 --- a/tests/com/google/bitcoin/core/WalletTest.java +++ b/tests/com/google/bitcoin/core/WalletTest.java @@ -327,16 +327,14 @@ public class WalletTest { @Test public void keyCreationTime() throws Exception { wallet = new Wallet(params); - // No keys throws an exception. - try { - wallet.getEarliestKeyCreationTime(); - fail(); - } catch (IllegalStateException e) {} long now = Utils.rollMockClock(0).getTime() / 1000; // Fix the mock clock. - wallet.addKey(new ECKey()); + // No keys returns current time. assertEquals(now, wallet.getEarliestKeyCreationTime()); Utils.rollMockClock(60); wallet.addKey(new ECKey()); - assertEquals(now, wallet.getEarliestKeyCreationTime()); + assertEquals(now + 60, wallet.getEarliestKeyCreationTime()); + Utils.rollMockClock(60); + wallet.addKey(new ECKey()); + assertEquals(now + 60, wallet.getEarliestKeyCreationTime()); } }