Sha256Hash: some tweaks and renamings in the API (backwards compatible).

This commit is contained in:
Mike Hearn 2015-03-05 13:59:15 -08:00
parent bf60a925bc
commit 6aa4e51de6
15 changed files with 47 additions and 41 deletions

View File

@ -562,13 +562,13 @@ public class Block extends Message {
maybeParseHeader(); maybeParseHeader();
Block block = new Block(params); Block block = new Block(params);
block.nonce = nonce; block.nonce = nonce;
block.prevBlockHash = prevBlockHash.duplicate(); block.prevBlockHash = prevBlockHash;
block.merkleRoot = getMerkleRoot().duplicate(); block.merkleRoot = getMerkleRoot();
block.version = version; block.version = version;
block.time = time; block.time = time;
block.difficultyTarget = difficultyTarget; block.difficultyTarget = difficultyTarget;
block.transactions = null; block.transactions = null;
block.hash = getHash().duplicate(); block.hash = getHash();
return block; return block;
} }

View File

@ -54,10 +54,16 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
this.bytes = Utils.HEX.decode(hexString); this.bytes = Utils.HEX.decode(hexString);
} }
/** /** Use Sha256Hash.hash(byte[]) instead: this old name is ambiguous */
* Calculates the (one-time) hash of contents and returns it as a new wrapped hash. @Deprecated
*/
public static Sha256Hash create(byte[] contents) { public static Sha256Hash create(byte[] contents) {
return hash(contents);
}
/**
* Calculates the (one-time) hash of contents and returns it.
*/
public static Sha256Hash hash(byte[] contents) {
try { try {
MessageDigest digest = MessageDigest.getInstance("SHA-256"); MessageDigest digest = MessageDigest.getInstance("SHA-256");
return new Sha256Hash(digest.digest(contents)); return new Sha256Hash(digest.digest(contents));
@ -66,10 +72,16 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
} }
} }
/** Use hashTwice(byte[]) instead: this old name is ambiguous. */
@Deprecated
public static Sha256Hash createDouble(byte[] contents) {
return hashTwice(contents);
}
/** /**
* Calculates the hash of the hash of the contents. This is a standard operation in Bitcoin. * Calculates the hash of the hash of the contents. This is a standard operation in Bitcoin.
*/ */
public static Sha256Hash createDouble(byte[] contents) { public static Sha256Hash hashTwice(byte[] contents) {
return new Sha256Hash(Utils.doubleDigest(contents)); return new Sha256Hash(Utils.doubleDigest(contents));
} }
@ -81,7 +93,7 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
public static Sha256Hash hashFileContents(File f) throws IOException { public static Sha256Hash hashFileContents(File f) throws IOException {
FileInputStream in = new FileInputStream(f); FileInputStream in = new FileInputStream(f);
try { try {
return create(ByteStreams.toByteArray(in)); return hash(ByteStreams.toByteArray(in));
} finally { } finally {
in.close(); in.close();
} }
@ -96,9 +108,9 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
} }
/** /**
* Hash code of the byte array as calculated by {@link Arrays#hashCode()}. Note the difference between a SHA256 * Returns the last four bytes of the wrapped hash. This should be unique enough to be a suitable hash code even for
* secure bytes and the type of quick/dirty bytes used by the Java hashCode method which is designed for use in * blocks, where the goal is to try and get the first bytes to be zeros (i.e. the value as a big integer lower
* bytes tables. * than the target value).
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
@ -118,14 +130,13 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
return new BigInteger(1, bytes); return new BigInteger(1, bytes);
} }
/**
* Returns the internal byte array, without defensively copying. Therefore do NOT modify the returned array.
*/
public byte[] getBytes() { public byte[] getBytes() {
return bytes; return bytes;
} }
public Sha256Hash duplicate() {
return new Sha256Hash(bytes);
}
@Override @Override
public int compareTo(Sha256Hash o) { public int compareTo(Sha256Hash o) {
int thisCode = this.hashCode(); int thisCode = this.hashCode();

View File

@ -180,7 +180,7 @@ public class MnemonicCode {
entropy[ii] |= 1 << (7 - jj); entropy[ii] |= 1 << (7 - jj);
// Take the digest of the entropy. // Take the digest of the entropy.
byte[] hash = Sha256Hash.create(entropy).getBytes(); byte[] hash = Sha256Hash.hash(entropy).getBytes();
boolean[] hashBits = bytesToBits(hash); boolean[] hashBits = bytesToBits(hash);
// Check all the checksum bits. // Check all the checksum bits.
@ -204,7 +204,7 @@ public class MnemonicCode {
// We take initial entropy of ENT bits and compute its // We take initial entropy of ENT bits and compute its
// checksum by taking first ENT / 32 bits of its SHA256 hash. // checksum by taking first ENT / 32 bits of its SHA256 hash.
byte[] hash = Sha256Hash.create(entropy).getBytes(); byte[] hash = Sha256Hash.hash(entropy).getBytes();
boolean[] hashBits = bytesToBits(hash); boolean[] hashBits = bytesToBits(hash);
boolean[] entropyBits = bytesToBits(entropy); boolean[] entropyBits = bytesToBits(entropy);

View File

@ -77,7 +77,7 @@ public class HttpDiscovery implements PeerDiscovery {
if (pubkey != null) { if (pubkey != null) {
if (!Arrays.equals(proto.getPubkey().toByteArray(), pubkey.getPubKey())) if (!Arrays.equals(proto.getPubkey().toByteArray(), pubkey.getPubKey()))
throw new PeerDiscoveryException("Public key mismatch"); throw new PeerDiscoveryException("Public key mismatch");
Sha256Hash hash = Sha256Hash.create(proto.getPeerSeeds().toByteArray()); Sha256Hash hash = Sha256Hash.hash(proto.getPeerSeeds().toByteArray());
pubkey.verifyOrThrow(hash.getBytes(), proto.getSignature().toByteArray()); pubkey.verifyOrThrow(hash.getBytes(), proto.getSignature().toByteArray());
} }
PeerSeedProtos.PeerSeeds seeds = PeerSeedProtos.PeerSeeds.parseFrom(proto.getPeerSeeds()); PeerSeedProtos.PeerSeeds seeds = PeerSeedProtos.PeerSeeds.parseFrom(proto.getPeerSeeds());

View File

@ -101,7 +101,7 @@ public class PaymentChannelClientConnection {
throws IOException, ValueOutOfRangeException { throws IOException, ValueOutOfRangeException {
// Glue the object which vends/ingests protobuf messages in order to manage state to the network object which // Glue the object which vends/ingests protobuf messages in order to manage state to the network object which
// reads/writes them to the wire in length prefixed form. // reads/writes them to the wire in length prefixed form.
channelClient = new PaymentChannelClient(wallet, myKey, maxValue, Sha256Hash.create(serverId.getBytes()), timeWindow, channelClient = new PaymentChannelClient(wallet, myKey, maxValue, Sha256Hash.hash(serverId.getBytes()), timeWindow,
userKeySetup, new PaymentChannelClient.ClientConnection() { userKeySetup, new PaymentChannelClient.ClientConnection() {
@Override @Override
public void sendToServer(Protos.TwoWayChannelMessage msg) { public void sendToServer(Protos.TwoWayChannelMessage msg) {

View File

@ -167,7 +167,7 @@ public class BlockTest {
Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE); Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE);
tx.addOutput(new TransactionOutput(params, null, Coin.SATOSHI, outputScript)); tx.addOutput(new TransactionOutput(params, null, Coin.SATOSHI, outputScript));
tx.addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE}, tx.addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE},
new TransactionOutPoint(params, 0, Sha256Hash.create(new byte[] {1})))); new TransactionOutPoint(params, 0, Sha256Hash.hash(new byte[]{1}))));
int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1; int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1;
assertEquals(tx.bitcoinSerialize().length, tx.length); assertEquals(tx.bitcoinSerialize().length, tx.length);
assertEquals(origTxLength, tx.length); assertEquals(origTxLength, tx.length);
@ -182,7 +182,7 @@ public class BlockTest {
assertEquals(block.length, origBlockLen + tx.length); assertEquals(block.length, origBlockLen + tx.length);
assertEquals(tx.length, origTxLength - 1); assertEquals(tx.length, origTxLength - 1);
block.getTransactions().get(1).addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE}, block.getTransactions().get(1).addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE},
new TransactionOutPoint(params, 0, Sha256Hash.create(new byte[] {1})))); new TransactionOutPoint(params, 0, Sha256Hash.hash(new byte[]{1}))));
assertEquals(block.length, origBlockLen + tx.length); assertEquals(block.length, origBlockLen + tx.length);
assertEquals(tx.length, origTxLength + 41); // - 1 + 40 + 1 + 1 assertEquals(tx.length, origTxLength + 41); // - 1 + 40 + 1 + 1
} }

View File

@ -87,7 +87,7 @@ public class ECKeyTest {
List<ListenableFuture<ECKey.ECDSASignature>> sigFutures = Lists.newArrayList(); List<ListenableFuture<ECKey.ECDSASignature>> sigFutures = Lists.newArrayList();
final ECKey key = new ECKey(); final ECKey key = new ECKey();
for (byte i = 0; i < ITERATIONS; i++) { for (byte i = 0; i < ITERATIONS; i++) {
final Sha256Hash hash = Sha256Hash.create(new byte[]{i}); final Sha256Hash hash = Sha256Hash.hash(new byte[]{i});
sigFutures.add(executor.submit(new Callable<ECKey.ECDSASignature>() { sigFutures.add(executor.submit(new Callable<ECKey.ECDSASignature>() {
@Override @Override
public ECKey.ECDSASignature call() throws Exception { public ECKey.ECDSASignature call() throws Exception {
@ -247,7 +247,7 @@ public class ECKeyTest {
public void keyRecovery() throws Exception { public void keyRecovery() throws Exception {
ECKey key = new ECKey(); ECKey key = new ECKey();
String message = "Hello World!"; String message = "Hello World!";
Sha256Hash hash = Sha256Hash.create(message.getBytes()); Sha256Hash hash = Sha256Hash.hash(message.getBytes());
ECKey.ECDSASignature sig = key.sign(hash); ECKey.ECDSASignature sig = key.sign(hash);
key = ECKey.fromPublicOnly(key.getPubKeyPoint()); key = ECKey.fromPublicOnly(key.getPubKeyPoint());
boolean found = false; boolean found = false;
@ -346,7 +346,7 @@ public class ECKeyTest {
ECKey encryptedKey = unencryptedKey.encrypt(keyCrypter, aesKey); ECKey encryptedKey = unencryptedKey.encrypt(keyCrypter, aesKey);
String message = "Goodbye Jupiter!"; String message = "Goodbye Jupiter!";
Sha256Hash hash = Sha256Hash.create(message.getBytes()); Sha256Hash hash = Sha256Hash.hash(message.getBytes());
ECKey.ECDSASignature sig = encryptedKey.sign(hash, aesKey); ECKey.ECDSASignature sig = encryptedKey.sign(hash, aesKey);
unencryptedKey = ECKey.fromPublicOnly(unencryptedKey.getPubKeyPoint()); unencryptedKey = ECKey.fromPublicOnly(unencryptedKey.getPubKeyPoint());
boolean found = false; boolean found = false;

View File

@ -981,7 +981,7 @@ public class FullBlockTestGenerator {
NewBlock b49 = createNextBlock(b44, chainHeadHeight + 16, out15, null); NewBlock b49 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
byte[] b49MerkleHash = Sha256Hash.ZERO_HASH.getBytes().clone(); byte[] b49MerkleHash = Sha256Hash.ZERO_HASH.getBytes().clone();
b49MerkleHash[1] = (byte) 0xDE; b49MerkleHash[1] = (byte) 0xDE;
b49.block.setMerkleRoot(Sha256Hash.create(b49MerkleHash)); b49.block.setMerkleRoot(Sha256Hash.hash(b49MerkleHash));
b49.solve(); b49.solve();
blocks.add(new BlockAndValidity(b49, false, true, b44.getHash(), chainHeadHeight + 15, "b49")); blocks.add(new BlockAndValidity(b49, false, true, b44.getHash(), chainHeadHeight + 15, "b49"));

View File

@ -708,7 +708,7 @@ public class PeerTest extends TestWithNetworkConnections {
Transaction t2 = new Transaction(unitTestParams); Transaction t2 = new Transaction(unitTestParams);
t2.setLockTime(999999); t2.setLockTime(999999);
// Add a fake input to t3 that goes nowhere. // Add a fake input to t3 that goes nowhere.
Sha256Hash t3 = Sha256Hash.create("abc".getBytes(Charset.forName("UTF-8"))); Sha256Hash t3 = Sha256Hash.hash("abc".getBytes(Charset.forName("UTF-8")));
t2.addInput(new TransactionInput(unitTestParams, t2, new byte[]{}, new TransactionOutPoint(unitTestParams, 0, t3))); t2.addInput(new TransactionInput(unitTestParams, t2, new byte[]{}, new TransactionOutPoint(unitTestParams, 0, t3)));
t2.getInput(0).setSequenceNumber(0xDEADBEEF); t2.getInput(0).setSequenceNumber(0xDEADBEEF);
t2.addOutput(COIN, new ECKey()); t2.addOutput(COIN, new ECKey());
@ -842,9 +842,9 @@ public class PeerTest extends TestWithNetworkConnections {
@Override @Override
public void bitcoinSerializeToStream(OutputStream stream) throws IOException { public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
// Add some hashes. // Add some hashes.
addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.create(new byte[] { 1 }))); addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.hash(new byte[]{1})));
addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.create(new byte[] { 2 }))); addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.hash(new byte[]{2})));
addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.create(new byte[] { 3 }))); addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.hash(new byte[]{3})));
// Write out a copy that's truncated in the middle. // Write out a copy that's truncated in the middle.
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();

View File

@ -157,7 +157,7 @@ public class ChildKeyDerivationTest {
assertFalse(decryptedKey2.isEncrypted()); assertFalse(decryptedKey2.isEncrypted());
assertEquals(key2, decryptedKey2); assertEquals(key2, decryptedKey2);
Sha256Hash hash = Sha256Hash.create("the mainstream media won't cover it. why is that?".getBytes()); Sha256Hash hash = Sha256Hash.hash("the mainstream media won't cover it. why is that?".getBytes());
try { try {
derivedKey2.sign(hash); derivedKey2.sign(hash);
fail(); fail();

View File

@ -290,7 +290,7 @@ public class ChannelConnectionTest extends TestWithWallet {
// Tests various aspects of channel resuming. // Tests various aspects of channel resuming.
Utils.setMockClock(); Utils.setMockClock();
final Sha256Hash someServerId = Sha256Hash.create(new byte[]{}); final Sha256Hash someServerId = Sha256Hash.hash(new byte[]{});
// Open up a normal channel. // Open up a normal channel.
ChannelTestUtils.RecordingPair pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster); ChannelTestUtils.RecordingPair pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
@ -340,7 +340,7 @@ public class ChannelConnectionTest extends TestWithWallet {
pair.server.receiveMessage(Protos.TwoWayChannelMessage.newBuilder() pair.server.receiveMessage(Protos.TwoWayChannelMessage.newBuilder()
.setType(MessageType.CLIENT_VERSION) .setType(MessageType.CLIENT_VERSION)
.setClientVersion(Protos.ClientVersion.newBuilder() .setClientVersion(Protos.ClientVersion.newBuilder()
.setPreviousChannelContractHash(ByteString.copyFrom(Sha256Hash.create(new byte[]{0x03}).getBytes())) .setPreviousChannelContractHash(ByteString.copyFrom(Sha256Hash.hash(new byte[]{0x03}).getBytes()))
.setMajor(CLIENT_MAJOR_VERSION).setMinor(42)) .setMajor(CLIENT_MAJOR_VERSION).setMinor(42))
.build()); .build());
pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION); pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION);

View File

@ -33,7 +33,7 @@ public class PaymentChannelClientTest {
wallet = createMock(Wallet.class); wallet = createMock(Wallet.class);
ecKey = createMock(ECKey.class); ecKey = createMock(ECKey.class);
maxValue = Coin.COIN; maxValue = Coin.COIN;
serverHash = Sha256Hash.create("serverId".getBytes()); serverHash = Sha256Hash.hash("serverId".getBytes());
connection = createMock(IPaymentChannelClient.ClientConnection.class); connection = createMock(IPaymentChannelClient.ClientConnection.class);
clientVersionCapture = new Capture<TwoWayChannelMessage>(); clientVersionCapture = new Capture<TwoWayChannelMessage>();
} }

View File

@ -292,7 +292,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
Utils.rollMockClock(60 * 60 * 2 + 60 * 5); Utils.rollMockClock(60 * 60 * 2 + 60 * 5);
// Now store the client state in a stored state object which handles the rebroadcasting // Now store the client state in a stored state object which handles the rebroadcasting
clientState.doStoreChannelInWallet(Sha256Hash.create(new byte[]{})); clientState.doStoreChannelInWallet(Sha256Hash.hash(new byte[]{}));
TxFuturePair clientBroadcastedMultiSig = broadcasts.take(); TxFuturePair clientBroadcastedMultiSig = broadcasts.take();
TxFuturePair broadcastRefund = broadcasts.take(); TxFuturePair broadcastRefund = broadcasts.take();
assertEquals(clientBroadcastedMultiSig.tx.getHash(), multisigContract.getHash()); assertEquals(clientBroadcastedMultiSig.tx.getHash(), multisigContract.getHash());

View File

@ -25,10 +25,6 @@ import org.bitcoinj.store.UnreadableWalletException;
import org.bitcoinj.utils.BriefLogFormatter; import org.bitcoinj.utils.BriefLogFormatter;
import org.bitcoinj.utils.Threading; import org.bitcoinj.utils.Threading;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.bitcoinj.wallet.AbstractKeyChainEventListener;
import org.bitcoinj.wallet.DeterministicKeyChain;
import org.bitcoinj.wallet.KeyChain;
import org.bitcoinj.wallet.Protos;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.KeyParameter;
@ -42,7 +38,7 @@ import static org.junit.Assert.*;
public class DeterministicKeyChainTest { public class DeterministicKeyChainTest {
private DeterministicKeyChain chain; private DeterministicKeyChain chain;
private final byte[] ENTROPY = Sha256Hash.create("don't use a string seed like this in real life".getBytes()).getBytes(); private final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes()).getBytes();
@Before @Before
public void setup() { public void setup() {

View File

@ -22,7 +22,6 @@ import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.utils.BriefLogFormatter; import org.bitcoinj.utils.BriefLogFormatter;
import org.bitcoinj.utils.Threading; import org.bitcoinj.utils.Threading;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.bitcoinj.wallet.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.KeyParameter;
@ -65,7 +64,7 @@ public class KeyChainGroupTest {
} }
private MarriedKeyChain createMarriedKeyChain() { private MarriedKeyChain createMarriedKeyChain() {
byte[] entropy = Sha256Hash.create("don't use a seed like this in real life".getBytes()).getBytes(); byte[] entropy = Sha256Hash.hash("don't use a seed like this in real life".getBytes()).getBytes();
DeterministicSeed seed = new DeterministicSeed(entropy, "", MnemonicCode.BIP39_STANDARDISATION_TIME_SECS); DeterministicSeed seed = new DeterministicSeed(entropy, "", MnemonicCode.BIP39_STANDARDISATION_TIME_SECS);
MarriedKeyChain chain = MarriedKeyChain.builder() MarriedKeyChain chain = MarriedKeyChain.builder()
.seed(seed) .seed(seed)