fix bugs with txes with many outputs

This commit is contained in:
Craig Raw 2020-06-18 12:58:59 +02:00
parent 0cd97649cc
commit 800512ee5b
5 changed files with 32 additions and 17 deletions

View file

@ -326,6 +326,7 @@ public class ElectrumServer {
batchRequest.add(reference.getHashAsString(), "blockchain.transaction.get", reference.getHashAsString());
}
String strErrorTx = Sha256Hash.ZERO_HASH.toString();
Map<String, String> result;
try {
result = batchRequest.execute();
@ -333,21 +334,22 @@ public class ElectrumServer {
result = (Map<String, String>)e.getSuccesses();
for(Object hash : e.getErrors().keySet()) {
String txhash = (String)hash;
result.put(txhash, Sha256Hash.ZERO_HASH.toString());
result.put(txhash, strErrorTx);
}
}
Map<Sha256Hash, BlockTransaction> transactionMap = new HashMap<>();
for(String txid : result.keySet()) {
Sha256Hash hash = Sha256Hash.wrap(txid);
String strRawTx = result.get(txid);
if(hash.equals(Sha256Hash.ZERO_HASH)) {
if(strRawTx.equals(strErrorTx)) {
transactionMap.put(hash, UNFETCHABLE_BLOCK_TRANSACTION);
checkReferences.removeIf(ref -> ref.getHash().equals(hash));
continue;
}
byte[] rawtx = Utils.hexToBytes(result.get(txid));
byte[] rawtx = Utils.hexToBytes(strRawTx);
Transaction transaction = new Transaction(rawtx);
Optional<BlockTransactionHash> optionalReference = references.stream().filter(reference -> reference.getHash().equals(hash)).findFirst();
@ -420,12 +422,12 @@ public class ElectrumServer {
Sha256Hash previousHash = input.getOutpoint().getHash();
BlockTransaction previousTransaction = wallet.getTransactions().get(previousHash);
if(previousTransaction.equals(UNFETCHABLE_BLOCK_TRANSACTION)) {
throw new IllegalStateException("Could not retrieve transaction for hash " + reference.getHashAsString());
} else if(previousTransaction == null) {
if(previousTransaction == null) {
//No referenced transaction found, cannot check if spends from wallet
//This is fine so long as all referenced transactions have been returned, in which case this refers to a transaction that does not affect this wallet
continue;
} else if(previousTransaction.equals(UNFETCHABLE_BLOCK_TRANSACTION)) {
throw new IllegalStateException("Could not retrieve transaction for hash " + reference.getHashAsString());
}
Optional<BlockTransactionHash> optionalTxHash = history.stream().filter(txHash -> txHash.getHash().equals(previousHash)).findFirst();
@ -957,13 +959,22 @@ public class ElectrumServer {
if(outputReferences != null) {
for(BlockTransactionHash reference : outputReferences) {
if(reference == UNFETCHABLE_BLOCK_TRANSACTION) {
blockTransactions.set(i, UNFETCHABLE_BLOCK_TRANSACTION);
if(blockTransactions.get(i) == null) {
blockTransactions.set(i, UNFETCHABLE_BLOCK_TRANSACTION);
}
} else {
BlockTransaction blockTransaction = transactionMap.get(reference.getHash());
for(TransactionInput input : blockTransaction.getTransaction().getInputs()) {
if(input.getOutpoint().getHash().equals(transaction.getTxId()) && input.getOutpoint().getIndex() == i) {
if(blockTransactions.set(i, blockTransaction) != null) {
throw new IllegalStateException("Double spend detected for output #" + i + " on hash " + reference.getHash());
if(blockTransaction.equals(UNFETCHABLE_BLOCK_TRANSACTION)) {
if(blockTransactions.get(i) == null) {
blockTransactions.set(i, UNFETCHABLE_BLOCK_TRANSACTION);
}
} else {
for(TransactionInput input : blockTransaction.getTransaction().getInputs()) {
if(input.getOutpoint().getHash().equals(transaction.getTxId()) && input.getOutpoint().getIndex() == i) {
BlockTransaction previousTx = blockTransactions.set(i, blockTransaction);
if(previousTx != null && !previousTx.equals(UNFETCHABLE_BLOCK_TRANSACTION)) {
throw new IllegalStateException("Double spend detected for output #" + i + " on hash " + reference.getHash());
}
}
}
}

View file

@ -85,7 +85,7 @@ public class OutputController extends TransactionFormController implements Initi
if(outputForm.getPsbt() != null) {
spent.setText("Unspent");
} else if(outputForm.getOutputTransactions() != null) {
} else if(outputForm.getOutputTransactions() != null && outputForm.getIndex() < outputForm.getMaxOutputFetched()) {
updateSpent(outputForm.getOutputTransactions());
} else {
spent.setText("Unknown");
@ -96,7 +96,7 @@ public class OutputController extends TransactionFormController implements Initi
}
private void updateSpent(List<BlockTransaction> outputTransactions) {
int outputIndex = outputForm.getTransactionOutputIndex();
int outputIndex = outputForm.getIndex();
spent.setText("Unspent");
if(outputIndex >= 0 && outputIndex < outputTransactions.size()) {

View file

@ -30,10 +30,6 @@ public class OutputForm extends IndexedTransactionForm {
return psbtOutput;
}
public int getTransactionOutputIndex() {
return getTransaction().getOutputs().indexOf(transactionOutput);
}
@Override
public Node getContents() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("output.fxml"));

View file

@ -102,6 +102,10 @@ public class TransactionData {
this.maxOutputFetched = Math.max(maxOutputFetched, pageEnd);
}
public int getMaxOutputFetched() {
return maxOutputFetched;
}
public boolean allOutputsFetched() {
return minOutputFetched == 0 && maxOutputFetched == transaction.getOutputs().size();
}

View file

@ -45,6 +45,10 @@ public abstract class TransactionForm {
return txdata.getOutputTransactions();
}
public int getMaxOutputFetched() {
return txdata.getMaxOutputFetched();
}
public boolean allOutputsFetched() {
return txdata.allOutputsFetched();
}