From 3456e896ecd1d8375dbdfdcd3f2fda7ef88c776b Mon Sep 17 00:00:00 2001 From: Sean Gilligan Date: Fri, 2 Jan 2015 23:02:25 -0800 Subject: [PATCH] Make Address (& super & subs) Cloneable * Implement Cloneable in VersionedChecksummedBytes * Override clone() in VersionedChecksummedBytes * Override clone() in Address * Add Unit test file for VersionedChecksummedBytes * Add clone unit tests for clone for all subclasses of VersionedChecksummedBytes TODO: Consider overriding clone() in DumpedPrivateKey and BIP38PrivateKey --- .../main/java/org/bitcoinj/core/Address.java | 8 +++ .../core/VersionedChecksummedBytes.java | 15 ++++- .../java/org/bitcoinj/core/AddressTest.java | 10 ++++ .../bitcoinj/core/DumpedPrivateKeyTest.java | 12 ++++ .../core/VersionedChecksummedBytesTest.java | 55 +++++++++++++++++++ .../bitcoinj/crypto/BIP38PrivateKeyTest.java | 12 ++++ 6 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java diff --git a/core/src/main/java/org/bitcoinj/core/Address.java b/core/src/main/java/org/bitcoinj/core/Address.java index 3289569f..934dc27e 100644 --- a/core/src/main/java/org/bitcoinj/core/Address.java +++ b/core/src/main/java/org/bitcoinj/core/Address.java @@ -168,4 +168,12 @@ public class Address extends VersionedChecksummedBytes { } return false; } + + /** + * This implementation narrows the return type to Address. + */ + @Override + public Address clone() throws CloneNotSupportedException { + return (Address) super.clone(); + } } diff --git a/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java b/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java index 4c4f9a49..1907cc9b 100644 --- a/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java +++ b/core/src/main/java/org/bitcoinj/core/VersionedChecksummedBytes.java @@ -31,7 +31,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 { +public class VersionedChecksummedBytes implements Serializable, Cloneable { protected final int version; protected byte[] bytes; @@ -82,6 +82,19 @@ public class VersionedChecksummedBytes implements Serializable { /** * 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 + * and allows subclasses to throw CloneNotSupportedException even though it + * is never thrown by this implementation. + */ + @Override + public VersionedChecksummedBytes clone() throws CloneNotSupportedException { + return (VersionedChecksummedBytes) super.clone(); + } + + + /** * * @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 ae1d1ca5..3269ab0c 100644 --- a/core/src/test/java/org/bitcoinj/core/AddressTest.java +++ b/core/src/test/java/org/bitcoinj/core/AddressTest.java @@ -168,4 +168,14 @@ public class AddressTest { Address address = Address.fromP2SHScript(mainParams, p2shScript); assertEquals("3N25saC4dT24RphDAwLtD8LUN4E2gZPJke", address.toString()); } + + @Test + public void cloning() throws Exception { + Address a = new Address(testParams, HEX.decode("fda79a24e50ff70ff42f7d89585da5bd19d9e5cc")); + Address b = a.clone(); + + assertEquals(a, b); + assertNotSame(a, b); + } + } diff --git a/core/src/test/java/org/bitcoinj/core/DumpedPrivateKeyTest.java b/core/src/test/java/org/bitcoinj/core/DumpedPrivateKeyTest.java index 82197757..e94c4f46 100644 --- a/core/src/test/java/org/bitcoinj/core/DumpedPrivateKeyTest.java +++ b/core/src/test/java/org/bitcoinj/core/DumpedPrivateKeyTest.java @@ -17,6 +17,7 @@ package org.bitcoinj.core; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -38,4 +39,15 @@ public class DumpedPrivateKeyTest { .readObject(); assertEquals(key, keyCopy); } + + @Test + public void cloning() throws Exception { + DumpedPrivateKey a = new DumpedPrivateKey(MainNetParams.get(), new ECKey().getPrivKeyBytes(), true); + // TODO: Consider overriding clone() in DumpedPrivateKey to narrow the type + DumpedPrivateKey b = (DumpedPrivateKey) a.clone(); + + assertEquals(a, b); + assertNotSame(a, b); + } + } diff --git a/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java b/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java new file mode 100644 index 00000000..3b78076f --- /dev/null +++ b/core/src/test/java/org/bitcoinj/core/VersionedChecksummedBytesTest.java @@ -0,0 +1,55 @@ +/** + * Copyright 2014 BitcoinJ Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoinj.core; + +import org.bitcoinj.params.MainNetParams; +import org.bitcoinj.params.TestNet3Params; +import org.junit.Test; + +import static org.bitcoinj.core.Utils.HEX; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +/** + * + */ +public class VersionedChecksummedBytesTest { + static final NetworkParameters testParams = TestNet3Params.get(); + static final NetworkParameters mainParams = MainNetParams.get(); + + @Test + public void stringification() throws Exception { + // Test a testnet address. + VersionedChecksummedBytes a = new VersionedChecksummedBytes(testParams.getAddressHeader(), HEX.decode("fda79a24e50ff70ff42f7d89585da5bd19d9e5cc")); + assertEquals("n4eA2nbYqErp7H6jebchxAN59DmNpksexv", a.toString()); + + VersionedChecksummedBytes b = new VersionedChecksummedBytes(mainParams.getAddressHeader(), HEX.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a")); + assertEquals("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL", b.toString()); + } + + @Test + public void cloning() throws Exception { + VersionedChecksummedBytes a = new VersionedChecksummedBytes(testParams.getAddressHeader(), HEX.decode("fda79a24e50ff70ff42f7d89585da5bd19d9e5cc")); + VersionedChecksummedBytes b = a.clone(); + + assertEquals(a, b); + assertNotSame(a, b); + } + +} diff --git a/core/src/test/java/org/bitcoinj/crypto/BIP38PrivateKeyTest.java b/core/src/test/java/org/bitcoinj/crypto/BIP38PrivateKeyTest.java index 844adc57..ddaf587f 100644 --- a/core/src/test/java/org/bitcoinj/crypto/BIP38PrivateKeyTest.java +++ b/core/src/test/java/org/bitcoinj/crypto/BIP38PrivateKeyTest.java @@ -28,6 +28,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; public class BIP38PrivateKeyTest { @@ -157,4 +158,15 @@ public class BIP38PrivateKeyTest { .readObject(); assertEquals(key, keyCopy); } + + @Test + public void cloning() throws Exception { + BIP38PrivateKey a = new BIP38PrivateKey(TESTNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb"); + // TODO: Consider overriding clone() in BIP38PrivateKey to narrow the type + BIP38PrivateKey b = (BIP38PrivateKey) a.clone(); + + assertEquals(a, b); + assertNotSame(a, b); + } + }