From 12c17252602773430ba8072ef0d704d168507438 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Tue, 6 Dec 2022 11:22:35 +0200 Subject: [PATCH] fix edge case when loading wallets with matching tx inputs and outputs --- .../sparrow/io/db/WalletNodeReducer.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/io/db/WalletNodeReducer.java b/src/main/java/com/sparrowwallet/sparrow/io/db/WalletNodeReducer.java index 6c28312a..0daf7594 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/db/WalletNodeReducer.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/db/WalletNodeReducer.java @@ -1,5 +1,6 @@ package com.sparrowwallet.sparrow.io.db; +import com.sparrowwallet.drongo.protocol.Sha256Hash; import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex; import com.sparrowwallet.drongo.wallet.WalletNode; import org.jdbi.v3.core.result.LinkedHashMapRowReducer; @@ -8,6 +9,8 @@ import org.jdbi.v3.core.result.RowView; import java.util.Map; public class WalletNodeReducer implements LinkedHashMapRowReducer { + private static final BlockTransactionHashIndex INPUT_MARKER = new BlockTransactionHashIndex(Sha256Hash.ZERO_HASH, 0, null, null, 0, 0); + @Override public void accumulate(Map map, RowView rowView) { WalletNode walletNode = map.computeIfAbsent(rowView.getColumn("walletNode.id", Long.class), id -> rowView.getRow(WalletNode.class)); @@ -20,11 +23,18 @@ public class WalletNodeReducer implements LinkedHashMapRowReducer ref.getId().equals(rowView.getColumn("blockTransactionHashIndex.spentBy", Long.class))).findFirst().orElseThrow(); + BlockTransactionHashIndex spentBy = walletNode.getTransactionOutputs().stream().filter(ref -> ref.getId().equals(rowView.getColumn("blockTransactionHashIndex.spentBy", Long.class))).findFirst() + .orElseThrow(() -> new IllegalStateException("Cannot find transaction output for " + rowView.getColumn("blockTransactionHashIndex.spentBy", Long.class))); blockTransactionHashIndex.setSpentBy(spentBy); walletNode.getTransactionOutputs().remove(spentBy); + spentBy.setSpentBy(null); + } + if(!walletNode.getTransactionOutputs().add(blockTransactionHashIndex)) { + //Can only happen if we add an input with the same hash, index, height etc as an existing output + //Set a marker we will clear when adding the output + blockTransactionHashIndex.setSpentBy(INPUT_MARKER); + walletNode.getTransactionOutputs().add(blockTransactionHashIndex); } - walletNode.getTransactionOutputs().add(blockTransactionHashIndex); } } }