From 284fbcc20fc902445b5a5a2ce54d9bec93305fc2 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Mon, 10 Mar 2025 10:42:16 +0100 Subject: [PATCH] SPVBlockStore: fix get() locates an invalid block if called with zero hash This happens if the store is relatively fresh and has not yet fully wrapped around at least once. Thus, entire entries of the ring buffer are still zeroed, and in particular the hash field of store entries will be zero. In consequence, get() is locating and returning an invalid block when asked to look for the zero hash. Valid blocks that hash to zero will require an astronomical amount of mining. So we fix this bug by hardcoding the zero hash to never be found in our store. Includes a test for this edge case. --- core/src/main/java/org/bitcoinj/store/SPVBlockStore.java | 7 +++++++ .../test/java/org/bitcoinj/store/SPVBlockStoreTest.java | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/core/src/main/java/org/bitcoinj/store/SPVBlockStore.java b/core/src/main/java/org/bitcoinj/store/SPVBlockStore.java index fc25026d6..f58e0d544 100644 --- a/core/src/main/java/org/bitcoinj/store/SPVBlockStore.java +++ b/core/src/main/java/org/bitcoinj/store/SPVBlockStore.java @@ -279,6 +279,13 @@ public class SPVBlockStore implements BlockStore { @Override @Nullable public StoredBlock get(Sha256Hash hash) throws BlockStoreException { + if (hash.equals(Sha256Hash.ZERO_HASH)) { + // Valid blocks will never hash to zero, as it will need an astronomical amount of mining to create one. + // Nevertheless, we need to catch this case here because our ring buffer contains all zeros at the + // beginning so this method would indeed locate and return an invalid block. + return null; + } + final MappedByteBuffer buffer = this.buffer; if (buffer == null) throw new BlockStoreException("Store closed"); diff --git a/core/src/test/java/org/bitcoinj/store/SPVBlockStoreTest.java b/core/src/test/java/org/bitcoinj/store/SPVBlockStoreTest.java index e31b03be8..8587dc255 100644 --- a/core/src/test/java/org/bitcoinj/store/SPVBlockStoreTest.java +++ b/core/src/test/java/org/bitcoinj/store/SPVBlockStoreTest.java @@ -93,6 +93,14 @@ public class SPVBlockStoreTest { store.close(); } + @Test + public void get_zeroHash() throws Exception { + SPVBlockStore store = new SPVBlockStore(TESTNET, blockStoreFile); + // Needs to fail locating a block even though our fresh ring buffer is full of zero hashes. + StoredBlock b = store.get(Sha256Hash.ZERO_HASH); + assertNull(b); + } + @Test(expected = BlockStoreException.class) public void twoStores_onSameFile() throws Exception { new SPVBlockStore(TESTNET, blockStoreFile);