Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create method to remove utxos used for a release transaction
Browse files Browse the repository at this point in the history
julia-zack committed Jan 3, 2025
1 parent 5c9e371 commit 6600cbc
Showing 2 changed files with 37 additions and 23 deletions.
56 changes: 33 additions & 23 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
Original file line number Diff line number Diff line change
@@ -65,6 +65,7 @@
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;

import org.apache.commons.lang3.tuple.Pair;
@@ -1097,7 +1098,17 @@ private void processSvpFundTransactionUnsigned(Keccak256 rskTxHash, Federation p
BtcTransaction svpFundTransactionUnsigned = createSvpFundTransaction(proposedFederation, spendableValueFromProposedFederation);
provider.setSvpFundTxHashUnsigned(svpFundTransactionUnsigned.getHash());
PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations = provider.getPegoutsWaitingForConfirmations();
settleReleaseRequest(pegoutsWaitingForConfirmations, svpFundTransactionUnsigned, rskTxHash, spendableValueFromProposedFederation);

Wallet activeFederationWallet = getActiveFederationWallet(true);
List<UTXO> availableUTXOs = activeFederationWallet
.getUTXOProvider()
.getOpenTransactionOutputs(activeFederationWallet.getWatchedAddresses());
settleReleaseRequest(availableUTXOs, pegoutsWaitingForConfirmations, svpFundTransactionUnsigned, rskTxHash, spendableValueFromProposedFederation);
} catch (UTXOProviderException e) {
logger.error(
"[processSvpFundTransactionUnsigned] Error when trying to remove spent utxos. Error message: {}",
e.getMessage()
);
} catch (InsufficientMoneyException e) {
logger.error(
"[processSvpFundTransactionUnsigned] Insufficient funds for creating the fund transaction. Error message: {}",
@@ -1310,12 +1321,8 @@ private void migrateFunds(
Coin amountMigrated = selectedUTXOs.stream()
.map(UTXO::getValue)
.reduce(Coin.ZERO, Coin::add);
settleReleaseRequest(pegoutsWaitingForConfirmations, migrationTransaction, rskTxHash, amountMigrated);

// Mark UTXOs as spent
availableUTXOs.removeIf(utxo -> selectedUTXOs.stream().anyMatch(selectedUtxo ->
utxo.getHash().equals(selectedUtxo.getHash()) && utxo.getIndex() == selectedUtxo.getIndex()
));
settleReleaseRequest(availableUTXOs, pegoutsWaitingForConfirmations, migrationTransaction, rskTxHash, amountMigrated);
}

/**
@@ -1361,11 +1368,23 @@ private void processPegoutRequests(Transaction rskTx) {
}
}

private void settleReleaseRequest(PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations, BtcTransaction pegoutTransaction, Keccak256 releaseCreationTxHash, Coin requestedAmount) {
addPegoutToPegoutsWaitingForConfirmations(pegoutsWaitingForConfirmations, pegoutTransaction, releaseCreationTxHash);
savePegoutTxSigHash(pegoutTransaction);
logReleaseRequested(releaseCreationTxHash, pegoutTransaction, requestedAmount);
logPegoutTransactionCreated(pegoutTransaction);
private void settleReleaseRequest(List<UTXO> availableUTXOs, PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations, BtcTransaction releaseTransaction, Keccak256 releaseCreationTxHash, Coin requestedAmount) {
removeSpentUtxos(availableUTXOs, releaseTransaction);
addPegoutToPegoutsWaitingForConfirmations(pegoutsWaitingForConfirmations, releaseTransaction, releaseCreationTxHash);
savePegoutTxSigHash(releaseTransaction);
logReleaseRequested(releaseCreationTxHash, releaseTransaction, requestedAmount);
logPegoutTransactionCreated(releaseTransaction);
}

private void removeSpentUtxos(List<UTXO> availableUTXOs, BtcTransaction releaseTx) {
List<UTXO> utxosToRemove = availableUTXOs.stream()
.filter(utxo -> releaseTx.getInputs().stream().anyMatch(input ->
input.getOutpoint().getHash().equals(utxo.getHash()) && input.getOutpoint().getIndex() == utxo.getIndex())
).toList();

logger.debug("[removeSpentUtxos] Used {} UTXOs for this release", utxosToRemove.size());

availableUTXOs.removeAll(utxosToRemove);
}

private void addPegoutToPegoutsWaitingForConfirmations(PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations, BtcTransaction pegoutTransaction, Keccak256 releaseCreationTxHash) {
@@ -1448,11 +1467,7 @@ private void processPegoutsIndividually(

BtcTransaction generatedTransaction = result.getBtcTx();
Keccak256 pegoutCreationTxHash = pegoutRequest.getRskTxHash();
settleReleaseRequest(pegoutsWaitingForConfirmations, generatedTransaction, pegoutCreationTxHash, pegoutRequest.getAmount());

// Mark UTXOs as spent
List<UTXO> selectedUTXOs = result.getSelectedUTXOs();
availableUTXOs.removeAll(selectedUTXOs);
settleReleaseRequest(availableUTXOs, pegoutsWaitingForConfirmations, generatedTransaction, pegoutCreationTxHash, pegoutRequest.getAmount());

adjustBalancesIfChangeOutputWasDust(generatedTransaction, pegoutRequest.getAmount(), wallet);

@@ -1512,18 +1527,13 @@ private void processPegoutsInBatch(
BtcTransaction batchPegoutTransaction = result.getBtcTx();
Keccak256 batchPegoutCreationTxHash = rskTx.getHash();

settleReleaseRequest(pegoutsWaitingForConfirmations, batchPegoutTransaction, batchPegoutCreationTxHash, totalPegoutValue);
settleReleaseRequest(availableUTXOs, pegoutsWaitingForConfirmations, batchPegoutTransaction, batchPegoutCreationTxHash, totalPegoutValue);

// Remove batched requests from the queue after successfully batching pegouts
pegoutRequests.removeEntries(pegoutEntries);

// Mark UTXOs as spent
List<UTXO> selectedUTXOs = result.getSelectedUTXOs();
logger.debug("[processPegoutsInBatch] used {} UTXOs for this pegout", selectedUTXOs.size());
availableUTXOs.removeAll(selectedUTXOs);

eventLogger.logBatchPegoutCreated(batchPegoutTransaction.getHash(),
pegoutEntries.stream().map(ReleaseRequestQueue.Entry::getRskTxHash).collect(Collectors.toList()));
pegoutEntries.stream().map(ReleaseRequestQueue.Entry::getRskTxHash).toList());

adjustBalancesIfChangeOutputWasDust(batchPegoutTransaction, totalPegoutValue, wallet);
}
4 changes: 4 additions & 0 deletions rskj-core/src/test/java/co/rsk/peg/BridgeSupportSvpTest.java
Original file line number Diff line number Diff line change
@@ -291,13 +291,17 @@ void updateCollections_whenThereAreNoEnoughUTXOs_shouldNotCreateFundTransaction(

@Test
void updateCollections_whenFundTxCanBeCreated_createsExpectedFundTxAndSavesTheHashInStorageEntryAndPerformsPegoutActions() throws Exception {
// arrange
int activeFederationUtxosSizeBeforeCreatingFundTx = federationSupport.getActiveFederationBtcUTXOs().size();

// act
bridgeSupport.updateCollections(rskTx);
bridgeStorageProvider.save();

// assert
Sha256Hash svpFundTxHashUnsigned = assertSvpFundTxHashUnsignedIsInStorage();
assertSvpFundTxReleaseWasSettled(svpFundTxHashUnsigned);
assertActiveFederationUtxosSize(activeFederationUtxosSizeBeforeCreatingFundTx - 1);
assertSvpFundTransactionHasExpectedInputsAndOutputs();
}

0 comments on commit 6600cbc

Please sign in to comment.