mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-19 05:33:44 +01:00
Switch to using SLF4J + the simple logger, allowing people to integrate BitCoinJ with whatever logging system they
are already using. Resolves issue 16.
This commit is contained in:
parent
a32a612630
commit
068dcba122
BIN
lib/slf4j-api-1.6.1.jar
Normal file
BIN
lib/slf4j-api-1.6.1.jar
Normal file
Binary file not shown.
BIN
lib/slf4j-simple-1.6.1.jar
Normal file
BIN
lib/slf4j-simple-1.6.1.jar
Normal file
Binary file not shown.
@ -22,6 +22,9 @@ import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.*;
|
||||
|
||||
/**
|
||||
@ -33,6 +36,7 @@ import static com.google.bitcoin.core.Utils.*;
|
||||
* or request one specifically using {@link Peer#getBlock(byte[])}, or grab one from a downloaded {@link BlockChain}.
|
||||
*/
|
||||
public class Block extends Message {
|
||||
private static final Logger log = LoggerFactory.getLogger(Block.class);
|
||||
private static final long serialVersionUID = 2738848929966035281L;
|
||||
|
||||
/** How many bytes are required to represent a block header. */
|
||||
@ -263,8 +267,8 @@ public class Block extends Message {
|
||||
List<byte[]> tree = buildMerkleTree();
|
||||
byte[] calculatedRoot = tree.get(tree.size() - 1);
|
||||
if (!Arrays.equals(calculatedRoot, merkleRoot)) {
|
||||
LOG("Merkle tree did not verify: ");
|
||||
for (byte[] b : tree) LOG(Utils.bytesToHexString(b));
|
||||
log.error("Merkle tree did not verify: ");
|
||||
for (byte[] b : tree) log.error(Utils.bytesToHexString(b));
|
||||
|
||||
throw new VerificationException("Merkle hashes do not match: " +
|
||||
bytesToHexString(calculatedRoot) + " vs " + bytesToHexString(merkleRoot));
|
||||
|
@ -19,7 +19,8 @@ package com.google.bitcoin.core;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.LOG;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A BlockChain holds a series of {@link Block} objects, links them together, and knows how to verify that the
|
||||
@ -46,6 +47,8 @@ import static com.google.bitcoin.core.Utils.LOG;
|
||||
* or if we connect to a peer that doesn't send us blocks in order.
|
||||
*/
|
||||
public class BlockChain {
|
||||
private static final Logger log = LoggerFactory.getLogger(BlockChain.class);
|
||||
|
||||
/** Keeps a map of block hashes to StoredBlocks. */
|
||||
protected BlockStore blockStore;
|
||||
|
||||
@ -78,7 +81,7 @@ public class BlockChain {
|
||||
try {
|
||||
this.blockStore = blockStore;
|
||||
chainHead = blockStore.getChainHead();
|
||||
LOG("chain head is: " + chainHead.getHeader().toString());
|
||||
log.info("chain head is:\n{}", chainHead.getHeader());
|
||||
} catch (BlockStoreException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -103,9 +106,9 @@ public class BlockChain {
|
||||
|
||||
private synchronized boolean add(Block block, boolean tryConnecting)
|
||||
throws BlockStoreException, VerificationException, ScriptException {
|
||||
LOG("Adding block " + block.getHashAsString() + " to the chain");
|
||||
log.info("Adding block " + block.getHashAsString() + " to the chain");
|
||||
if (blockStore.get(block.getHash()) != null) {
|
||||
LOG("Already have block");
|
||||
log.info("Already have block");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -113,8 +116,8 @@ public class BlockChain {
|
||||
try {
|
||||
block.verify();
|
||||
} catch (VerificationException e) {
|
||||
LOG("Failed to verify block: " + e.toString());
|
||||
LOG(block.toString());
|
||||
log.error("Failed to verify block:", e);
|
||||
log.error(block.toString());
|
||||
throw e;
|
||||
}
|
||||
|
||||
@ -125,7 +128,7 @@ public class BlockChain {
|
||||
// We can't find the previous block. Probably we are still in the process of downloading the chain and a
|
||||
// block was solved whilst we were doing it. We put it to one side and try to connect it later when we
|
||||
// have more blocks.
|
||||
LOG("Block does not connect: " + block.getHashAsString());
|
||||
log.warn("Block does not connect: {}", block.getHashAsString());
|
||||
unconnectedBlocks.add(block);
|
||||
return false;
|
||||
} else {
|
||||
@ -152,7 +155,7 @@ public class BlockChain {
|
||||
if (storedPrev.equals(chainHead)) {
|
||||
// This block connects to the best known block, it is a normal continuation of the system.
|
||||
setChainHead(newStoredBlock);
|
||||
LOG("Chain is now " + chainHead.getHeight() + " blocks high");
|
||||
log.info("Chain is now {} blocks high", chainHead.getHeight());
|
||||
if (newTransactions != null)
|
||||
sendTransactionsToWallet(newStoredBlock, NewBlockType.BEST_CHAIN, newTransactions);
|
||||
} else {
|
||||
@ -162,9 +165,9 @@ public class BlockChain {
|
||||
// to become the new best chain head. This simplifies handling of the re-org in the Wallet class.
|
||||
boolean causedSplit = newStoredBlock.moreWorkThan(chainHead);
|
||||
if (causedSplit) {
|
||||
LOG("Block is causing a re-organize");
|
||||
log.info("Block is causing a re-organize");
|
||||
} else {
|
||||
LOG("Block forks the chain, but it did not cause a reorganize.");
|
||||
log.info("Block forks the chain, but it did not cause a reorganize.");
|
||||
}
|
||||
|
||||
// We may not have any transactions if we received only a header. That never happens today but will in
|
||||
@ -187,10 +190,10 @@ public class BlockChain {
|
||||
// Firstly, calculate the block at which the chain diverged. We only need to examine the
|
||||
// chain from beyond this block to find differences.
|
||||
StoredBlock splitPoint = findSplit(newChainHead, chainHead);
|
||||
LOG("Re-organize after split at height " + splitPoint.getHeight());
|
||||
LOG("Old chain head: " + chainHead.getHeader().getHashAsString());
|
||||
LOG("New chain head: " + newChainHead.getHeader().getHashAsString());
|
||||
LOG("Split at block: " + splitPoint.getHeader().getHashAsString());
|
||||
log.info("Re-organize after split at height {}", splitPoint.getHeight());
|
||||
log.info("Old chain head: {}", chainHead.getHeader().getHashAsString());
|
||||
log.info("New chain head: {}", newChainHead.getHeader().getHashAsString());
|
||||
log.info("Split at block: {}", splitPoint.getHeader().getHashAsString());
|
||||
// Then build a list of all blocks in the old part of the chain and the new part.
|
||||
Set<StoredBlock> oldBlocks = getPartialChain(chainHead, splitPoint);
|
||||
Set<StoredBlock> newBlocks = getPartialChain(newChainHead, splitPoint);
|
||||
@ -267,7 +270,7 @@ public class BlockChain {
|
||||
} catch (ScriptException e) {
|
||||
// We don't want scripts we don't understand to break the block chain,
|
||||
// so just note that this tx was not scanned here and continue.
|
||||
LOG("Failed to parse a script: " + e.toString());
|
||||
log.warn("Failed to parse a script: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -307,7 +310,7 @@ public class BlockChain {
|
||||
blocksConnectedThisRound++;
|
||||
}
|
||||
if (blocksConnectedThisRound > 0) {
|
||||
LOG("Connected " + blocksConnectedThisRound + " floating blocks.");
|
||||
log.info("Connected {} floating blocks.", blocksConnectedThisRound);
|
||||
}
|
||||
} while (blocksConnectedThisRound > 0);
|
||||
}
|
||||
@ -353,7 +356,7 @@ public class BlockChain {
|
||||
newDifficulty = newDifficulty.divide(BigInteger.valueOf(params.targetTimespan));
|
||||
|
||||
if (newDifficulty.compareTo(params.proofOfWorkLimit) > 0) {
|
||||
LOG("Difficulty hit proof of work limit: " + newDifficulty.toString(16));
|
||||
log.warn("Difficulty hit proof of work limit: {}", newDifficulty.toString(16));
|
||||
newDifficulty = params.proofOfWorkLimit;
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,16 @@ import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.LOG;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Stores the block chain to disk but still holds it in memory. This is intended for desktop apps and tests.
|
||||
* Constrained environments like mobile phones probably won't want to or be able to store all the block headers in RAM.
|
||||
*/
|
||||
public class DiskBlockStore implements BlockStore {
|
||||
private static final Logger log = LoggerFactory.getLogger(DiskBlockStore.class);
|
||||
|
||||
private FileOutputStream stream;
|
||||
private Map<Sha256Hash, StoredBlock> blockMap;
|
||||
private Sha256Hash chainHead;
|
||||
@ -40,7 +43,7 @@ public class DiskBlockStore implements BlockStore {
|
||||
load(file);
|
||||
stream = new FileOutputStream(file, true); // Do append.
|
||||
} catch (IOException e) {
|
||||
LOG(e.toString());
|
||||
log.error("failed to load block store from file", e);
|
||||
createNewStore(params, file);
|
||||
}
|
||||
}
|
||||
@ -70,7 +73,7 @@ public class DiskBlockStore implements BlockStore {
|
||||
}
|
||||
|
||||
private void load(File file) throws IOException, BlockStoreException {
|
||||
LOG("Reading block store from " + file.getAbsolutePath());
|
||||
log.info("Reading block store from {}", file);
|
||||
InputStream input = new BufferedInputStream(new FileInputStream(file));
|
||||
// Read a version byte.
|
||||
int version = input.read();
|
||||
@ -85,7 +88,7 @@ public class DiskBlockStore implements BlockStore {
|
||||
byte[] chainHeadHash = new byte[32];
|
||||
input.read(chainHeadHash);
|
||||
this.chainHead = new Sha256Hash(chainHeadHash);
|
||||
LOG("Read chain head from disk: " + this.chainHead);
|
||||
log.info("Read chain head from disk: {}", this.chainHead);
|
||||
long now = System.currentTimeMillis();
|
||||
// Rest of file is raw block headers.
|
||||
byte[] headerBytes = new byte[Block.HEADER_SIZE];
|
||||
@ -126,7 +129,7 @@ public class DiskBlockStore implements BlockStore {
|
||||
throw new BlockStoreException(e);
|
||||
}
|
||||
long elapsed = System.currentTimeMillis() - now;
|
||||
LOG("Block chain read complete in " + elapsed + "ms");
|
||||
log.info("Block chain read complete in {}ms", elapsed);
|
||||
}
|
||||
|
||||
public synchronized void put(StoredBlock block) throws BlockStoreException {
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
package com.google.bitcoin.core;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@ -31,6 +34,8 @@ import java.util.Vector;
|
||||
* However, if all hosts passed fail to resolve a PeerDiscoveryException will be thrown during getPeers().
|
||||
*/
|
||||
public class DnsDiscovery implements PeerDiscovery {
|
||||
private static final Logger log = LoggerFactory.getLogger(DnsDiscovery.class);
|
||||
|
||||
private String[] hostNames;
|
||||
private NetworkParameters netParams;
|
||||
private static final String[] defaultHosts = new String[] {"bitseed.xf2.org","bitseed.bitcoin.org.uk"};
|
||||
@ -83,7 +88,7 @@ public class DnsDiscovery implements PeerDiscovery {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failedLookups++;
|
||||
Utils.LOG("DNS lookup for " + hostName + " failed.");
|
||||
log.info("DNS lookup for " + hostName + " failed.");
|
||||
|
||||
if (failedLookups == hostNames.length) {
|
||||
// All the lookups failed.
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
package com.google.bitcoin.core;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
@ -24,6 +27,8 @@ import java.util.*;
|
||||
* IrcDiscovery provides a way to find network peers by joining a pre-agreed rendevouz point on the LFnet IRC network.
|
||||
*/
|
||||
public class IrcDiscovery implements PeerDiscovery {
|
||||
private static final Logger log = LoggerFactory.getLogger(IrcDiscovery.class);
|
||||
|
||||
private String channel;
|
||||
private int port = 6667;
|
||||
private String server;
|
||||
@ -157,7 +162,7 @@ public class IrcDiscovery implements PeerDiscovery {
|
||||
// decodeChecked removes the checksum from the returned bytes.
|
||||
addressBytes = Base58.decodeChecked(user.substring(1));
|
||||
} catch (AddressFormatException e) {
|
||||
Utils.LOG("IRC nick does not parse as base58: " + user);
|
||||
log.warn("IRC nick does not parse as base58: " + user);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,9 @@ import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.Date;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.*;
|
||||
|
||||
/**
|
||||
@ -36,6 +39,8 @@ import static com.google.bitcoin.core.Utils.*;
|
||||
* Construction is blocking whilst the protocol version is negotiated.
|
||||
*/
|
||||
public class NetworkConnection {
|
||||
private static final Logger log = LoggerFactory.getLogger(NetworkConnection.class);
|
||||
|
||||
static final int COMMAND_LEN = 12;
|
||||
|
||||
// Message strings.
|
||||
@ -94,9 +99,13 @@ public class NetworkConnection {
|
||||
readMessage();
|
||||
// Switch to the new protocol version.
|
||||
int peerVersion = versionMessage.clientVersion;
|
||||
LOG(String.format("Connected to peer: version=%d, subVer='%s', services=0x%x, time=%s, blocks=%d",
|
||||
peerVersion, versionMessage.subVer,
|
||||
versionMessage.localServices, new Date(versionMessage.time * 1000).toString(), versionMessage.bestHeight));
|
||||
log.info("Connected to peer: version={}, subVer='{}', services=0x{}, time={}, blocks={}", new Object[] {
|
||||
peerVersion,
|
||||
versionMessage.subVer,
|
||||
versionMessage.localServices,
|
||||
new Date(versionMessage.time * 1000),
|
||||
versionMessage.bestHeight
|
||||
});
|
||||
// BitCoinJ is a client mode implementation. That means there's not much point in us talking to other client
|
||||
// mode nodes because we can't download the data from them we need to find/verify transactions.
|
||||
if (!versionMessage.hasBlockChain())
|
||||
@ -240,8 +249,11 @@ public class NetworkConnection {
|
||||
}
|
||||
}
|
||||
|
||||
if (PROTOCOL_LOG)
|
||||
LOG("Received " + size + " byte '" + command + "' message: " + Utils.bytesToHexString(payloadBytes));
|
||||
log.debug("Received {} byte '{}' message: {}", new Object[]{
|
||||
size,
|
||||
command,
|
||||
Utils.bytesToHexString(payloadBytes)
|
||||
});
|
||||
|
||||
try {
|
||||
Message message;
|
||||
@ -283,8 +295,7 @@ public class NetworkConnection {
|
||||
System.arraycopy(hash, 0, header, 4 + COMMAND_LEN + 4, 4);
|
||||
}
|
||||
|
||||
if (PROTOCOL_LOG)
|
||||
LOG("Sending " + name + " message: " + bytesToHexString(payload));
|
||||
log.debug("Sending {} message: {}", name, bytesToHexString(payload));
|
||||
|
||||
// Another writeMessage call may be running concurrently.
|
||||
synchronized (out) {
|
||||
|
@ -23,7 +23,8 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.LOG;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A Peer handles the high level communication with a BitCoin node. It requires a NetworkConnection to be set up for
|
||||
@ -31,6 +32,8 @@ import static com.google.bitcoin.core.Utils.LOG;
|
||||
* with the network. All these threads synchronize on the block chain.
|
||||
*/
|
||||
public class Peer {
|
||||
private static final Logger log = LoggerFactory.getLogger(Peer.class);
|
||||
|
||||
private final NetworkConnection conn;
|
||||
private final NetworkParameters params;
|
||||
private Thread thread;
|
||||
@ -88,13 +91,13 @@ public class Peer {
|
||||
// properly explore the network.
|
||||
} else {
|
||||
// TODO: Handle the other messages we can receive.
|
||||
LOG("Received unhandled message: " + m.toString());
|
||||
log.warn("Received unhandled message: {}", m);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof IOException && !running) {
|
||||
// This exception was expected because we are tearing down the socket as part of quitting.
|
||||
LOG("Shutting down peer thread");
|
||||
log.info("Shutting down peer thread");
|
||||
} else {
|
||||
// We caught an unexpected exception.
|
||||
e.printStackTrace();
|
||||
@ -144,12 +147,10 @@ public class Peer {
|
||||
}
|
||||
} catch (VerificationException e) {
|
||||
// We don't want verification failures to kill the thread.
|
||||
LOG(e.toString());
|
||||
e.printStackTrace();
|
||||
log.warn("block verification failed", e);
|
||||
} catch (ScriptException e) {
|
||||
// We don't want script failures to kill the thread.
|
||||
LOG(e.toString());
|
||||
e.printStackTrace();
|
||||
log.warn("script exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,7 +298,7 @@ public class Peer {
|
||||
//
|
||||
// So this is a complicated process but it has the advantage that we can download a chain of enormous length
|
||||
// in a relatively stateless manner and with constant/bounded memory usage.
|
||||
LOG("Peer.blockChainDownload: " + Utils.bytesToHexString(toHash));
|
||||
log.info("blockChainDownload({})", Utils.bytesToHexString(toHash));
|
||||
|
||||
// TODO: Block locators should be abstracted out rather than special cased here.
|
||||
List<byte[]> blockLocator = new LinkedList<byte[]>();
|
||||
|
@ -26,7 +26,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.LOG;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.bytesToHexString;
|
||||
|
||||
/**
|
||||
@ -38,6 +40,8 @@ import static com.google.bitcoin.core.Utils.bytesToHexString;
|
||||
* transactions generated by the official client, but non-standard transactions will fail.
|
||||
*/
|
||||
public class Script {
|
||||
private static Logger log = LoggerFactory.getLogger(Script.class);
|
||||
|
||||
// Some constants used for decoding the scripts.
|
||||
public static final int OP_PUSHDATA1 = 76;
|
||||
public static final int OP_PUSHDATA2 = 77;
|
||||
@ -171,7 +175,7 @@ public class Script {
|
||||
chunks.add(getData(len));
|
||||
} else if (opcode == OP_PUSHDATA4) {
|
||||
// Read a uint32, then read that many bytes of data.
|
||||
LOG("PUSHDATA4: Unimplemented");
|
||||
log.error("PUSHDATA4: Unimplemented");
|
||||
} else {
|
||||
chunks.add(new byte[] { (byte) opcode });
|
||||
}
|
||||
@ -260,11 +264,11 @@ public class Script {
|
||||
case OP_EQUALVERIFY: opEqualVerify(); break;
|
||||
case OP_CHECKSIG: opCheckSig(context); break;
|
||||
default:
|
||||
if (tracing) LOG("Unknown/unimplemented opcode: " + opcode);
|
||||
log.debug("Unknown/unimplemented opcode: {}", opcode);
|
||||
}
|
||||
} else {
|
||||
// Data block, push it onto the stack.
|
||||
if (tracing) LOG("Push " + Utils.bytesToHexString(chunk));
|
||||
log.debug("Push {}", Utils.bytesToHexString(chunk));
|
||||
stack.add(chunk);
|
||||
}
|
||||
}
|
||||
@ -276,7 +280,7 @@ public class Script {
|
||||
|
||||
void logStack() {
|
||||
for (int i = 0; i < stack.size(); i++) {
|
||||
LOG("Stack[" + i + "]: " + Utils.bytesToHexString(stack.get(i)));
|
||||
log.debug("Stack[{}]: {}",i , Utils.bytesToHexString(stack.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,7 +309,7 @@ public class Script {
|
||||
byte[] sig = new byte[sigAndHashType.length - 1];
|
||||
System.arraycopy(sigAndHashType, 0, sig, 0, sig.length);
|
||||
|
||||
if (tracing) LOG("CHECKSIG: hashtype=" + sigHash.toString() + " anyoneCanPay=" + anyoneCanPay);
|
||||
log.debug("CHECKSIG: hashtype={} anyoneCanPay={}", sigHash, anyoneCanPay);
|
||||
if (context == null) {
|
||||
// TODO: Fix the unit tests to run scripts in transaction context then remove this.
|
||||
pushBool(true);
|
||||
@ -327,7 +331,7 @@ public class Script {
|
||||
}
|
||||
|
||||
private void opEqualVerify() throws ScriptException {
|
||||
if (tracing) LOG("EQUALVERIFY");
|
||||
log.debug("EQUALVERIFY");
|
||||
byte[] a = stack.pop();
|
||||
byte[] b = stack.pop();
|
||||
if (!Arrays.areEqual(a, b))
|
||||
@ -340,12 +344,12 @@ public class Script {
|
||||
byte[] buf = stack.pop();
|
||||
byte[] hash = Utils.sha256hash160(buf);
|
||||
stack.add(hash);
|
||||
if (tracing) LOG("HASH160: output is " + Utils.bytesToHexString(hash));
|
||||
log.debug("HASH160: output is {}", Utils.bytesToHexString(hash));
|
||||
}
|
||||
|
||||
/** Duplicates the top item on the stack */
|
||||
private void opDup() {
|
||||
if (tracing) LOG("DUP");
|
||||
log.debug("DUP");
|
||||
stack.add(Arrays.clone(stack.lastElement()));
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,9 @@ import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.*;
|
||||
|
||||
/**
|
||||
@ -35,6 +38,7 @@ import static com.google.bitcoin.core.Utils.*;
|
||||
* or UI purposes.
|
||||
*/
|
||||
public class Transaction extends Message implements Serializable {
|
||||
private static final Logger log = LoggerFactory.getLogger(Transaction.class);
|
||||
private static final long serialVersionUID = -8567546957352643140L;
|
||||
|
||||
// These are serialized in both bitcoin and java serialization.
|
||||
@ -319,7 +323,7 @@ public class Transaction extends Message implements Serializable {
|
||||
// The anyoneCanPay feature isn't used at the moment.
|
||||
boolean anyoneCanPay = false;
|
||||
byte[] hash = hashTransactionForSignature(hashType, anyoneCanPay);
|
||||
Utils.LOG(" signInputs hash=" + Utils.bytesToHexString(hash));
|
||||
log.info(" signInputs hash={}", Utils.bytesToHexString(hash));
|
||||
// Set the script to empty again for the next input.
|
||||
input.scriptBytes = TransactionInput.EMPTY_ARRAY;
|
||||
|
||||
|
@ -51,12 +51,6 @@ public class Utils {
|
||||
*/
|
||||
public static final BigInteger CENT = new BigInteger("1000000", 10);
|
||||
|
||||
private static final boolean logging;
|
||||
|
||||
static {
|
||||
logging = Boolean.parseBoolean(System.getProperty("bitcoinj.logging", "false"));
|
||||
}
|
||||
|
||||
/** Convert an amount expressed in the way humans are used to into nanocoins. */
|
||||
public static BigInteger toNanoCoins(int coins, int cents) {
|
||||
assert cents < 100;
|
||||
@ -195,16 +189,6 @@ public class Utils {
|
||||
return ((bytes[offset] & 0xff) << 8) | bytes[offset + 1] & 0xff;
|
||||
}
|
||||
|
||||
static void LOG(String msg) {
|
||||
// Set this to true to see debug prints from the library.
|
||||
if (logging) {
|
||||
System.err.print("BitCoin: ");
|
||||
System.err.println(msg);
|
||||
System.err.flush();
|
||||
System.out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates RIPEMD160(SHA256(input)). This is used in Address calculations.
|
||||
*/
|
||||
|
@ -16,11 +16,13 @@
|
||||
|
||||
package com.google.bitcoin.core;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.bitcoin.core.Utils.LOG;
|
||||
import static com.google.bitcoin.core.Utils.bitcoinValueToFriendlyString;
|
||||
|
||||
/**
|
||||
@ -33,6 +35,7 @@ import static com.google.bitcoin.core.Utils.bitcoinValueToFriendlyString;
|
||||
* pull in a potentially large (code-size) third party serialization library.<p>
|
||||
*/
|
||||
public class Wallet implements Serializable {
|
||||
private static final Logger log = LoggerFactory.getLogger(Wallet.class);
|
||||
private static final long serialVersionUID = 2L;
|
||||
|
||||
// Algorithm for movement of transactions between pools. Outbound tx = us spending coins. Inbound tx = us
|
||||
@ -203,14 +206,14 @@ public class Wallet implements Serializable {
|
||||
BigInteger valueSentToMe = tx.getValueSentToMe(this);
|
||||
BigInteger valueDifference = valueSentToMe.subtract(valueSentFromMe);
|
||||
|
||||
LOG("Wallet: Received tx" + (sideChain ? " on a side chain" :"") + " for " +
|
||||
log.info("Wallet: Received tx" + (sideChain ? " on a side chain" :"") + " for " +
|
||||
bitcoinValueToFriendlyString(valueDifference) + " BTC");
|
||||
|
||||
// If this transaction is already in the wallet we may need to move it into a different pool. At the very
|
||||
// least we need to ensure we're manipulating the canonical object rather than a duplicate.
|
||||
Transaction wtx = null;
|
||||
if ((wtx = pending.remove(txHash)) != null) {
|
||||
LOG(" <-pending");
|
||||
log.info(" <-pending");
|
||||
// A transaction we created appeared in a block. Probably this is a spend we broadcast that has been
|
||||
// accepted by the network.
|
||||
//
|
||||
@ -219,19 +222,19 @@ public class Wallet implements Serializable {
|
||||
if (bestChain) {
|
||||
if (valueSentToMe.equals(BigInteger.ZERO)) {
|
||||
// There were no change transactions so this tx is fully spent.
|
||||
LOG(" ->spent");
|
||||
log.info(" ->spent");
|
||||
boolean alreadyPresent = spent.put(wtx.getHash(), wtx) != null;
|
||||
assert !alreadyPresent : "TX in both pending and spent pools";
|
||||
} else {
|
||||
// There was change back to us, or this tx was purely a spend back to ourselves (perhaps for
|
||||
// anonymization purposes).
|
||||
LOG(" ->unspent");
|
||||
log.info(" ->unspent");
|
||||
boolean alreadyPresent = unspent.put(wtx.getHash(), wtx) != null;
|
||||
assert !alreadyPresent : "TX in both pending and unspent pools";
|
||||
}
|
||||
} else if (sideChain) {
|
||||
// The transaction was accepted on an inactive side chain, but not yet by the best chain.
|
||||
LOG(" ->inactive");
|
||||
log.info(" ->inactive");
|
||||
// It's OK for this to already be in the inactive pool because there can be multiple independent side
|
||||
// chains in which it appears:
|
||||
//
|
||||
@ -240,7 +243,7 @@ public class Wallet implements Serializable {
|
||||
// \-> b4 (at this point it's already present in 'inactive'
|
||||
boolean alreadyPresent = inactive.put(wtx.getHash(), wtx) != null;
|
||||
if (alreadyPresent)
|
||||
LOG("Saw a transaction be incorporated into multiple independent side chains");
|
||||
log.info("Saw a transaction be incorporated into multiple independent side chains");
|
||||
// Put it back into the pending pool, because 'pending' means 'waiting to be included in best chain'.
|
||||
pending.put(wtx.getHash(), wtx);
|
||||
}
|
||||
@ -250,14 +253,14 @@ public class Wallet implements Serializable {
|
||||
// This TX didn't originate with us. It could be sending us coins and also spending our own coins if keys
|
||||
// are being shared between different wallets.
|
||||
if (sideChain) {
|
||||
LOG(" ->inactive");
|
||||
log.info(" ->inactive");
|
||||
inactive.put(tx.getHash(), tx);
|
||||
} else if (bestChain) {
|
||||
processTxFromBestChain(tx);
|
||||
}
|
||||
}
|
||||
|
||||
LOG("Balance is now: " + bitcoinValueToFriendlyString(getBalance()));
|
||||
log.info("Balance is now: " + bitcoinValueToFriendlyString(getBalance()));
|
||||
|
||||
// Inform anyone interested that we have new coins. Note: we may be re-entered by the event listener,
|
||||
// so we must not make assumptions about our state after this loop returns! For example,
|
||||
@ -281,12 +284,12 @@ public class Wallet implements Serializable {
|
||||
updateForSpends(tx);
|
||||
if (!tx.getValueSentToMe(this).equals(BigInteger.ZERO)) {
|
||||
// It's sending us coins.
|
||||
LOG(" ->unspent");
|
||||
log.info(" ->unspent");
|
||||
boolean alreadyPresent = unspent.put(tx.getHash(), tx) != null;
|
||||
assert !alreadyPresent : "TX was received twice";
|
||||
} else {
|
||||
// It spent some of our coins and did not send us any.
|
||||
LOG(" ->spent");
|
||||
log.info(" ->spent");
|
||||
boolean alreadyPresent = spent.put(tx.getHash(), tx) != null;
|
||||
assert !alreadyPresent : "TX was received twice";
|
||||
}
|
||||
@ -302,16 +305,16 @@ public class Wallet implements Serializable {
|
||||
if (input.outpoint.connect(unspent.values())) {
|
||||
TransactionOutput output = input.outpoint.getConnectedOutput();
|
||||
assert !output.isSpent : "Double spend accepted by the network?";
|
||||
LOG(" Saw some of my unspent outputs be spent by someone else who has my keys.");
|
||||
LOG(" Total spent value is " + bitcoinValueToFriendlyString(output.getValue()));
|
||||
log.info(" Saw some of my unspent outputs be spent by someone else who has my keys.");
|
||||
log.info(" Total spent value is " + bitcoinValueToFriendlyString(output.getValue()));
|
||||
output.isSpent = true;
|
||||
Transaction connectedTx = input.outpoint.fromTx;
|
||||
if (connectedTx.getValueSentToMe(this, false).equals(BigInteger.ZERO)) {
|
||||
// There's nothing left I can spend in this transaction.
|
||||
if (unspent.remove(connectedTx.getHash()) != null);
|
||||
LOG(" prevtx <-unspent");
|
||||
log.info(" prevtx <-unspent");
|
||||
spent.put(connectedTx.getHash(), connectedTx);
|
||||
LOG(" prevtx ->spent");
|
||||
log.info(" prevtx ->spent");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -400,7 +403,7 @@ public class Wallet implements Serializable {
|
||||
* @return a new {@link Transaction} or null if we cannot afford this send.
|
||||
*/
|
||||
synchronized Transaction createSend(Address address, BigInteger nanocoins, Address changeAddress) {
|
||||
LOG("Creating send tx to " + address.toString() + " for " +
|
||||
log.info("Creating send tx to " + address.toString() + " for " +
|
||||
bitcoinValueToFriendlyString(nanocoins));
|
||||
// To send money to somebody else, we need to do gather up transactions with unspent outputs until we have
|
||||
// sufficient value. Many coin selection algorithms are possible, we use a simple but suboptimal one.
|
||||
@ -418,7 +421,7 @@ public class Wallet implements Serializable {
|
||||
}
|
||||
// Can we afford this?
|
||||
if (valueGathered.compareTo(nanocoins) < 0) {
|
||||
LOG("Insufficient value in wallet for send, missing " +
|
||||
log.info("Insufficient value in wallet for send, missing " +
|
||||
bitcoinValueToFriendlyString(nanocoins.subtract(valueGathered)));
|
||||
// TODO: Should throw an exception here.
|
||||
return null;
|
||||
@ -431,7 +434,7 @@ public class Wallet implements Serializable {
|
||||
// The value of the inputs is greater than what we want to send. Just like in real life then,
|
||||
// we need to take back some coins ... this is called "change". Add another output that sends the change
|
||||
// back to us.
|
||||
LOG(" with " + bitcoinValueToFriendlyString(change) + " coins change");
|
||||
log.info(" with " + bitcoinValueToFriendlyString(change) + " coins change");
|
||||
sendTx.addOutput(new TransactionOutput(params, change, changeAddress, sendTx));
|
||||
}
|
||||
for (TransactionOutput output : gathered) {
|
||||
@ -567,7 +570,7 @@ public class Wallet implements Serializable {
|
||||
// If there is no difference it means we the user doesn't really care about this re-org but we still need to
|
||||
// update the transaction block pointers for next time.
|
||||
boolean affectedUs = !oldChainTransactions.equals(newChainTransactions);
|
||||
LOG(affectedUs ? "Re-org affected our transactions" : "Re-org had no effect on our transactions");
|
||||
log.info(affectedUs ? "Re-org affected our transactions" : "Re-org had no effect on our transactions");
|
||||
if (!affectedUs) return;
|
||||
|
||||
// Transactions that were in the old chain but aren't in the new chain. These will become inactive.
|
||||
@ -579,7 +582,7 @@ public class Wallet implements Serializable {
|
||||
assert !(gone.isEmpty() && fresh.isEmpty()) : "There must have been some changes to get here";
|
||||
|
||||
for (Transaction tx : gone) {
|
||||
LOG("tx not in new chain: <-unspent/spent ->inactive\n" + tx.toString());
|
||||
log.info("tx not in new chain: <-unspent/spent ->inactive\n" + tx.toString());
|
||||
unspent.remove(tx.getHash());
|
||||
spent.remove(tx.getHash());
|
||||
inactive.put(tx.getHash(), tx);
|
||||
|
@ -18,6 +18,8 @@ package com.google.bitcoin.core;
|
||||
|
||||
import com.google.bitcoin.bouncycastle.util.encoders.Hex;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -29,7 +31,9 @@ import java.util.Arrays;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BlockTest {
|
||||
private static Logger log = LoggerFactory.getLogger(BlockTest.class);
|
||||
static final NetworkParameters params = NetworkParameters.testNet();
|
||||
|
||||
static final byte[] blockBytes;
|
||||
|
||||
static {
|
||||
@ -139,8 +143,6 @@ public class BlockTest {
|
||||
// Note that this will actually check the transactions are equal by doing bitcoin serialization and checking
|
||||
// the bytestreams are the same! A true "deep equals" is not implemented for Transaction. The primary purpose
|
||||
// of this test is to ensure no errors occur during the Java serialization/deserialization process.
|
||||
Utils.LOG(Utils.bytesToHexString(tx.bitcoinSerialize()));
|
||||
Utils.LOG(Utils.bytesToHexString(tx2.bitcoinSerialize()));
|
||||
assertEquals(tx, tx2);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user