diff --git a/core/src/main/java/com/google/bitcoin/core/Base58.java b/core/src/main/java/com/google/bitcoin/core/Base58.java index e469a827..3da3c071 100644 --- a/core/src/main/java/com/google/bitcoin/core/Base58.java +++ b/core/src/main/java/com/google/bitcoin/core/Base58.java @@ -149,7 +149,7 @@ public class Base58 { public static byte[] decodeChecked(String input) throws AddressFormatException { byte tmp [] = decode(input); if (tmp.length < 4) - throw new AddressFormatException("Input to short"); + throw new AddressFormatException("Input too short"); byte[] bytes = copyOfRange(tmp, 0, tmp.length - 4); byte[] checksum = copyOfRange(tmp, tmp.length - 4, tmp.length); diff --git a/core/src/main/java/com/google/bitcoin/core/BitcoinSerializer.java b/core/src/main/java/com/google/bitcoin/core/BitcoinSerializer.java index 7992e78f..057e5d43 100644 --- a/core/src/main/java/com/google/bitcoin/core/BitcoinSerializer.java +++ b/core/src/main/java/com/google/bitcoin/core/BitcoinSerializer.java @@ -36,7 +36,7 @@ import static com.google.bitcoin.core.Utils.*; *

To be able to serialize and deserialize new Message subclasses the following criteria needs to be met.

* * diff --git a/core/src/test/java/com/google/bitcoin/core/Base58Test.java b/core/src/test/java/com/google/bitcoin/core/Base58Test.java index 481b647a..72d14338 100644 --- a/core/src/test/java/com/google/bitcoin/core/Base58Test.java +++ b/core/src/test/java/com/google/bitcoin/core/Base58Test.java @@ -17,11 +17,13 @@ package com.google.bitcoin.core; import junit.framework.TestCase; +import org.junit.Test; import java.math.BigInteger; import java.util.Arrays; public class Base58Test extends TestCase { + @Test public void testEncode() throws Exception { byte[] testbytes = "Hello World".getBytes(); assertEquals("JxF12TrwUP45BMd", Base58.encode(testbytes)); @@ -34,8 +36,12 @@ public class Base58Test extends TestCase { byte[] zeroBytes7 = new byte[7]; assertEquals("1111111", Base58.encode(zeroBytes7)); + + // test empty encode + assertEquals("", Base58.encode(new byte[0])); } - + + @Test public void testDecode() throws Exception { byte[] testbytes = "Hello World".getBytes(); byte[] actualbytes = Base58.decode("JxF12TrwUP45BMd"); @@ -48,12 +54,38 @@ public class Base58Test extends TestCase { Base58.decode("This isn't valid base58"); fail(); } catch (AddressFormatException e) { + // expected } Base58.decodeChecked("4stwEBjT6FYyVV"); + // Checksum should fail. + try { + Base58.decodeChecked("4stwEBjT6FYyVW"); + fail(); + } catch (AddressFormatException e) { + // expected + } + + // Input is too short. + try { + Base58.decodeChecked("4s"); + fail(); + } catch (AddressFormatException e) { + // expected + } + + // Test decode of empty String. + assertEquals(0, Base58.decode("").length); + // Now check we can correctly decode the case where the high bit of the first byte is not zero, so BigInteger // sign extends. Fix for a bug that stopped us parsing keys exported using sipas patch. Base58.decodeChecked("93VYUMzRG9DdbRP72uQXjaWibbQwygnvaCu9DumcqDjGybD864T"); } + + @Test + public void testDecodeToBigInteger() throws AddressFormatException { + byte[] input = Base58.decode("129"); + assertEquals(new BigInteger(1, input), Base58.decodeToBigInteger("129")); + } } diff --git a/core/src/test/java/com/google/bitcoin/core/BitcoinSerializerTest.java b/core/src/test/java/com/google/bitcoin/core/BitcoinSerializerTest.java index 201c355b..70301cae 100644 --- a/core/src/test/java/com/google/bitcoin/core/BitcoinSerializerTest.java +++ b/core/src/test/java/com/google/bitcoin/core/BitcoinSerializerTest.java @@ -23,6 +23,8 @@ import org.spongycastle.util.encoders.Hex; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.Arrays; import static org.junit.Assert.*; @@ -83,7 +85,6 @@ public class BitcoinSerializerTest { ByteArrayOutputStream bos = new ByteArrayOutputStream(); bs.serialize(tx, bos); assertEquals(true, Arrays.equals(txMessage, bos.toByteArray())); - } @Test @@ -229,5 +230,118 @@ public class BitcoinSerializerTest { assertEquals(thirdBlock.getNonce(), 2850094635L); } + @Test + public void testDeserializePayload() { + BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get()); + ByteArrayInputStream bais = new ByteArrayInputStream(Hex.decode("000000000000000000000000000000020000000000")); + BitcoinSerializer.BitcoinPacketHeader bitcoinPacketHeader = null; + + // Test socket is disconnected. + InputStream inputStream = new InputStream() { + @Override + public int read() throws IOException { + return -1; + } + }; + + try { + bitcoinPacketHeader = new BitcoinSerializer.BitcoinPacketHeader(bais); + } catch (ProtocolException e) { + fail(); + } catch (IOException e) { + fail(); + } + + try { + bs.deserializePayload(bitcoinPacketHeader, inputStream); + fail(); + } catch (ProtocolException e) { + fail(); + } catch (IOException e) { + // expected + } + + // TODO Test protocol exception in deserializePayload. + } + + @Test + public void testBitcoinPacketHeader() { + BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get()); + ByteArrayInputStream bais = new ByteArrayInputStream(new byte[]{}); + BitcoinSerializer.BitcoinPacketHeader bitcoinPacketHeader; + try { + bitcoinPacketHeader = new BitcoinSerializer.BitcoinPacketHeader(bais); + } catch (ProtocolException e) { + fail(); + } catch (IOException e) { + // expected + } + + // Message with a Message size which is 1 too big, in little endian format. + byte[] wrongMessageLength = Hex.decode("000000000000000000000000010000020000000000"); + bais = new ByteArrayInputStream(wrongMessageLength); + + try { + bitcoinPacketHeader = new BitcoinSerializer.BitcoinPacketHeader(bais); + fail(); + } catch (ProtocolException e) { + // expected + } catch (IOException e) { + fail(); + } + } + + @Test + public void testSeekPastMagicBytes() { + BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get()); + + // Empty byte stream, should give IOException. + ByteArrayInputStream bais = new ByteArrayInputStream(new byte[]{}); + try { + bs.seekPastMagicBytes(bais); + fail(); + } catch (IOException e) { + // expected + } + + // Fail in another way, there is data in the stream but no magic bytes. + byte[] brokenMessage = Hex.decode("000000"); + bais = new ByteArrayInputStream(brokenMessage); + try { + bs.seekPastMagicBytes(bais); + fail(); + } catch (IOException e) { + // expected + } + } + + @Test + /** + * Tests serialization of an unknown message. + */ + public void testSerializeUnknownMessage() { + BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get()); + + UnknownMessage a = new UnknownMessage(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(addrMessage.length); + try { + bs.serialize(a, bos); + fail(); + } catch (Throwable e) { + } + } + + /** + * Unknown message for testSerializeUnknownMessage. + */ + class UnknownMessage extends Message { + @Override + void parse() throws ProtocolException { + } + + @Override + protected void parseLite() throws ProtocolException { + } + } }