diff --git a/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java b/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java index 1907cc9b8..c919329da 100644 --- a/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java +++ b/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java @@ -22,6 +22,7 @@ import java.io.Serializable; import java.util.Arrays; import com.google.common.base.Objects; +import com.google.common.primitives.UnsignedBytes; /** *

In Bitcoin the following format is often used to represent some type of key:

@@ -31,7 +32,7 @@ import com.google.common.base.Objects; *

and the result is then Base58 encoded. This format is used for addresses, and private keys exported using the * dumpprivkey command.

*/ -public class VersionedChecksummedBytes implements Serializable, Cloneable { +public class VersionedChecksummedBytes implements Serializable, Cloneable, Comparable { protected final int version; protected byte[] bytes; @@ -80,8 +81,6 @@ public class VersionedChecksummedBytes implements Serializable, Cloneable { } /** - * Returns the "version" or "header" byte: the first byte of the data. This is used to disambiguate what the - * contents apply to, for example, which network the key or address is valid on. * {@inheritDoc} * * This implementation narrows the return type to VersionedChecksummedBytes @@ -93,8 +92,25 @@ public class VersionedChecksummedBytes implements Serializable, Cloneable { return (VersionedChecksummedBytes) super.clone(); } + /** + * {@inheritDoc} + * + * This implementation uses an optimized Google Guava method to compare bytes. + */ + @Override + public int compareTo(VersionedChecksummedBytes o) { + int versionCompare = Integer.valueOf(this.version).compareTo(Integer.valueOf(o.version)); // JDK 6 way + if (versionCompare == 0) { + // Would there be a performance benefit to caching the comparator? + return UnsignedBytes.lexicographicalComparator().compare(this.bytes, o.bytes); + } else { + return versionCompare; + } + } /** + * Returns the "version" or "header" byte: the first byte of the data. This is used to disambiguate what the + * contents apply to, for example, which network the key or address is valid on. * * @return A positive number between 0 and 255. */ diff --git a/core/src/test/java/org/bitcoinj/core/AddressTest.java b/core/src/test/java/org/bitcoinj/core/AddressTest.java index 3269ab0c2..8b7209ba9 100644 --- a/core/src/test/java/org/bitcoinj/core/AddressTest.java +++ b/core/src/test/java/org/bitcoinj/core/AddressTest.java @@ -178,4 +178,51 @@ public class AddressTest { assertNotSame(a, b); } + @Test + public void comparisonCloneEqualTo() throws Exception { + Address a = new Address(mainParams, "1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX"); + Address b = a.clone(); + + int result = a.compareTo(b); + assertEquals(0, result); + } + + @Test + public void comparisonEqualTo() throws Exception { + Address a = new Address(mainParams, "1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX"); + Address b = a.clone(); + + int result = a.compareTo(b); + assertEquals(0, result); + } + + @Test + public void comparisonLessThan() throws Exception { + Address a = new Address(mainParams, "1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX"); + Address b = new Address(mainParams, "1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P"); + + int result = a.compareTo(b); + assertTrue(result < 0); + } + + @Test + public void comparisonGreaterThan() throws Exception { + Address a = new Address(mainParams, "1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P"); + Address b = new Address(mainParams, "1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX"); + + int result = a.compareTo(b); + assertTrue(result > 0); + } + + @Test + public void comparisonBytesVsString() throws Exception { + // TODO: To properly test this we need a much larger data set + Address a = new Address(mainParams, "1Dorian4RoXcnBv9hnQ4Y2C1an6NJ4UrjX"); + Address b = new Address(mainParams, "1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P"); + + int resultBytes = a.compareTo(b); + int resultsString = a.toString().compareTo(b.toString()); + assertTrue( resultBytes < 0 ); + assertTrue( resultsString < 0 ); + } } diff --git a/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java b/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java index 3b78076fe..2b03ca250 100644 --- a/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java +++ b/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java @@ -52,4 +52,11 @@ public class VersionedChecksummedBytesTest { assertNotSame(a, b); } + @Test + public void comparisonCloneEqualTo() throws Exception { + VersionedChecksummedBytes a = new VersionedChecksummedBytes(testParams.getAddressHeader(), HEX.decode("fda79a24e50ff70ff42f7d89585da5bd19d9e5cc")); + VersionedChecksummedBytes b = a.clone(); + + assertTrue(a.compareTo(b) == 0); + } }