mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-12 10:15:52 +00:00
Cleanup.
Add lots more nullity annotations. Clear lots of nullity static analysis warnings. Delete some dead code. Simplify a few expressions. Resolves issue 317.
This commit is contained in:
parent
3d99be48bc
commit
d0cd770d62
@ -88,18 +88,19 @@ public class BlockChain extends AbstractBlockChain {
|
|||||||
@Override
|
@Override
|
||||||
protected TransactionOutputChanges connectTransactions(int height, Block block) {
|
protected TransactionOutputChanges connectTransactions(int height, Block block) {
|
||||||
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
||||||
return null;
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TransactionOutputChanges connectTransactions(StoredBlock newBlock) {
|
protected TransactionOutputChanges connectTransactions(StoredBlock newBlock) {
|
||||||
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
||||||
return null;
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void disconnectTransactions(StoredBlock block) {
|
protected void disconnectTransactions(StoredBlock block) {
|
||||||
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.bitcoin.core;
|
package com.google.bitcoin.core;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Message type that can be contained within another Message. ChildMessages that have a cached
|
* Represents a Message type that can be contained within another Message. ChildMessages that have a cached
|
||||||
* backing byte array need to invalidate their parent's caches as well as their own if they are modified.
|
* backing byte array need to invalidate their parent's caches as well as their own if they are modified.
|
||||||
@ -24,7 +26,7 @@ package com.google.bitcoin.core;
|
|||||||
public abstract class ChildMessage extends Message {
|
public abstract class ChildMessage extends Message {
|
||||||
private static final long serialVersionUID = -7657113383624517931L;
|
private static final long serialVersionUID = -7657113383624517931L;
|
||||||
|
|
||||||
private Message parent;
|
@Nullable private Message parent;
|
||||||
|
|
||||||
protected ChildMessage() {
|
protected ChildMessage() {
|
||||||
}
|
}
|
||||||
@ -47,13 +49,13 @@ public abstract class ChildMessage extends Message {
|
|||||||
super(params, msg, offset);
|
super(params, msg, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChildMessage(NetworkParameters params, byte[] msg, int offset, Message parent, boolean parseLazy, boolean parseRetain, int length)
|
public ChildMessage(NetworkParameters params, byte[] msg, int offset, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, msg, offset, parseLazy, parseRetain, length);
|
super(params, msg, offset, parseLazy, parseRetain, length);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParent(Message parent) {
|
public void setParent(@Nullable Message parent) {
|
||||||
if (this.parent != null && this.parent != parent && parent != null) {
|
if (this.parent != null && this.parent != parent && parent != null) {
|
||||||
// After old parent is unlinked it won't be able to receive notice if this ChildMessage
|
// After old parent is unlinked it won't be able to receive notice if this ChildMessage
|
||||||
// changes internally. To be safe we invalidate the parent cache to ensure it rebuilds
|
// changes internally. To be safe we invalidate the parent cache to ensure it rebuilds
|
||||||
|
@ -161,7 +161,7 @@ public class ECKey implements Serializable {
|
|||||||
* is more convenient if you are importing a key from elsewhere. The public key will be automatically derived
|
* is more convenient if you are importing a key from elsewhere. The public key will be automatically derived
|
||||||
* from the private key.
|
* from the private key.
|
||||||
*/
|
*/
|
||||||
public ECKey(byte[] privKeyBytes, byte[] pubKey) {
|
public ECKey(@Nullable byte[] privKeyBytes, @Nullable byte[] pubKey) {
|
||||||
this(privKeyBytes == null ? null : new BigInteger(1, privKeyBytes), pubKey);
|
this(privKeyBytes == null ? null : new BigInteger(1, privKeyBytes), pubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ public class ECKey implements Serializable {
|
|||||||
* @param pubKey The keys public key
|
* @param pubKey The keys public key
|
||||||
* @param keyCrypter The KeyCrypter that will be used, with an AES key, to encrypt and decrypt the private key
|
* @param keyCrypter The KeyCrypter that will be used, with an AES key, to encrypt and decrypt the private key
|
||||||
*/
|
*/
|
||||||
public ECKey(EncryptedPrivateKey encryptedPrivateKey, byte[] pubKey, KeyCrypter keyCrypter) {
|
public ECKey(@Nullable EncryptedPrivateKey encryptedPrivateKey, @Nullable byte[] pubKey, KeyCrypter keyCrypter) {
|
||||||
this((byte[])null, pubKey);
|
this((byte[])null, pubKey);
|
||||||
|
|
||||||
this.keyCrypter = Preconditions.checkNotNull(keyCrypter);
|
this.keyCrypter = Preconditions.checkNotNull(keyCrypter);
|
||||||
@ -186,13 +186,15 @@ public class ECKey implements Serializable {
|
|||||||
* be used for signing.
|
* be used for signing.
|
||||||
* @param compressed If set to true and pubKey is null, the derived public key will be in compressed form.
|
* @param compressed If set to true and pubKey is null, the derived public key will be in compressed form.
|
||||||
*/
|
*/
|
||||||
public ECKey(BigInteger privKey, byte[] pubKey, boolean compressed) {
|
public ECKey(@Nullable BigInteger privKey, @Nullable byte[] pubKey, boolean compressed) {
|
||||||
|
if (privKey == null && pubKey == null)
|
||||||
|
throw new IllegalArgumentException("ECKey requires at least private or public key");
|
||||||
this.priv = privKey;
|
this.priv = privKey;
|
||||||
this.pub = null;
|
this.pub = null;
|
||||||
if (pubKey == null && privKey != null) {
|
if (pubKey == null) {
|
||||||
// Derive public from private.
|
// Derive public from private.
|
||||||
this.pub = publicKeyFromPrivate(privKey, compressed);
|
this.pub = publicKeyFromPrivate(privKey, compressed);
|
||||||
} else if (pubKey != null) {
|
} else {
|
||||||
// We expect the pubkey to be in regular encoded form, just as a BigInteger. Therefore the first byte is
|
// We expect the pubkey to be in regular encoded form, just as a BigInteger. Therefore the first byte is
|
||||||
// a special marker byte.
|
// a special marker byte.
|
||||||
// TODO: This is probably not a useful API and may be confusing.
|
// TODO: This is probably not a useful API and may be confusing.
|
||||||
@ -206,7 +208,7 @@ public class ECKey implements Serializable {
|
|||||||
* the public key already correctly matches the public key. If only the public key is supplied, this ECKey cannot
|
* the public key already correctly matches the public key. If only the public key is supplied, this ECKey cannot
|
||||||
* be used for signing.
|
* be used for signing.
|
||||||
*/
|
*/
|
||||||
private ECKey(BigInteger privKey, byte[] pubKey) {
|
private ECKey(@Nullable BigInteger privKey, @Nullable byte[] pubKey) {
|
||||||
this(privKey, pubKey, false);
|
this(privKey, pubKey, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +383,7 @@ public class ECKey implements Serializable {
|
|||||||
r = (DERInteger) seq.getObjectAt(0);
|
r = (DERInteger) seq.getObjectAt(0);
|
||||||
s = (DERInteger) seq.getObjectAt(1);
|
s = (DERInteger) seq.getObjectAt(1);
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
return null;
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
decoder.close();
|
decoder.close();
|
||||||
// OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they should not be
|
// OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they should not be
|
||||||
@ -431,7 +433,7 @@ public class ECKey implements Serializable {
|
|||||||
* @param aesKey The AES key to use for decryption of the private key. If null then no decryption is required.
|
* @param aesKey The AES key to use for decryption of the private key. If null then no decryption is required.
|
||||||
* @throws KeyCrypterException if this ECKey doesn't have a private part.
|
* @throws KeyCrypterException if this ECKey doesn't have a private part.
|
||||||
*/
|
*/
|
||||||
public ECDSASignature sign(Sha256Hash input, KeyParameter aesKey) throws KeyCrypterException {
|
public ECDSASignature sign(Sha256Hash input, @Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||||
if (FAKE_SIGNATURES)
|
if (FAKE_SIGNATURES)
|
||||||
return TransactionSignature.dummy();
|
return TransactionSignature.dummy();
|
||||||
|
|
||||||
@ -601,7 +603,7 @@ public class ECKey implements Serializable {
|
|||||||
* @throws IllegalStateException if this ECKey does not have the private part.
|
* @throws IllegalStateException if this ECKey does not have the private part.
|
||||||
* @throws KeyCrypterException if this ECKey is encrypted and no AESKey is provided or it does not decrypt the ECKey.
|
* @throws KeyCrypterException if this ECKey is encrypted and no AESKey is provided or it does not decrypt the ECKey.
|
||||||
*/
|
*/
|
||||||
public String signMessage(String message, KeyParameter aesKey) throws KeyCrypterException {
|
public String signMessage(String message, @Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||||
if (priv == null)
|
if (priv == null)
|
||||||
throw new IllegalStateException("This ECKey does not have the private key necessary for signing.");
|
throw new IllegalStateException("This ECKey does not have the private key necessary for signing.");
|
||||||
byte[] data = Utils.formatMessageForSigning(message);
|
byte[] data = Utils.formatMessageForSigning(message);
|
||||||
@ -702,6 +704,7 @@ public class ECKey implements Serializable {
|
|||||||
* @param compressed Whether or not the original pubkey was compressed.
|
* @param compressed Whether or not the original pubkey was compressed.
|
||||||
* @return An ECKey containing only the public part, or null if recovery wasn't possible.
|
* @return An ECKey containing only the public part, or null if recovery wasn't possible.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public static ECKey recoverFromSignature(int recId, ECDSASignature sig, Sha256Hash message, boolean compressed) {
|
public static ECKey recoverFromSignature(int recId, ECDSASignature sig, Sha256Hash message, boolean compressed) {
|
||||||
Preconditions.checkArgument(recId >= 0, "recId must be positive");
|
Preconditions.checkArgument(recId >= 0, "recId must be positive");
|
||||||
Preconditions.checkArgument(sig.r.compareTo(BigInteger.ZERO) >= 0, "r must be positive");
|
Preconditions.checkArgument(sig.r.compareTo(BigInteger.ZERO) >= 0, "r must be positive");
|
||||||
|
@ -22,6 +22,7 @@ import com.google.bitcoin.store.FullPrunedBlockStore;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -124,6 +125,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
this.tx = tx; this.prevOutScripts = prevOutScripts; this.enforcePayToScriptHash = enforcePayToScriptHash;
|
this.tx = tx; this.prevOutScripts = prevOutScripts; this.enforcePayToScriptHash = enforcePayToScriptHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public VerificationException call() throws Exception {
|
public VerificationException call() throws Exception {
|
||||||
try{
|
try{
|
||||||
|
@ -380,7 +380,7 @@ public abstract class Message implements Serializable {
|
|||||||
* so BitcoinSerializer can avoid 2 instanceof checks + a casting.
|
* so BitcoinSerializer can avoid 2 instanceof checks + a casting.
|
||||||
*/
|
*/
|
||||||
public Sha256Hash getHash() {
|
public Sha256Hash getHash() {
|
||||||
return null;
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -388,8 +388,6 @@ public abstract class Message implements Serializable {
|
|||||||
* implemented in a subclass of ChildMessage lazy parsing may have no effect.
|
* implemented in a subclass of ChildMessage lazy parsing may have no effect.
|
||||||
*
|
*
|
||||||
* This default implementation is a safe fall back that will ensure it returns a correct value by parsing the message.
|
* This default implementation is a safe fall back that will ensure it returns a correct value by parsing the message.
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public int getMessageSize() {
|
public int getMessageSize() {
|
||||||
if (length != UNKNOWN_LENGTH)
|
if (length != UNKNOWN_LENGTH)
|
||||||
|
@ -22,6 +22,7 @@ import com.google.bitcoin.script.ScriptOpCodes;
|
|||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@ -185,6 +186,7 @@ public abstract class NetworkParameters implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the network parameters for the given string ID or NULL if not recognized. */
|
/** Returns the network parameters for the given string ID or NULL if not recognized. */
|
||||||
|
@Nullable
|
||||||
public static NetworkParameters fromID(String id) {
|
public static NetworkParameters fromID(String id) {
|
||||||
if (id.equals(ID_MAINNET)) {
|
if (id.equals(ID_MAINNET)) {
|
||||||
return MainNetParams.get();
|
return MainNetParams.get();
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.google.bitcoin.core;
|
package com.google.bitcoin.core;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,5 +86,6 @@ public interface PeerEventListener {
|
|||||||
* <p>Note that this will never be called if registered with any executor other than
|
* <p>Note that this will never be called if registered with any executor other than
|
||||||
* {@link com.google.bitcoin.utils.Threading#SAME_THREAD}</p>
|
* {@link com.google.bitcoin.utils.Threading#SAME_THREAD}</p>
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public List<Message> getData(Peer peer, GetDataMessage m);
|
public List<Message> getData(Peer peer, GetDataMessage m);
|
||||||
}
|
}
|
||||||
|
@ -149,14 +149,6 @@ public class PeerGroup extends AbstractExecutionThreadService implements Transac
|
|||||||
|
|
||||||
private LinkedBlockingQueue<Object> morePeersMailbox = new LinkedBlockingQueue<Object>();
|
private LinkedBlockingQueue<Object> morePeersMailbox = new LinkedBlockingQueue<Object>();
|
||||||
|
|
||||||
private void handleBlocksDownloaded() {
|
|
||||||
double rate = chain.getFalsePositiveRate();
|
|
||||||
if (rate > bloomFilterFPRate * MAX_FP_RATE_INCREASE) {
|
|
||||||
log.info("Force update Bloom filter due to high false positive rate");
|
|
||||||
recalculateFastCatchupAndFilter(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class PeerStartupListener extends AbstractPeerEventListener {
|
private class PeerStartupListener extends AbstractPeerEventListener {
|
||||||
@Override
|
@Override
|
||||||
public void onPeerConnected(Peer peer, int peerCount) {
|
public void onPeerConnected(Peer peer, int peerCount) {
|
||||||
|
@ -21,7 +21,6 @@ import com.google.bitcoin.crypto.TransactionSignature;
|
|||||||
import com.google.bitcoin.script.Script;
|
import com.google.bitcoin.script.Script;
|
||||||
import com.google.bitcoin.script.ScriptBuilder;
|
import com.google.bitcoin.script.ScriptBuilder;
|
||||||
import com.google.bitcoin.script.ScriptOpCodes;
|
import com.google.bitcoin.script.ScriptOpCodes;
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -35,6 +34,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static com.google.bitcoin.core.Utils.*;
|
import static com.google.bitcoin.core.Utils.*;
|
||||||
|
import static com.google.common.base.Preconditions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>A transaction represents the movement of coins from some addresses to some other addresses. It can also represent
|
* <p>A transaction represents the movement of coins from some addresses to some other addresses. It can also represent
|
||||||
@ -172,7 +172,7 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public Transaction(NetworkParameters params, byte[] msg, int offset, Message parent, boolean parseLazy, boolean parseRetain, int length)
|
public Transaction(NetworkParameters params, byte[] msg, int offset, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, msg, offset, parent, parseLazy, parseRetain, length);
|
super(params, msg, offset, parent, parseLazy, parseRetain, length);
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* Creates a transaction by reading payload starting from offset bytes in. Length of a transaction is fixed.
|
* Creates a transaction by reading payload starting from offset bytes in. Length of a transaction is fixed.
|
||||||
*/
|
*/
|
||||||
public Transaction(NetworkParameters params, byte[] msg, Message parent, boolean parseLazy, boolean parseRetain, int length)
|
public Transaction(NetworkParameters params, byte[] msg, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, msg, 0, parent, parseLazy, parseRetain, length);
|
super(params, msg, 0, parent, parseLazy, parseRetain, length);
|
||||||
}
|
}
|
||||||
@ -363,29 +363,6 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
return disconnected;
|
return disconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects all inputs using the provided transactions. If any input cannot be connected returns that input or
|
|
||||||
* null on success.
|
|
||||||
*/
|
|
||||||
TransactionInput connectForReorganize(Map<Sha256Hash, Transaction> transactions) {
|
|
||||||
maybeParse();
|
|
||||||
for (TransactionInput input : inputs) {
|
|
||||||
// Coinbase transactions, by definition, do not have connectable inputs.
|
|
||||||
if (input.isCoinBase()) continue;
|
|
||||||
TransactionInput.ConnectionResult result =
|
|
||||||
input.connect(transactions, TransactionInput.ConnectMode.ABORT_ON_CONFLICT);
|
|
||||||
// Connected to another tx in the wallet?
|
|
||||||
if (result == TransactionInput.ConnectionResult.SUCCESS)
|
|
||||||
continue;
|
|
||||||
// The input doesn't exist in the wallet, eg because it belongs to somebody else (inbound spend).
|
|
||||||
if (result == TransactionInput.ConnectionResult.NO_SUCH_TX)
|
|
||||||
continue;
|
|
||||||
// Could not connect this input, so return it and abort.
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if every output is marked as spent.
|
* Returns true if every output is marked as spent.
|
||||||
*/
|
*/
|
||||||
@ -795,11 +772,11 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
* @param aesKey The AES key to use to decrypt the key before signing. Null if no decryption is required.
|
* @param aesKey The AES key to use to decrypt the key before signing. Null if no decryption is required.
|
||||||
*/
|
*/
|
||||||
public synchronized void signInputs(SigHash hashType, Wallet wallet, @Nullable KeyParameter aesKey) throws ScriptException {
|
public synchronized void signInputs(SigHash hashType, Wallet wallet, @Nullable KeyParameter aesKey) throws ScriptException {
|
||||||
Preconditions.checkState(inputs.size() > 0);
|
checkState(inputs.size() > 0);
|
||||||
Preconditions.checkState(outputs.size() > 0);
|
checkState(outputs.size() > 0);
|
||||||
|
|
||||||
// I don't currently have an easy way to test other modes work, as the official client does not use them.
|
// I don't currently have an easy way to test other modes work, as the official client does not use them.
|
||||||
Preconditions.checkArgument(hashType == SigHash.ALL, "Only SIGHASH_ALL is currently supported");
|
checkArgument(hashType == SigHash.ALL, "Only SIGHASH_ALL is currently supported");
|
||||||
|
|
||||||
// The transaction is signed with the input scripts empty except for the input we are signing. In the case
|
// The transaction is signed with the input scripts empty except for the input we are signing. In the case
|
||||||
// where addInput has been used to set up a new transaction, they are already all empty. The input being signed
|
// where addInput has been used to set up a new transaction, they are already all empty. The input being signed
|
||||||
@ -832,8 +809,7 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
// Find the signing key we'll need to use.
|
// Find the signing key we'll need to use.
|
||||||
ECKey key = input.getOutpoint().getConnectedKey(wallet);
|
ECKey key = input.getOutpoint().getConnectedKey(wallet);
|
||||||
// This assert should never fire. If it does, it means the wallet is inconsistent.
|
// This assert should never fire. If it does, it means the wallet is inconsistent.
|
||||||
Preconditions.checkNotNull(key, "Transaction exists in wallet that we cannot redeem: %s",
|
checkNotNull(key, "Transaction exists in wallet that we cannot redeem: %s", input.getOutpoint().getHash());
|
||||||
input.getOutpoint().getHash());
|
|
||||||
// Keep the key around for the script creation step below.
|
// Keep the key around for the script creation step below.
|
||||||
signingKeys[i] = key;
|
signingKeys[i] = key;
|
||||||
// The anyoneCanPay feature isn't used at the moment.
|
// The anyoneCanPay feature isn't used at the moment.
|
||||||
@ -858,7 +834,9 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
if (signatures[i] == null)
|
if (signatures[i] == null)
|
||||||
continue;
|
continue;
|
||||||
TransactionInput input = inputs.get(i);
|
TransactionInput input = inputs.get(i);
|
||||||
Script scriptPubKey = input.getOutpoint().getConnectedOutput().getScriptPubKey();
|
final TransactionOutput connectedOutput = input.getOutpoint().getConnectedOutput();
|
||||||
|
checkNotNull(connectedOutput); // Quiet static analysis: is never null here but cannot be statically proven
|
||||||
|
Script scriptPubKey = connectedOutput.getScriptPubKey();
|
||||||
if (scriptPubKey.isSentToAddress()) {
|
if (scriptPubKey.isSentToAddress()) {
|
||||||
input.setScriptSig(ScriptBuilder.createInputScript(signatures[i], signingKeys[i]));
|
input.setScriptSig(ScriptBuilder.createInputScript(signatures[i], signingKeys[i]));
|
||||||
} else if (scriptPubKey.isSentToRawPubKey()) {
|
} else if (scriptPubKey.isSentToRawPubKey()) {
|
||||||
@ -887,7 +865,7 @@ public class Transaction extends ChildMessage implements Serializable {
|
|||||||
* @param anyoneCanPay Signing mode, see the SigHash enum for documentation.
|
* @param anyoneCanPay Signing mode, see the SigHash enum for documentation.
|
||||||
* @return A newly calculated signature object that wraps the r, s and sighash components.
|
* @return A newly calculated signature object that wraps the r, s and sighash components.
|
||||||
*/
|
*/
|
||||||
public synchronized TransactionSignature calculateSignature(int inputIndex, ECKey key, KeyParameter aesKey,
|
public synchronized TransactionSignature calculateSignature(int inputIndex, ECKey key, @Nullable KeyParameter aesKey,
|
||||||
byte[] connectedPubKeyScript,
|
byte[] connectedPubKeyScript,
|
||||||
SigHash hashType, boolean anyoneCanPay) {
|
SigHash hashType, boolean anyoneCanPay) {
|
||||||
Sha256Hash hash = hashForSignature(inputIndex, connectedPubKeyScript, hashType, anyoneCanPay);
|
Sha256Hash hash = hashForSignature(inputIndex, connectedPubKeyScript, hashType, anyoneCanPay);
|
||||||
|
@ -22,6 +22,7 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
@ -111,17 +112,6 @@ public class TransactionConfidence implements Serializable {
|
|||||||
public int getValue() {
|
public int getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConfidenceType valueOf(int value) {
|
|
||||||
switch (value) {
|
|
||||||
case 0: return UNKNOWN;
|
|
||||||
case 1: return BUILDING;
|
|
||||||
case 2: return PENDING;
|
|
||||||
case 4: return DEAD;
|
|
||||||
default: return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfidenceType confidenceType = ConfidenceType.UNKNOWN;
|
private ConfidenceType confidenceType = ConfidenceType.UNKNOWN;
|
||||||
@ -402,7 +392,7 @@ public class TransactionConfidence implements Serializable {
|
|||||||
* in such a way that the double-spending transaction takes precedence over this one. It will not become valid now
|
* in such a way that the double-spending transaction takes precedence over this one. It will not become valid now
|
||||||
* unless there is a re-org. Automatically sets the confidence type to DEAD.
|
* unless there is a re-org. Automatically sets the confidence type to DEAD.
|
||||||
*/
|
*/
|
||||||
public synchronized void setOverridingTransaction(Transaction overridingTransaction) {
|
public synchronized void setOverridingTransaction(@Nullable Transaction overridingTransaction) {
|
||||||
this.overridingTransaction = overridingTransaction;
|
this.overridingTransaction = overridingTransaction;
|
||||||
setConfidenceType(ConfidenceType.DEAD);
|
setConfidenceType(ConfidenceType.DEAD);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package com.google.bitcoin.core;
|
|||||||
import com.google.bitcoin.script.Script;
|
import com.google.bitcoin.script.Script;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -67,15 +68,13 @@ public class TransactionInput extends ChildMessage implements Serializable {
|
|||||||
length = 40 + (scriptBytes == null ? 1 : VarInt.sizeOf(scriptBytes.length) + scriptBytes.length);
|
length = 40 + (scriptBytes == null ? 1 : VarInt.sizeOf(scriptBytes.length) + scriptBytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransactionInput(NetworkParameters params, Transaction parentTransaction,
|
public TransactionInput(NetworkParameters params, @Nullable Transaction parentTransaction, byte[] scriptBytes,
|
||||||
byte[] scriptBytes,
|
|
||||||
TransactionOutPoint outpoint) {
|
TransactionOutPoint outpoint) {
|
||||||
super(params);
|
super(params);
|
||||||
this.scriptBytes = scriptBytes;
|
this.scriptBytes = scriptBytes;
|
||||||
this.outpoint = outpoint;
|
this.outpoint = outpoint;
|
||||||
this.sequence = NO_SEQUENCE;
|
this.sequence = NO_SEQUENCE;
|
||||||
this.parentTransaction = parentTransaction;
|
this.parentTransaction = parentTransaction;
|
||||||
|
|
||||||
length = 40 + (scriptBytes == null ? 1 : VarInt.sizeOf(scriptBytes.length) + scriptBytes.length);
|
length = 40 + (scriptBytes == null ? 1 : VarInt.sizeOf(scriptBytes.length) + scriptBytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,12 +277,12 @@ public class TransactionInput extends ChildMessage implements Serializable {
|
|||||||
*
|
*
|
||||||
* @return The TransactionOutput or null if the transactions map doesn't contain the referenced tx.
|
* @return The TransactionOutput or null if the transactions map doesn't contain the referenced tx.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
TransactionOutput getConnectedOutput(Map<Sha256Hash, Transaction> transactions) {
|
TransactionOutput getConnectedOutput(Map<Sha256Hash, Transaction> transactions) {
|
||||||
Transaction tx = transactions.get(outpoint.getHash());
|
Transaction tx = transactions.get(outpoint.getHash());
|
||||||
if (tx == null)
|
if (tx == null)
|
||||||
return null;
|
return null;
|
||||||
TransactionOutput out = tx.getOutputs().get((int) outpoint.getIndex());
|
return tx.getOutputs().get((int) outpoint.getIndex());
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ConnectMode {
|
public enum ConnectMode {
|
||||||
@ -414,6 +413,7 @@ public class TransactionInput extends ChildMessage implements Serializable {
|
|||||||
* {@link TransactionInput#connect(TransactionOutput)} or variants at some point. If it wasn't connected, then
|
* {@link TransactionInput#connect(TransactionOutput)} or variants at some point. If it wasn't connected, then
|
||||||
* this method returns null.
|
* this method returns null.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public TransactionOutput getConnectedOutput() {
|
public TransactionOutput getConnectedOutput() {
|
||||||
return getOutpoint().getConnectedOutput();
|
return getOutpoint().getConnectedOutput();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package com.google.bitcoin.core;
|
|||||||
|
|
||||||
import com.google.bitcoin.script.Script;
|
import com.google.bitcoin.script.Script;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -43,7 +44,7 @@ public class TransactionOutPoint extends ChildMessage implements Serializable {
|
|||||||
// It points to the connected transaction.
|
// It points to the connected transaction.
|
||||||
Transaction fromTx;
|
Transaction fromTx;
|
||||||
|
|
||||||
public TransactionOutPoint(NetworkParameters params, long index, Transaction fromTx) {
|
public TransactionOutPoint(NetworkParameters params, long index, @Nullable Transaction fromTx) {
|
||||||
super(params);
|
super(params);
|
||||||
this.index = index;
|
this.index = index;
|
||||||
if (fromTx != null) {
|
if (fromTx != null) {
|
||||||
@ -114,6 +115,7 @@ public class TransactionOutPoint extends ChildMessage implements Serializable {
|
|||||||
* sides in memory, and they have been linked together, this returns a pointer to the connected output, or null
|
* sides in memory, and they have been linked together, this returns a pointer to the connected output, or null
|
||||||
* if there is no such connection.
|
* if there is no such connection.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public TransactionOutput getConnectedOutput() {
|
public TransactionOutput getConnectedOutput() {
|
||||||
if (fromTx == null) return null;
|
if (fromTx == null) return null;
|
||||||
return fromTx.getOutputs().get((int) index);
|
return fromTx.getOutputs().get((int) index);
|
||||||
@ -121,25 +123,20 @@ public class TransactionOutPoint extends ChildMessage implements Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pubkey script from the connected output.
|
* Returns the pubkey script from the connected output.
|
||||||
|
* @throws java.lang.NullPointerException if there is no connected output.
|
||||||
*/
|
*/
|
||||||
byte[] getConnectedPubKeyScript() {
|
byte[] getConnectedPubKeyScript() {
|
||||||
byte[] result = checkNotNull(getConnectedOutput().getScriptBytes());
|
byte[] result = checkNotNull(getConnectedOutput()).getScriptBytes();
|
||||||
checkState(result.length > 0);
|
checkState(result.length > 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method to get the connected outputs pubkey hash.
|
|
||||||
*/
|
|
||||||
byte[] getConnectedPubKeyHash() throws ScriptException {
|
|
||||||
return getConnectedOutput().getScriptPubKey().getPubKeyHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ECKey identified in the connected output, for either pay-to-address scripts or pay-to-key scripts.
|
* Returns the ECKey identified in the connected output, for either pay-to-address scripts or pay-to-key scripts.
|
||||||
* If the script forms cannot be understood, throws ScriptException.
|
* If the script forms cannot be understood, throws ScriptException.
|
||||||
* @return an ECKey or null if the connected key cannot be found in the wallet.
|
* @return an ECKey or null if the connected key cannot be found in the wallet.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public ECKey getConnectedKey(Wallet wallet) throws ScriptException {
|
public ECKey getConnectedKey(Wallet wallet) throws ScriptException {
|
||||||
TransactionOutput connectedOutput = getConnectedOutput();
|
TransactionOutput connectedOutput = getConnectedOutput();
|
||||||
checkNotNull(connectedOutput, "Input is not connected so cannot retrieve key");
|
checkNotNull(connectedOutput, "Input is not connected so cannot retrieve key");
|
||||||
|
@ -28,9 +28,7 @@ import java.io.OutputStream;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.*;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TransactionOutput message contains a scriptPubKey that controls who is able to spend its value. It is a sub-part
|
* A TransactionOutput message contains a scriptPubKey that controls who is able to spend its value. It is a sub-part
|
||||||
@ -62,7 +60,7 @@ public class TransactionOutput extends ChildMessage implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* Deserializes a transaction output message. This is usually part of a transaction message.
|
* Deserializes a transaction output message. This is usually part of a transaction message.
|
||||||
*/
|
*/
|
||||||
public TransactionOutput(NetworkParameters params, Transaction parent, byte[] payload,
|
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, byte[] payload,
|
||||||
int offset) throws ProtocolException {
|
int offset) throws ProtocolException {
|
||||||
super(params, payload, offset);
|
super(params, payload, offset);
|
||||||
parentTransaction = parent;
|
parentTransaction = parent;
|
||||||
@ -311,11 +309,10 @@ public class TransactionOutput extends ChildMessage implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transaction that owns this output, or null if this is a free standing object.
|
* Returns the transaction that owns this output, or throws NullPointerException if unowned.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
public Transaction getParentTransaction() {
|
public Transaction getParentTransaction() {
|
||||||
return parentTransaction;
|
return checkNotNull(parentTransaction, "Free-standing TransactionOutput");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -218,7 +218,7 @@ public class VersionMessage extends Message {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
byte[] getChecksum() {
|
byte[] getChecksum() {
|
||||||
return null;
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,6 +226,7 @@ public class VersionMessage extends Message {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void setChecksum(byte[] checksum) {
|
void setChecksum(byte[] checksum) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,7 +137,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
|
|||||||
|
|
||||||
private final NetworkParameters params;
|
private final NetworkParameters params;
|
||||||
|
|
||||||
private Sha256Hash lastBlockSeenHash;
|
@Nullable private Sha256Hash lastBlockSeenHash;
|
||||||
private int lastBlockSeenHeight;
|
private int lastBlockSeenHeight;
|
||||||
private long lastBlockSeenTimeSecs;
|
private long lastBlockSeenTimeSecs;
|
||||||
|
|
||||||
@ -2584,7 +2584,8 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the hash of the last seen best-chain block. */
|
/** Returns the hash of the last seen best-chain block, or null if the wallet is too old to store this data. */
|
||||||
|
@Nullable
|
||||||
public Sha256Hash getLastBlockSeenHash() {
|
public Sha256Hash getLastBlockSeenHash() {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
@ -2594,7 +2595,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastBlockSeenHash(Sha256Hash lastBlockSeenHash) {
|
public void setLastBlockSeenHash(@Nullable Sha256Hash lastBlockSeenHash) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
this.lastBlockSeenHash = lastBlockSeenHash;
|
this.lastBlockSeenHash = lastBlockSeenHash;
|
||||||
|
@ -156,9 +156,12 @@ public class TransactionSignature extends ECKey.ECDSASignature {
|
|||||||
// Bitcoin encoding is DER signature + sighash byte.
|
// Bitcoin encoding is DER signature + sighash byte.
|
||||||
if (requireCanonical && !isEncodingCanonical(bytes))
|
if (requireCanonical && !isEncodingCanonical(bytes))
|
||||||
throw new VerificationException("Signature encoding is not canonical.");
|
throw new VerificationException("Signature encoding is not canonical.");
|
||||||
ECKey.ECDSASignature sig = ECKey.ECDSASignature.decodeFromDER(bytes);
|
ECKey.ECDSASignature sig;
|
||||||
if (sig == null)
|
try {
|
||||||
throw new VerificationException("Could not decode DER component.");
|
sig = ECKey.ECDSASignature.decodeFromDER(bytes);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new VerificationException("Could not decode DER", e);
|
||||||
|
}
|
||||||
TransactionSignature tsig = new TransactionSignature(sig.r, sig.s);
|
TransactionSignature tsig = new TransactionSignature(sig.r, sig.s);
|
||||||
// In Bitcoin, any value of the final byte is valid, but not necessarily canonical. See javadocs for
|
// In Bitcoin, any value of the final byte is valid, but not necessarily canonical. See javadocs for
|
||||||
// isEncodingCanonical to learn more about this.
|
// isEncodingCanonical to learn more about this.
|
||||||
|
@ -18,7 +18,6 @@ package com.google.bitcoin.net;
|
|||||||
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -42,8 +41,8 @@ public class BlockingClient implements MessageWriteTarget {
|
|||||||
private static final int BUFFER_SIZE_LOWER_BOUND = 4096;
|
private static final int BUFFER_SIZE_LOWER_BOUND = 4096;
|
||||||
private static final int BUFFER_SIZE_UPPER_BOUND = 65536;
|
private static final int BUFFER_SIZE_UPPER_BOUND = 65536;
|
||||||
|
|
||||||
@Nonnull private final ByteBuffer dbuf;
|
private final ByteBuffer dbuf;
|
||||||
@Nonnull private final Socket socket;
|
private final Socket socket;
|
||||||
private volatile boolean vCloseRequested = false;
|
private volatile boolean vCloseRequested = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,6 +21,7 @@ import com.google.bitcoin.utils.Threading;
|
|||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
import javax.annotation.concurrent.GuardedBy;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -54,7 +55,7 @@ class ConnectionHandler implements MessageWriteTarget {
|
|||||||
@GuardedBy("lock") private final ByteBuffer readBuff;
|
@GuardedBy("lock") private final ByteBuffer readBuff;
|
||||||
@GuardedBy("lock") private final SocketChannel channel;
|
@GuardedBy("lock") private final SocketChannel channel;
|
||||||
@GuardedBy("lock") private final SelectionKey key;
|
@GuardedBy("lock") private final SelectionKey key;
|
||||||
@GuardedBy("lock") final StreamParser parser;
|
@GuardedBy("lock") StreamParser parser;
|
||||||
@GuardedBy("lock") private boolean closeCalled = false;
|
@GuardedBy("lock") private boolean closeCalled = false;
|
||||||
|
|
||||||
@GuardedBy("lock") private long bytesToWriteRemaining = 0;
|
@GuardedBy("lock") private long bytesToWriteRemaining = 0;
|
||||||
@ -68,15 +69,15 @@ class ConnectionHandler implements MessageWriteTarget {
|
|||||||
throw new IOException("Parser factory.getNewParser returned null");
|
throw new IOException("Parser factory.getNewParser returned null");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionHandler(StreamParser parser, SelectionKey key) {
|
private ConnectionHandler(@Nullable StreamParser parser, SelectionKey key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.channel = checkNotNull(((SocketChannel)key.channel()));
|
this.channel = checkNotNull(((SocketChannel)key.channel()));
|
||||||
this.parser = parser;
|
|
||||||
if (parser == null) {
|
if (parser == null) {
|
||||||
readBuff = null;
|
readBuff = null;
|
||||||
closeConnection();
|
closeConnection();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.parser = parser;
|
||||||
readBuff = ByteBuffer.allocateDirect(Math.min(Math.max(parser.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND));
|
readBuff = ByteBuffer.allocateDirect(Math.min(Math.max(parser.getMaxMessageSize(), BUFFER_SIZE_LOWER_BOUND), BUFFER_SIZE_UPPER_BOUND));
|
||||||
parser.setWriteTarget(this); // May callback into us (eg closeConnection() now)
|
parser.setWriteTarget(this); // May callback into us (eg closeConnection() now)
|
||||||
connectedHandlers = null;
|
connectedHandlers = null;
|
||||||
@ -212,7 +213,7 @@ class ConnectionHandler implements MessageWriteTarget {
|
|||||||
// "flip" the buffer - setting the limit to the current position and setting position to 0
|
// "flip" the buffer - setting the limit to the current position and setting position to 0
|
||||||
handler.readBuff.flip();
|
handler.readBuff.flip();
|
||||||
// Use parser.receiveBytes's return value as a check that it stopped reading at the right location
|
// Use parser.receiveBytes's return value as a check that it stopped reading at the right location
|
||||||
int bytesConsumed = handler.parser.receiveBytes(handler.readBuff);
|
int bytesConsumed = checkNotNull(handler.parser).receiveBytes(handler.readBuff);
|
||||||
checkState(handler.readBuff.position() == bytesConsumed);
|
checkState(handler.readBuff.position() == bytesConsumed);
|
||||||
// Now drop the bytes which were read by compacting readBuff (resetting limit and keeping relative
|
// Now drop the bytes which were read by compacting readBuff (resetting limit and keeping relative
|
||||||
// position)
|
// position)
|
||||||
|
@ -17,6 +17,7 @@ package com.google.bitcoin.net.discovery;
|
|||||||
|
|
||||||
import com.google.bitcoin.core.NetworkParameters;
|
import com.google.bitcoin.core.NetworkParameters;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@ -42,6 +43,7 @@ public class SeedPeers implements PeerDiscovery {
|
|||||||
* @return InetSocketAddress - The address/port of the next node.
|
* @return InetSocketAddress - The address/port of the next node.
|
||||||
* @throws PeerDiscoveryException
|
* @throws PeerDiscoveryException
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public InetSocketAddress getPeer() throws PeerDiscoveryException {
|
public InetSocketAddress getPeer() throws PeerDiscoveryException {
|
||||||
try {
|
try {
|
||||||
return nextPeer();
|
return nextPeer();
|
||||||
@ -50,6 +52,7 @@ public class SeedPeers implements PeerDiscovery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private InetSocketAddress nextPeer() throws UnknownHostException {
|
private InetSocketAddress nextPeer() throws UnknownHostException {
|
||||||
if (pnseedIndex >= seedAddrs.length) return null;
|
if (pnseedIndex >= seedAddrs.length) return null;
|
||||||
return new InetSocketAddress(convertAddress(seedAddrs[pnseedIndex++]),
|
return new InetSocketAddress(convertAddress(seedAddrs[pnseedIndex++]),
|
||||||
|
@ -16,14 +16,6 @@
|
|||||||
|
|
||||||
package com.google.bitcoin.protocols.channels;
|
package com.google.bitcoin.protocols.channels;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.SocketAddress;
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Sha256Hash;
|
import com.google.bitcoin.core.Sha256Hash;
|
||||||
import com.google.bitcoin.core.TransactionBroadcaster;
|
import com.google.bitcoin.core.TransactionBroadcaster;
|
||||||
import com.google.bitcoin.core.Wallet;
|
import com.google.bitcoin.core.Wallet;
|
||||||
@ -32,6 +24,13 @@ import com.google.bitcoin.net.ProtobufParser;
|
|||||||
import com.google.bitcoin.net.StreamParserFactory;
|
import com.google.bitcoin.net.StreamParserFactory;
|
||||||
import org.bitcoin.paymentchannel.Protos;
|
import org.bitcoin.paymentchannel.Protos;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,7 +119,7 @@ public class PaymentChannelServerListener {
|
|||||||
private PaymentChannelCloseException.CloseReason closeReason;
|
private PaymentChannelCloseException.CloseReason closeReason;
|
||||||
|
|
||||||
// The user-provided event handler
|
// The user-provided event handler
|
||||||
@Nonnull private ServerConnectionEventHandler eventHandler;
|
private ServerConnectionEventHandler eventHandler;
|
||||||
|
|
||||||
// The payment channel server which does the actual payment channel handling
|
// The payment channel server which does the actual payment channel handling
|
||||||
private final PaymentChannelServer paymentChannelManager;
|
private final PaymentChannelServer paymentChannelManager;
|
||||||
|
@ -303,7 +303,7 @@ public class PaymentChannelServerState {
|
|||||||
// was not connected to the peergroup when the contract was broadcast (which may cause issues down the road, and
|
// was not connected to the peergroup when the contract was broadcast (which may cause issues down the road, and
|
||||||
// disables our double-spend check next)
|
// disables our double-spend check next)
|
||||||
Transaction walletContract = wallet.getTransaction(multisigContract.getHash());
|
Transaction walletContract = wallet.getTransaction(multisigContract.getHash());
|
||||||
checkState(walletContract != null, "Wallet did not contain multisig contract {} after state was marked READY", multisigContract.getHash());
|
checkNotNull(walletContract, "Wallet did not contain multisig contract {} after state was marked READY", multisigContract.getHash());
|
||||||
|
|
||||||
// Note that we check for DEAD state here, but this test is essentially useless in production because we will
|
// Note that we check for DEAD state here, but this test is essentially useless in production because we will
|
||||||
// miss most double-spends due to bloom filtering right now anyway. This will eventually fixed by network-wide
|
// miss most double-spends due to bloom filtering right now anyway. This will eventually fixed by network-wide
|
||||||
|
@ -22,6 +22,8 @@ import com.google.bitcoin.core.Sha256Hash;
|
|||||||
import com.google.bitcoin.net.ProtobufParser;
|
import com.google.bitcoin.net.ProtobufParser;
|
||||||
import org.bitcoin.paymentchannel.Protos;
|
import org.bitcoin.paymentchannel.Protos;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A connection-specific event handler that handles events generated by client connections on a
|
* A connection-specific event handler that handles events generated by client connections on a
|
||||||
* {@link PaymentChannelServerListener}
|
* {@link PaymentChannelServerListener}
|
||||||
@ -30,7 +32,7 @@ public abstract class ServerConnectionEventHandler {
|
|||||||
private ProtobufParser connectionChannel;
|
private ProtobufParser connectionChannel;
|
||||||
// Called by ServerListener before channelOpen to set connectionChannel when it is ready to received application messages
|
// Called by ServerListener before channelOpen to set connectionChannel when it is ready to received application messages
|
||||||
// Also called with null to clear connectionChannel after channelClosed()
|
// Also called with null to clear connectionChannel after channelClosed()
|
||||||
synchronized void setConnectionChannel(ProtobufParser connectionChannel) { this.connectionChannel = connectionChannel; }
|
synchronized void setConnectionChannel(@Nullable ProtobufParser connectionChannel) { this.connectionChannel = connectionChannel; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Closes the channel with the client (will generate a
|
* <p>Closes the channel with the client (will generate a
|
||||||
|
@ -141,6 +141,7 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
|
|||||||
/**
|
/**
|
||||||
* Finds a channel with the given id and contract hash and returns it, or returns null.
|
* Finds a channel with the given id and contract hash and returns it, or returns null.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
StoredClientChannel getChannel(Sha256Hash id, Sha256Hash contractHash) {
|
StoredClientChannel getChannel(Sha256Hash id, Sha256Hash contractHash) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
|
@ -18,6 +18,7 @@ package com.google.bitcoin.protocols.channels;
|
|||||||
|
|
||||||
import com.google.bitcoin.core.*;
|
import com.google.bitcoin.core.*;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -41,8 +42,8 @@ public class StoredServerChannel {
|
|||||||
private PaymentChannelServer connectedHandler = null;
|
private PaymentChannelServer connectedHandler = null;
|
||||||
PaymentChannelServerState state = null;
|
PaymentChannelServerState state = null;
|
||||||
|
|
||||||
StoredServerChannel(PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
|
StoredServerChannel(@Nullable PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
|
||||||
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, byte[] bestValueSignature) {
|
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, @Nullable byte[] bestValueSignature) {
|
||||||
this.contract = contract;
|
this.contract = contract;
|
||||||
this.clientOutput = clientOutput;
|
this.clientOutput = clientOutput;
|
||||||
this.refundTransactionUnlockTimeSecs = refundTransactionUnlockTimeSecs;
|
this.refundTransactionUnlockTimeSecs = refundTransactionUnlockTimeSecs;
|
||||||
|
@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -458,6 +459,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public StoredBlock get(Sha256Hash hash, boolean wasUndoableOnly) throws BlockStoreException {
|
public StoredBlock get(Sha256Hash hash, boolean wasUndoableOnly) throws BlockStoreException {
|
||||||
// Optimize for chain head
|
// Optimize for chain head
|
||||||
if (chainHeadHash != null && chainHeadHash.equals(hash))
|
if (chainHeadHash != null && chainHeadHash.equals(hash))
|
||||||
@ -467,8 +469,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
maybeConnect();
|
maybeConnect();
|
||||||
PreparedStatement s = null;
|
PreparedStatement s = null;
|
||||||
try {
|
try {
|
||||||
s = conn.get()
|
s = conn.get().prepareStatement("SELECT chainWork, height, header, wasUndoable FROM headers WHERE hash = ?");
|
||||||
.prepareStatement("SELECT chainWork, height, header, wasUndoable FROM headers WHERE hash = ?");
|
|
||||||
// We skip the first 4 bytes because (on prodnet) the minimum target has 4 0-bytes
|
// We skip the first 4 bytes because (on prodnet) the minimum target has 4 0-bytes
|
||||||
byte[] hashBytes = new byte[28];
|
byte[] hashBytes = new byte[28];
|
||||||
System.arraycopy(hash.getBytes(), 3, hashBytes, 0, 28);
|
System.arraycopy(hash.getBytes(), 3, hashBytes, 0, 28);
|
||||||
@ -478,16 +479,13 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Parse it.
|
// Parse it.
|
||||||
|
|
||||||
if (wasUndoableOnly && !results.getBoolean(4))
|
if (wasUndoableOnly && !results.getBoolean(4))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
BigInteger chainWork = new BigInteger(results.getBytes(1));
|
BigInteger chainWork = new BigInteger(results.getBytes(1));
|
||||||
int height = results.getInt(2);
|
int height = results.getInt(2);
|
||||||
Block b = new Block(params, results.getBytes(3));
|
Block b = new Block(params, results.getBytes(3));
|
||||||
b.verifyHeader();
|
b.verifyHeader();
|
||||||
StoredBlock stored = new StoredBlock(b, chainWork, height);
|
return new StoredBlock(b, chainWork, height);
|
||||||
return stored;
|
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new BlockStoreException(ex);
|
throw new BlockStoreException(ex);
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
@ -498,21 +496,27 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
// blocks.
|
// blocks.
|
||||||
throw new BlockStoreException(e);
|
throw new BlockStoreException(e);
|
||||||
} finally {
|
} finally {
|
||||||
if (s != null)
|
if (s != null) {
|
||||||
try {
|
try {
|
||||||
s.close();
|
s.close();
|
||||||
} catch (SQLException e) { throw new BlockStoreException("Failed to close PreparedStatement"); }
|
} catch (SQLException e) {
|
||||||
|
throw new BlockStoreException("Failed to close PreparedStatement");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
||||||
return get(hash, false);
|
return get(hash, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
|
public StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
|
||||||
return get(hash, true);
|
return get(hash, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
|
public StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
|
||||||
maybeConnect();
|
maybeConnect();
|
||||||
PreparedStatement s = null;
|
PreparedStatement s = null;
|
||||||
@ -629,6 +633,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public StoredTransactionOutput getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
|
public StoredTransactionOutput getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
|
||||||
maybeConnect();
|
maybeConnect();
|
||||||
PreparedStatement s = null;
|
PreparedStatement s = null;
|
||||||
@ -647,8 +652,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
int height = results.getInt(1);
|
int height = results.getInt(1);
|
||||||
BigInteger value = new BigInteger(results.getBytes(2));
|
BigInteger value = new BigInteger(results.getBytes(2));
|
||||||
// Tell the StoredTransactionOutput that we are a coinbase, as that is encoded in height
|
// Tell the StoredTransactionOutput that we are a coinbase, as that is encoded in height
|
||||||
StoredTransactionOutput txout = new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3));
|
return new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3));
|
||||||
return txout;
|
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new BlockStoreException(ex);
|
throw new BlockStoreException(ex);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -21,99 +21,10 @@ import com.google.common.base.Objects;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A StoredTransaction message contains the information necessary to check a transaction later (ie after a reorg).
|
|
||||||
* It is used to avoid having to store the entire transaction when we only need its inputs+outputs.
|
|
||||||
*/
|
|
||||||
class StoredTransaction implements Serializable {
|
|
||||||
private static final long serialVersionUID = 6243881368122528323L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A transaction has some value and a script used for authenticating that the redeemer is allowed to spend
|
|
||||||
* this output.
|
|
||||||
*/
|
|
||||||
private List<StoredTransactionOutput> outputs;
|
|
||||||
private List<TransactionInput> inputs;
|
|
||||||
private long version;
|
|
||||||
private long lockTime;
|
|
||||||
private Sha256Hash hash;
|
|
||||||
|
|
||||||
public StoredTransaction(NetworkParameters params, Transaction tx, int height) {
|
|
||||||
inputs = new LinkedList<TransactionInput>();
|
|
||||||
outputs = new LinkedList<StoredTransactionOutput>();
|
|
||||||
for (TransactionInput in : tx.getInputs())
|
|
||||||
inputs.add(new TransactionInput(params, null, in.getScriptBytes(), in.getOutpoint()));
|
|
||||||
for (TransactionOutput out : tx.getOutputs())
|
|
||||||
outputs.add(new StoredTransactionOutput(null, out, height, tx.isCoinBase()));
|
|
||||||
this.version = tx.getVersion();
|
|
||||||
this.lockTime = tx.getLockTime();
|
|
||||||
this.hash = tx.getHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The lits of inputs in this transaction
|
|
||||||
*/
|
|
||||||
public List<TransactionInput> getInputs() {
|
|
||||||
return inputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The lits of outputs in this transaction
|
|
||||||
* Note that the hashes of all of these are null
|
|
||||||
*/
|
|
||||||
public List<StoredTransactionOutput> getOutputs() {
|
|
||||||
return outputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The hash of this stored transaction
|
|
||||||
*/
|
|
||||||
public Sha256Hash getHash() {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The lockTime of the stored transaction
|
|
||||||
*/
|
|
||||||
public long getLockTime() {
|
|
||||||
return lockTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version of the stored transaction
|
|
||||||
*/
|
|
||||||
public long getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A coinbase transaction is one that creates a new coin. They are the first transaction in each block and their
|
|
||||||
* value is determined by a formula that all implementations of BitCoin share. In 2011 the value of a coinbase
|
|
||||||
* transaction is 50 coins, but in future it will be less. A coinbase transaction is defined not only by its
|
|
||||||
* position in a block but by the data in the inputs.
|
|
||||||
*/
|
|
||||||
public boolean isCoinBase() {
|
|
||||||
return inputs.get(0).isCoinBase();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return "Stored Transaction: " + hash.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
return getHash().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof StoredTransaction)) return false;
|
|
||||||
return ((StoredTransaction) o).getHash().equals(this.getHash());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used as a key for memory map (to avoid having to think about NetworkParameters,
|
* Used as a key for memory map (to avoid having to think about NetworkParameters,
|
||||||
* which is required for {@link TransactionOutPoint}
|
* which is required for {@link TransactionOutPoint}
|
||||||
@ -203,6 +114,7 @@ class TransactionalHashMap<KeyType, ValueType> {
|
|||||||
tempMap.remove();
|
tempMap.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public ValueType get(KeyType key) {
|
public ValueType get(KeyType key) {
|
||||||
if (Boolean.TRUE.equals(inTransaction.get())) {
|
if (Boolean.TRUE.equals(inTransaction.get())) {
|
||||||
if (tempMap.get() != null) {
|
if (tempMap.get() != null) {
|
||||||
@ -228,6 +140,7 @@ class TransactionalHashMap<KeyType, ValueType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public ValueType remove(KeyType key) {
|
public ValueType remove(KeyType key) {
|
||||||
if (Boolean.TRUE.equals(inTransaction.get())) {
|
if (Boolean.TRUE.equals(inTransaction.get())) {
|
||||||
ValueType retVal = map.get(key);
|
ValueType retVal = map.get(key);
|
||||||
@ -275,6 +188,7 @@ class TransactionalMultiKeyHashMap<UniqueKeyType, MultiKeyType, ValueType> {
|
|||||||
mapValues.abortDatabaseBatchWrite();
|
mapValues.abortDatabaseBatchWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public ValueType get(UniqueKeyType key) {
|
public ValueType get(UniqueKeyType key) {
|
||||||
return mapValues.get(key);
|
return mapValues.get(key);
|
||||||
}
|
}
|
||||||
@ -291,6 +205,7 @@ class TransactionalMultiKeyHashMap<UniqueKeyType, MultiKeyType, ValueType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public ValueType removeByUniqueKey(UniqueKeyType key) {
|
public ValueType removeByUniqueKey(UniqueKeyType key) {
|
||||||
return mapValues.remove(key);
|
return mapValues.remove(key);
|
||||||
}
|
}
|
||||||
@ -360,18 +275,21 @@ public class MemoryFullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
blockMap.put(hash, new StoredBlockAndWasUndoableFlag(storedBlock, true));
|
blockMap.put(hash, new StoredBlockAndWasUndoableFlag(storedBlock, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public synchronized StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
public synchronized StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
||||||
Preconditions.checkNotNull(blockMap, "MemoryFullPrunedBlockStore is closed");
|
Preconditions.checkNotNull(blockMap, "MemoryFullPrunedBlockStore is closed");
|
||||||
StoredBlockAndWasUndoableFlag storedBlock = blockMap.get(hash);
|
StoredBlockAndWasUndoableFlag storedBlock = blockMap.get(hash);
|
||||||
return storedBlock == null ? null : storedBlock.block;
|
return storedBlock == null ? null : storedBlock.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public synchronized StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
|
public synchronized StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
|
||||||
Preconditions.checkNotNull(blockMap, "MemoryFullPrunedBlockStore is closed");
|
Preconditions.checkNotNull(blockMap, "MemoryFullPrunedBlockStore is closed");
|
||||||
StoredBlockAndWasUndoableFlag storedBlock = blockMap.get(hash);
|
StoredBlockAndWasUndoableFlag storedBlock = blockMap.get(hash);
|
||||||
return (storedBlock != null && storedBlock.wasUndoable) ? storedBlock.block : null;
|
return (storedBlock != null && storedBlock.wasUndoable) ? storedBlock.block : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public synchronized StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
|
public synchronized StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
|
||||||
Preconditions.checkNotNull(fullBlockMap, "MemoryFullPrunedBlockStore is closed");
|
Preconditions.checkNotNull(fullBlockMap, "MemoryFullPrunedBlockStore is closed");
|
||||||
return fullBlockMap.get(hash);
|
return fullBlockMap.get(hash);
|
||||||
@ -408,6 +326,7 @@ public class MemoryFullPrunedBlockStore implements FullPrunedBlockStore {
|
|||||||
transactionOutputMap = null;
|
transactionOutputMap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public synchronized StoredTransactionOutput getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
|
public synchronized StoredTransactionOutput getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
|
||||||
Preconditions.checkNotNull(transactionOutputMap, "MemoryFullPrunedBlockStore is closed");
|
Preconditions.checkNotNull(transactionOutputMap, "MemoryFullPrunedBlockStore is closed");
|
||||||
return transactionOutputMap.get(new StoredTransactionOutPoint(hash, index));
|
return transactionOutputMap.get(new StoredTransactionOutPoint(hash, index));
|
||||||
|
@ -21,6 +21,7 @@ import com.google.bitcoin.utils.Threading;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
@ -74,10 +75,10 @@ public class SPVBlockStore implements BlockStore {
|
|||||||
//
|
//
|
||||||
// We don't care about the value in this cache. It is always notFoundMarker. Unfortunately LinkedHashSet does not
|
// We don't care about the value in this cache. It is always notFoundMarker. Unfortunately LinkedHashSet does not
|
||||||
// provide the removeEldestEntry control.
|
// provide the removeEldestEntry control.
|
||||||
protected static final StoredBlock notFoundMarker = new StoredBlock(null, null, -1);
|
protected static final Object notFoundMarker = new Object();
|
||||||
protected LinkedHashMap<Sha256Hash, StoredBlock> notFoundCache = new LinkedHashMap<Sha256Hash, StoredBlock>() {
|
protected LinkedHashMap<Sha256Hash, Object> notFoundCache = new LinkedHashMap<Sha256Hash, Object>() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean removeEldestEntry(Map.Entry<Sha256Hash, StoredBlock> entry) {
|
protected boolean removeEldestEntry(Map.Entry<Sha256Hash, Object> entry) {
|
||||||
return size() > 100; // This was chosen arbitrarily.
|
return size() > 100; // This was chosen arbitrarily.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -181,6 +182,7 @@ public class SPVBlockStore implements BlockStore {
|
|||||||
} finally { lock.unlock(); }
|
} finally { lock.unlock(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
||||||
final MappedByteBuffer buffer = this.buffer;
|
final MappedByteBuffer buffer = this.buffer;
|
||||||
if (buffer == null) throw new BlockStoreException("Store closed");
|
if (buffer == null) throw new BlockStoreException("Store closed");
|
||||||
|
@ -364,7 +364,10 @@ public class WalletProtobufSerializer {
|
|||||||
public Wallet readWallet(InputStream input) throws UnreadableWalletException {
|
public Wallet readWallet(InputStream input) throws UnreadableWalletException {
|
||||||
try {
|
try {
|
||||||
Protos.Wallet walletProto = parseToProto(input);
|
Protos.Wallet walletProto = parseToProto(input);
|
||||||
NetworkParameters params = NetworkParameters.fromID(walletProto.getNetworkIdentifier());
|
final String paramsID = walletProto.getNetworkIdentifier();
|
||||||
|
NetworkParameters params = NetworkParameters.fromID(paramsID);
|
||||||
|
if (params == null)
|
||||||
|
throw new UnreadableWalletException("Unknown network parameters ID " + paramsID);
|
||||||
Wallet wallet = new Wallet(params);
|
Wallet wallet = new Wallet(params);
|
||||||
readWallet(walletProto, wallet);
|
readWallet(walletProto, wallet);
|
||||||
return wallet;
|
return wallet;
|
||||||
|
@ -25,6 +25,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A coin selector that takes all coins assigned to keys created before the given timestamp.
|
* A coin selector that takes all coins assigned to keys created before the given timestamp.
|
||||||
* Used as part of the implementation of {@link Wallet#setKeyRotationTime(java.util.Date)}.
|
* Used as part of the implementation of {@link Wallet#setKeyRotationTime(java.util.Date)}.
|
||||||
@ -65,6 +67,7 @@ public class KeyTimeCoinSelector implements CoinSelector {
|
|||||||
log.info("Skipping tx output {} because it's not of simple form.", output);
|
log.info("Skipping tx output {} because it's not of simple form.", output);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
checkNotNull(controllingKey, "Coin selector given output as candidate for which we lack the key");
|
||||||
if (controllingKey.getCreationTimeSeconds() >= unixTimeSeconds) continue;
|
if (controllingKey.getCreationTimeSeconds() >= unixTimeSeconds) continue;
|
||||||
// It's older than the cutoff time so select.
|
// It's older than the cutoff time so select.
|
||||||
valueGathered = valueGathered.add(output.getValue());
|
valueGathered = valueGathered.add(output.getValue());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user