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:
parent
35ff3e1735
commit
bf11bf08c3
@ -16,11 +16,20 @@
|
||||
|
||||
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.spongycastle.util.encoders.Hex;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class ScriptTest {
|
||||
// From tx 05e04c26c12fe408a3c1b71aa7996403f6acad1045252b1c62e055496f4d2cb1 on the testnet.
|
||||
@ -57,4 +66,315 @@ public class ScriptTest {
|
||||
Script s = new Script(params, bytes, 0, bytes.length);
|
||||
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
@ -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]
|
||||
]
|
@ -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]
|
||||
]
|
Loading…
Reference in New Issue
Block a user