mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-03-10 09:20:04 +01:00
Fix Sha256Hash hashcode function.
Delete wallet deserialization unit test, as we now consciously are breaking serialization compatibility. Resolves issue 213.
This commit is contained in:
parent
ec096993e6
commit
9d46c48db9
3 changed files with 3 additions and 82 deletions
|
@ -31,42 +31,9 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
* map. It also checks that the length is correct and provides a bit more type safety.
|
||||
*/
|
||||
public class Sha256Hash implements Serializable {
|
||||
private static final long serialVersionUID = 3778897922647016546L;
|
||||
|
||||
private byte[] bytes;
|
||||
private int hash = -1;
|
||||
|
||||
/**
|
||||
* @see setHashcodeByteLength(int hashcodeByteLength)
|
||||
*/
|
||||
private static int HASHCODE_BYTES_TO_CHECK = 5;
|
||||
private static boolean HASHCODE_BYTES_TO_CHECK_CHANGED = false;
|
||||
|
||||
|
||||
public static final Sha256Hash ZERO_HASH = new Sha256Hash(new byte[32]);
|
||||
|
||||
/**
|
||||
* Alters the number of bytes from the backing array to use when generating java hashCodes.
|
||||
* <br/><br/>
|
||||
* The default value of 5 gives approximately 1 trillion possible unique combinations.
|
||||
* Given that an int hashcode only has 4 billion possible values it should be more than enough.
|
||||
* <br/><br/>
|
||||
* Changing this value after Sha256Hashes have been stored in hashed collections breaks the
|
||||
* hashCode contract and will result in unpredictable behaviour. If this
|
||||
* needs to be set to a different value it should be done once and only once
|
||||
* and before any calls to hashCode() are made on any instance of Sha256Hash instances.
|
||||
* <br/>
|
||||
*
|
||||
* @param hashcodeByteLength the number of bytes in the hash to use for generating the hashcode.
|
||||
* @throws IllegalStateException if called more than once.
|
||||
*/
|
||||
public static void setHashcodeByteLength(int hashcodeByteLength) {
|
||||
if (HASHCODE_BYTES_TO_CHECK_CHANGED)
|
||||
throw new IllegalStateException("setHashcodeByteLength can only be called once and should be called before any instances of Sha256Hash are constructed");
|
||||
HASHCODE_BYTES_TO_CHECK = hashcodeByteLength;
|
||||
HASHCODE_BYTES_TO_CHECK_CHANGED = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Sha256Hash by wrapping the given byte array. It must be 32 bytes long.
|
||||
*/
|
||||
|
@ -76,12 +43,6 @@ public class Sha256Hash implements Serializable {
|
|||
|
||||
}
|
||||
|
||||
private Sha256Hash(byte[] bytes, int hash) {
|
||||
checkArgument(bytes.length == 32);
|
||||
this.bytes = bytes;
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Sha256Hash by decoding the given hex string. It must be 64 characters long.
|
||||
*/
|
||||
|
@ -118,12 +79,8 @@ public class Sha256Hash implements Serializable {
|
|||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (hash == -1) {
|
||||
hash = 1;
|
||||
for (int i = 0; i < HASHCODE_BYTES_TO_CHECK; i++)
|
||||
hash = 31 * hash + bytes[i];
|
||||
}
|
||||
return hash;
|
||||
// Use the last 4 bytes, not the first 4 which are often zeros in Bitcoin.
|
||||
return (bytes[31] & 0xFF) | ((bytes[30] & 0xFF) << 8) | ((bytes[29] & 0xFF) << 16) | ((bytes[28] & 0xFF) << 24);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -143,6 +100,6 @@ public class Sha256Hash implements Serializable {
|
|||
}
|
||||
|
||||
public Sha256Hash duplicate() {
|
||||
return new Sha256Hash(bytes, hash);
|
||||
return new Sha256Hash(bytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,18 +19,13 @@ package com.google.bitcoin.core;
|
|||
import com.google.bitcoin.core.WalletTransaction.Pool;
|
||||
import com.google.bitcoin.store.BlockStore;
|
||||
import com.google.bitcoin.store.MemoryBlockStore;
|
||||
import com.google.bitcoin.store.WalletProtobufSerializer;
|
||||
import com.google.bitcoin.utils.BriefLogFormatter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.bitcoin.core.TestUtils.*;
|
||||
import static com.google.bitcoin.core.Utils.bitcoinValueToFriendlyString;
|
||||
|
@ -622,37 +617,6 @@ public class WalletTest {
|
|||
assertNull(tx1.appearsIn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oldWalletsDeserialize() throws Exception {
|
||||
// Check that the Wallet class fills out tx confidences as best it can when loading old wallets. The new
|
||||
// API provides a superset of the info that used to be available so it's impossible to do a complete
|
||||
// migration but we can do some.
|
||||
//
|
||||
// TODO: This test does not check migration of dead or pending transactions.
|
||||
InputStream stream = getClass().getResourceAsStream("old1.wallet");
|
||||
wallet = Wallet.loadFromFileStream(stream);
|
||||
Set<Transaction> transactions = wallet.getTransactions(true, true);
|
||||
assertEquals(91, transactions.size());
|
||||
Transaction tx = wallet.unspent.get(new Sha256Hash("5649c63ad55002ce2f39d1d4744996ebaccc1d15e0491c9e8d60eb3720dabebd"));
|
||||
assertEquals(tx.getAppearsInHashes().iterator().next(), new Sha256Hash("00000000019380f5aef28393827737f55a1cf8abb51a36d46ab6f2db0a5b9cb8"));
|
||||
assertEquals(TransactionConfidence.ConfidenceType.BUILDING, tx.getConfidence().getConfidenceType());
|
||||
assertEquals(42814, tx.getConfidence().getAppearedAtChainHeight());
|
||||
|
||||
// Re-serialize the wallet. Make sure it's all still there.
|
||||
ByteArrayOutputStream bios = new ByteArrayOutputStream();
|
||||
wallet.saveToFileStream(bios);
|
||||
wallet = Wallet.loadFromFileStream(new ByteArrayInputStream(bios.toByteArray()));
|
||||
assertEquals(91, transactions.size());
|
||||
tx = wallet.unspent.get(new Sha256Hash("5649c63ad55002ce2f39d1d4744996ebaccc1d15e0491c9e8d60eb3720dabebd"));
|
||||
assertEquals(tx.getAppearsInHashes().iterator().next(), new Sha256Hash("00000000019380f5aef28393827737f55a1cf8abb51a36d46ab6f2db0a5b9cb8"));
|
||||
assertEquals(TransactionConfidence.ConfidenceType.BUILDING, tx.getConfidence().getConfidenceType());
|
||||
assertEquals(42814, tx.getConfidence().getAppearedAtChainHeight());
|
||||
|
||||
// Now check we can serialize old wallets to protocol buffers. Covers bug 134.
|
||||
bios.reset();
|
||||
new WalletProtobufSerializer().writeWallet(wallet, bios);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spendToSameWallet() throws Exception {
|
||||
// Test that a spend to the same wallet is dealt with correctly.
|
||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue