Commit c3362447 authored by Daniel Connolly's avatar Daniel Connolly

Merge ilozanof updates

parents 211c5fa7 d4f474db
......@@ -2,6 +2,7 @@
* Copyright 2011 Google Inc.
* Copyright 2014 Andreas Schildbach
* Copyright 2014-2016 the libsecp256k1 contributors
* Copyright 2018 the bitcoinj-cash developers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -14,10 +15,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file has been modified by the bitcoinj-cash developers for the bitcoinj-cash project.
* The original file was from the bitcoinj project (https://github.com/bitcoinj/bitcoinj).
*/
package org.bitcoinj.core;
import org.bitcoinj.core.VerificationException.*;
import org.bitcoinj.crypto.*;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
......@@ -580,19 +585,15 @@ public class ECKey implements EncryptableItem {
decoder = new ASN1InputStream(bytes);
DLSequence seq = (DLSequence) decoder.readObject();
if (seq == null)
throw new RuntimeException("Reached past end of ASN.1 stream.");
throw new SignatureFormatError("Reached past end of ASN.1 stream.");
ASN1Integer r, s;
try {
r = (ASN1Integer) seq.getObjectAt(0);
s = (ASN1Integer) seq.getObjectAt(1);
} catch (ClassCastException e) {
throw new IllegalArgumentException(e);
}
r = (ASN1Integer) seq.getObjectAt(0);
s = (ASN1Integer) seq.getObjectAt(1);
// OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they should not be
// Thus, we always use the positive versions. See: http://r6.ca/blog/20111119T211504Z.html
return new ECDSASignature(r.getPositiveValue(), s.getPositiveValue());
} catch (IOException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new SignatureFormatError(e);
} finally {
if (decoder != null)
try { decoder.close(); } catch (IOException x) {}
......@@ -713,15 +714,19 @@ public class ECKey implements EncryptableItem {
}
ECDSASigner signer = new ECDSASigner();
ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE);
signer.init(false, params);
try {
ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE);
signer.init(false, params);
return signer.verifySignature(data, signature.r, signature.s);
} catch (NullPointerException e) {
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. Those signatures
// are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
log.error("Caught NPE inside bouncy castle", e);
return false;
} catch (IllegalArgumentException e) {
throw new SignatureFormatError(e);
} catch (ArrayIndexOutOfBoundsException e) {
throw new SignatureFormatError(e);
}
}
......
/*
* Copyright 2011 Google Inc.
* Copyright 2018 the bitcoinj-cash developers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -12,18 +13,36 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file has been modified by the bitcoinj-cash developers for the bitcoinj-cash project.
* The original file was from the bitcoinj project (https://github.com/bitcoinj/bitcoinj).
*/
package org.bitcoinj.core;
@SuppressWarnings("serial")
import org.bitcoinj.script.ScriptError;
public class ScriptException extends VerificationException {
public ScriptException(String msg) {
private ScriptError err = null;
public ScriptException(ScriptError err, String msg) {
super(msg);
this.err = err;
}
public ScriptException(String msg, Exception e) {
public ScriptException(ScriptError err, String msg, Exception e) {
super(msg, e);
this.err = err;
}
public ScriptException(String msg) {
super(msg);
}
public ScriptError getError() {
return err;
}
}
......@@ -160,6 +160,24 @@ public class Transaction extends ChildMessage {
// can properly keep track of optimal encoded size
private int optimalEncodingMessageSize;
public boolean isOpReturn() {
if (getOpReturnData() != null) {
return true;
}
return false;
}
public byte[] getOpReturnData() {
// Only one OP_RETURN output per transaction is allowed as "standard" transaction
// So just return the first OP_RETURN data found
for (TransactionOutput output : outputs) {
if (output.isOpReturn()) {
return output.getOpReturnData();
}
}
return null;
}
/**
* This enum describes the underlying reason the transaction was created. It's useful for rendering wallet GUIs
* more appropriately.
......@@ -953,6 +971,12 @@ public class Transaction extends ChildMessage {
return addOutput(new TransactionOutput(params, this, value, address));
}
public TransactionOutput addData(byte[] data) {
Script script = ScriptBuilder.createOpReturnScript(data);
return addOutput(new TransactionOutput(params, this, Coin.ZERO, script.getProgram()));
}
/**
* Creates an output that pays to the given pubkey directly (no address) with the given value, adds it to this
* transaction, and returns the new output.
......@@ -1063,9 +1087,10 @@ public class Transaction extends ChildMessage {
byte[] redeemScript,
Coin value,
SigHash hashType,
boolean anyoneCanPay)
boolean anyoneCanPay,
Set<Script.VerifyFlag> verifyFlags)
{
Sha256Hash hash = hashForSignatureWitness(inputIndex, redeemScript, value, hashType, anyoneCanPay);
Sha256Hash hash = hashForSignatureWitness(inputIndex, redeemScript, value, hashType, anyoneCanPay, verifyFlags);
return new TransactionSignature(key.sign(hash, aesKey), hashType, anyoneCanPay, true);
}
......@@ -1101,9 +1126,10 @@ public class Transaction extends ChildMessage {
Script redeemScript,
Coin value,
SigHash hashType,
boolean anyoneCanPay)
boolean anyoneCanPay,
Set<Script.VerifyFlag> verifyFlags)
{
Sha256Hash hash = hashForSignatureWitness(inputIndex, redeemScript.getProgram(), value, hashType, anyoneCanPay);
Sha256Hash hash = hashForSignatureWitness(inputIndex, redeemScript.getProgram(), value, hashType, anyoneCanPay, verifyFlags);
return new TransactionSignature(key.sign(hash, aesKey), hashType, anyoneCanPay, true);
}
/**
......@@ -1251,6 +1277,18 @@ public class Transaction extends ChildMessage {
* @param type Should be SigHash.ALL
* @param anyoneCanPay should be false.
*/
public synchronized Sha256Hash hashForSignatureWitness(
int inputIndex,
Script scriptCode,
Coin prevValue,
SigHash type,
boolean anyoneCanPay,
Set<Script.VerifyFlag> verifyFlags)
{
byte[] connectedScript = scriptCode.getProgram();
return hashForSignatureWitness(inputIndex, connectedScript, prevValue, type, anyoneCanPay, verifyFlags);
}
public synchronized Sha256Hash hashForSignatureWitness(
int inputIndex,
Script scriptCode,
......@@ -1259,7 +1297,7 @@ public class Transaction extends ChildMessage {
boolean anyoneCanPay)
{
byte[] connectedScript = scriptCode.getProgram();
return hashForSignatureWitness(inputIndex, connectedScript, prevValue, type, anyoneCanPay);
return hashForSignatureWitness(inputIndex, connectedScript, prevValue, type, anyoneCanPay, null);
}
public synchronized Sha256Hash hashForSignatureWitness(
......@@ -1267,11 +1305,38 @@ public class Transaction extends ChildMessage {
byte[] connectedScript,
Coin prevValue,
SigHash type,
boolean anyoneCanPay)
boolean anyoneCanPay) {
return hashForSignatureWitness(inputIndex, connectedScript, prevValue, type, anyoneCanPay, null);
}
public synchronized Sha256Hash hashForSignatureWitness(
int inputIndex,
byte[] connectedScript,
Coin prevValue,
SigHash type,
boolean anyoneCanPay,
Set<Script.VerifyFlag> verifyFlags)
{
byte sigHashType = (byte) TransactionSignature.calcSigHashValue(type, anyoneCanPay, true);
ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(length == UNKNOWN_LENGTH ? 256 : length + 4);
try {
// Replay Protection Implementation:
// If the "REPLAY PRIOTECTION" Flag is activated, we implement the Replay Protection Algorithm, which
// allows us the use different Fork IDS in the future. The Fork ID will be stored in the 24 more significant
// bits of nSigHashType (which is not a single byte now, but a 32 one).
// The following implementation is based on the one from bitcoin-abc:
int nSigHashType = sigHashType;
if ((verifyFlags!= null) && verifyFlags.contains(Script.VerifyFlag.REPLAY_PROTECTION)) {
// Legacy chain's value for fork id must be of the form 0xffxxxx.
// By xoring with 0xdead, we ensure that the value will be different
// from the original one, even if it already starts with 0xff.
int forkId = 0; // for now, the forkID is ZERO.
int newForkValue = forkId ^ 0xdead;
nSigHashType = sigHashType | ((0xff0000 | newForkValue) << 8);
}
byte[] hashPrevouts = new byte[32];
byte[] hashSequence = new byte[32];
byte[] hashOutputs = new byte[32];
......@@ -1326,7 +1391,8 @@ public class Transaction extends ChildMessage {
uint32ToByteStreamLE(inputs.get(inputIndex).getSequenceNumber(), bos);
bos.write(hashOutputs);
uint32ToByteStreamLE(this.lockTime, bos);
uint32ToByteStreamLE(0x000000ff & sigHashType, bos);
// uint32ToByteStreamLE(0x000000ff & sigHashType, bos);
uint32ToByteStreamLE(nSigHashType, bos);
} catch (IOException e) {
throw new RuntimeException(e); // Cannot happen.
}
......
......@@ -50,6 +50,23 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class TransactionInput extends ChildMessage {
/** Magic sequence number that indicates there is no sequence number. */
public static final long NO_SEQUENCE = 0xFFFFFFFFL;
/**
* BIP68: If this flag set, sequence is NOT interpreted as a relative lock-time.
*/
public static final long SEQUENCE_LOCKTIME_DISABLE_FLAG = 1L << 31;
/**
* BIP68: If sequence encodes a relative lock-time and this flag is set, the relative lock-time has units of 512
* seconds, otherwise it specifies blocks with a granularity of 1.
*/
public static final long SEQUENCE_LOCKTIME_TYPE_FLAG = 1L << 22;
/**
* BIP68: If sequence encodes a relative lock-time, this mask is applied to extract that lock-time from the sequence
* field.
*/
public static final long SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
private static final byte[] EMPTY_ARRAY = new byte[0];
// Magic outpoint index that indicates the input is in fact unconnected.
private static final long UNCONNECTED = 0xFFFFFFFFL;
......
......@@ -427,4 +427,16 @@ public class TransactionOutput extends ChildMessage {
public int hashCode() {
return Objects.hashCode(value, parent, Arrays.hashCode(scriptBytes));
}
public boolean isOpReturn() {
return getScriptPubKey() != null && getScriptPubKey().isOpReturn();
}
public byte[] getOpReturnData() {
if (isOpReturn()) {
return getScriptPubKey().getChunks().get(1).data;
}
return null;
}
}
/*
* Copyright 2011 Google Inc.
* Copyright 2018 the bitcoinj-cash developers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -12,6 +13,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file has been modified by the bitcoinj-cash developers for the bitcoinj-cash project.
* The original file was from the bitcoinj project (https://github.com/bitcoinj/bitcoinj).
*/
package org.bitcoinj.core;
......@@ -30,15 +34,22 @@ public class VerificationException extends RuntimeException {
super(msg, t);
}
public static class EmptyInputsOrOutputs extends VerificationException {
public EmptyInputsOrOutputs() {
super("Transaction had no inputs or no outputs.");
public static class BlockVersionOutOfDate extends VerificationException {
public BlockVersionOutOfDate(final long version) {
super("Block version #"
+ version + " is outdated.");
}
}
public static class LargerThanMaxBlockSize extends VerificationException {
public LargerThanMaxBlockSize() {
super("Transaction larger than MAX_BLOCK_SIZE");
public static class CoinbaseHeightMismatch extends VerificationException {
public CoinbaseHeightMismatch(final String message) {
super(message);
}
}
public static class CoinbaseScriptSizeOutOfRange extends VerificationException {
public CoinbaseScriptSizeOutOfRange() {
super("Coinbase script size out of range");
}
}
......@@ -48,9 +59,9 @@ public class VerificationException extends RuntimeException {
}
}
public static class NegativeValueOutput extends VerificationException {
public NegativeValueOutput() {
super("Transaction output negative");
public static class EmptyInputsOrOutputs extends VerificationException {
public EmptyInputsOrOutputs() {
super("Transaction had no inputs or no outputs.");
}
}
......@@ -60,30 +71,32 @@ public class VerificationException extends RuntimeException {
}
}
public static class LargerThanMaxBlockSize extends VerificationException {
public LargerThanMaxBlockSize() {
super("Transaction larger than MAX_BLOCK_SIZE");
}
}
public static class CoinbaseScriptSizeOutOfRange extends VerificationException {
public CoinbaseScriptSizeOutOfRange() {
super("Coinbase script size out of range");
public static class NegativeValueOutput extends VerificationException {
public NegativeValueOutput() {
super("Transaction output negative");
}
}
public static class SignatureFormatError extends VerificationException {
public SignatureFormatError(String msg) {
super(msg);
}
public static class BlockVersionOutOfDate extends VerificationException {
public BlockVersionOutOfDate(final long version) {
super("Block version #"
+ version + " is outdated.");
public SignatureFormatError(Exception e) {
super(e);
}
}
public static class UnexpectedCoinbaseInput extends VerificationException {
public UnexpectedCoinbaseInput() {
super("Coinbase input as input in non-coinbase transaction");
}
}
public static class CoinbaseHeightMismatch extends VerificationException {
public CoinbaseHeightMismatch(final String message) {
super(message);
}
}
}
......@@ -89,6 +89,20 @@ public class TransactionSignature extends ECKey.ECDSASignature {
return sighashFlags;
}
/**
* Checkes if the Hashtype is properly set in the signature.
* (from bicopinj-cash)
*
* @param signature Signature
* @return True (correct Hashtype)/ False
*/
public static boolean isValidHashType(byte[] signature) {
boolean result = true;
int hashType = (signature[signature.length-1] & 0xff) & ~(Transaction.SigHash.ANYONECANPAY.value| SigHash.FORKID.value); // mask the byte to prevent sign-extension hurting us
if (hashType < Transaction.SigHash.ALL.value || hashType > Transaction.SigHash.SINGLE.value)
result = false;
return result;
}
/**
* Returns true if the given signature is has canonical encoding, and will thus be accepted as standard by
* Bitcoin Core. DER and the SIGHASH encoding allow for quite some flexibility in how the same structures
......@@ -103,11 +117,9 @@ public class TransactionSignature extends ECKey.ECDSASignature {
// Where R and S are not negative (their first byte has its highest bit not set), and not
// excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
// in which case a single 0 byte is necessary and even required).
if (signature.length < 9 || signature.length > 73)
return false;
int hashType = (signature[signature.length-1] & 0xff) & ~(Transaction.SigHash.ANYONECANPAY.value| SigHash.FORKID.value); // mask the byte to prevent sign-extension hurting us
if (hashType < Transaction.SigHash.ALL.value || hashType > Transaction.SigHash.SINGLE.value)
if (signature.length < 9 || signature.length > 73)
return false;
// "wrong type" "wrong length marker"
......
......@@ -23,6 +23,8 @@
package org.bitcoinj.script;
import org.bitcoinj.core.*;
import org.bitcoinj.core.VerificationException.*;
import org.bitcoinj.crypto.TransactionSignature;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
......@@ -78,12 +80,34 @@ public class Script {
SIGPUSHONLY, // Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
MINIMALDATA, // Require minimal encodings for all push operations and number encodings
DISCOURAGE_UPGRADABLE_NOPS, // Discourage use of NOPs reserved for upgrades (NOP1-10)
MINIMALIF,
NULLFAIL,
CLEANSTACK, // Require that only a single stack element remains after evaluation.
CHECKLOCKTIMEVERIFY, // Enable CHECKLOCKTIMEVERIFY operation
ENABLESIGHASHFORKID,
MONOLITH_OPCODES // May 15, 2018 Hard fork
}
public static final EnumSet<VerifyFlag> ALL_VERIFY_FLAGS = EnumSet.allOf(VerifyFlag.class);
CHECKSEQUENCEVERIFY,
SIGHASH_FORKID,
REPLAY_PROTECTION,
MONOLITH_OPCODES, // May 15, 2018 Hard fork
PUBKEYTYPE // June 26, 29018.
}
// The outcome of the script execution is affected by the Verification flags used. The more verifications are
// implemented, the more restrictions are applied on it. The ALL_VERIFY_FLAGS variable is used to store those
// verifications that can be used as a Basis for executing and validating a Script. So this Set of Flags is used
// through the Bitcoin-core and several tests when some script needs to be executed.
// After the implementation of the last verification Flags, including all of them in this Set is not safe anymore,
// since some of these flags affect the outcome of the script to a big extent, which can make other legacy tests
// to fail.
// For instance, the SIGHASH_FORKID Flag forces the Script engine to expect all the Signatures to have the SIGHASH
// FORK ID bit set. The REPLAY_PROTECTION flag, on the other hand, changes the way the Transaction Hash is
// calculated.
// A possible solution might be to parameterize all the calls to the Script Engine, adding the Flags as a new
// parameter, and refactor the whole project so every single call needs to acknowledge the Verification Flags used.
// This refactoring is a possible solution. At this moment, and in order not to break the existing code and the
// legacy tests, we remove from the SET those flags which affect the Script the most and might break the legacy code
public static final EnumSet<VerifyFlag> ALL_VERIFY_FLAGS = EnumSet.complementOf(EnumSet.of(VerifyFlag.SIGHASH_FORKID, VerifyFlag.REPLAY_PROTECTION));
private static final Logger log = LoggerFactory.getLogger(Script.class);
public static final long MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
......@@ -117,13 +141,13 @@ public class Script {
* validity.
* @param programBytes Array of program bytes from a transaction.
*/
public Script(byte[] programBytes) throws ScriptException {
public Script(byte[] programBytes) {
program = programBytes;
parse(programBytes);
creationTimeSeconds = 0;
}
public Script(byte[] programBytes, long creationTimeSeconds) throws ScriptException {
public Script(byte[] programBytes, long creationTimeSeconds) {
program = programBytes;
parse(programBytes);
this.creationTimeSeconds = creationTimeSeconds;
......@@ -183,7 +207,7 @@ public class Script {
* This is necessary to render the to/from addresses of transactions in a user interface.
* Bitcoin Core does something similar.</p>
*/
private void parse(byte[] program) throws ScriptException {
private void parse(byte[] program) {
chunks = new ArrayList<ScriptChunk>(5); // Common size.
ByteArrayInputStream bis = new ByteArrayInputStream(program);
int initialSize = bis.available();
......@@ -196,16 +220,19 @@ public class Script {
// Read some bytes of data, where how many is the opcode value itself.
dataToRead = opcode;
} else if (opcode == OP_PUSHDATA1) {
if (bis.available() < 1) throw new ScriptException("Unexpected end of script");
if (bis.available() < 1)
throw new ScriptException(ScriptError.SCRIPT_ERR_BAD_OPCODE, "an illegal opcode is present in the script");
dataToRead = bis.read();
} else if (opcode == OP_PUSHDATA2) {
// Read a short, then read that many bytes of data.
if (bis.available() < 2) throw new ScriptException("Unexpected end of script");
if (bis.available() < 2)
throw new ScriptException(ScriptError.SCRIPT_ERR_INVALID_STACK_OPERATION, "he operation was invalid given the contents of the stack");
dataToRead = bis.read() | (bis.read() << 8);
} else if (opcode == OP_PUSHDATA4) {
// Read a uint32, then read that many bytes of data.
// Though this is allowed, because its value cannot be > 520, it should never actually be used
if (bis.available() < 4) throw new ScriptException("Unexpected end of script");
if (bis.available() < 4) throw new ScriptException(ScriptError.SCRIPT_ERR_INVALID_STACK_OPERATION, "he operation was invalid given the contents of the stack");
dataToRead = ((long)bis.read()) | (((long)bis.read()) << 8) | (((long)bis.read()) << 16) | (((long)bis.read()) << 24);
}
......@@ -214,7 +241,7 @@ public class Script {
chunk = new ScriptChunk(opcode, null, startLocationInProgram);
} else {
if (dataToRead > bis.available())
throw new ScriptException("Push of data element that is larger than remaining data");
throw new ScriptException(ScriptError.SCRIPT_ERR_BAD_OPCODE, "an illegal opcode is present in the script");
byte[] data = new byte[(int)dataToRead];
checkState(dataToRead == 0 || bis.read(data, 0, (int)dataToRead) == dataToRead);
chunk = new ScriptChunk(opcode, data, startLocationInProgram);
......@@ -273,13 +300,13 @@ public class Script {
* <p>Otherwise it throws a ScriptException.</p>
*
*/
public byte[] getPubKeyHash() throws ScriptException {
public byte[] getPubKeyHash() {
if (isSentToAddress())
return chunks.get(2).data;
else if (isPayToScriptHash())
return chunks.get(1).data;
else
throw new ScriptException("Script not in the standard scriptPubKey form");
throw new ScriptException(ScriptError.SCRIPT_ERR_STANDARD, "script is not a recognized standard script");
}
/**
......@@ -290,9 +317,9 @@ public class Script {
*
* @throws ScriptException if the script is none of the named forms.
*/
public byte[] getPubKey() throws ScriptException {
public byte[] getPubKey() {
if (chunks.size() != 2) {
throw new ScriptException("Script not of right size, expecting 2 but got " + chunks.size());
throw new ScriptException(ScriptError.SCRIPT_ERR_INVALID_STACK_OPERATION, "he operation was invalid given the contents of the stack");
}
final ScriptChunk chunk0 = chunks.get(0);
final byte[] chunk0data = chunk0.data;
......@@ -305,7 +332,7 @@ public class Script {
// A large constant followed by an OP_CHECKSIG is the key.
return chunk0data;
} else {
throw new ScriptException("Script did not match expected form: " + this);
throw new ScriptException(ScriptError.SCRIPT_ERR_INVALID_STACK_OPERATION, "he operation was invalid given the contents of the stack");
}
}
......@@ -313,7 +340,7 @@ public class Script {
* Retrieves the sender public key from a LOCKTIMEVERIFY transaction
* @throws ScriptException
*/
public byte[] getCLTVPaymentChannelSenderPubKey() throws ScriptException {
public byte[] getCLTVPaymentChannelSenderPubKey() {
if (!isSentToCLTVPaymentChannel()) {
throw new ScriptException("Script not a standard CHECKLOCKTIMVERIFY transaction: " + this);
}
......@@ -324,7 +351,7 @@ public class Script {
* Retrieves the recipient public key from a LOCKTIMEVERIFY transaction
* @throws ScriptException
*/
public byte[] getCLTVPaymentChannelRecipientPubKey() throws ScriptException {
public byte[] getCLTVPaymentChannelRecipientPubKey() {
if (!isSentToCLTVPaymentChannel()) {
throw new ScriptException("Script not a standard CHECKLOCKTIMVERIFY transaction: " + this);
}
......@@ -346,14 +373,14 @@ public class Script {
* transaction can actually receive coins on it. This method may be removed in future.
*/
@Deprecated
public Address getFromAddress(NetworkParameters params) throws ScriptException {
public Address getFromAddress(NetworkParameters params) {
return new Address(params, Utils.sha256hash160(getPubKey()));
}
/**
* Gets the destination address from this script, if it's in the required form (see getPubKey).
*/
public Address getToAddress(NetworkParameters params) throws ScriptException {
public Address getToAddress(NetworkParameters params) {
return getToAddress(params, false);
}
......@@ -364,7 +391,7 @@ public class Script {
* If true, allow payToPubKey to be casted to the corresponding address. This is useful if you prefer
* showing addresses rather than pubkeys.
*/
public Address getToAddress(NetworkParameters params, boolean forcePayToPubKey) throws ScriptException {
public Address getToAddress(NetworkParameters params, boolean forcePayToPubKey) {
if (isSentToAddress())
return new Address(params, getPubKeyHash());
else if (isPayToScriptHash())
......@@ -554,7 +581,7 @@ public class Script {
////////////////////// Interface used during verification of transactions/blocks ////////////////////////////////
private static int getSigOpCount(List<ScriptChunk> chunks, boolean accurate) throws ScriptException {
private static int getSigOpCount(List<ScriptChunk> chunks, boolean accurate) {
int sigOps = 0;
int lastOpCode = OP_INVALIDOPCODE;
for (ScriptChunk chunk : chunks) {
......@@ -603,7 +630,7 @@ public class Script {
/**
* Gets the count of regular SigOps in the script program (counting multisig ops as 20)
*/
public static int getSigOpCount(byte[] program) throws ScriptException {
public static int getSigOpCount(byte[] program) {
Script script = new Script();
try {
script.parse(program);
......@@ -616,7 +643,7 @@ public class Script {
/**
* Gets the count of P2SH Sig Ops in the Script scriptSig
*/
public static long getP2SHSigOpCount(byte[] scriptSig) throws ScriptException {
public static long getP2SHSigOpCount(byte[] scriptSig) {
Script script = new Script();
try {
script.parse(scriptSig);
......@@ -814,7 +841,7 @@ public class Script {
* sizes.
* @throws ScriptException if the chunk is longer than 4 bytes.
*/
private static BigInteger castToBigInteger(byte[] chunk, boolean enforceMinimal) throws ScriptException {
private static BigInteger castToBigInteger(byte[] chunk, boolean enforceMinimal) {
if (chunk.length > DEFAULT_MAX_NUM_ELEMENT_SIZE)
throw new ScriptException("Script attempted to use an integer larger than 4 bytes");
if (enforceMinimal && !Utils.checkMinimallyEncodedLE(chunk, DEFAULT_MAX_NUM_ELEMENT_SIZE))
......@@ -832,7 +859,7 @@ public class Script {
* @param maxLength the maximum length in bytes.
* @throws ScriptException if the chunk is longer than the specified maximum.
*/
private static BigInteger castToBigInteger(final byte[] chunk, final int maxLength, boolean enforceMinimal) throws ScriptException {
private static BigInteger castToBigInteger(final byte[] chunk, final int maxLength, boolean enforceMinimal) {
if (chunk.length > maxLength)
throw new ScriptException("Script attempted to use an integer larger than "
+ maxLength + " bytes");
......@@ -857,7 +884,7 @@ public class Script {
*/
@Deprecated
public static void executeScript(@Nullable Transaction txContainingThis, long index,
Script script, LinkedList<byte[]> stack, boolean enforceNullDummy) throws ScriptException {
Script script, LinkedList<byte[]> stack, boolean enforceNullDummy) {
final EnumSet<VerifyFlag> flags = enforceNullDummy
? EnumSet.of(VerifyFlag.NULLDUMMY)
: EnumSet.noneOf(VerifyFlag.class);
......@@ -867,7 +894,7 @@ public class Script {
@Deprecated
public static void executeScript(@Nullable Transaction txContainingThis, long index,
Script script, LinkedList<byte[]> stack, Set<VerifyFlag> verifyFlags) throws ScriptException {
Script script, LinkedList<byte[]> stack, Set<VerifyFlag> verifyFlags) {
executeScript(txContainingThis, index, script, stack, Coin.ZERO, verifyFlags);
}
......@@ -983,36 +1010,49 @@ public class Script {
stack.add(new byte[] {});
} else if (!chunk.isOpCode()) {
if (chunk.data.length > MAX_SCRIPT_ELEMENT_SIZE)
throw new ScriptException("Attempted to push a data string larger than 520 bytes");
throw new ScriptException(ScriptError.SCRIPT_ERR_PUSH_SIZE, "attempted to push value on the stack that was too large");
if (!shouldExecute)
continue;
if (enforceMinimal && !chunk.isShortestPossiblePushData())
throw new ScriptException(ScriptError.SCRIPT_ERR_MINIMALDATA
, "PushData operation not compliant to Minimal data. A more specific opCode should be used.");
stack.add(chunk.data);