WalletAppKit: Clear the blockchain file (as opposed to delete it) in preparation for restore.

This adds a new clear() method to SPVBlockStore.
This commit is contained in:
Oscar Guindzberg 2019-02-15 12:58:17 -03:00 committed by Andreas Schildbach
parent 19ce48afd9
commit 6c944f4142
3 changed files with 44 additions and 24 deletions

View file

@ -69,7 +69,7 @@ public class WalletAppKit extends AbstractIdleService {
protected final KeyChainGroupStructure structure;
protected final String filePrefix;
protected volatile BlockChain vChain;
protected volatile BlockStore vStore;
protected volatile SPVBlockStore vStore;
protected volatile Wallet vWallet;
protected volatile PeerGroup vPeerGroup;
@ -245,13 +245,6 @@ public class WalletAppKit extends AbstractIdleService {
return ImmutableList.of();
}
/**
* Override this to use a {@link BlockStore} that isn't the default of {@link SPVBlockStore}.
*/
protected BlockStore provideBlockStore(File file) throws BlockStoreException {
return new SPVBlockStore(params, file);
}
/**
* This method is invoked on a background thread after all objects are initialised, but before the peer group
* or block chain download is started. You can tweak the objects configuration here.
@ -301,7 +294,7 @@ public class WalletAppKit extends AbstractIdleService {
vWallet = createOrLoadWallet(shouldReplayWallet);
// Initiate Bitcoin network objects (block store, blockchain and peer group)
vStore = provideBlockStore(chainFile);
vStore = new SPVBlockStore(params, chainFile);
if (!chainFileExists || restoreFromSeed != null || restoreFromKey != null) {
if (checkpoints == null && !Utils.isAndroidRuntime()) {
checkpoints = CheckpointManager.openStream(params);
@ -313,20 +306,14 @@ public class WalletAppKit extends AbstractIdleService {
if (restoreFromSeed != null) {
time = restoreFromSeed.getCreationTimeSeconds();
if (chainFileExists) {
log.info("Deleting the chain file in preparation from restore.");
vStore.close();
if (!chainFile.delete())
throw new IOException("Failed to delete chain file in preparation for restore.");
vStore = provideBlockStore(chainFile);
log.info("Clearing the chain file in preparation for restore.");
vStore.clear();
}
} else if (restoreFromKey != null) {
time = restoreFromKey.getCreationTimeSeconds();
if (chainFileExists) {
log.info("Deleting the chain file in preparation from restore.");
vStore.close();
if (!chainFile.delete())
throw new IOException("Failed to delete chain file in preparation for restore.");
vStore = provideBlockStore(chainFile);
log.info("Clearing the chain file in preparation for restore.");
vStore.clear();
}
}
else
@ -338,11 +325,8 @@ public class WalletAppKit extends AbstractIdleService {
else
log.warn("Creating a new uncheckpointed block store due to a wallet with a creation time of zero: this will result in a very slow chain sync");
} else if (chainFileExists) {
log.info("Deleting the chain file in preparation from restore.");
vStore.close();
if (!chainFile.delete())
throw new IOException("Failed to delete chain file in preparation for restore.");
vStore = provideBlockStore(chainFile);
log.info("Clearing the chain file in preparation for restore.");
vStore.clear();
}
}
vChain = new BlockChain(params, vStore);

View file

@ -326,4 +326,22 @@ public class SPVBlockStore implements BlockStore {
checkArgument(newCursor >= 0);
buffer.putInt(4, newCursor);
}
public void clear() throws Exception {
lock.lock();
try {
// Clear caches
blockCache.clear();
notFoundCache.clear();
// Clear file content
buffer.position(0);
long fileLength = randomAccessFile.length();
for (int i = 0; i < fileLength; i++) {
buffer.put((byte)0);
}
// Initialize store again
buffer.position(0);
initNewStore(params);
} finally { lock.unlock(); }
}
}

View file

@ -19,6 +19,7 @@ package org.bitcoinj.store;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNull;
import java.io.File;
import java.math.BigInteger;
@ -146,4 +147,21 @@ public class SPVBlockStoreTest {
watch.elapsed(TimeUnit.MILLISECONDS) < THRESHOLD_MS);
store.close();
}
@Test
public void clear() throws Exception {
SPVBlockStore store = new SPVBlockStore(UNITTEST, blockStoreFile);
// Build a new block.
Address to = LegacyAddress.fromKey(UNITTEST, new ECKey());
StoredBlock genesis = store.getChainHead();
StoredBlock b1 = genesis.build(genesis.getHeader().createNextBlock(to).cloneAsHeader());
store.put(b1);
store.setChainHead(b1);
assertEquals(b1.getHeader().getHash(), store.getChainHead().getHeader().getHash());
store.clear();
assertNull(store.get(b1.getHeader().getHash()));
assertEquals(UNITTEST.getGenesisBlock().getHash(), store.getChainHead().getHeader().getHash());
store.close();
}
}