diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java index 5adb5cd1..39b75c7a 100644 --- a/core/src/main/java/org/bitcoinj/core/Transaction.java +++ b/core/src/main/java/org/bitcoinj/core/Transaction.java @@ -20,6 +20,7 @@ package org.bitcoinj.core; import org.bitcoinj.core.TransactionConfidence.ConfidenceType; import org.bitcoinj.crypto.TransactionSignature; import org.bitcoinj.script.Script; +import org.bitcoinj.script.Script.ScriptType; import org.bitcoinj.script.ScriptBuilder; import org.bitcoinj.script.ScriptError; import org.bitcoinj.script.ScriptException; @@ -733,8 +734,8 @@ public class Transaction extends ChildMessage { s.append(" "); s.append("out "); try { - String scriptPubKeyStr = out.getScriptPubKey().toString(); - s.append(!Strings.isNullOrEmpty(scriptPubKeyStr) ? scriptPubKeyStr : ""); + Script scriptPubKey = out.getScriptPubKey(); + s.append(scriptPubKey.getChunks().size() > 0 ? scriptPubKey.toString() : ""); s.append(" "); s.append(out.getValue().toFriendlyString()); if (!out.isAvailableForSpending()) { @@ -745,6 +746,10 @@ public class Transaction extends ChildMessage { s.append(" by "); s.append(spentBy.getParentTransaction().getHashAsString()); } + s.append('\n'); + ScriptType scriptType = scriptPubKey.getScriptType(); + if (scriptType != null) + s.append(" " + scriptType + " addr:" + scriptPubKey.getToAddress(params)); } catch (Exception e) { s.append("[exception: ").append(e.getMessage()).append("]"); } diff --git a/core/src/main/java/org/bitcoinj/script/Script.java b/core/src/main/java/org/bitcoinj/script/Script.java index 4d1e9511..e84a75b7 100644 --- a/core/src/main/java/org/bitcoinj/script/Script.java +++ b/core/src/main/java/org/bitcoinj/script/Script.java @@ -1614,6 +1614,10 @@ public class Script { return ScriptType.P2PK; if (ScriptPattern.isPayToScriptHash(this)) return ScriptType.P2SH; + if (ScriptPattern.isPayToWitnessPubKeyHash(this)) + return ScriptType.P2WPKH; + if (ScriptPattern.isPayToWitnessScriptHash(this)) + return ScriptType.P2WSH; return null; } diff --git a/core/src/main/java/org/bitcoinj/script/ScriptPattern.java b/core/src/main/java/org/bitcoinj/script/ScriptPattern.java index 32391c47..c8f964bd 100644 --- a/core/src/main/java/org/bitcoinj/script/ScriptPattern.java +++ b/core/src/main/java/org/bitcoinj/script/ScriptPattern.java @@ -156,6 +156,34 @@ public class ScriptPattern { return true; } + /** + * Returns true if this script is of the form OP_0 and hash is 20 bytes long. This can only be a P2WPKH + * scriptPubKey. This script type was introduced with segwit. + */ + public static boolean isPayToWitnessPubKeyHash(Script script) { + if (!isPayToWitnessHash(script)) + return false; + List chunks = script.chunks; + if (!chunks.get(0).equalsOpCode(OP_0)) + return false; + byte[] chunk1data = chunks.get(1).data; + return chunk1data != null && chunk1data.length == SegwitAddress.WITNESS_PROGRAM_LENGTH_PKH; + } + + /** + * Returns true if this script is of the form OP_0 and hash is 32 bytes long. This can only be a P2WSH + * scriptPubKey. This script type was introduced with segwit. + */ + public static boolean isPayToWitnessScriptHash(Script script) { + if (!isPayToWitnessHash(script)) + return false; + List chunks = script.chunks; + if (!chunks.get(0).equalsOpCode(OP_0)) + return false; + byte[] chunk1data = chunks.get(1).data; + return chunk1data != null && chunk1data.length == SegwitAddress.WITNESS_PROGRAM_LENGTH_SH; + } + /** * Extract the pubkey hash from a P2WPKH or the script hash from a P2WSH scriptPubKey. It's important that the * script is in the correct form, so you will want to guard calls to this method with diff --git a/core/src/test/java/org/bitcoinj/script/ScriptPatternTest.java b/core/src/test/java/org/bitcoinj/script/ScriptPatternTest.java index 8c334da4..04f737be 100644 --- a/core/src/test/java/org/bitcoinj/script/ScriptPatternTest.java +++ b/core/src/test/java/org/bitcoinj/script/ScriptPatternTest.java @@ -47,10 +47,10 @@ public class ScriptPatternTest { assertTrue(ScriptPattern.isPayToPubKey( ScriptBuilder.createOutputScript(keys.get(0)) )); - assertTrue(ScriptPattern.isPayToWitnessHash( + assertTrue(ScriptPattern.isPayToWitnessPubKeyHash( ScriptBuilder.createOutputScript(SegwitAddress.fromHash(MAINNET, keys.get(0).getPubKeyHash())) )); - assertTrue(ScriptPattern.isPayToWitnessHash( + assertTrue(ScriptPattern.isPayToWitnessScriptHash( ScriptBuilder.createOutputScript(SegwitAddress.fromHash(MAINNET, Sha256Hash.hash(new byte[0]))) )); assertTrue(ScriptPattern.isSentToMultisig(