diff --git a/convex-core/src/main/java/convex/core/data/ABlob.java b/convex-core/src/main/java/convex/core/data/ABlob.java index bf8cb0ae9..d451f7032 100644 --- a/convex-core/src/main/java/convex/core/data/ABlob.java +++ b/convex-core/src/main/java/convex/core/data/ABlob.java @@ -148,7 +148,12 @@ public final Hash computeHash(MessageDigest digest) { return Hash.wrap(digest.digest()); } - protected abstract void updateDigest(MessageDigest digest); + /** + * Updates a MessageDigest with the contents of this Blob + * + * @param digest MessageDigest instance + */ + public abstract void updateDigest(MessageDigest digest); /** * Gets the byte at the specified position diff --git a/convex-core/src/main/java/convex/core/data/BlobTree.java b/convex-core/src/main/java/convex/core/data/BlobTree.java index fb2e2ea26..1c11892e6 100644 --- a/convex-core/src/main/java/convex/core/data/BlobTree.java +++ b/convex-core/src/main/java/convex/core/data/BlobTree.java @@ -241,7 +241,7 @@ public Blob toFlatBlob() { } @Override - protected void updateDigest(MessageDigest digest) { + public void updateDigest(MessageDigest digest) { int n = children.length; for (int i = 0; i < n; i++) { getChild(i).updateDigest(digest); diff --git a/convex-core/src/main/java/convex/core/data/LongBlob.java b/convex-core/src/main/java/convex/core/data/LongBlob.java index ef9411e25..82f629edc 100644 --- a/convex-core/src/main/java/convex/core/data/LongBlob.java +++ b/convex-core/src/main/java/convex/core/data/LongBlob.java @@ -41,9 +41,10 @@ public ABlob slice(long start, long end) { @Override - protected void updateDigest(MessageDigest digest) { - byte[] bs = getEncoding().getInternalArray(); - digest.update(bs, 2, (int) LENGTH); + public void updateDigest(MessageDigest digest) { + Blob b=getEncoding(); + byte[] bs = b.getInternalArray(); + digest.update(bs, b.getInternalOffset()+2, (int) LENGTH); } @Override diff --git a/convex-core/src/main/java/convex/core/data/ADerivedBlob.java b/convex-core/src/main/java/convex/core/data/impl/ADerivedBlob.java similarity index 94% rename from convex-core/src/main/java/convex/core/data/ADerivedBlob.java rename to convex-core/src/main/java/convex/core/data/impl/ADerivedBlob.java index 6ac707512..6233a743f 100644 --- a/convex-core/src/main/java/convex/core/data/ADerivedBlob.java +++ b/convex-core/src/main/java/convex/core/data/impl/ADerivedBlob.java @@ -1,8 +1,11 @@ -package convex.core.data; +package convex.core.data.impl; import java.nio.ByteBuffer; import java.security.MessageDigest; +import convex.core.data.ABlob; +import convex.core.data.ABlobLike; +import convex.core.data.Blob; import convex.core.util.Utils; /** @@ -51,7 +54,7 @@ public Blob toFlatBlob() { } @Override - protected void updateDigest(MessageDigest digest) { + public void updateDigest(MessageDigest digest) { ABlob can=getCanonical(); can.updateDigest(digest); } diff --git a/convex-core/src/main/java/convex/core/data/impl/RepeatByteBlob.java b/convex-core/src/main/java/convex/core/data/impl/RepeatByteBlob.java new file mode 100644 index 000000000..36f8393a5 --- /dev/null +++ b/convex-core/src/main/java/convex/core/data/impl/RepeatByteBlob.java @@ -0,0 +1,30 @@ +package convex.core.data.impl; + +import org.bouncycastle.util.Arrays; + +public class RepeatByteBlob extends ADerivedBlob { + private final byte b; + + protected RepeatByteBlob(long count, byte b) { + super(count); + this.b=b; + } + + @Override + public RepeatByteBlob sliceImpl(long start, long end) { + return new RepeatByteBlob(end-start,b); + } + + @Override + public int getBytes(byte[] dest, int destOffset) { + int end=destOffset+size(); + Arrays.fill(dest, destOffset,end,(byte)0); + return end; + } + + @Override + public byte byteAtUnchecked(long i) { + return b; + } + +} diff --git a/convex-core/src/main/java/convex/core/data/impl/ZeroBlob.java b/convex-core/src/main/java/convex/core/data/impl/ZeroBlob.java index 67e914349..b7a5040b8 100644 --- a/convex-core/src/main/java/convex/core/data/impl/ZeroBlob.java +++ b/convex-core/src/main/java/convex/core/data/impl/ZeroBlob.java @@ -3,7 +3,6 @@ import org.bouncycastle.util.Arrays; import convex.core.data.ABlob; -import convex.core.data.ADerivedBlob; import convex.core.data.Cells; /** diff --git a/convex-core/src/test/java/convex/core/data/BlobsTest.java b/convex-core/src/test/java/convex/core/data/BlobsTest.java index 4ed8e1df9..e9f21bfbd 100644 --- a/convex-core/src/test/java/convex/core/data/BlobsTest.java +++ b/convex-core/src/test/java/convex/core/data/BlobsTest.java @@ -578,6 +578,19 @@ public void testLongBlobBroken() throws BadFormatException, IOException { assertEquals(b, Format.encodedBlob(o)); assertEquals(pref.getValue(), o); } + + @Test + public void testLongBlobDecoded() throws BadFormatException { + long V=0xFF1234567899L; + // LongBlob has custom hash implementation, we want to make sure it reads from encoding correctly + LongBlob l0=LongBlob.create(V); + Blob enc=(Blob.fromHex("F000").append(l0.getEncoding()).toFlatBlob().slice(2)); + + LongBlob l1=LongBlob.create(V); + l1.attachEncoding(enc); + + assertEquals(l0.getHash(),l1.getHash()); + } /** * Generic tests for an arbitrary ABlob instance