3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Add data-driven Script tests from the reference client.

This commit is contained in:
Matt Corallo 2012-08-01 20:27:27 +02:00 committed by Mike Hearn
parent 35ff3e1735
commit bf11bf08c3
5 changed files with 1013 additions and 0 deletions

View File

@ -16,11 +16,20 @@
package com.google.bitcoin.core; package com.google.bitcoin.core;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.junit.Test; import org.junit.Test;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class ScriptTest { public class ScriptTest {
// From tx 05e04c26c12fe408a3c1b71aa7996403f6acad1045252b1c62e055496f4d2cb1 on the testnet. // From tx 05e04c26c12fe408a3c1b71aa7996403f6acad1045252b1c62e055496f4d2cb1 on the testnet.
@ -57,4 +66,315 @@ public class ScriptTest {
Script s = new Script(params, bytes, 0, bytes.length); Script s = new Script(params, bytes, 0, bytes.length);
assertTrue(s.isSentToRawPubKey()); assertTrue(s.isSentToRawPubKey());
} }
static HashMap<String, Integer> mapOpNames;
private Script parseScriptString(NetworkParameters params, String string) throws Exception {
if (mapOpNames == null) {
mapOpNames = new HashMap<String, Integer>();
for (int op = Script.OP_NOP; op <= Script.OP_NOP10; op++) {
String name = Script.getOpCodeName((byte)op);
if (name.startsWith("NON_OP("))
continue;
// The reference client's implementation supports OP_*, but we only support *
mapOpNames.put(name, op);
}
}
String[] words = string.split("[ \\t\\n]");
UnsafeByteArrayOutputStream out = new UnsafeByteArrayOutputStream();
for(String w : words) {
if (w.equals(""))
continue;
if (w.matches("^-?[0-9]*$")) {
// Number
long val = Long.parseLong(w);
if (val == -1 || (val >= 1 && val <= 16))
out.write((int)val + Script.OP_1 - 1);
else
Script.writeBytes(out, Utils.reverseBytes(Utils.encodeMPI(BigInteger.valueOf(val), false)));
} else if (w.matches("^0x[0-9a-fA-F]*$")) {
// Raw hex data, inserted NOT pushed onto stack:
out.write(Hex.decode(w.substring(2)));
} else if (w.length() >= 2 && w.startsWith("'") && w.endsWith("'")) {
// Single-quoted string, pushed as data. NOTE: this is poor-man's
// parsing, spaces/tabs/newlines in single-quoted strings won't work.
Script.writeBytes(out, w.substring(1, w.length() - 1).getBytes());
} else if (mapOpNames.containsKey(w)) {
// opcode, e.g. OP_ADD or OP_1:
out.write(mapOpNames.get(w));
} else if (w.startsWith("OP_") && mapOpNames.containsKey(w.substring(3))) {
// opcode, e.g. OP_ADD or OP_1:
out.write(mapOpNames.get(w.substring(3)));
} else {
throw new RuntimeException("Invalid Data");
}
}
return new Script(params, out.toByteArray(), 0, out.size());
}
@Test
public void dataDrivenValidScripts() throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("script_valid.json")));
NetworkParameters params = NetworkParameters.testNet();
// Poor man's JSON parser (because pulling in a lib for this is overkill)
String script = "";
while (in.ready()) {
String line = in.readLine();
script += line;
if (line.equals("]") && script.equals("]") && !in.ready())
break; // ignore last ]
if (line.trim().endsWith("],") || line.trim().endsWith("]")) {
String[] scripts = script.split(",");
Script scriptSig = parseScriptString(params, scripts[0].replaceAll("[\"\\[\\]]", "").trim());
Script scriptPubKey = parseScriptString(params, scripts[1].replaceAll("[\"\\[\\]]", "").trim());
scriptSig.correctlySpends(new Transaction(params), 0, scriptPubKey, true);
script = "";
}
}
in.close();
}
@Test
public void dataDrivenInvalidScripts() throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("script_invalid.json")));
NetworkParameters params = NetworkParameters.testNet();
// Poor man's JSON parser (because pulling in a lib for this is overkill)
String script = "";
while (in.ready()) {
String line = in.readLine();
script += line;
if (line.equals("]") && script.equals("]") && !in.ready())
break; // ignore last ]
if (line.trim().endsWith("],") || line.trim().equals("]")) {
String[] scripts = script.split(",");
try {
Script scriptSig = parseScriptString(params, scripts[0].replaceAll("[\"\\[\\]]", "").trim());
Script scriptPubKey = parseScriptString(params, scripts[1].replaceAll("[\"\\[\\]]", "").trim());
scriptSig.correctlySpends(new Transaction(params), 0, scriptPubKey, true);
fail();
} catch (VerificationException e) {}
catch (ScriptException e) {}
script = "";
}
}
in.close();
}
class JSONObject {
String string;
List<JSONObject> list;
boolean booleanValue;
Integer integer;
JSONObject(String string) { this.string = string; }
JSONObject(List<JSONObject> list) { this.list = list; }
JSONObject(Integer integer) { this.integer = integer; }
JSONObject(boolean value) { this.booleanValue = value; }
boolean isList() { return list != null; }
boolean isString() { return string != null; }
boolean isInteger() { return integer != null; }
boolean isBoolean() { return !isList() && !isString() && !isInteger(); }
}
private boolean appendToList(List<JSONObject> tx, StringBuffer buffer) {
if (buffer.length() == 0)
return true;
switch(buffer.charAt(0)) {
case '[':
int closePos = 0;
boolean inString = false;
int inArray = 0;
for (int i = 1; i < buffer.length() && closePos == 0; i++) {
switch (buffer.charAt(i)) {
case '"':
if (buffer.charAt(i-1) != '\\')
inString = !inString;
break;
case ']':
if (!inString) {
if (inArray == 0)
closePos = i;
else
inArray--;
}
break;
case '[':
if (!inString)
inArray++;
break;
}
}
if (inArray != 0 || closePos == 0)
return false;
List<JSONObject> subList = new ArrayList<JSONObject>(5);
StringBuffer subBuff = new StringBuffer(buffer.substring(1, closePos));
boolean finished = appendToList(subList, subBuff);
if (finished) {
buffer.delete(0, closePos + 1);
tx.add(new JSONObject(subList));
return appendToList(tx, buffer);
} else
return false;
case '"':
int finishPos = 0;
do {
finishPos = buffer.indexOf("\"", finishPos + 1);
} while (finishPos == -1 || buffer.charAt(finishPos - 1) == '\\');
if (finishPos == -1)
return false;
tx.add(new JSONObject(buffer.substring(1, finishPos)));
buffer.delete(0, finishPos + 1);
return appendToList(tx, buffer);
case ',':
case ' ':
buffer.delete(0, 1);
return appendToList(tx, buffer);
default:
String first = buffer.toString().split(",")[0].trim();
if (first.equals("true")) {
tx.add(new JSONObject(true));
buffer.delete(0, 4);
return appendToList(tx, buffer);
} else if (first.equals("false")) {
tx.add(new JSONObject(false));
buffer.delete(0, 5);
return appendToList(tx, buffer);
} else if (first.matches("^-?[0-9]*$")) {
tx.add(new JSONObject(Integer.parseInt(first)));
buffer.delete(0, first.length());
return appendToList(tx, buffer);
} else
fail();
}
return false;
}
@Test
public void dataDrivenValidTransactions() throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("tx_valid.json")));
NetworkParameters params = NetworkParameters.testNet();
// Poor man's (aka. really, really poor) JSON parser (because pulling in a lib for this is probably not overkill)
List<JSONObject> tx = new ArrayList<JSONObject>(3);
in.read(); // remove first [
StringBuffer buffer = new StringBuffer(1000);
while (in.ready()) {
String line = in.readLine();
if (line.equals(""))
continue;
buffer.append(line);
if (line.equals("]") && buffer.toString().equals("]") && !in.ready())
break;
boolean isFinished = appendToList(tx, buffer);
while (tx.size() > 0 && tx.get(0).isList() && tx.get(0).list.size() == 1 && tx.get(0).list.get(0).isString())
tx.remove(0); // ignore last ]
if (isFinished && tx.size() == 1 && tx.get(0).list.size() == 3) {
HashMap<TransactionOutPoint, Script> scriptPubKeys = new HashMap<TransactionOutPoint, Script>();
for (JSONObject input : tx.get(0).list.get(0).list) {
String hash = input.list.get(0).string;
int index = input.list.get(1).integer;
String script = input.list.get(2).string;
scriptPubKeys.put(new TransactionOutPoint(params, index, new Sha256Hash(Hex.decode(hash.getBytes()))), parseScriptString(params, script));
}
Transaction transaction = new Transaction(params, Hex.decode(tx.get(0).list.get(1).string.getBytes()));
boolean enforceP2SH = tx.get(0).list.get(2).booleanValue;
assertTrue(tx.get(0).list.get(2).isBoolean());
transaction.verify();
for (int i = 0; i < transaction.getInputs().size(); i++) {
TransactionInput input = transaction.getInputs().get(i);
if (input.getOutpoint().getIndex() == 0xffffffffL)
input.getOutpoint().setIndex(-1);
assertTrue(scriptPubKeys.containsKey(input.getOutpoint()));
input.getScriptSig().correctlySpends(transaction, i, scriptPubKeys.get(input.getOutpoint()), enforceP2SH);
}
tx.clear();
}
}
in.close();
}
@Test
public void dataDrivenInvalidTransactions() throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("tx_invalid.json")));
NetworkParameters params = NetworkParameters.testNet();
// Poor man's (aka. really, really poor) JSON parser (because pulling in a lib for this is probably not overkill)
List<JSONObject> tx = new ArrayList<JSONObject>(1);
in.read(); // remove first [
StringBuffer buffer = new StringBuffer(1000);
while (in.ready()) {
String line = in.readLine();
if (line.equals(""))
continue;
buffer.append(line);
if (line.equals("]") && buffer.toString().equals("]") && !in.ready())
break; // ignore last ]
boolean isFinished = appendToList(tx, buffer);
while (tx.size() > 0 && tx.get(0).isList() && tx.get(0).list.size() == 1 && tx.get(0).list.get(0).isString())
tx.remove(0);
if (isFinished && tx.size() == 1 && tx.get(0).list.size() == 3) {
HashMap<TransactionOutPoint, Script> scriptPubKeys = new HashMap<TransactionOutPoint, Script>();
for (JSONObject input : tx.get(0).list.get(0).list) {
String hash = input.list.get(0).string;
int index = input.list.get(1).integer;
String script = input.list.get(2).string;
scriptPubKeys.put(new TransactionOutPoint(params, index, new Sha256Hash(Hex.decode(hash.getBytes()))), parseScriptString(params, script));
}
Transaction transaction = new Transaction(params, Hex.decode(tx.get(0).list.get(1).string.getBytes()));
boolean enforceP2SH = tx.get(0).list.get(2).booleanValue;
assertTrue(tx.get(0).list.get(2).isBoolean());
boolean valid = true;
try {
transaction.verify();
} catch (VerificationException e) {
valid = false;
}
// The reference client checks this case in CheckTransaction, but we leave it to
// later where we will see an attempt to double-spend, so we explicitly check here
HashSet<TransactionOutPoint> set = new HashSet<TransactionOutPoint>();
for(TransactionInput input : transaction.getInputs()) {
if (set.contains(input.getOutpoint()))
valid = false;
set.add(input.getOutpoint());
}
for (int i = 0; i < transaction.getInputs().size() && valid; i++) {
TransactionInput input = transaction.getInputs().get(i);
assertTrue(scriptPubKeys.containsKey(input.getOutpoint()));
try {
input.getScriptSig().correctlySpends(transaction, i, scriptPubKeys.get(input.getOutpoint()), enforceP2SH);
} catch (VerificationException e) {
valid = false;
}
catch (ScriptException e) {
valid = false;
}
}
if (valid)
fail();
tx.clear();
}
}
in.close();
}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,64 @@
[
["The following are deserialized transactions which are invalid."],
["They are in the form"],
["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"],
["serializedTransaction, enforceP2SH]"],
["Objects that are only a single string (like this one) are ignored"],
["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"],
[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]],
"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true],
["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"],
["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"],
["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
["An invalid P2SH Transaction"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true],
["Tests for CTransaction::CheckTransaction()"],
["No inputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"0100000000010000000000000000015100000000", true],
["No outputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true],
["Negative output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xae609aca8061d77c5e111f6bb62501a6bbe2bfdb EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", true],
["MAX_MONEY + 1 output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true],
["MAX_MONEY output + 1 output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true],
["Duplicate inputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x236d0639db62b0773fd8ac34dc85ae19e9aba80a EQUAL"]],
"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", true],
["Coinbase of size 1"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", true],
["Coinbase of size 101"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true],
["Null txin"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true]
]

View File

@ -0,0 +1,71 @@
[
["The following are deserialized transactions which are valid."],
["They are in the form"],
["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"],
["serializedTransaction, enforceP2SH]"],
["Objects that are only a single string (like this one) are ignored"],
["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"],
["See http://r6.ca/blog/20111119T211504Z.html"],
["It is also the first OP_CHECKMULTISIG transaction in standard form"],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true],
["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
["It has an arbitrary extra byte stuffed into the signature at pos length - 2"],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true],
["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"],
["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"],
[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]],
"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true],
["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"],
["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"],
[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"],
["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]],
"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true],
["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"],
["It results in signing the constant 1, instead of something generated based on the transaction,"],
["when the input doing the signing has an index greater than the maximum output index"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]],
"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true],
["An invalid P2SH Transaction"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false],
["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true],
["Tests for CTransaction::CheckTransaction()"],
["MAX_MONEY output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true],
["MAX_MONEY output + 0 output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true],
["Coinbase of size 2"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true],
["Coinbase of size 100"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true]
]