diff --git a/core/pom.xml b/core/pom.xml
index 625f89e2..15395d57 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -158,11 +158,6 @@
test
-
- org.apache.derby
- derby
-
-
com.h2database
h2
diff --git a/core/src/main/java/com/google/bitcoin/store/DerbyBlockStore.java b/core/src/main/java/com/google/bitcoin/store/DerbyBlockStore.java
deleted file mode 100644
index 6a40dfbb..00000000
--- a/core/src/main/java/com/google/bitcoin/store/DerbyBlockStore.java
+++ /dev/null
@@ -1,331 +0,0 @@
-package com.google.bitcoin.store;
-
-/**
- * Copyright 2011 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.
- */
-
-import com.google.bitcoin.core.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-import java.sql.*;
-
-/**
- * A block store using the Apache Derby pure-java embedded database.
- *
- * @author miron@google.com (Miron Cuperman)
- */
-public class DerbyBlockStore implements BlockStore {
- private static final int COMMIT_INTERVAL = 2 * 1000;
-
- private static final Logger log = LoggerFactory.getLogger(DerbyBlockStore.class);
-
- private StoredBlock chainHeadBlock;
- private Sha256Hash chainHeadHash;
- private NetworkParameters params;
- private Connection conn;
-
- private String dbName;
-
- private Thread committerThread;
-
- static final String driver = "org.apache.derby.jdbc.EmbeddedDriver";
- static final String CREATE_SETTINGS_TABLE = "CREATE TABLE settings ( "
- + "name VARCHAR(32) NOT NULL CONSTRAINT settings_pk PRIMARY KEY,"
- + "value BLOB"
- + ")";
- static final String CREATE_BLOCKS_TABLE = "CREATE TABLE blocks ( "
- + "hash CHAR(32) FOR BIT DATA NOT NULL CONSTRAINT blocks_pk PRIMARY KEY,"
- + "chainWork BLOB NOT NULL,"
- + "height BIGINT NOT NULL,"
- + "header BLOB NOT NULL"
- + ")";
- static final String CHAIN_HEAD_SETTING = "chainhead";
-
- public static void main(String[] args) throws Exception {
- DerbyBlockStore store = new DerbyBlockStore(NetworkParameters.testNet(), ".bitcoinj-test.derby");
- store.resetStore();
- }
-
- public synchronized void close() {
- String connectionURL = "jdbc:derby:" + dbName + ";shutdown=true";
- try {
- if (conn != null) {
- conn.commit();
- conn = null;
- }
- if (committerThread != null)
- committerThread.interrupt();
- DriverManager.getConnection(connectionURL);
- } catch (SQLException ex) {
- if (( (ex.getErrorCode() == 45000)
- && ("08006".equals(ex.getSQLState()) ))) {
- // we got the expected exception
- log.info("Derby shut down normally");
- // Note that for single database shutdown, the expected
- // SQL state is "08006", and the error code is 45000.
- }
- else {
- throw new RuntimeException(ex);
- }
- }
- }
-
- private synchronized void commit() throws BlockStoreException {
- try {
- if (conn != null)
- conn.commit();
- } catch (SQLException ex) {
- log.error("commit failed", ex);
- throw new BlockStoreException(ex);
- }
- }
-
- public DerbyBlockStore(NetworkParameters params, String dbName) throws BlockStoreException {
- this.params = params;
- this.dbName = dbName;
- String connectionURL = "jdbc:derby:" + dbName + ";create=true";
-
- try {
- Class.forName(driver);
- log.info(driver + " loaded. ");
- } catch (java.lang.ClassNotFoundException e) {
- log.error("check CLASSPATH for Derby jar ", e);
- }
-
- try {
- conn = DriverManager.getConnection(connectionURL);
- conn.setAutoCommit(false);
- log.info("Connected to database " + connectionURL);
-
- // Create tables if needed
- if (!isTableExists("settings")) {
- createTables();
- }
- initFromDatabase();
- } catch (SQLException ex) {
- throw new BlockStoreException(ex);
- }
- }
-
- public void resetStore() throws BlockStoreException {
- Statement s;
- try {
- s = conn.createStatement();
- s.executeUpdate("DROP TABLE settings");
- s.executeUpdate("DROP TABLE blocks");
- s.close();
- createTables();
- initFromDatabase();
- startCommitter();
- } catch (SQLException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- private void createTables() throws SQLException, BlockStoreException {
- Statement s = conn.createStatement();
- log.debug("DerbyBlockStore : CREATE blocks table");
- s.executeUpdate(CREATE_BLOCKS_TABLE);
-
- log.debug("DerbyBlockStore : CREATE settings table");
- s.executeUpdate(CREATE_SETTINGS_TABLE);
-
- s.executeUpdate("INSERT INTO settings(name, value) VALUES('chainhead', NULL)");
- createNewStore(params);
- }
-
- private void initFromDatabase() throws SQLException, BlockStoreException {
- Statement s = conn.createStatement();
- ResultSet rs = s.executeQuery("SELECT value FROM settings WHERE name = 'chainhead'");
- if (!rs.next()) {
- throw new BlockStoreException("corrupt Derby block store - no chain head pointer");
- }
- Sha256Hash hash = new Sha256Hash(rs.getBytes(1));
- this.chainHeadBlock = get(hash);
- if (this.chainHeadBlock == null)
- {
- throw new BlockStoreException("corrupt Derby block store - head block not found");
- }
- this.chainHeadHash = hash;
- }
-
- private void createNewStore(NetworkParameters params) throws BlockStoreException {
- try {
- // Set up the genesis block. When we start out fresh, it is by
- // definition the top of the chain.
- Block genesis = params.genesisBlock.cloneAsHeader();
- StoredBlock storedGenesis = new StoredBlock(genesis,
- genesis.getWork(), 0);
- this.chainHeadBlock = storedGenesis;
- this.chainHeadHash = storedGenesis.getHeader().getHash();
- setChainHead(storedGenesis);
- put(storedGenesis);
- } catch (VerificationException e1) {
- throw new RuntimeException(e1); // Cannot happen.
- }
- }
-
- private boolean isTableExists(String table) throws SQLException {
- Statement s = conn.createStatement();
- try {
- ResultSet results = s.executeQuery("SELECT * FROM " + table + " WHERE 1 = 2");
- results.close();
- return true;
- } catch (SQLException ex) {
- return false;
- } finally {
- s.close();
- }
- }
-
- public void put(StoredBlock stored) throws BlockStoreException {
- try {
- PreparedStatement s =
- conn.prepareStatement("INSERT INTO blocks(hash, chainWork, height, header)"
- + " VALUES(?, ?, ?, ?)");
- s.setBytes(1, stored.getHeader().getHash().getBytes());
- s.setBytes(2, stored.getChainWork().toByteArray());
- s.setLong(3, stored.getHeight());
- s.setBytes(4, stored.getHeader().unsafeBitcoinSerialize());
- s.executeUpdate();
- s.close();
- startCommitter();
- } catch (SQLException ex) {
- throw new BlockStoreException(ex);
- }
- }
-
- public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
- // Optimize for chain head
- if (chainHeadHash != null && chainHeadHash.equals(hash))
- return chainHeadBlock;
- try {
- PreparedStatement s = conn
- .prepareStatement("SELECT chainWork, height, header FROM blocks WHERE hash = ?");
- s.setBytes(1, hash.getBytes());
- ResultSet results = s.executeQuery();
- if (!results.next()) {
- return null;
- }
- // Parse it.
-
- BigInteger chainWork = new BigInteger(results.getBytes(1));
- int height = results.getInt(2);
- Block b = new Block(params, results.getBytes(3));
- StoredBlock stored;
- b.verifyHeader();
- stored = new StoredBlock(b, chainWork, height);
- return stored;
- } catch (SQLException ex) {
- throw new BlockStoreException(ex);
- } catch (ProtocolException e) {
- // Corrupted database.
- throw new BlockStoreException(e);
- } catch (VerificationException e) {
- // Should not be able to happen unless the database contains bad
- // blocks.
- throw new BlockStoreException(e);
- }
- }
-
- public StoredBlock getChainHead() throws BlockStoreException {
- return chainHeadBlock;
- }
-
- public void setChainHead(StoredBlock chainHead) throws BlockStoreException {
- Sha256Hash hash = chainHead.getHeader().getHash();
- this.chainHeadHash = hash;
- this.chainHeadBlock = chainHead;
- try {
- PreparedStatement s = conn
- .prepareStatement("UPDATE settings SET value = ? WHERE name = ?");
- s.setString(2, CHAIN_HEAD_SETTING);
- s.setBytes(1, hash.getBytes());
- s.executeUpdate();
- s.close();
- startCommitter();
- } catch (SQLException ex) {
- throw new BlockStoreException(ex);
- }
- }
-
- public void dump() throws SQLException {
- Statement s = conn.createStatement();
- System.out.println("settings");
- ResultSet rs = s.executeQuery("SELECT name, value FROM settings");
- while (rs.next()) {
- System.out.print(rs.getString(1));
- System.out.print(" ");
- System.out.println(Utils.bytesToHexString(rs.getBytes(2)));
- }
- rs.close();
- System.out.println("blocks");
- rs = s.executeQuery("SELECT hash, chainWork, height, header FROM blocks");
- while (rs.next()) {
- System.out.print(Utils.bytesToHexString(rs.getBytes(1)));
- System.out.print(" ");
- System.out.print(Utils.bytesToHexString(rs.getBytes(2)));
- System.out.print(" ");
- System.out.print(rs.getInt(3));
- System.out.print(" ");
- //System.out.print(Utils.bytesToHexString(rs.getBytes(4)));
- System.out.println();
- }
- rs.close();
- System.out.println("end");
- s.close();
- }
-
- protected synchronized void startCommitter() {
- if (committerThread != null)
- return;
-
- // A thread that is guaranteed to try a commit as long as
- // committerThread is not null
- Runnable committer = new Runnable() {
- public void run() {
- try {
- log.info("commit scheduled");
- Thread.sleep(COMMIT_INTERVAL);
- } catch (InterruptedException ex) {
- // ignore
- }
- synchronized (DerbyBlockStore.this) {
- try {
- if (conn != null) {
- commit();
- log.info("commit success");
- }
- else {
- log.info("committer noticed that we are shutting down");
- }
- }
- catch (BlockStoreException e) {
- log.warn("commit failed");
- // ignore
- }
- finally {
- committerThread = null;
- }
- }
- }
- };
-
- committerThread = new Thread(committer, "DerbyBlockStore committer");
- committerThread.start();
- }
-}
diff --git a/core/src/test/java/com/google/bitcoin/store/DerbyBlockStoreTest.java b/core/src/test/java/com/google/bitcoin/store/DerbyBlockStoreTest.java
deleted file mode 100644
index 9a3d152e..00000000
--- a/core/src/test/java/com/google/bitcoin/store/DerbyBlockStoreTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Copyright 2011 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.
- */
-package com.google.bitcoin.store;
-
-import com.google.bitcoin.core.Address;
-import com.google.bitcoin.core.ECKey;
-import com.google.bitcoin.core.NetworkParameters;
-import com.google.bitcoin.core.StoredBlock;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import java.io.File;
-
-import static org.junit.Assert.assertEquals;
-
-public class DerbyBlockStoreTest {
- @Rule
- public TemporaryFolder folder = new TemporaryFolder();
-
- @Before
- public void shutUp() {
- // Prevent Derby writing a useless error log file.
- System.getProperties().setProperty("derby.stream.error.file", "");
- }
-
- @Test
- public void testStorage() throws Exception {
- File file = new File(folder.getRoot(), "derby");
- String path = file.getAbsolutePath();
- NetworkParameters params = NetworkParameters.unitTests();
- Address to = new ECKey().toAddress(params);
- DerbyBlockStore store = new DerbyBlockStore(params, path);
- store.resetStore();
- store.dump();
- // Check the first block in a new store is the genesis block.
- StoredBlock genesis = store.getChainHead();
- assertEquals(params.genesisBlock, genesis.getHeader());
-
- // Build a new block.
- StoredBlock b1 = genesis.build(genesis.getHeader().createNextBlock(to).cloneAsHeader());
- store.put(b1);
- store.setChainHead(b1);
- store.dump();
- // Check we can get it back out again if we rebuild the store object.
- store = new DerbyBlockStore(params, path);
- StoredBlock b2 = store.get(b1.getHeader().getHash());
- assertEquals(b1, b2);
- // Check the chain head was stored correctly also.
- assertEquals(b1, store.getChainHead());
-
- StoredBlock g1 = store.get(params.genesisBlock.getHash());
- assertEquals(params.genesisBlock, g1.getHeader());
- store.dump();
- store.close();
- }
-}
diff --git a/examples/src/main/java/com/google/bitcoin/examples/DerbyPingService.java b/examples/src/main/java/com/google/bitcoin/examples/DerbyPingService.java
deleted file mode 100644
index 6e45eb75..00000000
--- a/examples/src/main/java/com/google/bitcoin/examples/DerbyPingService.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * Copyright 2011 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.
- */
-
-package com.google.bitcoin.examples;
-
-import com.google.bitcoin.core.*;
-import com.google.bitcoin.store.BlockStoreException;
-import com.google.bitcoin.store.DerbyBlockStore;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.util.concurrent.ExecutionException;
-
-/**
- * PingService demonstrates basic usage of the library. It sits on the network and when it receives coins, simply
- * sends them right back to the previous owner, determined rather arbitrarily by the address of the first input.
- */
-public class DerbyPingService {
- public static void main(String[] args) throws Exception {
- boolean testNet = args.length > 0 && args[0].equalsIgnoreCase("testnet");
- final NetworkParameters params = testNet ? NetworkParameters.testNet() : NetworkParameters.prodNet();
- String suffix = testNet ? "testnet" : "prodnet";
- String filePrefix = "pingservice-" + suffix;
-
- // Try to read the wallet from storage, create a new one if not possible.
- Wallet wallet;
- final File walletFile = new File(filePrefix + ".wallet");
- try {
- wallet = Wallet.loadFromFile(walletFile);
- } catch (IOException e) {
- wallet = new Wallet(params);
- wallet.keychain.add(new ECKey());
- wallet.saveToFile(walletFile);
- }
- // Fetch the first key in the wallet (should be the only key).
- ECKey key = wallet.keychain.get(0);
-
- // Load the block chain, if there is one stored locally.
- System.out.println("Reading block store from disk");
- long time = System.currentTimeMillis();
- DerbyBlockStore blockStore = new DerbyBlockStore(params, ".bitcoinj-" + suffix);
- System.out.println("Opened block store in " + (System.currentTimeMillis() - time) + " ms");
-
- //iterateAll(blockStore);
- //blockStore.close();
- //System.exit(1);
-
- // Connect to the localhost node. One minute timeout since we won't try any other peers
- System.out.println("Connecting ...");
- BlockChain chain = new BlockChain(params, wallet, blockStore);
- final PeerGroup peerGroup = new PeerGroup(params, chain);
- peerGroup.addAddress(new PeerAddress(InetAddress.getLocalHost()));
- peerGroup.addWallet(wallet);
- peerGroup.start();
-
- // We want to know when the balance changes.
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
- // Running on a peer thread.
- assert !newBalance.equals(BigInteger.ZERO);
- // It's impossible to pick one specific identity that you receive coins from in BitCoin as there
- // could be inputs from many addresses. So instead we just pick the first and assume they were all
- // owned by the same person.
- try {
- TransactionInput input = tx.getInputs().get(0);
- Address from = input.getFromAddress();
- BigInteger value = tx.getValueSentToMe(w);
- System.out.println("Received " + Utils.bitcoinValueToFriendlyString(value) + " from " + from.toString());
- // Now send the coins back!
- Wallet.SendResult sendTx = w.sendCoins(peerGroup, from, value);
- assert sendTx.tx != null; // We should never try to send more coins than we have!
- System.out.println("Sent coins back! Transaction hash is " + sendTx.tx.getHashAsString());
- sendTx.broadcastComplete.get();
- w.saveToFile(walletFile);
- } catch (ScriptException e) {
- // If we didn't understand the scriptSig, just crash.
- e.printStackTrace();
- throw new RuntimeException(e);
- } catch (IOException e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } catch (ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
- });
-
- peerGroup.downloadBlockChain();
-
- System.out.println("Send coins to: " + key.toAddress(params).toString());
- System.out.println("Waiting for coins to arrive. Press Ctrl-C to quit.");
- // The peer thread keeps us alive until something kills the process.
- }
-
- /**
- * @param blockStore
- * @throws BlockStoreException
- */
- static void iterateAll(DerbyBlockStore blockStore) throws BlockStoreException {
- long time = System.currentTimeMillis();
- StoredBlock block = blockStore.getChainHead();
- int count = 0;
- while (block != null) {
- count++;
- if (count % 1000 == 0)
- System.out.println("iterated " + count);
- block = block.getPrev(blockStore);
- }
- System.out.println("iterated " + count);
- System.out.println("Iterated block store in " + (System.currentTimeMillis() - time) + " ms");
- }
-}