From 51b2608abce869d9312cdc5be367ccf26b47671a Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Sun, 14 Jun 2020 14:00:37 +0200 Subject: [PATCH] check if locking script is p2sh, fix output reference bug --- drongo | 2 +- .../sparrow/io/ElectrumServer.java | 20 ++++++++++++++++--- .../sparrow/transaction/InputController.java | 9 ++++++++- .../sparrow/transaction/InputForm.java | 13 ++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/drongo b/drongo index 75701c72..601c11bd 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 75701c725d00a11f7a3931190d029378a04be8f6 +Subproject commit 601c11bd50405cc781bc35f8c680ba4c5e48ae91 diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ElectrumServer.java b/src/main/java/com/sparrowwallet/sparrow/io/ElectrumServer.java index b630918d..49d8bb4d 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/ElectrumServer.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/ElectrumServer.java @@ -228,7 +228,21 @@ public class ElectrumServer { for(Integer index : result.keySet()) { ScriptHashTx[] txes = result.get(index); - Set references = Arrays.stream(txes).map(ScriptHashTx::getBlockchainTransactionHash).filter(ref -> !ref.getHash().equals(transaction.getTxId())).collect(Collectors.toCollection(TreeSet::new)); + int txBlockHeight = 0; + Optional optionalTxHash = Arrays.stream(txes) + .map(ScriptHashTx::getBlockchainTransactionHash) + .filter(ref -> ref.getHash().equals(transaction.getTxId())) + .findFirst(); + if(optionalTxHash.isPresent()) { + txBlockHeight = optionalTxHash.get().getHeight(); + } + + final int minBlockHeight = txBlockHeight; + Set references = Arrays.stream(txes) + .map(ScriptHashTx::getBlockchainTransactionHash) + .filter(ref -> !ref.getHash().equals(transaction.getTxId()) && ref.getHeight() >= minBlockHeight) + .collect(Collectors.toCollection(TreeSet::new)); + blockTransactionHashes.set(index, references); } @@ -934,9 +948,9 @@ public class ElectrumServer { } else { BlockTransaction blockTransaction = transactionMap.get(reference.getHash()); for(TransactionInput input : blockTransaction.getTransaction().getInputs()) { - if(input.getOutpoint().getHash().equals(transaction.getTxId())) { + if(input.getOutpoint().getHash().equals(transaction.getTxId()) && input.getOutpoint().getIndex() == i) { if(blockTransactions.set(i, blockTransaction) != null) { - throw new IllegalStateException("Double spend detected on hash " + reference.getHash()); + throw new IllegalStateException("Double spend detected for output #" + i + " on hash " + reference.getHash()); } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java index bf04306e..19152a38 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java @@ -214,8 +214,15 @@ public class InputController extends TransactionFormController implements Initia } private void initializeScriptFields(TransactionInput txInput, PSBTInput psbtInput) { - //TODO: Is this safe? + //TODO: While we immediately check if the referenced transaction output is P2SH, where this is not present getting the first nested script is not safe Script redeemScript = txInput.getScriptSig().getFirstNestedScript(); + if(redeemScript != null && inputForm.getReferencedTransactionOutput() != null) { + Script lockingScript = inputForm.getReferencedTransactionOutput().getScript(); + if(!ScriptType.P2SH.isScriptType(lockingScript)) { + redeemScript = null; + } + } + if(redeemScript == null && psbtInput != null && psbtInput.getRedeemScript() != null) { addPSBTDecoration(redeemScriptArea, "PSBT Redeem Script", "non-final"); redeemScript = psbtInput.getRedeemScript(); diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java b/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java index def1c4d6..e70743ba 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/InputForm.java @@ -2,9 +2,11 @@ package com.sparrowwallet.sparrow.transaction; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.protocol.TransactionInput; +import com.sparrowwallet.drongo.protocol.TransactionOutput; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTInput; import com.sparrowwallet.drongo.wallet.BlockTransaction; +import com.sparrowwallet.sparrow.io.ElectrumServer; import javafx.fxml.FXMLLoader; import javafx.scene.Node; @@ -38,6 +40,17 @@ public class InputForm extends TransactionForm { return psbtInput; } + public TransactionOutput getReferencedTransactionOutput() { + if(getInputTransactions() != null) { + BlockTransaction inputTransaction = getInputTransactions().get(transactionInput.getOutpoint().getHash()); + if(inputTransaction != null && !inputTransaction.equals(ElectrumServer.UNFETCHABLE_BLOCK_TRANSACTION)) { + return inputTransaction.getTransaction().getOutputs().get((int)transactionInput.getOutpoint().getIndex()); + } + } + + return null; + } + @Override public Node getContents() throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("input.fxml"));