3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Cleanup and finish merge with 0.3

This commit is contained in:
Miron Cuperman 2011-12-13 12:04:04 -08:00 committed by Miron Cuperman
parent f731c8591d
commit b7b1c039dc
4 changed files with 73 additions and 46 deletions

View File

@ -245,6 +245,12 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.8.2.2</version>
</dependency>
<!-- In Android these libraries are incomplete,
so use the dedicated artifact (bitcoinj-<version>-android.jar) -->
<dependency>
@ -263,4 +269,4 @@
<slf4j.version>1.6.2</slf4j.version>
</properties>
</project>
</project>

View File

@ -16,14 +16,26 @@
package com.google.bitcoin.examples;
import com.google.bitcoin.core.*;
import com.google.bitcoin.core.AbstractWalletEventListener;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.BlockChain;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.PeerAddress;
import com.google.bitcoin.core.PeerGroup;
import com.google.bitcoin.core.ScriptException;
import com.google.bitcoin.core.StoredBlock;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.TransactionInput;
import com.google.bitcoin.core.Utils;
import com.google.bitcoin.core.Wallet;
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.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* PingService demonstrates basic usage of the library. It sits on the network and when it receives coins, simply
@ -61,14 +73,14 @@ public class DerbyPingService {
// Connect to the localhost node. One minute timeout since we won't try any other peers
System.out.println("Connecting ...");
NetworkConnection conn = new NetworkConnection(InetAddress.getLocalHost(), params,
blockStore.getChainHead().getHeight(), 60000);
BlockChain chain = new BlockChain(params, wallet, blockStore);
final Peer peer = new Peer(params, conn, chain);
peer.start();
final PeerGroup peerGroup = new PeerGroup(blockStore, params, chain);
peerGroup.addAddress(new PeerAddress(InetAddress.getLocalHost()));
peerGroup.start();
// We want to know when the balance changes.
wallet.addEventListener(new WalletEventListener() {
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);
@ -81,7 +93,7 @@ public class DerbyPingService {
BigInteger value = tx.getValueSentToMe(w);
System.out.println("Received " + Utils.bitcoinValueToFriendlyString(value) + " from " + from.toString());
// Now send the coins back!
Transaction sendTx = w.sendCoins(peer, from, value);
Transaction sendTx = w.sendCoins(peerGroup, from, value);
assert sendTx != null; // We should never try to send more coins than we have!
System.out.println("Sent coins back! Transaction hash is " + sendTx.getHashAsString());
w.saveToFile(walletFile);
@ -96,18 +108,8 @@ public class DerbyPingService {
}
});
CountDownLatch progress = peer.startBlockChainDownload();
long max = progress.getCount(); // Racy but no big deal.
if (max > 0) {
System.out.println("Downloading block chain. " + (max > 1000 ? "This may take a while." : ""));
long current = max;
while (current > 0) {
double pct = 100.0 - (100.0 * (current / (double)max));
System.out.println(String.format("Chain download %d%% done", (int)pct));
progress.await(1, TimeUnit.SECONDS);
current = progress.getCount();
}
}
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.
@ -117,7 +119,7 @@ public class DerbyPingService {
* @param blockStore
* @throws BlockStoreException
*/
private static void iterateAll(DerbyBlockStore blockStore) throws BlockStoreException {
static void iterateAll(DerbyBlockStore blockStore) throws BlockStoreException {
long time = System.currentTimeMillis();
StoredBlock block = blockStore.getChainHead();
int count = 0;

View File

@ -1,4 +1,4 @@
package com.google.bitcoin.core;
package com.google.bitcoin.store;
/**
* Copyright 2011 Google Inc.
@ -16,6 +16,14 @@ package com.google.bitcoin.core;
* limitations under the License.
*/
import com.google.bitcoin.core.Block;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.ProtocolException;
import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.StoredBlock;
import com.google.bitcoin.core.Utils;
import com.google.bitcoin.core.VerificationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -33,9 +41,6 @@ import java.sql.Statement;
* @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);
@ -161,13 +166,13 @@ public class DerbyBlockStore implements BlockStore {
if (!rs.next()) {
throw new BlockStoreException("corrupt Derby block store - no chain head pointer");
}
byte[] hash = rs.getBytes(1);
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 = new Sha256Hash(hash);
this.chainHeadHash = hash;
}
private void createNewStore(NetworkParameters params) throws BlockStoreException {
@ -178,7 +183,7 @@ public class DerbyBlockStore implements BlockStore {
StoredBlock storedGenesis = new StoredBlock(genesis,
genesis.getWork(), 0);
this.chainHeadBlock = storedGenesis;
this.chainHeadHash = new Sha256Hash(storedGenesis.getHeader().getHash());
this.chainHeadHash = storedGenesis.getHeader().getHash();
setChainHead(storedGenesis);
put(storedGenesis);
} catch (VerificationException e1) {
@ -199,13 +204,12 @@ public class DerbyBlockStore implements BlockStore {
}
}
@Override
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());
s.setBytes(1, stored.getHeader().getHash().getBytes());
s.setBytes(2, stored.getChainWork().toByteArray());
s.setLong(3, stored.getHeight());
s.setBytes(4, stored.getHeader().bitcoinSerialize());
@ -217,15 +221,14 @@ public class DerbyBlockStore implements BlockStore {
}
}
@Override
public StoredBlock get(byte[] hash) throws BlockStoreException {
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
// Optimize for chain head
if (chainHeadHash != null && chainHeadHash.equals(new Sha256Hash(hash)))
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);
.prepareStatement("SELECT chainWork, height, header FROM blocks WHERE hash = ?");
s.setBytes(1, hash.getBytes());
ResultSet results = s.executeQuery();
if (!results.next()) {
return null;
@ -240,7 +243,7 @@ public class DerbyBlockStore implements BlockStore {
stored = new StoredBlock(params.genesisBlock.cloneAsHeader(),
params.genesisBlock.getWork(), 0);
} else {
b.verify();
b.verifyHeader();
stored = new StoredBlock(b, chainWork, height);
}
return stored;
@ -257,21 +260,19 @@ public class DerbyBlockStore implements BlockStore {
}
@SuppressWarnings("unused")
@Override
public StoredBlock getChainHead() throws BlockStoreException {
return chainHeadBlock;
}
@Override
public void setChainHead(StoredBlock chainHead) throws BlockStoreException {
byte[] hash = chainHead.getHeader().getHash();
this.chainHeadHash = new Sha256Hash(hash);
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);
s.setBytes(1, hash.getBytes());
s.executeUpdate();
s.close();
startCommitter();
@ -316,7 +317,6 @@ public class DerbyBlockStore implements BlockStore {
// A thread that is guaranteed to try a commit as long as
// committerThread is not null
Runnable committer = new Runnable() {
@Override
public void run() {
try {
log.info("commit scheduled");

View File

@ -13,20 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.bitcoin.core;
package com.google.bitcoin.store;
import static org.junit.Assert.assertEquals;
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.Test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class DerbyBlockStoreTest {
/**
*
* This path will be deleted recursively!
*/
private static final String DB_NAME = ".bitcoinj.unittest.derby";
@Test
public void testStorage() throws Exception {
deleteRecursively(new File(DB_NAME));
NetworkParameters params = NetworkParameters.unitTests();
Address to = new ECKey().toAddress(params);
DerbyBlockStore store = new DerbyBlockStore(params, DB_NAME);
@ -49,4 +59,13 @@ public class DerbyBlockStoreTest {
assertEquals(b1, store.getChainHead());
store.dump();
}
void deleteRecursively(File f) throws IOException {
if (f.isDirectory()) {
for (File c : f.listFiles())
deleteRecursively(c);
}
if (!f.delete())
throw new FileNotFoundException("Failed to delete file: " + f);
}
}