mirror of
https://github.com/sparrowwallet/drongo.git
synced 2024-12-27 02:26:44 +00:00
transaction and script parsing improvements
This commit is contained in:
parent
14767c3250
commit
0cebee3d22
6 changed files with 46 additions and 12 deletions
|
@ -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();
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue