mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-11-02 05:27:17 +00:00
ScriptException extends VerificationExtension, code cleanup follows
Just cleans up code now that ScriptException extends VerificationExtension.
This commit is contained in:
@@ -153,20 +153,12 @@ public abstract class AbstractBlockChain {
|
|||||||
* exception is thrown. If the block is OK but cannot be connected to the chain at this time, returns false.
|
* exception is thrown. If the block is OK but cannot be connected to the chain at this time, returns false.
|
||||||
* If the block can be connected to the chain, returns true.
|
* If the block can be connected to the chain, returns true.
|
||||||
*/
|
*/
|
||||||
public synchronized boolean add(Block block) throws VerificationException, ScriptException, PrunedException {
|
public synchronized boolean add(Block block) throws VerificationException, PrunedException {
|
||||||
try {
|
try {
|
||||||
return add(block, true);
|
return add(block, true);
|
||||||
} catch (BlockStoreException e) {
|
} catch (BlockStoreException e) {
|
||||||
// TODO: Figure out a better way to propagate this exception to the user.
|
// TODO: Figure out a better way to propagate this exception to the user.
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (ScriptException e) {
|
|
||||||
// TODO: ScriptException should extend VerificationException.
|
|
||||||
try {
|
|
||||||
notSettingChainHead();
|
|
||||||
} catch (BlockStoreException e1) {
|
|
||||||
throw new RuntimeException(e1);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
try {
|
try {
|
||||||
notSettingChainHead();
|
notSettingChainHead();
|
||||||
@@ -210,7 +202,7 @@ public abstract class AbstractBlockChain {
|
|||||||
private long statsBlocksAdded;
|
private long statsBlocksAdded;
|
||||||
|
|
||||||
private synchronized boolean add(Block block, boolean tryConnecting)
|
private synchronized boolean add(Block block, boolean tryConnecting)
|
||||||
throws BlockStoreException, VerificationException, ScriptException, PrunedException {
|
throws BlockStoreException, VerificationException, PrunedException {
|
||||||
// Note on locking: this method runs with the block chain locked. All mutations to the chain are serialized.
|
// Note on locking: this method runs with the block chain locked. All mutations to the chain are serialized.
|
||||||
// This has the undesirable consequence that during block chain download, it's slow to read the current chain
|
// This has the undesirable consequence that during block chain download, it's slow to read the current chain
|
||||||
// head and other chain info because the accessors are constantly waiting for the chain to become free. To
|
// head and other chain info because the accessors are constantly waiting for the chain to become free. To
|
||||||
@@ -528,7 +520,7 @@ public abstract class AbstractBlockChain {
|
|||||||
/**
|
/**
|
||||||
* For each block in orphanBlocks, see if we can now fit it on top of the chain and if so, do so.
|
* For each block in orphanBlocks, see if we can now fit it on top of the chain and if so, do so.
|
||||||
*/
|
*/
|
||||||
private void tryConnectingOrphans() throws VerificationException, ScriptException, BlockStoreException, PrunedException {
|
private void tryConnectingOrphans() throws VerificationException, BlockStoreException, PrunedException {
|
||||||
// For each block in our orphan list, try and fit it onto the head of the chain. If we succeed remove it
|
// For each block in our orphan list, try and fit it onto the head of the chain. If we succeed remove it
|
||||||
// from the list and keep going. If we changed the head of the list at the end of the round try again until
|
// from the list and keep going. If we changed the head of the list at the end of the round try again until
|
||||||
// we can't fit anything else on the top.
|
// we can't fit anything else on the top.
|
||||||
|
|||||||
@@ -601,11 +601,7 @@ public class Block extends Message {
|
|||||||
// comments for MAX_BLOCK_SIGOPS.
|
// comments for MAX_BLOCK_SIGOPS.
|
||||||
int sigOps = 0;
|
int sigOps = 0;
|
||||||
for (Transaction tx : transactions) {
|
for (Transaction tx : transactions) {
|
||||||
try {
|
sigOps += tx.getSigOpCount();
|
||||||
sigOps += tx.getSigOpCount();
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
throw new VerificationException("Unreadable script in transaction");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (sigOps > MAX_BLOCK_SIGOPS)
|
if (sigOps > MAX_BLOCK_SIGOPS)
|
||||||
throw new VerificationException("Block had too many Signature Operations");
|
throw new VerificationException("Block had too many Signature Operations");
|
||||||
|
|||||||
@@ -127,13 +127,8 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
// being added twice (bug) or the block is a BIP30 violator.
|
// being added twice (bug) or the block is a BIP30 violator.
|
||||||
if (blockStore.hasUnspentOutputs(hash, tx.getOutputs().size()))
|
if (blockStore.hasUnspentOutputs(hash, tx.getOutputs().size()))
|
||||||
throw new VerificationException("Block failed BIP30 test!");
|
throw new VerificationException("Block failed BIP30 test!");
|
||||||
if (enforceBIP16) { // We already check non-BIP16 sigops in Block.verifyTransactions(true)
|
if (enforceBIP16) // We already check non-BIP16 sigops in Block.verifyTransactions(true)
|
||||||
try {
|
sigOps += tx.getSigOpCount();
|
||||||
sigOps += tx.getSigOpCount();
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
throw new VerificationException("Invalid script in transaction");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BigInteger totalFees = BigInteger.ZERO;
|
BigInteger totalFees = BigInteger.ZERO;
|
||||||
@@ -159,12 +154,8 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
// TODO: Check we're not spending the genesis transaction here. Satoshis code won't allow it.
|
// TODO: Check we're not spending the genesis transaction here. Satoshis code won't allow it.
|
||||||
valueIn = valueIn.add(prevOut.getValue());
|
valueIn = valueIn.add(prevOut.getValue());
|
||||||
if (enforceBIP16) {
|
if (enforceBIP16) {
|
||||||
try {
|
if (new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length).isPayToScriptHash())
|
||||||
if (new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length).isPayToScriptHash())
|
sigOps += Script.getP2SHSigOpCount(in.getScriptBytes());
|
||||||
sigOps += Script.getP2SHSigOpCount(in.getScriptBytes());
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
throw new VerificationException("Error reading script in transaction");
|
|
||||||
}
|
|
||||||
if (sigOps > Block.MAX_BLOCK_SIGOPS)
|
if (sigOps > Block.MAX_BLOCK_SIGOPS)
|
||||||
throw new VerificationException("Too many P2SH SigOps in block");
|
throw new VerificationException("Too many P2SH SigOps in block");
|
||||||
}
|
}
|
||||||
@@ -182,24 +173,12 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
} catch (ProtocolException e1) {
|
} catch (ProtocolException e1) {
|
||||||
throw new RuntimeException(e1);
|
throw new RuntimeException(e1);
|
||||||
}
|
}
|
||||||
final Script scriptSig;
|
final Script scriptSig = in.getScriptSig();
|
||||||
try {
|
final Script scriptPubKey = new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length);
|
||||||
scriptSig = in.getScriptSig();
|
|
||||||
} catch (ScriptException e2) {
|
|
||||||
throw new VerificationException("Error verifying script", e2);
|
|
||||||
}
|
|
||||||
final Script scriptPubKey;
|
|
||||||
try {
|
|
||||||
scriptPubKey = new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length);
|
|
||||||
} catch (ScriptException e1) {
|
|
||||||
throw new VerificationException("Error verifying script", e1);
|
|
||||||
}
|
|
||||||
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
||||||
public VerificationException call() {
|
public VerificationException call() {
|
||||||
try{
|
try{
|
||||||
scriptSig.correctlySpends(txCache, currentIndex, scriptPubKey, enforceBIP16);
|
scriptSig.correctlySpends(txCache, currentIndex, scriptPubKey, enforceBIP16);
|
||||||
} catch (ScriptException e) {
|
|
||||||
return new VerificationException("Error verifying script: " + e.getMessage());
|
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -208,11 +187,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
scriptVerificationExecutor.execute(future);
|
scriptVerificationExecutor.execute(future);
|
||||||
listScriptVerificationResults.add(future);
|
listScriptVerificationResults.add(future);
|
||||||
|
|
||||||
/*try{
|
//in.getScriptSig().correctlySpends(tx, index, new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length));
|
||||||
in.getScriptSig().correctlySpends(tx, index, new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length));
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
throw new VerificationException("Error verifying script: " + e.getMessage());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
blockStore.removeUnspentTransactionOutput(prevOut);
|
blockStore.removeUnspentTransactionOutput(prevOut);
|
||||||
txOutsSpent.add(prevOut);
|
txOutsSpent.add(prevOut);
|
||||||
@@ -318,13 +293,9 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
throw new VerificationException("Tried to spend coinbase at depth " + (newBlock.getHeight() - prevOut.getHeight()));
|
throw new VerificationException("Tried to spend coinbase at depth " + (newBlock.getHeight() - prevOut.getHeight()));
|
||||||
valueIn = valueIn.add(prevOut.getValue());
|
valueIn = valueIn.add(prevOut.getValue());
|
||||||
if (enforcePayToScriptHash) {
|
if (enforcePayToScriptHash) {
|
||||||
try {
|
Script script = new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length);
|
||||||
Script script = new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length);
|
if (script.isPayToScriptHash())
|
||||||
if (script.isPayToScriptHash())
|
sigOps += Script.getP2SHSigOpCount(in.getScriptBytes());
|
||||||
sigOps += Script.getP2SHSigOpCount(in.getScriptBytes());
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
throw new VerificationException("Error reading script in transaction");
|
|
||||||
}
|
|
||||||
if (sigOps > Block.MAX_BLOCK_SIGOPS)
|
if (sigOps > Block.MAX_BLOCK_SIGOPS)
|
||||||
throw new VerificationException("Too many P2SH SigOps in block");
|
throw new VerificationException("Too many P2SH SigOps in block");
|
||||||
}
|
}
|
||||||
@@ -337,29 +308,18 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
|||||||
// TODO: Find out the underlying issue and create a better work-around
|
// TODO: Find out the underlying issue and create a better work-around
|
||||||
// TODO: Thoroughly test that this fixes the issue like the non-StoredBlock version does
|
// TODO: Thoroughly test that this fixes the issue like the non-StoredBlock version does
|
||||||
final int currentIndex = index;
|
final int currentIndex = index;
|
||||||
final Script scriptSig;
|
final Script scriptSig = in.getScriptSig();
|
||||||
try {
|
final Script scriptPubKey = new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length);
|
||||||
scriptSig = in.getScriptSig();
|
|
||||||
} catch (ScriptException e2) {
|
|
||||||
throw new VerificationException("Error verifying script", e2);
|
|
||||||
}
|
|
||||||
final Script scriptPubKey;
|
|
||||||
try {
|
|
||||||
scriptPubKey = new Script(params, prevOut.getScriptBytes(), 0, prevOut.getScriptBytes().length);
|
|
||||||
} catch (ScriptException e1) {
|
|
||||||
throw new VerificationException("Error verifying script", e1);
|
|
||||||
}
|
|
||||||
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
||||||
public VerificationException call() {
|
public VerificationException call() {
|
||||||
try{
|
try{
|
||||||
scriptSig.correctlySpends(tx, currentIndex, scriptPubKey, enforcePayToScriptHash);
|
scriptSig.correctlySpends(tx, currentIndex, scriptPubKey, enforcePayToScriptHash);
|
||||||
} catch (ScriptException e) {
|
|
||||||
return new VerificationException("Error verifying script: " + e.getMessage());
|
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}});
|
}
|
||||||
|
});
|
||||||
scriptVerificationExecutor.execute(future);
|
scriptVerificationExecutor.execute(future);
|
||||||
listScriptVerificationResults.add(future);
|
listScriptVerificationResults.add(future);
|
||||||
|
|
||||||
|
|||||||
@@ -306,9 +306,6 @@ public class Peer {
|
|||||||
blockChainDownload(Sha256Hash.ZERO_HASH);
|
blockChainDownload(Sha256Hash.ZERO_HASH);
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
log.warn("Block header verification failed", e);
|
log.warn("Block header verification failed", e);
|
||||||
} catch (ScriptException e) {
|
|
||||||
// There are no transactions and thus no scripts in these blocks, so this should never happen.
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (PrunedException e) {
|
} catch (PrunedException e) {
|
||||||
// Unreachable when in SPV mode.
|
// Unreachable when in SPV mode.
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@@ -396,9 +393,6 @@ public class Peer {
|
|||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
// We don't want verification failures to kill the thread.
|
// We don't want verification failures to kill the thread.
|
||||||
log.warn("Block verification failed", e);
|
log.warn("Block verification failed", e);
|
||||||
} catch (ScriptException e) {
|
|
||||||
// We don't want script failures to kill the thread.
|
|
||||||
log.warn("Script exception", e);
|
|
||||||
} catch (PrunedException e) {
|
} catch (PrunedException e) {
|
||||||
// We pruned away some of the data we need to properly handle this block. We need to request the needed
|
// We pruned away some of the data we need to properly handle this block. We need to request the needed
|
||||||
// data from the remote peer and fix things. Or just give up.
|
// data from the remote peer and fix things. Or just give up.
|
||||||
|
|||||||
@@ -867,13 +867,13 @@ public class Script {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BigInteger castToBigInteger(byte[] chunk) throws VerificationException {
|
private static BigInteger castToBigInteger(byte[] chunk) throws ScriptException {
|
||||||
if (chunk.length > 4)
|
if (chunk.length > 4)
|
||||||
throw new VerificationException("Script attempted to use an integer larger than 4 bytes");
|
throw new ScriptException("Script attempted to use an integer larger than 4 bytes");
|
||||||
return Utils.decodeMPI(Utils.reverseBytes(chunk), false);
|
return Utils.decodeMPI(Utils.reverseBytes(chunk), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void executeScript(Transaction txContainingThis, long index, Script script, LinkedList<byte[]> stack) throws ScriptException, VerificationException {
|
private static void executeScript(Transaction txContainingThis, long index, Script script, LinkedList<byte[]> stack) throws ScriptException {
|
||||||
int opCount = 0;
|
int opCount = 0;
|
||||||
int lastCodeSepLocation = 0;
|
int lastCodeSepLocation = 0;
|
||||||
|
|
||||||
@@ -885,7 +885,7 @@ public class Script {
|
|||||||
|
|
||||||
if (!chunk.isOpCode) {
|
if (!chunk.isOpCode) {
|
||||||
if (chunk.data.length > 520)
|
if (chunk.data.length > 520)
|
||||||
throw new VerificationException("Attempted to push a data string larger than 520 bytes");
|
throw new ScriptException("Attempted to push a data string larger than 520 bytes");
|
||||||
|
|
||||||
if (!shouldExecute)
|
if (!shouldExecute)
|
||||||
continue;
|
continue;
|
||||||
@@ -896,17 +896,17 @@ public class Script {
|
|||||||
if (opcode > OP_16) {
|
if (opcode > OP_16) {
|
||||||
opCount++;
|
opCount++;
|
||||||
if (opCount > 201)
|
if (opCount > 201)
|
||||||
throw new VerificationException("More script operations than is allowed");
|
throw new ScriptException("More script operations than is allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == OP_VERIF || opcode == OP_VERNOTIF)
|
if (opcode == OP_VERIF || opcode == OP_VERNOTIF)
|
||||||
throw new VerificationException("Script included OP_VERIF or OP_VERNOTIF");
|
throw new ScriptException("Script included OP_VERIF or OP_VERNOTIF");
|
||||||
|
|
||||||
if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || opcode == OP_RIGHT ||
|
if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || opcode == OP_RIGHT ||
|
||||||
opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || opcode == OP_XOR ||
|
opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || opcode == OP_XOR ||
|
||||||
opcode == OP_2MUL || opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV ||
|
opcode == OP_2MUL || opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV ||
|
||||||
opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT)
|
opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT)
|
||||||
throw new VerificationException("Script included a disabled Script Op.");
|
throw new ScriptException("Script included a disabled Script Op.");
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case OP_IF:
|
case OP_IF:
|
||||||
@@ -915,7 +915,7 @@ public class Script {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_IF on an empty stack");
|
throw new ScriptException("Attempted OP_IF on an empty stack");
|
||||||
ifStack.add(castToBool(stack.pollLast()));
|
ifStack.add(castToBool(stack.pollLast()));
|
||||||
continue;
|
continue;
|
||||||
case OP_NOTIF:
|
case OP_NOTIF:
|
||||||
@@ -924,17 +924,17 @@ public class Script {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_NOTIF on an empty stack");
|
throw new ScriptException("Attempted OP_NOTIF on an empty stack");
|
||||||
ifStack.add(!castToBool(stack.pollLast()));
|
ifStack.add(!castToBool(stack.pollLast()));
|
||||||
continue;
|
continue;
|
||||||
case OP_ELSE:
|
case OP_ELSE:
|
||||||
if (ifStack.isEmpty())
|
if (ifStack.isEmpty())
|
||||||
throw new VerificationException("Attempted OP_ELSE without OP_IF/NOTIF");
|
throw new ScriptException("Attempted OP_ELSE without OP_IF/NOTIF");
|
||||||
ifStack.add(!ifStack.pollLast());
|
ifStack.add(!ifStack.pollLast());
|
||||||
continue;
|
continue;
|
||||||
case OP_ENDIF:
|
case OP_ENDIF:
|
||||||
if (ifStack.isEmpty())
|
if (ifStack.isEmpty())
|
||||||
throw new VerificationException("Attempted OP_ENDIF without OP_IF/NOTIF");
|
throw new ScriptException("Attempted OP_ENDIF without OP_IF/NOTIF");
|
||||||
ifStack.pollLast();
|
ifStack.pollLast();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -969,31 +969,31 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_VERIFY:
|
case OP_VERIFY:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_VERIFY on an empty stack");
|
throw new ScriptException("Attempted OP_VERIFY on an empty stack");
|
||||||
if (!castToBool(stack.pollLast()))
|
if (!castToBool(stack.pollLast()))
|
||||||
throw new VerificationException("OP_VERIFY failed");
|
throw new ScriptException("OP_VERIFY failed");
|
||||||
break;
|
break;
|
||||||
case OP_RETURN:
|
case OP_RETURN:
|
||||||
throw new VerificationException("Script called OP_RETURN");
|
throw new ScriptException("Script called OP_RETURN");
|
||||||
case OP_TOALTSTACK:
|
case OP_TOALTSTACK:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_TOALTSTACK on an empty stack");
|
throw new ScriptException("Attempted OP_TOALTSTACK on an empty stack");
|
||||||
altstack.add(stack.pollLast());
|
altstack.add(stack.pollLast());
|
||||||
break;
|
break;
|
||||||
case OP_FROMALTSTACK:
|
case OP_FROMALTSTACK:
|
||||||
if (altstack.size() < 1)
|
if (altstack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_TOALTSTACK on an empty altstack");
|
throw new ScriptException("Attempted OP_TOALTSTACK on an empty altstack");
|
||||||
stack.add(altstack.pollLast());
|
stack.add(altstack.pollLast());
|
||||||
break;
|
break;
|
||||||
case OP_2DROP:
|
case OP_2DROP:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_2DROP on a stack with size < 2");
|
throw new ScriptException("Attempted OP_2DROP on a stack with size < 2");
|
||||||
stack.pollLast();
|
stack.pollLast();
|
||||||
stack.pollLast();
|
stack.pollLast();
|
||||||
break;
|
break;
|
||||||
case OP_2DUP:
|
case OP_2DUP:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_2DUP on a stack with size < 2");
|
throw new ScriptException("Attempted OP_2DUP on a stack with size < 2");
|
||||||
Iterator<byte[]> it2DUP = stack.descendingIterator();
|
Iterator<byte[]> it2DUP = stack.descendingIterator();
|
||||||
byte[] OP2DUPtmpChunk2 = it2DUP.next();
|
byte[] OP2DUPtmpChunk2 = it2DUP.next();
|
||||||
stack.add(it2DUP.next());
|
stack.add(it2DUP.next());
|
||||||
@@ -1001,7 +1001,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_3DUP:
|
case OP_3DUP:
|
||||||
if (stack.size() < 3)
|
if (stack.size() < 3)
|
||||||
throw new VerificationException("Attempted OP_3DUP on a stack with size < 3");
|
throw new ScriptException("Attempted OP_3DUP on a stack with size < 3");
|
||||||
Iterator<byte[]> it3DUP = stack.descendingIterator();
|
Iterator<byte[]> it3DUP = stack.descendingIterator();
|
||||||
byte[] OP3DUPtmpChunk3 = it3DUP.next();
|
byte[] OP3DUPtmpChunk3 = it3DUP.next();
|
||||||
byte[] OP3DUPtmpChunk2 = it3DUP.next();
|
byte[] OP3DUPtmpChunk2 = it3DUP.next();
|
||||||
@@ -1011,7 +1011,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_2OVER:
|
case OP_2OVER:
|
||||||
if (stack.size() < 4)
|
if (stack.size() < 4)
|
||||||
throw new VerificationException("Attempted OP_2OVER on a stack with size < 4");
|
throw new ScriptException("Attempted OP_2OVER on a stack with size < 4");
|
||||||
Iterator<byte[]> it2OVER = stack.descendingIterator();
|
Iterator<byte[]> it2OVER = stack.descendingIterator();
|
||||||
it2OVER.next();
|
it2OVER.next();
|
||||||
it2OVER.next();
|
it2OVER.next();
|
||||||
@@ -1021,7 +1021,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_2ROT:
|
case OP_2ROT:
|
||||||
if (stack.size() < 6)
|
if (stack.size() < 6)
|
||||||
throw new VerificationException("Attempted OP_2ROT on a stack with size < 6");
|
throw new ScriptException("Attempted OP_2ROT on a stack with size < 6");
|
||||||
byte[] OP2ROTtmpChunk6 = stack.pollLast();
|
byte[] OP2ROTtmpChunk6 = stack.pollLast();
|
||||||
byte[] OP2ROTtmpChunk5 = stack.pollLast();
|
byte[] OP2ROTtmpChunk5 = stack.pollLast();
|
||||||
byte[] OP2ROTtmpChunk4 = stack.pollLast();
|
byte[] OP2ROTtmpChunk4 = stack.pollLast();
|
||||||
@@ -1037,7 +1037,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_2SWAP:
|
case OP_2SWAP:
|
||||||
if (stack.size() < 4)
|
if (stack.size() < 4)
|
||||||
throw new VerificationException("Attempted OP_2SWAP on a stack with size < 4");
|
throw new ScriptException("Attempted OP_2SWAP on a stack with size < 4");
|
||||||
byte[] OP2SWAPtmpChunk4 = stack.pollLast();
|
byte[] OP2SWAPtmpChunk4 = stack.pollLast();
|
||||||
byte[] OP2SWAPtmpChunk3 = stack.pollLast();
|
byte[] OP2SWAPtmpChunk3 = stack.pollLast();
|
||||||
byte[] OP2SWAPtmpChunk2 = stack.pollLast();
|
byte[] OP2SWAPtmpChunk2 = stack.pollLast();
|
||||||
@@ -1049,7 +1049,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_IFDUP:
|
case OP_IFDUP:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_IFDUP on an empty stack");
|
throw new ScriptException("Attempted OP_IFDUP on an empty stack");
|
||||||
if (castToBool(stack.getLast()))
|
if (castToBool(stack.getLast()))
|
||||||
stack.add(stack.getLast());
|
stack.add(stack.getLast());
|
||||||
break;
|
break;
|
||||||
@@ -1058,24 +1058,24 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_DROP:
|
case OP_DROP:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_DROP on an empty stack");
|
throw new ScriptException("Attempted OP_DROP on an empty stack");
|
||||||
stack.pollLast();
|
stack.pollLast();
|
||||||
break;
|
break;
|
||||||
case OP_DUP:
|
case OP_DUP:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_DUP on an empty stack");
|
throw new ScriptException("Attempted OP_DUP on an empty stack");
|
||||||
stack.add(stack.getLast());
|
stack.add(stack.getLast());
|
||||||
break;
|
break;
|
||||||
case OP_NIP:
|
case OP_NIP:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_NIP on a stack with size < 2");
|
throw new ScriptException("Attempted OP_NIP on a stack with size < 2");
|
||||||
byte[] OPNIPtmpChunk = stack.pollLast();
|
byte[] OPNIPtmpChunk = stack.pollLast();
|
||||||
stack.pollLast();
|
stack.pollLast();
|
||||||
stack.add(OPNIPtmpChunk);
|
stack.add(OPNIPtmpChunk);
|
||||||
break;
|
break;
|
||||||
case OP_OVER:
|
case OP_OVER:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_OVER on a stack with size < 2");
|
throw new ScriptException("Attempted OP_OVER on a stack with size < 2");
|
||||||
Iterator<byte[]> itOVER = stack.descendingIterator();
|
Iterator<byte[]> itOVER = stack.descendingIterator();
|
||||||
itOVER.next();
|
itOVER.next();
|
||||||
stack.add(itOVER.next());
|
stack.add(itOVER.next());
|
||||||
@@ -1083,10 +1083,10 @@ public class Script {
|
|||||||
case OP_PICK:
|
case OP_PICK:
|
||||||
case OP_ROLL:
|
case OP_ROLL:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_PICK/OP_ROLL on an empty stack");
|
throw new ScriptException("Attempted OP_PICK/OP_ROLL on an empty stack");
|
||||||
long val = castToBigInteger(stack.pollLast()).longValue();
|
long val = castToBigInteger(stack.pollLast()).longValue();
|
||||||
if (val < 0 || val >= stack.size())
|
if (val < 0 || val >= stack.size())
|
||||||
throw new VerificationException("OP_PICK/OP_ROLL attempted to get data deeper than stack size");
|
throw new ScriptException("OP_PICK/OP_ROLL attempted to get data deeper than stack size");
|
||||||
Iterator<byte[]> itPICK = stack.descendingIterator();
|
Iterator<byte[]> itPICK = stack.descendingIterator();
|
||||||
for (long i = 0; i < val; i++)
|
for (long i = 0; i < val; i++)
|
||||||
itPICK.next();
|
itPICK.next();
|
||||||
@@ -1097,7 +1097,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_ROT:
|
case OP_ROT:
|
||||||
if (stack.size() < 3)
|
if (stack.size() < 3)
|
||||||
throw new VerificationException("Attempted OP_ROT on a stack with size < 3");
|
throw new ScriptException("Attempted OP_ROT on a stack with size < 3");
|
||||||
byte[] OPROTtmpChunk3 = stack.pollLast();
|
byte[] OPROTtmpChunk3 = stack.pollLast();
|
||||||
byte[] OPROTtmpChunk2 = stack.pollLast();
|
byte[] OPROTtmpChunk2 = stack.pollLast();
|
||||||
byte[] OPROTtmpChunk1 = stack.pollLast();
|
byte[] OPROTtmpChunk1 = stack.pollLast();
|
||||||
@@ -1108,7 +1108,7 @@ public class Script {
|
|||||||
case OP_SWAP:
|
case OP_SWAP:
|
||||||
case OP_TUCK:
|
case OP_TUCK:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_SWAP on a stack with size < 2");
|
throw new ScriptException("Attempted OP_SWAP on a stack with size < 2");
|
||||||
byte[] OPSWAPtmpChunk2 = stack.pollLast();
|
byte[] OPSWAPtmpChunk2 = stack.pollLast();
|
||||||
byte[] OPSWAPtmpChunk1 = stack.pollLast();
|
byte[] OPSWAPtmpChunk1 = stack.pollLast();
|
||||||
stack.add(OPSWAPtmpChunk2);
|
stack.add(OPSWAPtmpChunk2);
|
||||||
@@ -1120,27 +1120,27 @@ public class Script {
|
|||||||
case OP_SUBSTR:
|
case OP_SUBSTR:
|
||||||
case OP_LEFT:
|
case OP_LEFT:
|
||||||
case OP_RIGHT:
|
case OP_RIGHT:
|
||||||
throw new VerificationException("Attempted to use disabled Script Op.");
|
throw new ScriptException("Attempted to use disabled Script Op.");
|
||||||
case OP_SIZE:
|
case OP_SIZE:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_SIZE on an empty stack");
|
throw new ScriptException("Attempted OP_SIZE on an empty stack");
|
||||||
stack.add(Utils.reverseBytes(Utils.encodeMPI(BigInteger.valueOf(stack.getLast().length), false)));
|
stack.add(Utils.reverseBytes(Utils.encodeMPI(BigInteger.valueOf(stack.getLast().length), false)));
|
||||||
break;
|
break;
|
||||||
case OP_INVERT:
|
case OP_INVERT:
|
||||||
case OP_AND:
|
case OP_AND:
|
||||||
case OP_OR:
|
case OP_OR:
|
||||||
case OP_XOR:
|
case OP_XOR:
|
||||||
throw new VerificationException("Attempted to use disabled Script Op.");
|
throw new ScriptException("Attempted to use disabled Script Op.");
|
||||||
case OP_EQUAL:
|
case OP_EQUAL:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_EQUALVERIFY on a stack with size < 2");
|
throw new ScriptException("Attempted OP_EQUALVERIFY on a stack with size < 2");
|
||||||
stack.add(Arrays.equals(stack.pollLast(), stack.pollLast()) ? new byte[] {1} : new byte[] {0});
|
stack.add(Arrays.equals(stack.pollLast(), stack.pollLast()) ? new byte[] {1} : new byte[] {0});
|
||||||
break;
|
break;
|
||||||
case OP_EQUALVERIFY:
|
case OP_EQUALVERIFY:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_EQUALVERIFY on a stack with size < 2");
|
throw new ScriptException("Attempted OP_EQUALVERIFY on a stack with size < 2");
|
||||||
if (!Arrays.equals(stack.pollLast(), stack.pollLast()))
|
if (!Arrays.equals(stack.pollLast(), stack.pollLast()))
|
||||||
throw new VerificationException("OP_EQUALVERIFY: non-equal data");
|
throw new ScriptException("OP_EQUALVERIFY: non-equal data");
|
||||||
break;
|
break;
|
||||||
case OP_1ADD:
|
case OP_1ADD:
|
||||||
case OP_1SUB:
|
case OP_1SUB:
|
||||||
@@ -1149,7 +1149,7 @@ public class Script {
|
|||||||
case OP_NOT:
|
case OP_NOT:
|
||||||
case OP_0NOTEQUAL:
|
case OP_0NOTEQUAL:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted a numeric op on an empty stack");
|
throw new ScriptException("Attempted a numeric op on an empty stack");
|
||||||
BigInteger numericOPnum = castToBigInteger(stack.pollLast());
|
BigInteger numericOPnum = castToBigInteger(stack.pollLast());
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
@@ -1184,7 +1184,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_2MUL:
|
case OP_2MUL:
|
||||||
case OP_2DIV:
|
case OP_2DIV:
|
||||||
throw new VerificationException("Attempted to use disabled Script Op.");
|
throw new ScriptException("Attempted to use disabled Script Op.");
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
case OP_SUB:
|
case OP_SUB:
|
||||||
case OP_BOOLAND:
|
case OP_BOOLAND:
|
||||||
@@ -1198,7 +1198,7 @@ public class Script {
|
|||||||
case OP_MIN:
|
case OP_MIN:
|
||||||
case OP_MAX:
|
case OP_MAX:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted a numeric op on a stack with size < 2");
|
throw new ScriptException("Attempted a numeric op on a stack with size < 2");
|
||||||
BigInteger numericOPnum2 = castToBigInteger(stack.pollLast());
|
BigInteger numericOPnum2 = castToBigInteger(stack.pollLast());
|
||||||
BigInteger numericOPnum1 = castToBigInteger(stack.pollLast());
|
BigInteger numericOPnum1 = castToBigInteger(stack.pollLast());
|
||||||
|
|
||||||
@@ -1281,19 +1281,19 @@ public class Script {
|
|||||||
case OP_MOD:
|
case OP_MOD:
|
||||||
case OP_LSHIFT:
|
case OP_LSHIFT:
|
||||||
case OP_RSHIFT:
|
case OP_RSHIFT:
|
||||||
throw new VerificationException("Attempted to use disabled Script Op.");
|
throw new ScriptException("Attempted to use disabled Script Op.");
|
||||||
case OP_NUMEQUALVERIFY:
|
case OP_NUMEQUALVERIFY:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_NUMEQUALVERIFY on a stack with size < 2");
|
throw new ScriptException("Attempted OP_NUMEQUALVERIFY on a stack with size < 2");
|
||||||
BigInteger OPNUMEQUALVERIFYnum2 = castToBigInteger(stack.pollLast());
|
BigInteger OPNUMEQUALVERIFYnum2 = castToBigInteger(stack.pollLast());
|
||||||
BigInteger OPNUMEQUALVERIFYnum1 = castToBigInteger(stack.pollLast());
|
BigInteger OPNUMEQUALVERIFYnum1 = castToBigInteger(stack.pollLast());
|
||||||
|
|
||||||
if (!OPNUMEQUALVERIFYnum1.equals(OPNUMEQUALVERIFYnum2))
|
if (!OPNUMEQUALVERIFYnum1.equals(OPNUMEQUALVERIFYnum2))
|
||||||
throw new VerificationException("OP_NUMEQUALVERIFY failed");
|
throw new ScriptException("OP_NUMEQUALVERIFY failed");
|
||||||
break;
|
break;
|
||||||
case OP_WITHIN:
|
case OP_WITHIN:
|
||||||
if (stack.size() < 3)
|
if (stack.size() < 3)
|
||||||
throw new VerificationException("Attempted OP_WITHIN on a stack with size < 3");
|
throw new ScriptException("Attempted OP_WITHIN on a stack with size < 3");
|
||||||
BigInteger OPWITHINnum3 = castToBigInteger(stack.pollLast());
|
BigInteger OPWITHINnum3 = castToBigInteger(stack.pollLast());
|
||||||
BigInteger OPWITHINnum2 = castToBigInteger(stack.pollLast());
|
BigInteger OPWITHINnum2 = castToBigInteger(stack.pollLast());
|
||||||
BigInteger OPWITHINnum1 = castToBigInteger(stack.pollLast());
|
BigInteger OPWITHINnum1 = castToBigInteger(stack.pollLast());
|
||||||
@@ -1304,7 +1304,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_RIPEMD160:
|
case OP_RIPEMD160:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_RIPEMD160 on an empty stack");
|
throw new ScriptException("Attempted OP_RIPEMD160 on an empty stack");
|
||||||
RIPEMD160Digest digest = new RIPEMD160Digest();
|
RIPEMD160Digest digest = new RIPEMD160Digest();
|
||||||
byte[] dataToHash = stack.pollLast();
|
byte[] dataToHash = stack.pollLast();
|
||||||
digest.update(dataToHash, 0, dataToHash.length);
|
digest.update(dataToHash, 0, dataToHash.length);
|
||||||
@@ -1314,7 +1314,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_SHA1:
|
case OP_SHA1:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_SHA1 on an empty stack");
|
throw new ScriptException("Attempted OP_SHA1 on an empty stack");
|
||||||
try {
|
try {
|
||||||
stack.add(MessageDigest.getInstance("SHA-1").digest(stack.pollLast()));
|
stack.add(MessageDigest.getInstance("SHA-1").digest(stack.pollLast()));
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
@@ -1323,7 +1323,7 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_SHA256:
|
case OP_SHA256:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_SHA256 on an empty stack");
|
throw new ScriptException("Attempted OP_SHA256 on an empty stack");
|
||||||
try {
|
try {
|
||||||
stack.add(MessageDigest.getInstance("SHA-256").digest(stack.pollLast()));
|
stack.add(MessageDigest.getInstance("SHA-256").digest(stack.pollLast()));
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
@@ -1332,12 +1332,12 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
case OP_HASH160:
|
case OP_HASH160:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_HASH160 on an empty stack");
|
throw new ScriptException("Attempted OP_HASH160 on an empty stack");
|
||||||
stack.add(Utils.sha256hash160(stack.pollLast()));
|
stack.add(Utils.sha256hash160(stack.pollLast()));
|
||||||
break;
|
break;
|
||||||
case OP_HASH256:
|
case OP_HASH256:
|
||||||
if (stack.size() < 1)
|
if (stack.size() < 1)
|
||||||
throw new VerificationException("Attempted OP_SHA256 on an empty stack");
|
throw new ScriptException("Attempted OP_SHA256 on an empty stack");
|
||||||
stack.add(Utils.doubleDigest(stack.pollLast()));
|
stack.add(Utils.doubleDigest(stack.pollLast()));
|
||||||
break;
|
break;
|
||||||
case OP_CODESEPARATOR:
|
case OP_CODESEPARATOR:
|
||||||
@@ -1346,7 +1346,7 @@ public class Script {
|
|||||||
case OP_CHECKSIG:
|
case OP_CHECKSIG:
|
||||||
case OP_CHECKSIGVERIFY:
|
case OP_CHECKSIGVERIFY:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_CHECKSIG(VERIFY) on a stack with size < 2");
|
throw new ScriptException("Attempted OP_CHECKSIG(VERIFY) on a stack with size < 2");
|
||||||
byte[] CHECKSIGpubKey = stack.pollLast();
|
byte[] CHECKSIGpubKey = stack.pollLast();
|
||||||
byte[] CHECKSIGsig = stack.pollLast();
|
byte[] CHECKSIGsig = stack.pollLast();
|
||||||
|
|
||||||
@@ -1377,20 +1377,20 @@ public class Script {
|
|||||||
stack.add(CHECKSIGsigValid ? new byte[] {1} : new byte[] {0});
|
stack.add(CHECKSIGsigValid ? new byte[] {1} : new byte[] {0});
|
||||||
else if (opcode == OP_CHECKSIGVERIFY)
|
else if (opcode == OP_CHECKSIGVERIFY)
|
||||||
if (!CHECKSIGsigValid)
|
if (!CHECKSIGsigValid)
|
||||||
throw new VerificationException("Script failed OP_CHECKSIGVERIFY");
|
throw new ScriptException("Script failed OP_CHECKSIGVERIFY");
|
||||||
break;
|
break;
|
||||||
case OP_CHECKMULTISIG:
|
case OP_CHECKMULTISIG:
|
||||||
case OP_CHECKMULTISIGVERIFY:
|
case OP_CHECKMULTISIGVERIFY:
|
||||||
if (stack.size() < 2)
|
if (stack.size() < 2)
|
||||||
throw new VerificationException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < 2");
|
throw new ScriptException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < 2");
|
||||||
int CHECKMULTISIGpubKeyCount = castToBigInteger(stack.pollLast()).intValue();
|
int CHECKMULTISIGpubKeyCount = castToBigInteger(stack.pollLast()).intValue();
|
||||||
if (CHECKMULTISIGpubKeyCount < 0 || CHECKMULTISIGpubKeyCount > 20)
|
if (CHECKMULTISIGpubKeyCount < 0 || CHECKMULTISIGpubKeyCount > 20)
|
||||||
throw new VerificationException("OP_CHECKMULTISIG(VERIFY) with pubkey count out of range");
|
throw new ScriptException("OP_CHECKMULTISIG(VERIFY) with pubkey count out of range");
|
||||||
opCount += CHECKMULTISIGpubKeyCount;
|
opCount += CHECKMULTISIGpubKeyCount;
|
||||||
if (opCount > 201)
|
if (opCount > 201)
|
||||||
throw new VerificationException("Total op count > 201 during OP_CHECKMULTISIG(VERIFY)");
|
throw new ScriptException("Total op count > 201 during OP_CHECKMULTISIG(VERIFY)");
|
||||||
if (stack.size() < CHECKMULTISIGpubKeyCount + 1)
|
if (stack.size() < CHECKMULTISIGpubKeyCount + 1)
|
||||||
throw new VerificationException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < num_of_pubkeys + 2");
|
throw new ScriptException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < num_of_pubkeys + 2");
|
||||||
|
|
||||||
LinkedList<byte[]> CHECKMULTISIGpubkeys = new LinkedList<byte[]>();
|
LinkedList<byte[]> CHECKMULTISIGpubkeys = new LinkedList<byte[]>();
|
||||||
for (int i = 0; i < CHECKMULTISIGpubKeyCount; i++)
|
for (int i = 0; i < CHECKMULTISIGpubKeyCount; i++)
|
||||||
@@ -1398,9 +1398,9 @@ public class Script {
|
|||||||
|
|
||||||
int CHECKMULTISIGsigCount = castToBigInteger(stack.pollLast()).intValue();
|
int CHECKMULTISIGsigCount = castToBigInteger(stack.pollLast()).intValue();
|
||||||
if (CHECKMULTISIGsigCount < 0 || CHECKMULTISIGsigCount > CHECKMULTISIGpubKeyCount)
|
if (CHECKMULTISIGsigCount < 0 || CHECKMULTISIGsigCount > CHECKMULTISIGpubKeyCount)
|
||||||
throw new VerificationException("OP_CHECKMULTISIG(VERIFY) with sig count out of range");
|
throw new ScriptException("OP_CHECKMULTISIG(VERIFY) with sig count out of range");
|
||||||
if (stack.size() < CHECKMULTISIGsigCount + 1)
|
if (stack.size() < CHECKMULTISIGsigCount + 1)
|
||||||
throw new VerificationException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < num_of_pubkeys + num_of_signatures + 3");
|
throw new ScriptException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < num_of_pubkeys + num_of_signatures + 3");
|
||||||
|
|
||||||
LinkedList<byte[]> CHECKMULTISIGsigs = new LinkedList<byte[]>();
|
LinkedList<byte[]> CHECKMULTISIGsigs = new LinkedList<byte[]>();
|
||||||
for (int i = 0; i < CHECKMULTISIGsigCount; i++)
|
for (int i = 0; i < CHECKMULTISIGsigCount; i++)
|
||||||
@@ -1448,7 +1448,7 @@ public class Script {
|
|||||||
stack.add(CHECKMULTISIGValid ? new byte[] {1} : new byte[] {0});
|
stack.add(CHECKMULTISIGValid ? new byte[] {1} : new byte[] {0});
|
||||||
else if (opcode == OP_CHECKMULTISIGVERIFY)
|
else if (opcode == OP_CHECKMULTISIGVERIFY)
|
||||||
if (!CHECKMULTISIGValid)
|
if (!CHECKMULTISIGValid)
|
||||||
throw new VerificationException("Script failed OP_CHECKMULTISIGVERIFY");
|
throw new ScriptException("Script failed OP_CHECKMULTISIGVERIFY");
|
||||||
break;
|
break;
|
||||||
case OP_NOP1:
|
case OP_NOP1:
|
||||||
case OP_NOP2:
|
case OP_NOP2:
|
||||||
@@ -1463,23 +1463,23 @@ public class Script {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new VerificationException("Script used a reserved Op Code");
|
throw new ScriptException("Script used a reserved Op Code");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.size() + altstack.size() > 1000 || stack.size() + altstack.size() < 0)
|
if (stack.size() + altstack.size() > 1000 || stack.size() + altstack.size() < 0)
|
||||||
throw new VerificationException("Stack size exceeded range");
|
throw new ScriptException("Stack size exceeded range");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ifStack.isEmpty())
|
if (!ifStack.isEmpty())
|
||||||
throw new VerificationException("OP_IF/OP_NOTIF without OP_ENDIF");
|
throw new ScriptException("OP_IF/OP_NOTIF without OP_ENDIF");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that this script (interpreted as a scriptSig) correctly spends the given scriptPubKey.
|
* Verifies that this script (interpreted as a scriptSig) correctly spends the given scriptPubKey.
|
||||||
* @throws VerificationException if this script does not correctly spend the scriptPubKey
|
* @throws VerificationException if this script does not correctly spend the scriptPubKey
|
||||||
*/
|
*/
|
||||||
public void correctlySpends(Transaction txContainingThis, long index, Script scriptPubKey, boolean enforceP2SH) throws VerificationException, ScriptException {
|
public void correctlySpends(Transaction txContainingThis, long index, Script scriptPubKey, boolean enforceP2SH) throws ScriptException {
|
||||||
if (program.length > 10000 || scriptPubKey.program.length > 10000)
|
if (program.length > 10000 || scriptPubKey.program.length > 10000)
|
||||||
throw new ScriptException("Script larger than 10,000 bytes");
|
throw new ScriptException("Script larger than 10,000 bytes");
|
||||||
|
|
||||||
@@ -1492,10 +1492,10 @@ public class Script {
|
|||||||
executeScript(txContainingThis, index, scriptPubKey, stack);
|
executeScript(txContainingThis, index, scriptPubKey, stack);
|
||||||
|
|
||||||
if (stack.size() == 0)
|
if (stack.size() == 0)
|
||||||
throw new VerificationException("Stack empty at end of script execution.");
|
throw new ScriptException("Stack empty at end of script execution.");
|
||||||
|
|
||||||
if (!castToBool(stack.pollLast()))
|
if (!castToBool(stack.pollLast()))
|
||||||
throw new VerificationException("Script resulted in a non-true stack");
|
throw new ScriptException("Script resulted in a non-true stack");
|
||||||
|
|
||||||
// P2SH is pay to script hash. It means that the scriptPubKey has a special form which is a valid
|
// P2SH is pay to script hash. It means that the scriptPubKey has a special form which is a valid
|
||||||
// program but it has "useless" form that if evaluated as a normal program always returns true.
|
// program but it has "useless" form that if evaluated as a normal program always returns true.
|
||||||
@@ -1513,7 +1513,7 @@ public class Script {
|
|||||||
if (enforceP2SH && scriptPubKey.isPayToScriptHash()) {
|
if (enforceP2SH && scriptPubKey.isPayToScriptHash()) {
|
||||||
for (ScriptChunk chunk : chunks)
|
for (ScriptChunk chunk : chunks)
|
||||||
if (chunk.isOpCode && (chunk.data[0] & 0xff) > OP_16)
|
if (chunk.isOpCode && (chunk.data[0] & 0xff) > OP_16)
|
||||||
throw new VerificationException("Attempted to spend a P2SH scriptPubKey with a script that contained script ops");
|
throw new ScriptException("Attempted to spend a P2SH scriptPubKey with a script that contained script ops");
|
||||||
|
|
||||||
byte[] scriptPubKeyBytes = p2shStack.pollLast();
|
byte[] scriptPubKeyBytes = p2shStack.pollLast();
|
||||||
Script scriptPubKeyP2SH = new Script(params, scriptPubKeyBytes, 0, scriptPubKeyBytes.length);
|
Script scriptPubKeyP2SH = new Script(params, scriptPubKeyBytes, 0, scriptPubKeyBytes.length);
|
||||||
@@ -1521,10 +1521,10 @@ public class Script {
|
|||||||
executeScript(txContainingThis, index, scriptPubKeyP2SH, p2shStack);
|
executeScript(txContainingThis, index, scriptPubKeyP2SH, p2shStack);
|
||||||
|
|
||||||
if (p2shStack.size() == 0)
|
if (p2shStack.size() == 0)
|
||||||
throw new VerificationException("P2SH stack empty at end of script execution.");
|
throw new ScriptException("P2SH stack empty at end of script execution.");
|
||||||
|
|
||||||
if (!castToBool(p2shStack.pollLast()))
|
if (!castToBool(p2shStack.pollLast()))
|
||||||
throw new VerificationException("P2SH script execution resulted in a non-true stack");
|
throw new ScriptException("P2SH script execution resulted in a non-true stack");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
package com.google.bitcoin.core;
|
package com.google.bitcoin.core;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class ScriptException extends Exception {
|
public class ScriptException extends VerificationException {
|
||||||
|
|
||||||
public ScriptException(String msg) {
|
public ScriptException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
|
|||||||
@@ -601,7 +601,7 @@ public class Wallet implements Serializable {
|
|||||||
* block might change which chain is best causing a reorganize. A re-org can totally change our balance!
|
* block might change which chain is best causing a reorganize. A re-org can totally change our balance!
|
||||||
*/
|
*/
|
||||||
public synchronized void receiveFromBlock(Transaction tx, StoredBlock block,
|
public synchronized void receiveFromBlock(Transaction tx, StoredBlock block,
|
||||||
BlockChain.NewBlockType blockType) throws VerificationException, ScriptException {
|
BlockChain.NewBlockType blockType) throws VerificationException {
|
||||||
receive(tx, block, blockType, false);
|
receive(tx, block, blockType, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,9 +614,8 @@ public class Wallet implements Serializable {
|
|||||||
*
|
*
|
||||||
* @param tx
|
* @param tx
|
||||||
* @throws VerificationException
|
* @throws VerificationException
|
||||||
* @throws ScriptException
|
|
||||||
*/
|
*/
|
||||||
public synchronized void receivePending(Transaction tx) throws VerificationException, ScriptException {
|
public synchronized void receivePending(Transaction tx) throws VerificationException {
|
||||||
// Can run in a peer thread.
|
// Can run in a peer thread.
|
||||||
|
|
||||||
// Ignore it if we already know about this transaction. Receiving a pending transaction never moves it
|
// Ignore it if we already know about this transaction. Receiving a pending transaction never moves it
|
||||||
@@ -718,7 +717,7 @@ public class Wallet implements Serializable {
|
|||||||
|
|
||||||
private synchronized void receive(Transaction tx, StoredBlock block,
|
private synchronized void receive(Transaction tx, StoredBlock block,
|
||||||
BlockChain.NewBlockType blockType,
|
BlockChain.NewBlockType blockType,
|
||||||
boolean reorg) throws VerificationException, ScriptException {
|
boolean reorg) throws VerificationException {
|
||||||
// Runs in a peer thread.
|
// Runs in a peer thread.
|
||||||
BigInteger prevBalance = getBalance();
|
BigInteger prevBalance = getBalance();
|
||||||
|
|
||||||
@@ -884,7 +883,7 @@ public class Wallet implements Serializable {
|
|||||||
* Handle when a transaction becomes newly active on the best chain, either due to receiving a new block or a
|
* Handle when a transaction becomes newly active on the best chain, either due to receiving a new block or a
|
||||||
* re-org making inactive transactions active.
|
* re-org making inactive transactions active.
|
||||||
*/
|
*/
|
||||||
private void processTxFromBestChain(Transaction tx) throws VerificationException, ScriptException {
|
private void processTxFromBestChain(Transaction tx) throws VerificationException {
|
||||||
// This TX may spend our existing outputs even though it was not pending. This can happen in unit
|
// This TX may spend our existing outputs even though it was not pending. This can happen in unit
|
||||||
// tests, if keys are moved between wallets, if we're catching up to the chain given only a set of keys,
|
// tests, if keys are moved between wallets, if we're catching up to the chain given only a set of keys,
|
||||||
// or if a dead coinbase transaction has moved back onto the main chain.
|
// or if a dead coinbase transaction has moved back onto the main chain.
|
||||||
@@ -2179,9 +2178,6 @@ public class Wallet implements Serializable {
|
|||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
log.warn("Received broadcast transaction that does not validate: {}", t);
|
log.warn("Received broadcast transaction that does not validate: {}", t);
|
||||||
log.warn("VerificationException caught", e);
|
log.warn("VerificationException caught", e);
|
||||||
} catch (ScriptException e) {
|
|
||||||
log.warn("Received broadcast transaction with not understood scripts: {}", t);
|
|
||||||
log.warn("ScriptException caught", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class BlockChainTest {
|
|||||||
unitTestParams = NetworkParameters.unitTests();
|
unitTestParams = NetworkParameters.unitTests();
|
||||||
wallet = new Wallet(unitTestParams) {
|
wallet = new Wallet(unitTestParams) {
|
||||||
@Override
|
@Override
|
||||||
public void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType) throws VerificationException, ScriptException {
|
public void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType) throws VerificationException {
|
||||||
super.receiveFromBlock(tx, block, blockType);
|
super.receiveFromBlock(tx, block, blockType);
|
||||||
BlockChainTest.this.block[0] = block;
|
BlockChainTest.this.block[0] = block;
|
||||||
if (tx.isCoinBase()) {
|
if (tx.isCoinBase()) {
|
||||||
|
|||||||
@@ -163,7 +163,6 @@ public class ScriptTest {
|
|||||||
scriptSig.correctlySpends(new Transaction(params), 0, scriptPubKey, true);
|
scriptSig.correctlySpends(new Transaction(params), 0, scriptPubKey, true);
|
||||||
fail();
|
fail();
|
||||||
} catch (VerificationException e) {}
|
} catch (VerificationException e) {}
|
||||||
catch (ScriptException e) {}
|
|
||||||
script = "";
|
script = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,9 +363,6 @@ public class ScriptTest {
|
|||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
catch (ScriptException e) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
|
|||||||
Reference in New Issue
Block a user