mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-11-14 03:17:19 +00:00
Cleanup and finish merge with 0.3
This commit is contained in:
committed by
Miron Cuperman
parent
f731c8591d
commit
b7b1c039dc
6
pom.xml
6
pom.xml
@@ -245,6 +245,12 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.derby</groupId>
|
||||||
|
<artifactId>derby</artifactId>
|
||||||
|
<version>10.8.2.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- In Android these libraries are incomplete,
|
<!-- In Android these libraries are incomplete,
|
||||||
so use the dedicated artifact (bitcoinj-<version>-android.jar) -->
|
so use the dedicated artifact (bitcoinj-<version>-android.jar) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -16,14 +16,26 @@
|
|||||||
|
|
||||||
package com.google.bitcoin.examples;
|
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.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.InetAddress;
|
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
|
* 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
|
// Connect to the localhost node. One minute timeout since we won't try any other peers
|
||||||
System.out.println("Connecting ...");
|
System.out.println("Connecting ...");
|
||||||
NetworkConnection conn = new NetworkConnection(InetAddress.getLocalHost(), params,
|
|
||||||
blockStore.getChainHead().getHeight(), 60000);
|
|
||||||
BlockChain chain = new BlockChain(params, wallet, blockStore);
|
BlockChain chain = new BlockChain(params, wallet, blockStore);
|
||||||
final Peer peer = new Peer(params, conn, chain);
|
final PeerGroup peerGroup = new PeerGroup(blockStore, params, chain);
|
||||||
peer.start();
|
peerGroup.addAddress(new PeerAddress(InetAddress.getLocalHost()));
|
||||||
|
peerGroup.start();
|
||||||
|
|
||||||
// We want to know when the balance changes.
|
// 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) {
|
public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
|
||||||
// Running on a peer thread.
|
// Running on a peer thread.
|
||||||
assert !newBalance.equals(BigInteger.ZERO);
|
assert !newBalance.equals(BigInteger.ZERO);
|
||||||
@@ -81,7 +93,7 @@ public class DerbyPingService {
|
|||||||
BigInteger value = tx.getValueSentToMe(w);
|
BigInteger value = tx.getValueSentToMe(w);
|
||||||
System.out.println("Received " + Utils.bitcoinValueToFriendlyString(value) + " from " + from.toString());
|
System.out.println("Received " + Utils.bitcoinValueToFriendlyString(value) + " from " + from.toString());
|
||||||
// Now send the coins back!
|
// 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!
|
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());
|
System.out.println("Sent coins back! Transaction hash is " + sendTx.getHashAsString());
|
||||||
w.saveToFile(walletFile);
|
w.saveToFile(walletFile);
|
||||||
@@ -96,18 +108,8 @@ public class DerbyPingService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CountDownLatch progress = peer.startBlockChainDownload();
|
peerGroup.downloadBlockChain();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("Send coins to: " + key.toAddress(params).toString());
|
System.out.println("Send coins to: " + key.toAddress(params).toString());
|
||||||
System.out.println("Waiting for coins to arrive. Press Ctrl-C to quit.");
|
System.out.println("Waiting for coins to arrive. Press Ctrl-C to quit.");
|
||||||
// The peer thread keeps us alive until something kills the process.
|
// The peer thread keeps us alive until something kills the process.
|
||||||
@@ -117,7 +119,7 @@ public class DerbyPingService {
|
|||||||
* @param blockStore
|
* @param blockStore
|
||||||
* @throws BlockStoreException
|
* @throws BlockStoreException
|
||||||
*/
|
*/
|
||||||
private static void iterateAll(DerbyBlockStore blockStore) throws BlockStoreException {
|
static void iterateAll(DerbyBlockStore blockStore) throws BlockStoreException {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
StoredBlock block = blockStore.getChainHead();
|
StoredBlock block = blockStore.getChainHead();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.google.bitcoin.core;
|
package com.google.bitcoin.store;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright 2011 Google Inc.
|
* Copyright 2011 Google Inc.
|
||||||
@@ -16,6 +16,14 @@ package com.google.bitcoin.core;
|
|||||||
* limitations under the License.
|
* 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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -33,9 +41,6 @@ import java.sql.Statement;
|
|||||||
* @author miron@google.com (Miron Cuperman)
|
* @author miron@google.com (Miron Cuperman)
|
||||||
*/
|
*/
|
||||||
public class DerbyBlockStore implements BlockStore {
|
public class DerbyBlockStore implements BlockStore {
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final int COMMIT_INTERVAL = 2 * 1000;
|
private static final int COMMIT_INTERVAL = 2 * 1000;
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(DerbyBlockStore.class);
|
private static final Logger log = LoggerFactory.getLogger(DerbyBlockStore.class);
|
||||||
@@ -161,13 +166,13 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
if (!rs.next()) {
|
if (!rs.next()) {
|
||||||
throw new BlockStoreException("corrupt Derby block store - no chain head pointer");
|
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);
|
this.chainHeadBlock = get(hash);
|
||||||
if (this.chainHeadBlock == null)
|
if (this.chainHeadBlock == null)
|
||||||
{
|
{
|
||||||
throw new BlockStoreException("corrupt Derby block store - head block not found");
|
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 {
|
private void createNewStore(NetworkParameters params) throws BlockStoreException {
|
||||||
@@ -178,7 +183,7 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
StoredBlock storedGenesis = new StoredBlock(genesis,
|
StoredBlock storedGenesis = new StoredBlock(genesis,
|
||||||
genesis.getWork(), 0);
|
genesis.getWork(), 0);
|
||||||
this.chainHeadBlock = storedGenesis;
|
this.chainHeadBlock = storedGenesis;
|
||||||
this.chainHeadHash = new Sha256Hash(storedGenesis.getHeader().getHash());
|
this.chainHeadHash = storedGenesis.getHeader().getHash();
|
||||||
setChainHead(storedGenesis);
|
setChainHead(storedGenesis);
|
||||||
put(storedGenesis);
|
put(storedGenesis);
|
||||||
} catch (VerificationException e1) {
|
} catch (VerificationException e1) {
|
||||||
@@ -199,13 +204,12 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void put(StoredBlock stored) throws BlockStoreException {
|
public void put(StoredBlock stored) throws BlockStoreException {
|
||||||
try {
|
try {
|
||||||
PreparedStatement s =
|
PreparedStatement s =
|
||||||
conn.prepareStatement("INSERT INTO blocks(hash, chainWork, height, header)"
|
conn.prepareStatement("INSERT INTO blocks(hash, chainWork, height, header)"
|
||||||
+ " VALUES(?, ?, ?, ?)");
|
+ " VALUES(?, ?, ?, ?)");
|
||||||
s.setBytes(1, stored.getHeader().getHash());
|
s.setBytes(1, stored.getHeader().getHash().getBytes());
|
||||||
s.setBytes(2, stored.getChainWork().toByteArray());
|
s.setBytes(2, stored.getChainWork().toByteArray());
|
||||||
s.setLong(3, stored.getHeight());
|
s.setLong(3, stored.getHeight());
|
||||||
s.setBytes(4, stored.getHeader().bitcoinSerialize());
|
s.setBytes(4, stored.getHeader().bitcoinSerialize());
|
||||||
@@ -217,15 +221,14 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
||||||
public StoredBlock get(byte[] hash) throws BlockStoreException {
|
|
||||||
// Optimize for chain head
|
// Optimize for chain head
|
||||||
if (chainHeadHash != null && chainHeadHash.equals(new Sha256Hash(hash)))
|
if (chainHeadHash != null && chainHeadHash.equals(hash))
|
||||||
return chainHeadBlock;
|
return chainHeadBlock;
|
||||||
try {
|
try {
|
||||||
PreparedStatement s = conn
|
PreparedStatement s = conn
|
||||||
.prepareStatement("SELECT chainWork, height, header FROM blocks WHERE hash = ?");
|
.prepareStatement("SELECT chainWork, height, header FROM blocks WHERE hash = ?");
|
||||||
s.setBytes(1, hash);
|
s.setBytes(1, hash.getBytes());
|
||||||
ResultSet results = s.executeQuery();
|
ResultSet results = s.executeQuery();
|
||||||
if (!results.next()) {
|
if (!results.next()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -240,7 +243,7 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
stored = new StoredBlock(params.genesisBlock.cloneAsHeader(),
|
stored = new StoredBlock(params.genesisBlock.cloneAsHeader(),
|
||||||
params.genesisBlock.getWork(), 0);
|
params.genesisBlock.getWork(), 0);
|
||||||
} else {
|
} else {
|
||||||
b.verify();
|
b.verifyHeader();
|
||||||
stored = new StoredBlock(b, chainWork, height);
|
stored = new StoredBlock(b, chainWork, height);
|
||||||
}
|
}
|
||||||
return stored;
|
return stored;
|
||||||
@@ -257,21 +260,19 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Override
|
|
||||||
public StoredBlock getChainHead() throws BlockStoreException {
|
public StoredBlock getChainHead() throws BlockStoreException {
|
||||||
return chainHeadBlock;
|
return chainHeadBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setChainHead(StoredBlock chainHead) throws BlockStoreException {
|
public void setChainHead(StoredBlock chainHead) throws BlockStoreException {
|
||||||
byte[] hash = chainHead.getHeader().getHash();
|
Sha256Hash hash = chainHead.getHeader().getHash();
|
||||||
this.chainHeadHash = new Sha256Hash(hash);
|
this.chainHeadHash = hash;
|
||||||
this.chainHeadBlock = chainHead;
|
this.chainHeadBlock = chainHead;
|
||||||
try {
|
try {
|
||||||
PreparedStatement s = conn
|
PreparedStatement s = conn
|
||||||
.prepareStatement("UPDATE settings SET value = ? WHERE name = ?");
|
.prepareStatement("UPDATE settings SET value = ? WHERE name = ?");
|
||||||
s.setString(2, CHAIN_HEAD_SETTING);
|
s.setString(2, CHAIN_HEAD_SETTING);
|
||||||
s.setBytes(1, hash);
|
s.setBytes(1, hash.getBytes());
|
||||||
s.executeUpdate();
|
s.executeUpdate();
|
||||||
s.close();
|
s.close();
|
||||||
startCommitter();
|
startCommitter();
|
||||||
@@ -316,7 +317,6 @@ public class DerbyBlockStore implements BlockStore {
|
|||||||
// A thread that is guaranteed to try a commit as long as
|
// A thread that is guaranteed to try a commit as long as
|
||||||
// committerThread is not null
|
// committerThread is not null
|
||||||
Runnable committer = new Runnable() {
|
Runnable committer = new Runnable() {
|
||||||
@Override
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
log.info("commit scheduled");
|
log.info("commit scheduled");
|
||||||
@@ -13,20 +13,30 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.bitcoin.core;
|
package com.google.bitcoin.store;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
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 org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class DerbyBlockStoreTest {
|
public class DerbyBlockStoreTest {
|
||||||
/**
|
/**
|
||||||
*
|
* This path will be deleted recursively!
|
||||||
*/
|
*/
|
||||||
private static final String DB_NAME = ".bitcoinj.unittest.derby";
|
private static final String DB_NAME = ".bitcoinj.unittest.derby";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStorage() throws Exception {
|
public void testStorage() throws Exception {
|
||||||
|
deleteRecursively(new File(DB_NAME));
|
||||||
NetworkParameters params = NetworkParameters.unitTests();
|
NetworkParameters params = NetworkParameters.unitTests();
|
||||||
Address to = new ECKey().toAddress(params);
|
Address to = new ECKey().toAddress(params);
|
||||||
DerbyBlockStore store = new DerbyBlockStore(params, DB_NAME);
|
DerbyBlockStore store = new DerbyBlockStore(params, DB_NAME);
|
||||||
@@ -49,4 +59,13 @@ public class DerbyBlockStoreTest {
|
|||||||
assertEquals(b1, store.getChainHead());
|
assertEquals(b1, store.getChainHead());
|
||||||
store.dump();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user