Skip to content

Commit

Permalink
Create method to remove utxos used for a release transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
julia-zack committed Jan 6, 2025
1 parent 5c9e371 commit b337a78
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 26 deletions.
61 changes: 35 additions & 26 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,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> utxosToUse = activeFederationWallet
.getUTXOProvider()
.getOpenTransactionOutputs(activeFederationWallet.getWatchedAddresses());
settleReleaseRequest(utxosToUse, 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: {}",
Expand Down Expand Up @@ -1295,7 +1305,7 @@ private void migrateFunds(
Keccak256 rskTxHash,
Wallet retiringFederationWallet,
Address activeFederationAddress,
List<UTXO> availableUTXOs) throws IOException {
List<UTXO> utxosToUse) throws IOException {

PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations = provider.getPegoutsWaitingForConfirmations();
Pair<BtcTransaction, List<UTXO>> createResult = createMigrationTransaction(retiringFederationWallet, activeFederationAddress);
Expand All @@ -1310,12 +1320,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(utxosToUse, pegoutsWaitingForConfirmations, migrationTransaction, rskTxHash, amountMigrated);
}

/**
Expand Down Expand Up @@ -1361,11 +1367,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> utxosToUse, PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations, BtcTransaction releaseTransaction, Keccak256 releaseCreationTxHash, Coin requestedAmount) {
removeSpentUtxos(utxosToUse, releaseTransaction);
addPegoutToPegoutsWaitingForConfirmations(pegoutsWaitingForConfirmations, releaseTransaction, releaseCreationTxHash);
savePegoutTxSigHash(releaseTransaction);
logReleaseRequested(releaseCreationTxHash, releaseTransaction, requestedAmount);
logPegoutTransactionCreated(releaseTransaction);
}

private void removeSpentUtxos(List<UTXO> utxosToUse, BtcTransaction releaseTx) {
List<UTXO> utxosToRemove = utxosToUse.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());

utxosToUse.removeAll(utxosToRemove);
}

private void addPegoutToPegoutsWaitingForConfirmations(PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations, BtcTransaction pegoutTransaction, Keccak256 releaseCreationTxHash) {
Expand Down Expand Up @@ -1423,7 +1441,7 @@ private void logPegoutTransactionCreated(BtcTransaction pegoutTransaction) {
private void processPegoutsIndividually(
ReleaseRequestQueue pegoutRequests,
ReleaseTransactionBuilder txBuilder,
List<UTXO> availableUTXOs,
List<UTXO> utxosToUse,
PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations,
Wallet wallet
) {
Expand All @@ -1448,11 +1466,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(utxosToUse, pegoutsWaitingForConfirmations, generatedTransaction, pegoutCreationTxHash, pegoutRequest.getAmount());

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

Expand All @@ -1463,7 +1477,7 @@ private void processPegoutsIndividually(
private void processPegoutsInBatch(
ReleaseRequestQueue pegoutRequests,
ReleaseTransactionBuilder txBuilder,
List<UTXO> availableUTXOs,
List<UTXO> utxosToUse,
PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations,
Wallet wallet,
Transaction rskTx) {
Expand Down Expand Up @@ -1512,18 +1526,13 @@ private void processPegoutsInBatch(
BtcTransaction batchPegoutTransaction = result.getBtcTx();
Keccak256 batchPegoutCreationTxHash = rskTx.getHash();

settleReleaseRequest(pegoutsWaitingForConfirmations, batchPegoutTransaction, batchPegoutCreationTxHash, totalPegoutValue);
settleReleaseRequest(utxosToUse, 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);
}
Expand Down
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
Expand Up @@ -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();
}

Expand Down

0 comments on commit b337a78

Please sign in to comment.