mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-11-14 11:28:00 +00:00
Use the standard Maven directory layout, rename "lib" to "core". Mavenize submodules.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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!
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.Wallet;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* DumpWallet loads a serialized wallet and prints information about what it contains.
|
||||
*/
|
||||
public class DumpWallet {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 1) {
|
||||
System.out.println("Usage: java DumpWallet <filename>");
|
||||
return;
|
||||
}
|
||||
|
||||
Wallet wallet = Wallet.loadFromFile(new File(args[0]));
|
||||
System.out.println(wallet.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.BlockStore;
|
||||
import com.google.bitcoin.store.MemoryBlockStore;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Downloads the block given a block hash from the localhost node and prints it out.
|
||||
*/
|
||||
public class FetchBlock {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Connecting to node");
|
||||
final NetworkParameters params = NetworkParameters.prodNet();
|
||||
|
||||
BlockStore blockStore = new MemoryBlockStore(params);
|
||||
BlockChain chain = new BlockChain(params, blockStore);
|
||||
final Peer peer = new Peer(params, new PeerAddress(InetAddress.getLocalHost()), chain);
|
||||
peer.connect();
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
peer.run();
|
||||
} catch (PeerException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
Sha256Hash blockHash = new Sha256Hash(args[0]);
|
||||
Future<Block> future = peer.getBlock(blockHash);
|
||||
System.out.println("Waiting for node to send us the requested block: " + blockHash);
|
||||
Block block = future.get();
|
||||
System.out.println(block);
|
||||
peer.disconnect();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* 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.discovery.DnsDiscovery;
|
||||
import com.google.bitcoin.store.BlockStore;
|
||||
import com.google.bitcoin.store.BlockStoreException;
|
||||
import com.google.bitcoin.store.BoundedOverheadBlockStore;
|
||||
import com.google.bitcoin.utils.BriefLogFormatter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If running on TestNet (slow but better than using real coins on prodnet) do the following:
|
||||
* <ol>
|
||||
* <li>Backup your current wallet.dat in case of unforeseen problems</li>
|
||||
* <li>Start your bitcoin client in test mode <code>bitcoin -testnet</code>. This will create a new sub-directory called testnet and should not interfere with normal wallets or operations.</li>
|
||||
* <li>(Optional) Choose a fresh address</li>
|
||||
* <li>(Optional) Visit the Testnet faucet (https://testnet.freebitcoins.appspot.com/) to load your client with test coins</li>
|
||||
* <li>Run <code>PingService testnet</code></li>
|
||||
* <li>Wait for the block chain to download</li>
|
||||
* <li>Send some coins from your bitcoin client to the address provided in the PingService console</li>
|
||||
* <li>Leave it running until you get the coins back again</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*
|
||||
* <p>The testnet can be slow or flaky as it's a shared resource. You can use the <a href="http://sourceforge
|
||||
* .net/projects/bitcoin/files/Bitcoin/testnet-in-a-box/">testnet in a box</a> to do everything purely locally.</p>
|
||||
*/
|
||||
public class PingService {
|
||||
|
||||
private Wallet w;
|
||||
private final PeerGroup peerGroup;
|
||||
private final BlockChain chain;
|
||||
private final BlockStore blockStore;
|
||||
private final File walletFile;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
BriefLogFormatter.init();
|
||||
new PingService(args);
|
||||
}
|
||||
|
||||
public PingService(String[] args) throws Exception {
|
||||
String peerHost = args.length > 0 ? args[0] : null;
|
||||
int peerPort = args.length > 1 ? Integer.parseInt(args[1]) : NetworkParameters.prodNet().port;
|
||||
|
||||
boolean testNet = peerPort != NetworkParameters.prodNet().port;
|
||||
final NetworkParameters params = testNet ? NetworkParameters.testNet() : NetworkParameters.prodNet();
|
||||
String filePrefix = testNet ? "pingservice-testnet" : "pingservice-prodnet";
|
||||
|
||||
// Try to read the wallet from storage, create a new one if not possible.
|
||||
walletFile = new File(filePrefix + ".wallet");
|
||||
try {
|
||||
w = Wallet.loadFromFile(walletFile);
|
||||
} catch (IOException e) {
|
||||
w = new Wallet(params);
|
||||
w.keychain.add(new ECKey());
|
||||
w.saveToFile(walletFile);
|
||||
}
|
||||
final Wallet wallet = w;
|
||||
// Fetch the first key in the wallet (should be the only key).
|
||||
ECKey key = wallet.keychain.get(0);
|
||||
|
||||
System.out.println(wallet);
|
||||
|
||||
// Load the block chain, if there is one stored locally.
|
||||
System.out.println("Reading block store from disk");
|
||||
blockStore = new BoundedOverheadBlockStore(params, new File(filePrefix + ".blockchain"));
|
||||
|
||||
// Connect to the localhost node. One minute timeout since we won't try any other peers
|
||||
System.out.println("Connecting ...");
|
||||
chain = new BlockChain(params, wallet, blockStore);
|
||||
|
||||
peerGroup = new PeerGroup(params, chain);
|
||||
// Set some version info.
|
||||
peerGroup.setUserAgent("PingService", "1.0");
|
||||
// Download headers only until a day ago.
|
||||
peerGroup.setFastCatchupTimeSecs((new Date().getTime() / 1000) - (60 * 60 * 24));
|
||||
if (peerHost != null) {
|
||||
peerGroup.addAddress(new PeerAddress(InetAddress.getByName(peerHost), peerPort));
|
||||
} else {
|
||||
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
|
||||
}
|
||||
|
||||
peerGroup.addWallet(wallet);
|
||||
peerGroup.start();
|
||||
|
||||
peerGroup.addEventListener(new AbstractPeerEventListener() {
|
||||
@Override
|
||||
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) {
|
||||
super.onBlocksDownloaded(peer, block, blocksLeft);
|
||||
|
||||
// Don't bother printing during block chain downloads.
|
||||
if (blocksLeft > 0)
|
||||
return;
|
||||
|
||||
Set<Transaction> transactions = wallet.getTransactions(false, false);
|
||||
if (transactions.size() == 0) return;
|
||||
System.out.println("Confidences of wallet transactions:");
|
||||
for (Transaction tx : transactions) {
|
||||
System.out.println(tx);
|
||||
try {
|
||||
System.out.println(tx.getConfidence());
|
||||
if (tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||
System.out.println("Work done: " + tx.getConfidence().getWorkDone(chain).toString());
|
||||
} catch (BlockStoreException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 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);
|
||||
if (tx.isPending()) {
|
||||
// Broadcast, but we can't really verify it's valid until it appears in a block.
|
||||
BigInteger value = tx.getValueSentToMe(w);
|
||||
System.out.println("Received pending tx for " + Utils.bitcoinValueToFriendlyString(value) +
|
||||
": " + tx);
|
||||
System.out.println(tx.getConfidence());
|
||||
tx.getConfidence().addEventListener(new TransactionConfidence.Listener() {
|
||||
public void onConfidenceChanged(Transaction tx2) {
|
||||
if (tx2.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
|
||||
// Coins were confirmed.
|
||||
bounceCoins(tx2);
|
||||
tx2.getConfidence().removeEventListener(this);
|
||||
} else {
|
||||
System.out.println(String.format("Confidence of %s changed, is now: %s",
|
||||
tx2.getHashAsString(), tx2.getConfidence().toString()));
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
w.saveToFile(walletFile);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// Ignore for now, as we won't be allowed to spend until the tx is no longer pending. This is
|
||||
// something that should be fixed in future.
|
||||
return;
|
||||
} else {
|
||||
// We found the coins in a block directly, without it being broadcast first (catching up with
|
||||
// the chain), so just send them right back immediately.
|
||||
bounceCoins(tx);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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 PeerGroup thread keeps us alive until something kills the process.
|
||||
}
|
||||
|
||||
private void bounceCoins(Transaction tx) {
|
||||
// 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 {
|
||||
BigInteger value = tx.getValueSentToMe(w);
|
||||
TransactionInput input = tx.getInputs().get(0);
|
||||
Address from = input.getFromAddress();
|
||||
System.out.println("Received " + Utils.bitcoinValueToFriendlyString(value) + " from " + from.toString());
|
||||
// Now send the coins back!
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright 2011 John Sample.
|
||||
*
|
||||
* 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.NetworkConnection;
|
||||
import com.google.bitcoin.core.NetworkParameters;
|
||||
import com.google.bitcoin.core.TCPNetworkConnection;
|
||||
import com.google.bitcoin.discovery.DnsDiscovery;
|
||||
import com.google.bitcoin.discovery.IrcDiscovery;
|
||||
import com.google.bitcoin.discovery.PeerDiscoveryException;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Prints a list of IP addresses connected to the rendezvous point on the LFnet IRC channel.
|
||||
*/
|
||||
public class PrintPeers {
|
||||
private static InetSocketAddress[] dnsPeers, ircPeers;
|
||||
|
||||
private static void printElapsed(long start) {
|
||||
long now = System.currentTimeMillis();
|
||||
System.out.println(String.format("Took %.2f seconds", (now - start) / 1000.0));
|
||||
}
|
||||
|
||||
private static void printPeers(InetSocketAddress[] addresses) {
|
||||
for (InetSocketAddress address : addresses) {
|
||||
String hostAddress = address.getAddress().getHostAddress();
|
||||
System.out.println(String.format("%s:%d", hostAddress.toString(), address.getPort()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void printIRC() throws PeerDiscoveryException {
|
||||
long start = System.currentTimeMillis();
|
||||
IrcDiscovery d = new IrcDiscovery("#bitcoin") {
|
||||
@Override
|
||||
protected void onIRCReceive(String message) {
|
||||
System.out.println("<- " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onIRCSend(String message) {
|
||||
System.out.println("-> " + message);
|
||||
}
|
||||
};
|
||||
ircPeers = d.getPeers();
|
||||
printPeers(ircPeers);
|
||||
printElapsed(start);
|
||||
}
|
||||
|
||||
private static void printDNS() throws PeerDiscoveryException {
|
||||
long start = System.currentTimeMillis();
|
||||
DnsDiscovery dns = new DnsDiscovery(NetworkParameters.prodNet());
|
||||
dnsPeers = dns.getPeers();
|
||||
printPeers(dnsPeers);
|
||||
printElapsed(start);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("=== IRC ===");
|
||||
printIRC();
|
||||
System.out.println("=== DNS ===");
|
||||
printDNS();
|
||||
System.out.println("=== Version/chain heights ===");
|
||||
|
||||
ExecutorService pool = Executors.newFixedThreadPool(100);
|
||||
ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
|
||||
for (InetSocketAddress peer : dnsPeers) addrs.add(peer.getAddress());
|
||||
for (InetSocketAddress peer : ircPeers) addrs.add(peer.getAddress());
|
||||
System.out.println("Scanning " + addrs.size() + " peers:");
|
||||
|
||||
final Object lock = new Object();
|
||||
final long[] bestHeight = new long[1];
|
||||
|
||||
for (final InetAddress addr : addrs) {
|
||||
pool.submit(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
NetworkConnection conn = new TCPNetworkConnection(addr,
|
||||
NetworkParameters.prodNet(), 0, 1000);
|
||||
synchronized (lock) {
|
||||
long nodeHeight = conn.getVersionMessage().bestHeight;
|
||||
long diff = bestHeight[0] - nodeHeight;
|
||||
if (diff > 0) {
|
||||
System.out.println("Node is behind by " + diff + " blocks: " + addr.toString());
|
||||
} else {
|
||||
bestHeight[0] = nodeHeight;
|
||||
}
|
||||
}
|
||||
conn.shutdown();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
pool.awaitTermination(3600 * 24, TimeUnit.SECONDS); // 1 Day
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.MemoryBlockStore;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* This example shows how to solve the challenge Hal posted here:<p>
|
||||
*
|
||||
* <a href="http://www.bitcoin.org/smf/index.php?topic=3638.0">http://www.bitcoin.org/smf/index.php?topic=3638
|
||||
* .0</a><p>
|
||||
*
|
||||
* in which a private key with some coins associated with it is published. The goal is to import the private key,
|
||||
* claim the coins and then send them to a different address.
|
||||
*/
|
||||
public class PrivateKeys {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// TODO: Assumes production network not testnet. Make it selectable.
|
||||
NetworkParameters params = NetworkParameters.prodNet();
|
||||
try {
|
||||
// Decode the private key from Satoshis Base58 variant. If 51 characters long then it's from Bitcoins
|
||||
// dumpprivkey command and includes a version byte and checksum. Otherwise assume it's a raw key.
|
||||
ECKey key;
|
||||
if (args[0].length() == 51) {
|
||||
DumpedPrivateKey dumpedPrivateKey = new DumpedPrivateKey(params, args[0]);
|
||||
key = dumpedPrivateKey.getKey();
|
||||
} else {
|
||||
BigInteger privKey = Base58.decodeToBigInteger(args[0]);
|
||||
key = new ECKey(privKey);
|
||||
}
|
||||
System.out.println("Address from private key is: " + key.toAddress(params).toString());
|
||||
// And the address ...
|
||||
Address destination = new Address(params, args[1]);
|
||||
|
||||
// Import the private key to a fresh wallet.
|
||||
Wallet wallet = new Wallet(params);
|
||||
wallet.addKey(key);
|
||||
|
||||
// Find the transactions that involve those coins.
|
||||
final MemoryBlockStore blockStore = new MemoryBlockStore(params);
|
||||
BlockChain chain = new BlockChain(params, wallet, blockStore);
|
||||
|
||||
final PeerGroup peerGroup = new PeerGroup(params, chain);
|
||||
peerGroup.addAddress(new PeerAddress(InetAddress.getLocalHost()));
|
||||
peerGroup.start();
|
||||
peerGroup.downloadBlockChain();
|
||||
peerGroup.stop();
|
||||
|
||||
// And take them!
|
||||
System.out.println("Claiming " + Utils.bitcoinValueToFriendlyString(wallet.getBalance()) + " coins");
|
||||
wallet.sendCoins(peerGroup, destination, wallet.getBalance());
|
||||
// Wait a few seconds to let the packets flush out to the network (ugly).
|
||||
Thread.sleep(5000);
|
||||
System.exit(0);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println("First arg should be private key in Base58 format. Second argument should be address " +
|
||||
"to send to.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.BlockStore;
|
||||
import com.google.bitcoin.store.MemoryBlockStore;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* RefreshWallet loads a wallet, then processes the block chain to update the transaction pools within it.
|
||||
*/
|
||||
public class RefreshWallet {
|
||||
public static void main(String[] args) throws Exception {
|
||||
File file = new File(args[0]);
|
||||
Wallet wallet = Wallet.loadFromFile(file);
|
||||
System.out.println(wallet.toString());
|
||||
|
||||
// Set up the components and link them together.
|
||||
final NetworkParameters params = NetworkParameters.testNet();
|
||||
BlockStore blockStore = new MemoryBlockStore(params);
|
||||
BlockChain chain = new BlockChain(params, wallet, blockStore);
|
||||
|
||||
final PeerGroup peerGroup = new PeerGroup(params, chain);
|
||||
peerGroup.addAddress(new PeerAddress(InetAddress.getLocalHost()));
|
||||
peerGroup.start();
|
||||
|
||||
wallet.addEventListener(new AbstractWalletEventListener() {
|
||||
@Override
|
||||
public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
|
||||
System.out.println("\nReceived tx " + tx.getHashAsString());
|
||||
System.out.println(tx.toString());
|
||||
}
|
||||
});
|
||||
|
||||
// Now download and process the block chain.
|
||||
peerGroup.downloadBlockChain();
|
||||
peerGroup.stop();
|
||||
wallet.saveToFile(file);
|
||||
System.out.println("\nDone!\n");
|
||||
System.out.println(wallet.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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.toywallet;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.bitcoin.discovery.DnsDiscovery;
|
||||
import com.google.bitcoin.store.BoundedOverheadBlockStore;
|
||||
import com.google.bitcoin.utils.BriefLogFormatter;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A GUI demo that lets you watch received transactions as they accumulate confidence.
|
||||
*/
|
||||
public class ToyWallet {
|
||||
private final TxListModel txListModel = new TxListModel();
|
||||
private JList txList;
|
||||
private NetworkParameters params;
|
||||
private Wallet wallet;
|
||||
private PeerGroup peerGroup;
|
||||
private BlockChain chain;
|
||||
private JLabel networkStats;
|
||||
private File walletFile;
|
||||
private JScrollPane txScrollPane;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
BriefLogFormatter.init();
|
||||
new ToyWallet(false, args);
|
||||
}
|
||||
|
||||
public ToyWallet(boolean testnet, String[] args) throws Exception {
|
||||
// Set up a Bitcoin connection + empty wallet. TODO: Simplify the setup for this use case.
|
||||
if (testnet) {
|
||||
params = NetworkParameters.testNet();
|
||||
} else {
|
||||
params = NetworkParameters.prodNet();
|
||||
}
|
||||
|
||||
// Try to read the wallet from storage, create a new one if not possible.
|
||||
boolean freshWallet = false;
|
||||
walletFile = new File("toy.wallet");
|
||||
try {
|
||||
wallet = Wallet.loadFromFile(walletFile);
|
||||
} catch (IOException e) {
|
||||
wallet = new Wallet(params);
|
||||
|
||||
// Allow user to specify the first key on the command line as:
|
||||
// hex-encoded-key:creation-time-seconds
|
||||
ECKey key;
|
||||
if (args.length > 0) {
|
||||
try {
|
||||
String[] parts = args[0].split(":");
|
||||
byte[] pubKey = Hex.decode(parts[0]);
|
||||
key = new ECKey(null, pubKey);
|
||||
long creationTimeSeconds = Long.parseLong(parts[1]);
|
||||
key.setCreationTimeSeconds(creationTimeSeconds);
|
||||
System.out.println(String.format("Using address from command line %s, created on %s",
|
||||
key.toAddress(params).toString(), new Date(creationTimeSeconds*1000).toString()));
|
||||
} catch (Exception e2) {
|
||||
System.err.println("Could not understand argument. Try a hex encoded pub key with a creation " +
|
||||
"time in seconds appended with a colon in between: " + e2.toString());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
key = new ECKey(); // Generate a fresh key.
|
||||
}
|
||||
wallet.keychain.add(key);
|
||||
|
||||
wallet.saveToFile(walletFile);
|
||||
freshWallet = true;
|
||||
}
|
||||
System.out.println("Send to: " + wallet.keychain.get(0).toAddress(params));
|
||||
System.out.println(wallet);
|
||||
|
||||
File blockChainFile = new File("toy.blockchain");
|
||||
if (!blockChainFile.exists() && !freshWallet) {
|
||||
// No block chain, but we had a wallet. So empty out the transactions in the wallet so when we rescan
|
||||
// the blocks there are no problems (wallets don't support replays without being emptied).
|
||||
wallet.clearTransactions(0);
|
||||
}
|
||||
chain = new BlockChain(params, wallet, new BoundedOverheadBlockStore(params, blockChainFile));
|
||||
|
||||
peerGroup = new PeerGroup(params, chain);
|
||||
peerGroup.setUserAgent("ToyWallet", "1.0");
|
||||
if (testnet) {
|
||||
peerGroup.addAddress(new PeerAddress(InetAddress.getByName("plan99.net"), 18333));
|
||||
peerGroup.addAddress(new PeerAddress(InetAddress.getByName("localhost"), 18333));
|
||||
} else {
|
||||
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
|
||||
}
|
||||
peerGroup.addWallet(wallet);
|
||||
peerGroup.setFastCatchupTimeSecs(wallet.getEarliestKeyCreationTime());
|
||||
|
||||
// Watch for peers coming and going so we can update the UI.
|
||||
peerGroup.addEventListener(new AbstractPeerEventListener() {
|
||||
@Override
|
||||
public void onPeerConnected(Peer peer, int peerCount) {
|
||||
super.onPeerConnected(peer, peerCount);
|
||||
triggerNetworkStatsUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPeerDisconnected(Peer peer, int peerCount) {
|
||||
super.onPeerDisconnected(peer, peerCount);
|
||||
triggerNetworkStatsUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) {
|
||||
super.onBlocksDownloaded(peer, block, blocksLeft);
|
||||
triggerNetworkStatsUpdate();
|
||||
handleNewBlock();
|
||||
}
|
||||
});
|
||||
|
||||
wallet.addEventListener(new AbstractWalletEventListener() {
|
||||
@Override
|
||||
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
|
||||
super.onCoinsReceived(wallet, tx, prevBalance, newBalance);
|
||||
handleNewTransaction(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
|
||||
super.onCoinsSent(wallet, tx, prevBalance, newBalance);
|
||||
handleNewTransaction(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange() {
|
||||
try {
|
||||
System.out.println("Wallet changed");
|
||||
wallet.saveToFile(walletFile);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create the GUI.
|
||||
JFrame window = new JFrame("Toy wallet");
|
||||
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setupWindow(window);
|
||||
window.pack();
|
||||
window.setSize(640, 480);
|
||||
|
||||
// Put the transactions stored in the wallet, into the GUI.
|
||||
final Set<Transaction> walletTransactions = wallet.getTransactions(true, true);
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
for (final Transaction tx : walletTransactions) {
|
||||
txListModel.monitorTx(tx);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Go!
|
||||
window.setVisible(true);
|
||||
peerGroup.start();
|
||||
peerGroup.downloadBlockChain();
|
||||
}
|
||||
|
||||
private void handleNewBlock() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
txListModel.newBlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleNewTransaction(final Transaction t) {
|
||||
// Running on a peer thread, switch to Swing thread before adding and updating the UI.
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
txListModel.monitorTx(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void triggerNetworkStatsUpdate() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
int numPeers = peerGroup.numConnectedPeers();
|
||||
StoredBlock chainHead = chain.getChainHead();
|
||||
String date = chainHead.getHeader().getTime().toString();
|
||||
String plural = numPeers > 1 ? "peers" : "peer";
|
||||
String status = String.format("%d %s connected. %d blocks: %s",
|
||||
numPeers, plural, chainHead.getHeight(), date);
|
||||
networkStats.setText(status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupWindow(JFrame window) {
|
||||
JLabel instructions = new JLabel(
|
||||
"<html>Broadcast transactions appear below. Watch them gain confidence.<br>" +
|
||||
"Send coins to: <b>" + wallet.keychain.get(0).toAddress(params) + "</b>");
|
||||
window.getContentPane().add(instructions, BorderLayout.NORTH);
|
||||
|
||||
// The list of transactions.
|
||||
txList = new JList(txListModel);
|
||||
txList.setCellRenderer(new TxListLabel());
|
||||
txList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
txList.setLayoutOrientation(JList.VERTICAL);
|
||||
txScrollPane = new JScrollPane(txList);
|
||||
window.getContentPane().add(txScrollPane, BorderLayout.CENTER);
|
||||
|
||||
networkStats = new JLabel("Connecting to the Bitcoin network ...");
|
||||
window.getContentPane().add(networkStats, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
// Object that manages the contents of the list view.
|
||||
private class TxListModel extends AbstractListModel {
|
||||
private List<Transaction> transactions = new ArrayList<Transaction>();
|
||||
|
||||
public void monitorTx(Transaction tx) {
|
||||
assert SwingUtilities.isEventDispatchThread();
|
||||
transactions.add(tx);
|
||||
// Set up a tx confidence change event listener, so we know when to update the list.
|
||||
tx.getConfidence().addEventListener(new TransactionConfidence.Listener() {
|
||||
public void onConfidenceChanged(Transaction tx) {
|
||||
// Note that this does NOT get called for every block that is received, just when we transition
|
||||
// between confidence states.
|
||||
int txIndex = transactions.indexOf(tx);
|
||||
fireContentsChanged(this, txIndex, txIndex);
|
||||
}
|
||||
});
|
||||
fireIntervalAdded(this, transactions.size() - 1, transactions.size() - 1);
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return transactions.size();
|
||||
}
|
||||
|
||||
public Object getElementAt(int i) {
|
||||
Transaction tx = transactions.get(i);
|
||||
return tx.toString() + "\n" + tx.getConfidence().toString();
|
||||
}
|
||||
|
||||
public void newBlock() {
|
||||
fireContentsChanged(this, 0, getSize() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private class TxListLabel extends JLabel implements ListCellRenderer {
|
||||
public Component getListCellRendererComponent(JList list, Object contents,
|
||||
int index, boolean isSelected,
|
||||
boolean cellHasFocus) {
|
||||
String value = (String) contents;
|
||||
final String key = wallet.keychain.get(0).toAddress(params).toString();
|
||||
value = "<html>" + value.replaceAll("\n", "<br>").replaceAll("<br> ", "<br> ")
|
||||
.replaceAll(key, "<i>" + key + "</i>");
|
||||
setText(value);
|
||||
setOpaque(true);
|
||||
setBackground(index % 2 == 1 ? new Color(230, 230, 230) : Color.WHITE);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user