Move clear blockstore feature to bitcoinj

This commit is contained in:
Oscar Guindzberg 2019-03-18 18:24:44 -03:00
parent 591ec7f5dc
commit aee1c6fa31
4 changed files with 6 additions and 154 deletions

View File

@ -33,7 +33,7 @@ configure(subprojects) {
jmockitVersion = '1.42'
joptVersion = '5.0.3'
langVersion = '3.4'
bitcoinjVersion = '3e7ff3a'
bitcoinjVersion = 'eedd41e'
logbackVersion = '1.1.10'
lombokVersion = '1.18.2'
mockitoVersion = '2.21.0'

View File

@ -1,141 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* 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.
*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.btc.setup;
import org.bitcoinj.core.Block;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.ProtocolException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.store.ChainFileLockedException;
import org.bitcoinj.store.SPVBlockStore;
import org.bitcoinj.utils.Threading;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* ClearableSPVBlockStore fixes some issues on SPVBlockStore that made
* "restore from seed" to fail on windows:
* - It allows the blockstore file to be cleared (as a replacement for deleting
* and recreating the file).
* - It overrides close() to avoid invoking WindowsMMapHack on windows
* which fails on jdk10.
* See https://github.com/bisq-network/bisq/issues/2402
*/
public class ClearableSPVBlockStore extends SPVBlockStore {
/**
* Creates and initializes an SPV block store. Will create the given file if it's missing. This operation
* will block on disk.
* @param params
* @param file
*/
public ClearableSPVBlockStore(NetworkParameters params, File file) throws BlockStoreException {
super(params, file);
}
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);
initNewStoreCopy(params);
} finally { lock.unlock(); }
}
// Copy of SPVBlockStore.initNewStore() that can not be used here because it is private
private void initNewStoreCopy(NetworkParameters params) throws Exception {
byte[] header;
header = HEADER_MAGIC.getBytes("US-ASCII");
buffer.put(header);
// Insert the genesis block.
lock.lock();
try {
setRingCursorCopy(buffer, FILE_PROLOGUE_BYTES);
} finally {
lock.unlock();
}
Block genesis = params.getGenesisBlock().cloneAsHeader();
StoredBlock storedGenesis = new StoredBlock(genesis, genesis.getWork(), 0);
put(storedGenesis);
setChainHead(storedGenesis);
}
// Copy of SPVBlockStore.setRingCursor() that can not be used here because it is private
private void setRingCursorCopy(ByteBuffer buffer, int newCursor) {
checkArgument(newCursor >= 0);
buffer.putInt(4, newCursor);
}
// Override close() to avoid invoking WindowsMMapHack on windows which fails on jdk10
@Override
public void close() throws BlockStoreException {
try {
buffer.force();
buffer = null; // Allow it to be GCd and the underlying file mapping to go away.
randomAccessFile.close();
} catch (IOException e) {
throw new BlockStoreException(e);
}
}
}

View File

@ -124,7 +124,7 @@ public class WalletConfig extends AbstractIdleService {
private DeterministicSeed seed;
private volatile BlockChain vChain;
private volatile BlockStore vStore;
private volatile SPVBlockStore vStore;
private volatile PeerGroup vPeerGroup;
private boolean useAutoSave = true;
private PeerAddress[] peerAddresses;
@ -325,13 +325,6 @@ public class WalletConfig extends AbstractIdleService {
return ImmutableList.of();
}
/**
* Override this to use a {@link BlockStore} that isn't the default of {@link SPVBlockStore}.
*/
private BlockStore provideBlockStore(File file) throws BlockStoreException {
return new ClearableSPVBlockStore(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.
@ -402,7 +395,7 @@ public class WalletConfig extends AbstractIdleService {
vBsqWallet.setRiskAnalyzer(new BisqRiskAnalysis.Analyzer());
// Initiate Bitcoin network objects (block store, blockchain and peer group)
vStore = provideBlockStore(chainFile);
vStore = new SPVBlockStore(params, chainFile);
if (!chainFileExists || seed != null) {
if (checkpoints != null) {
// Initialize the chain file with a checkpoint to speed up first-run sync.
@ -413,7 +406,7 @@ public class WalletConfig extends AbstractIdleService {
time = seed.getCreationTimeSeconds();
if (chainFileExists) {
log.info("Clearing the chain file in preparation from restore.");
((ClearableSPVBlockStore) vStore).clear();
vStore.clear();
}
} else {
time = vBtcWallet.getEarliestKeyCreationTime();
@ -426,7 +419,7 @@ public class WalletConfig extends AbstractIdleService {
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("Clearing the chain file in preparation from restore.");
((ClearableSPVBlockStore) vStore).clear();
vStore.clear();
}
}
vChain = new BlockChain(params, vStore);

View File

@ -37,7 +37,7 @@ dependencyVerification {
'com.googlecode.json-simple:json-simple:4e69696892b88b41c55d49ab2fdcc21eead92bf54acc588c0050596c3b75199c',
'org.springframework:spring-core:c451e8417adb2ffb2445636da5e44a2f59307c4100037a1fe387c3fba4f29b52',
'ch.qos.logback:logback-classic:e66efc674e94837344bc5b748ff510c37a44eeff86cbfdbf9e714ef2eb374013',
'com.github.bisq-network.bitcoinj:bitcoinj-core:15b2ac7e7a3af442f9d734d05a872586e7cd70c451c1bbaaf152830fc3421ec8',
'com.github.bisq-network.bitcoinj:bitcoinj-core:5c9cc2762b2d51d84dd22a83dd72ae3ee9e862c57f0efd5f2d8b1808e2ca8324',
'org.slf4j:slf4j-api:3a4cd4969015f3beb4b5b4d81dbafc01765fb60b8a439955ca64d8476fef553e',
'ch.qos.logback:logback-core:4cd46fa17d77057b39160058df2f21ebbc2aded51d0edcc25d2c1cecc042a005',
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',