transaction and script parsing improvements

This commit is contained in:
Craig Raw 2020-04-11 15:04:46 +02:00
parent 14767c3250
commit 0cebee3d22
6 changed files with 46 additions and 12 deletions

View file

@ -23,8 +23,14 @@ public class Script {
protected byte[] program; protected byte[] program;
public Script(byte[] programBytes) { public Script(byte[] programBytes) {
this(programBytes, true);
}
Script(byte[] programBytes, boolean parse) {
program = programBytes; program = programBytes;
parse(programBytes); if(parse) {
parse();
}
} }
public Script(List<ScriptChunk> chunks) { public Script(List<ScriptChunk> chunks) {
@ -38,7 +44,7 @@ public class Script {
new ScriptChunk(ScriptOpCodes.OP_CHECKSIG, null, 24), new ScriptChunk(ScriptOpCodes.OP_CHECKSIG, null, 24),
}; };
private void parse(byte[] program) { void parse() {
chunks = new ArrayList<>(5); // Common size. chunks = new ArrayList<>(5); // Common size.
ByteArrayInputStream bis = new ByteArrayInputStream(program); ByteArrayInputStream bis = new ByteArrayInputStream(program);
int initialSize = bis.available(); int initialSize = bis.available();

View file

@ -110,12 +110,18 @@ public class ScriptChunk {
} }
try { try {
new Script(data); Script script = new Script(data);
//Flaky: Test if contains a non-zero opcode, otherwise not a script
for(ScriptChunk chunk : script.getChunks()) {
if(chunk.getOpcode() != OP_0) {
return true;
}
}
} catch(ProtocolException e) { } catch(ProtocolException e) {
return false; return false;
} }
return true; return false;
} }
public Script getScript() { public Script getScript() {

View file

@ -291,25 +291,25 @@ public class ScriptOpCodes {
} }
/** /**
* Converts the given OpCode into a string (eg "0", "PUSHDATA", or "NON_OP(10)") * Converts the given OpCode into a string (eg "0", "PUSHDATA", or "RETURN_10")
*/ */
public static String getOpCodeName(int opcode) { public static String getOpCodeName(int opcode) {
if (opCodeNameMap.containsKey((Integer)opcode)) { if (opCodeNameMap.containsKey((Integer)opcode)) {
return opCodeNameMap.get(opcode); return opCodeNameMap.get(opcode);
} }
return "NON_OP(" + opcode + ")"; return "RETURN_" + opcode;
} }
/** /**
* Converts the given pushdata OpCode into a string (eg "PUSHDATA2", or "PUSHDATA(23)") * Converts the given pushdata OpCode into a string (eg "PUSHDATA_2", or "PUSHDATA_23")
*/ */
public static String getPushDataName(int opcode) { public static String getPushDataName(int opcode) {
if (opCodeNameMap.containsKey(opcode)) { if (opCodeNameMap.containsKey(opcode)) {
return opCodeNameMap.get(opcode); return opCodeNameMap.get(opcode);
} }
return "PUSHDATA(" + opcode + ")"; return "PUSHDATA_" + opcode;
} }
/** /**

View file

@ -320,6 +320,12 @@ public class Transaction extends TransactionPart {
return inputs.size() == 1 && inputs.get(0).isCoinBase(); return inputs.size() == 1 && inputs.get(0).isCoinBase();
} }
public static boolean isTransaction(byte[] bytes) {
//Incomplete quick test
long version = Utils.readUint32(bytes, 0);
return version > 0 && version < 5;
}
public Sha256Hash hashForSignature(int inputIndex, Script redeemScript, SigHash type, boolean anyoneCanPay) { public Sha256Hash hashForSignature(int inputIndex, Script redeemScript, SigHash type, boolean anyoneCanPay) {
int sigHash = TransactionSignature.calcSigHashValue(type, anyoneCanPay); int sigHash = TransactionSignature.calcSigHashValue(type, anyoneCanPay);
return hashForSignature(inputIndex, redeemScript.getProgram(), (byte) sigHash); return hashForSignature(inputIndex, redeemScript.getProgram(), (byte) sigHash);

View file

@ -45,8 +45,18 @@ public class TransactionInput extends TransactionPart {
public Script getScriptSig() { public Script getScriptSig() {
if(scriptSig == null) { if(scriptSig == null) {
if(isCoinBase()) {
//ScriptSig may be invalid, attempt to parse
scriptSig = new Script(scriptBytes, false);
try {
scriptSig.parse();
} catch (ProtocolException e) {
scriptSig = new Script(scriptSig.getChunks());
}
} else {
scriptSig = new Script(scriptBytes); scriptSig = new Script(scriptBytes);
} }
}
return scriptSig; return scriptSig;
} }

View file

@ -519,9 +519,15 @@ public class PSBT {
} }
public static boolean isPSBT(byte[] b) { public static boolean isPSBT(byte[] b) {
try {
ByteBuffer buffer = ByteBuffer.wrap(b); ByteBuffer buffer = ByteBuffer.wrap(b);
int header = buffer.getInt(); int header = buffer.getInt();
return header == PSBT_MAGIC_INT; return header == PSBT_MAGIC_INT;
} catch (Exception e) {
//ignore
}
return false;
} }
public static boolean isPSBT(String s) { public static boolean isPSBT(String s) {