mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-07 14:54:15 +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
|
||||
protected TransactionOutputChanges connectTransactions(int height, Block block) {
|
||||
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
||||
return null;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionOutputChanges connectTransactions(StoredBlock newBlock) {
|
||||
// Don't have to do anything as this is only called if(shouldVerifyTransactions())
|
||||
return null;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
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
|
||||
* 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 {
|
||||
private static final long serialVersionUID = -7657113383624517931L;
|
||||
|
||||
private Message parent;
|
||||
@Nullable private Message parent;
|
||||
|
||||
protected ChildMessage() {
|
||||
}
|
||||
@ -47,13 +49,13 @@ public abstract class ChildMessage extends Message {
|
||||
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 {
|
||||
super(params, msg, offset, parseLazy, parseRetain, length);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void setParent(Message parent) {
|
||||
public void setParent(@Nullable Message parent) {
|
||||
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
|
||||
// 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
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ public class ECKey implements Serializable {
|
||||
* @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
|
||||
*/
|
||||
public ECKey(EncryptedPrivateKey encryptedPrivateKey, byte[] pubKey, KeyCrypter keyCrypter) {
|
||||
public ECKey(@Nullable EncryptedPrivateKey encryptedPrivateKey, @Nullable byte[] pubKey, KeyCrypter keyCrypter) {
|
||||
this((byte[])null, pubKey);
|
||||
|
||||
this.keyCrypter = Preconditions.checkNotNull(keyCrypter);
|
||||
@ -186,13 +186,15 @@ public class ECKey implements Serializable {
|
||||
* be used for signing.
|
||||
* @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.pub = null;
|
||||
if (pubKey == null && privKey != null) {
|
||||
if (pubKey == null) {
|
||||
// Derive public from private.
|
||||
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
|
||||
// a special marker byte.
|
||||
// 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
|
||||
* be used for signing.
|
||||
*/
|
||||
private ECKey(BigInteger privKey, byte[] pubKey) {
|
||||
private ECKey(@Nullable BigInteger privKey, @Nullable byte[] pubKey) {
|
||||
this(privKey, pubKey, false);
|
||||
}
|
||||
|
||||
@ -381,7 +383,7 @@ public class ECKey implements Serializable {
|
||||
r = (DERInteger) seq.getObjectAt(0);
|
||||
s = (DERInteger) seq.getObjectAt(1);
|
||||
} catch (ClassCastException e) {
|
||||
return null;
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
decoder.close();
|
||||
// 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.
|
||||
* @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)
|
||||
return TransactionSignature.dummy();
|
||||
|
||||
@ -601,7 +603,7 @@ public class ECKey implements Serializable {
|
||||
* @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.
|
||||
*/
|
||||
public String signMessage(String message, KeyParameter aesKey) throws KeyCrypterException {
|
||||
public String signMessage(String message, @Nullable KeyParameter aesKey) throws KeyCrypterException {
|
||||
if (priv == null)
|
||||
throw new IllegalStateException("This ECKey does not have the private key necessary for signing.");
|
||||
byte[] data = Utils.formatMessageForSigning(message);
|
||||
@ -702,6 +704,7 @@ public class ECKey implements Serializable {
|
||||
* @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.
|
||||
*/
|
||||
@Nullable
|
||||
public static ECKey recoverFromSignature(int recId, ECDSASignature sig, Sha256Hash message, boolean compressed) {
|
||||
Preconditions.checkArgument(recId >= 0, "recId 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.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
@ -124,6 +125,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
||||
this.tx = tx; this.prevOutScripts = prevOutScripts; this.enforcePayToScriptHash = enforcePayToScriptHash;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public VerificationException call() throws Exception {
|
||||
try{
|
||||
|
@ -380,7 +380,7 @@ public abstract class Message implements Serializable {
|
||||
* so BitcoinSerializer can avoid 2 instanceof checks + a casting.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This default implementation is a safe fall back that will ensure it returns a correct value by parsing the message.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getMessageSize() {
|
||||
if (length != UNKNOWN_LENGTH)
|
||||
|
@ -22,6 +22,7 @@ import com.google.bitcoin.script.ScriptOpCodes;
|
||||
import com.google.common.base.Objects;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Serializable;
|
||||
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. */
|
||||
@Nullable
|
||||
public static NetworkParameters fromID(String id) {
|
||||
if (id.equals(ID_MAINNET)) {
|
||||
return MainNetParams.get();
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.google.bitcoin.core;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
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
|
||||
* {@link com.google.bitcoin.utils.Threading#SAME_THREAD}</p>
|
||||
*/
|
||||
@Nullable
|
||||
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 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 {
|
||||
@Override
|
||||
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.ScriptBuilder;
|
||||
import com.google.bitcoin.script.ScriptOpCodes;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -35,6 +34,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
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
|
||||
@ -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
|
||||
* @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 {
|
||||
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.
|
||||
*/
|
||||
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 {
|
||||
super(params, msg, 0, parent, parseLazy, parseRetain, length);
|
||||
}
|
||||
@ -363,29 +363,6 @@ public class Transaction extends ChildMessage implements Serializable {
|
||||
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.
|
||||
*/
|
||||
@ -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.
|
||||
*/
|
||||
public synchronized void signInputs(SigHash hashType, Wallet wallet, @Nullable KeyParameter aesKey) throws ScriptException {
|
||||
Preconditions.checkState(inputs.size() > 0);
|
||||
Preconditions.checkState(outputs.size() > 0);
|
||||
checkState(inputs.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.
|
||||
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
|
||||
// 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.
|
||||
ECKey key = input.getOutpoint().getConnectedKey(wallet);
|
||||
// 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",
|
||||
input.getOutpoint().getHash());
|
||||
checkNotNull(key, "Transaction exists in wallet that we cannot redeem: %s", input.getOutpoint().getHash());
|
||||
// Keep the key around for the script creation step below.
|
||||
signingKeys[i] = key;
|
||||
// The anyoneCanPay feature isn't used at the moment.
|
||||
@ -858,7 +834,9 @@ public class Transaction extends ChildMessage implements Serializable {
|
||||
if (signatures[i] == null)
|
||||
continue;
|
||||
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()) {
|
||||
input.setScriptSig(ScriptBuilder.createInputScript(signatures[i], signingKeys[i]));
|
||||
} 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.
|
||||
* @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,
|
||||
SigHash hashType, boolean 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.SettableFuture;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ListIterator;
|
||||
@ -111,17 +112,6 @@ public class TransactionConfidence implements Serializable {
|
||||
public int getValue() {
|
||||
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;
|
||||
@ -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
|
||||
* 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;
|
||||
setConfidenceType(ConfidenceType.DEAD);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package com.google.bitcoin.core;
|
||||
import com.google.bitcoin.script.Script;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
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);
|
||||
}
|
||||
|
||||
public TransactionInput(NetworkParameters params, Transaction parentTransaction,
|
||||
byte[] scriptBytes,
|
||||
TransactionOutPoint outpoint) {
|
||||
public TransactionInput(NetworkParameters params, @Nullable Transaction parentTransaction, byte[] scriptBytes,
|
||||
TransactionOutPoint outpoint) {
|
||||
super(params);
|
||||
this.scriptBytes = scriptBytes;
|
||||
this.outpoint = outpoint;
|
||||
this.sequence = NO_SEQUENCE;
|
||||
this.parentTransaction = parentTransaction;
|
||||
|
||||
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.
|
||||
*/
|
||||
@Nullable
|
||||
TransactionOutput getConnectedOutput(Map<Sha256Hash, Transaction> transactions) {
|
||||
Transaction tx = transactions.get(outpoint.getHash());
|
||||
if (tx == null)
|
||||
return null;
|
||||
TransactionOutput out = tx.getOutputs().get((int) outpoint.getIndex());
|
||||
return out;
|
||||
return tx.getOutputs().get((int) outpoint.getIndex());
|
||||
}
|
||||
|
||||
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
|
||||
* this method returns null.
|
||||
*/
|
||||
@Nullable
|
||||
public TransactionOutput getConnectedOutput() {
|
||||
return getOutpoint().getConnectedOutput();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package com.google.bitcoin.core;
|
||||
|
||||
import com.google.bitcoin.script.Script;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -43,7 +44,7 @@ public class TransactionOutPoint extends ChildMessage implements Serializable {
|
||||
// It points to the connected transaction.
|
||||
Transaction fromTx;
|
||||
|
||||
public TransactionOutPoint(NetworkParameters params, long index, Transaction fromTx) {
|
||||
public TransactionOutPoint(NetworkParameters params, long index, @Nullable Transaction fromTx) {
|
||||
super(params);
|
||||
this.index = index;
|
||||
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
|
||||
* if there is no such connection.
|
||||
*/
|
||||
@Nullable
|
||||
public TransactionOutput getConnectedOutput() {
|
||||
if (fromTx == null) return null;
|
||||
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.
|
||||
* @throws java.lang.NullPointerException if there is no connected output.
|
||||
*/
|
||||
byte[] getConnectedPubKeyScript() {
|
||||
byte[] result = checkNotNull(getConnectedOutput().getScriptBytes());
|
||||
byte[] result = checkNotNull(getConnectedOutput()).getScriptBytes();
|
||||
checkState(result.length > 0);
|
||||
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.
|
||||
* If the script forms cannot be understood, throws ScriptException.
|
||||
* @return an ECKey or null if the connected key cannot be found in the wallet.
|
||||
*/
|
||||
@Nullable
|
||||
public ECKey getConnectedKey(Wallet wallet) throws ScriptException {
|
||||
TransactionOutput connectedOutput = getConnectedOutput();
|
||||
checkNotNull(connectedOutput, "Input is not connected so cannot retrieve key");
|
||||
|
@ -28,9 +28,7 @@ import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public TransactionOutput(NetworkParameters params, Transaction parent, byte[] payload,
|
||||
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, byte[] payload,
|
||||
int offset) throws ProtocolException {
|
||||
super(params, payload, offset);
|
||||
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() {
|
||||
return parentTransaction;
|
||||
return checkNotNull(parentTransaction, "Free-standing TransactionOutput");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -218,7 +218,7 @@ public class VersionMessage extends Message {
|
||||
*/
|
||||
@Override
|
||||
byte[] getChecksum() {
|
||||
return null;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,6 +226,7 @@ public class VersionMessage extends Message {
|
||||
*/
|
||||
@Override
|
||||
void setChecksum(byte[] checksum) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -137,7 +137,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
|
||||
|
||||
private final NetworkParameters params;
|
||||
|
||||
private Sha256Hash lastBlockSeenHash;
|
||||
@Nullable private Sha256Hash lastBlockSeenHash;
|
||||
private int lastBlockSeenHeight;
|
||||
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() {
|
||||
lock.lock();
|
||||
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();
|
||||
try {
|
||||
this.lastBlockSeenHash = lastBlockSeenHash;
|
||||
|
@ -156,9 +156,12 @@ public class TransactionSignature extends ECKey.ECDSASignature {
|
||||
// Bitcoin encoding is DER signature + sighash byte.
|
||||
if (requireCanonical && !isEncodingCanonical(bytes))
|
||||
throw new VerificationException("Signature encoding is not canonical.");
|
||||
ECKey.ECDSASignature sig = ECKey.ECDSASignature.decodeFromDER(bytes);
|
||||
if (sig == null)
|
||||
throw new VerificationException("Could not decode DER component.");
|
||||
ECKey.ECDSASignature sig;
|
||||
try {
|
||||
sig = ECKey.ECDSASignature.decodeFromDER(bytes);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new VerificationException("Could not decode DER", e);
|
||||
}
|
||||
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
|
||||
// isEncodingCanonical to learn more about this.
|
||||
|
@ -18,7 +18,6 @@ package com.google.bitcoin.net;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
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_UPPER_BOUND = 65536;
|
||||
|
||||
@Nonnull private final ByteBuffer dbuf;
|
||||
@Nonnull private final Socket socket;
|
||||
private final ByteBuffer dbuf;
|
||||
private final Socket socket;
|
||||
private volatile boolean vCloseRequested = false;
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,7 @@ import com.google.bitcoin.utils.Threading;
|
||||
import com.google.common.base.Throwables;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -54,7 +55,7 @@ class ConnectionHandler implements MessageWriteTarget {
|
||||
@GuardedBy("lock") private final ByteBuffer readBuff;
|
||||
@GuardedBy("lock") private final SocketChannel channel;
|
||||
@GuardedBy("lock") private final SelectionKey key;
|
||||
@GuardedBy("lock") final StreamParser parser;
|
||||
@GuardedBy("lock") StreamParser parser;
|
||||
@GuardedBy("lock") private boolean closeCalled = false;
|
||||
|
||||
@GuardedBy("lock") private long bytesToWriteRemaining = 0;
|
||||
@ -68,15 +69,15 @@ class ConnectionHandler implements MessageWriteTarget {
|
||||
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.channel = checkNotNull(((SocketChannel)key.channel()));
|
||||
this.parser = parser;
|
||||
if (parser == null) {
|
||||
readBuff = null;
|
||||
closeConnection();
|
||||
return;
|
||||
}
|
||||
this.parser = parser;
|
||||
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)
|
||||
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
|
||||
handler.readBuff.flip();
|
||||
// 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);
|
||||
// Now drop the bytes which were read by compacting readBuff (resetting limit and keeping relative
|
||||
// position)
|
||||
|
@ -17,6 +17,7 @@ package com.google.bitcoin.net.discovery;
|
||||
|
||||
import com.google.bitcoin.core.NetworkParameters;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
@ -42,6 +43,7 @@ public class SeedPeers implements PeerDiscovery {
|
||||
* @return InetSocketAddress - The address/port of the next node.
|
||||
* @throws PeerDiscoveryException
|
||||
*/
|
||||
@Nullable
|
||||
public InetSocketAddress getPeer() throws PeerDiscoveryException {
|
||||
try {
|
||||
return nextPeer();
|
||||
@ -50,6 +52,7 @@ public class SeedPeers implements PeerDiscovery {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private InetSocketAddress nextPeer() throws UnknownHostException {
|
||||
if (pnseedIndex >= seedAddrs.length) return null;
|
||||
return new InetSocketAddress(convertAddress(seedAddrs[pnseedIndex++]),
|
||||
|
@ -16,14 +16,6 @@
|
||||
|
||||
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.TransactionBroadcaster;
|
||||
import com.google.bitcoin.core.Wallet;
|
||||
@ -32,6 +24,13 @@ import com.google.bitcoin.net.ProtobufParser;
|
||||
import com.google.bitcoin.net.StreamParserFactory;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -120,7 +119,7 @@ public class PaymentChannelServerListener {
|
||||
private PaymentChannelCloseException.CloseReason closeReason;
|
||||
|
||||
// The user-provided event handler
|
||||
@Nonnull private ServerConnectionEventHandler eventHandler;
|
||||
private ServerConnectionEventHandler eventHandler;
|
||||
|
||||
// The payment channel server which does the actual payment channel handling
|
||||
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
|
||||
// disables our double-spend check next)
|
||||
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
|
||||
// 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 org.bitcoin.paymentchannel.Protos;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A connection-specific event handler that handles events generated by client connections on a
|
||||
* {@link PaymentChannelServerListener}
|
||||
@ -30,7 +32,7 @@ public abstract class ServerConnectionEventHandler {
|
||||
private ProtobufParser connectionChannel;
|
||||
// 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()
|
||||
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
|
||||
|
@ -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.
|
||||
*/
|
||||
@Nullable
|
||||
StoredClientChannel getChannel(Sha256Hash id, Sha256Hash contractHash) {
|
||||
lock.lock();
|
||||
try {
|
||||
|
@ -18,6 +18,7 @@ package com.google.bitcoin.protocols.channels;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
|
||||
@ -41,8 +42,8 @@ public class StoredServerChannel {
|
||||
private PaymentChannelServer connectedHandler = null;
|
||||
PaymentChannelServerState state = null;
|
||||
|
||||
StoredServerChannel(PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
|
||||
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, byte[] bestValueSignature) {
|
||||
StoredServerChannel(@Nullable PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
|
||||
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, @Nullable byte[] bestValueSignature) {
|
||||
this.contract = contract;
|
||||
this.clientOutput = clientOutput;
|
||||
this.refundTransactionUnlockTimeSecs = refundTransactionUnlockTimeSecs;
|
||||
|
@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@ -458,6 +459,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StoredBlock get(Sha256Hash hash, boolean wasUndoableOnly) throws BlockStoreException {
|
||||
// Optimize for chain head
|
||||
if (chainHeadHash != null && chainHeadHash.equals(hash))
|
||||
@ -467,8 +469,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
maybeConnect();
|
||||
PreparedStatement s = null;
|
||||
try {
|
||||
s = conn.get()
|
||||
.prepareStatement("SELECT chainWork, height, header, wasUndoable FROM headers WHERE hash = ?");
|
||||
s = conn.get().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
|
||||
byte[] hashBytes = new byte[28];
|
||||
System.arraycopy(hash.getBytes(), 3, hashBytes, 0, 28);
|
||||
@ -478,16 +479,13 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
return null;
|
||||
}
|
||||
// Parse it.
|
||||
|
||||
if (wasUndoableOnly && !results.getBoolean(4))
|
||||
return null;
|
||||
|
||||
BigInteger chainWork = new BigInteger(results.getBytes(1));
|
||||
int height = results.getInt(2);
|
||||
Block b = new Block(params, results.getBytes(3));
|
||||
b.verifyHeader();
|
||||
StoredBlock stored = new StoredBlock(b, chainWork, height);
|
||||
return stored;
|
||||
return new StoredBlock(b, chainWork, height);
|
||||
} catch (SQLException ex) {
|
||||
throw new BlockStoreException(ex);
|
||||
} catch (ProtocolException e) {
|
||||
@ -498,21 +496,27 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
// blocks.
|
||||
throw new BlockStoreException(e);
|
||||
} finally {
|
||||
if (s != null)
|
||||
if (s != null) {
|
||||
try {
|
||||
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 {
|
||||
return get(hash, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
|
||||
return get(hash, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
|
||||
maybeConnect();
|
||||
PreparedStatement s = null;
|
||||
@ -629,6 +633,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StoredTransactionOutput getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
|
||||
maybeConnect();
|
||||
PreparedStatement s = null;
|
||||
@ -647,8 +652,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
int height = results.getInt(1);
|
||||
BigInteger value = new BigInteger(results.getBytes(2));
|
||||
// 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 txout;
|
||||
return new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3));
|
||||
} catch (SQLException ex) {
|
||||
throw new BlockStoreException(ex);
|
||||
} finally {
|
||||
|
@ -21,99 +21,10 @@ import com.google.common.base.Objects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serializable;
|
||||
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,
|
||||
* which is required for {@link TransactionOutPoint}
|
||||
@ -203,6 +114,7 @@ class TransactionalHashMap<KeyType, ValueType> {
|
||||
tempMap.remove();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ValueType get(KeyType key) {
|
||||
if (Boolean.TRUE.equals(inTransaction.get())) {
|
||||
if (tempMap.get() != null) {
|
||||
@ -228,6 +140,7 @@ class TransactionalHashMap<KeyType, ValueType> {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ValueType remove(KeyType key) {
|
||||
if (Boolean.TRUE.equals(inTransaction.get())) {
|
||||
ValueType retVal = map.get(key);
|
||||
@ -275,6 +188,7 @@ class TransactionalMultiKeyHashMap<UniqueKeyType, MultiKeyType, ValueType> {
|
||||
mapValues.abortDatabaseBatchWrite();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ValueType get(UniqueKeyType key) {
|
||||
return mapValues.get(key);
|
||||
}
|
||||
@ -291,6 +205,7 @@ class TransactionalMultiKeyHashMap<UniqueKeyType, MultiKeyType, ValueType> {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ValueType removeByUniqueKey(UniqueKeyType key) {
|
||||
return mapValues.remove(key);
|
||||
}
|
||||
@ -360,18 +275,21 @@ public class MemoryFullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
blockMap.put(hash, new StoredBlockAndWasUndoableFlag(storedBlock, true));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
||||
Preconditions.checkNotNull(blockMap, "MemoryFullPrunedBlockStore is closed");
|
||||
StoredBlockAndWasUndoableFlag storedBlock = blockMap.get(hash);
|
||||
return storedBlock == null ? null : storedBlock.block;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized StoredBlock getOnceUndoableStoredBlock(Sha256Hash hash) throws BlockStoreException {
|
||||
Preconditions.checkNotNull(blockMap, "MemoryFullPrunedBlockStore is closed");
|
||||
StoredBlockAndWasUndoableFlag storedBlock = blockMap.get(hash);
|
||||
return (storedBlock != null && storedBlock.wasUndoable) ? storedBlock.block : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized StoredUndoableBlock getUndoBlock(Sha256Hash hash) throws BlockStoreException {
|
||||
Preconditions.checkNotNull(fullBlockMap, "MemoryFullPrunedBlockStore is closed");
|
||||
return fullBlockMap.get(hash);
|
||||
@ -408,6 +326,7 @@ public class MemoryFullPrunedBlockStore implements FullPrunedBlockStore {
|
||||
transactionOutputMap = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized StoredTransactionOutput getTransactionOutput(Sha256Hash hash, long index) throws BlockStoreException {
|
||||
Preconditions.checkNotNull(transactionOutputMap, "MemoryFullPrunedBlockStore is closed");
|
||||
return transactionOutputMap.get(new StoredTransactionOutPoint(hash, index));
|
||||
|
@ -21,6 +21,7 @@ import com.google.bitcoin.utils.Threading;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
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
|
||||
// provide the removeEldestEntry control.
|
||||
protected static final StoredBlock notFoundMarker = new StoredBlock(null, null, -1);
|
||||
protected LinkedHashMap<Sha256Hash, StoredBlock> notFoundCache = new LinkedHashMap<Sha256Hash, StoredBlock>() {
|
||||
protected static final Object notFoundMarker = new Object();
|
||||
protected LinkedHashMap<Sha256Hash, Object> notFoundCache = new LinkedHashMap<Sha256Hash, Object>() {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Sha256Hash, StoredBlock> entry) {
|
||||
protected boolean removeEldestEntry(Map.Entry<Sha256Hash, Object> entry) {
|
||||
return size() > 100; // This was chosen arbitrarily.
|
||||
}
|
||||
};
|
||||
@ -181,6 +182,7 @@ public class SPVBlockStore implements BlockStore {
|
||||
} finally { lock.unlock(); }
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
|
||||
final MappedByteBuffer buffer = this.buffer;
|
||||
if (buffer == null) throw new BlockStoreException("Store closed");
|
||||
|
@ -364,7 +364,10 @@ public class WalletProtobufSerializer {
|
||||
public Wallet readWallet(InputStream input) throws UnreadableWalletException {
|
||||
try {
|
||||
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);
|
||||
readWallet(walletProto, wallet);
|
||||
return wallet;
|
||||
|
@ -25,6 +25,8 @@ import org.slf4j.LoggerFactory;
|
||||
import java.math.BigInteger;
|
||||
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.
|
||||
* 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);
|
||||
continue;
|
||||
}
|
||||
checkNotNull(controllingKey, "Coin selector given output as candidate for which we lack the key");
|
||||
if (controllingKey.getCreationTimeSeconds() >= unixTimeSeconds) continue;
|
||||
// It's older than the cutoff time so select.
|
||||
valueGathered = valueGathered.add(output.getValue());
|
||||
|
Loading…
x
Reference in New Issue
Block a user