diff --git a/src/main/java/com/sparrowwallet/drongo/crypto/ECKey.java b/src/main/java/com/sparrowwallet/drongo/crypto/ECKey.java index 777883d..13761eb 100644 --- a/src/main/java/com/sparrowwallet/drongo/crypto/ECKey.java +++ b/src/main/java/com/sparrowwallet/drongo/crypto/ECKey.java @@ -116,6 +116,18 @@ public class ECKey { throw new IllegalArgumentException(Hex.toHexString(encoded)); } + /** + * Returns true if the given bytes represent a public key. + */ + public static boolean isPubKey(byte[] encoded) { + if (encoded.length == 33 && (encoded[0] == 0x02 || encoded[0] == 0x03)) + return true; + else if (encoded.length == 65 && encoded[0] == 0x04) + return true; + else + return false; + } + /** * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given encoded point. * The compression state of pub will be preserved. diff --git a/src/main/java/com/sparrowwallet/drongo/protocol/Script.java b/src/main/java/com/sparrowwallet/drongo/protocol/Script.java index b95df67..8b6e77c 100644 --- a/src/main/java/com/sparrowwallet/drongo/protocol/Script.java +++ b/src/main/java/com/sparrowwallet/drongo/protocol/Script.java @@ -106,6 +106,10 @@ public class Script { return Hex.toHexString(getProgram()); } + public List getChunks() { + return Collections.unmodifiableList(chunks); + } + /** * Returns true if this script has the required form to contain a destination address */ @@ -241,6 +245,34 @@ public class Script { return builder.toString().trim(); } + public String toDisplayString() { + StringBuilder builder = new StringBuilder(); + int signatureCount = 1; + int pubKeyCount = 1; + for(ScriptChunk chunk : chunks) { + if(chunk.isSignature()) { + builder.append(""); + } else if(chunk.isScript()) { + Script nestedScript = new Script(chunk.getData()); + if(ScriptPattern.isP2WPKH(nestedScript)) { + builder.append("(OP_0 )"); + } else if(ScriptPattern.isP2WSH(nestedScript)) { + builder.append("(OP_0 )"); + } else { + builder.append("(").append(nestedScript.toDisplayString()).append(")"); + } + } else if(chunk.isPubKey()) { + builder.append(""); + } else { + builder.append(chunk.toString()); + } + + builder.append(" "); + } + + return builder.toString().trim(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/com/sparrowwallet/drongo/protocol/ScriptChunk.java b/src/main/java/com/sparrowwallet/drongo/protocol/ScriptChunk.java index f4c4105..71a184d 100644 --- a/src/main/java/com/sparrowwallet/drongo/protocol/ScriptChunk.java +++ b/src/main/java/com/sparrowwallet/drongo/protocol/ScriptChunk.java @@ -1,6 +1,7 @@ package com.sparrowwallet.drongo.protocol; import com.sparrowwallet.drongo.Utils; +import com.sparrowwallet.drongo.crypto.ECKey; import org.bouncycastle.util.encoders.Hex; import java.io.ByteArrayOutputStream; @@ -73,6 +74,50 @@ public class ScriptChunk { } } + public int getOpcode() { + return opcode; + } + + public byte[] getData() { + return data; + } + + public boolean isSignature() { + if(data == null || data.length == 0) { + return false; + } + + try { + ECKey.ECDSASignature.decodeFromDER(data); + } catch(SignatureDecodeException e) { + return false; + } + + return true; + } + + public boolean isScript() { + if(data == null || data.length == 0) { + return false; + } + + try { + new Script(data); + } catch(ProtocolException e) { + return false; + } + + return true; + } + + public boolean isPubKey() { + if(data == null || data.length == 0) { + return false; + } + + return ECKey.isPubKey(data); + } + public byte[] toByteArray() { ByteArrayOutputStream stream = new ByteArrayOutputStream(); try { @@ -105,7 +150,7 @@ public class ScriptChunk { return "OP_" + getOpCodeName(opcode); } if (data.length == 0) { - return "0"; + return "OP_0"; } return Hex.toHexString(data); diff --git a/src/main/java/com/sparrowwallet/drongo/protocol/TransactionWitness.java b/src/main/java/com/sparrowwallet/drongo/protocol/TransactionWitness.java index 7fb4faf..160c308 100644 --- a/src/main/java/com/sparrowwallet/drongo/protocol/TransactionWitness.java +++ b/src/main/java/com/sparrowwallet/drongo/protocol/TransactionWitness.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class TransactionWitness { @@ -18,6 +19,10 @@ public class TransactionWitness { pushes = new ArrayList<>(Math.min(pushCount, Utils.MAX_INITIAL_ARRAY_LENGTH)); } + public List getPushes() { + return Collections.unmodifiableList(pushes); + } + public void setPush(int i, byte[] value) { while (i >= pushes.size()) { pushes.add(new byte[]{});