Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create updateSvpState method #2838

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 78 additions & 31 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -1010,20 +1010,70 @@ public void updateCollections(Transaction rskTx) throws IOException {
processConfirmedPegouts(rskTx);

updateFederationCreationBlockHeights();

updateSvpState(rskTx);
}

private void logUpdateCollections(Transaction rskTx) {
RskAddress sender = rskTx.getSender(signatureCache);
eventLogger.logUpdateCollections(sender);
}

protected void processSVPFailure(Federation proposedFederation) {
private void updateSvpState(Transaction rskTx) {
Optional<Federation> proposedFederationOpt = federationSupport.getProposedFederation();
if (proposedFederationOpt.isEmpty()) {
marcos-iov marked this conversation as resolved.
Show resolved Hide resolved
logger.trace("[updateSvpState] Proposed federation does not exist, so there's no svp going on.");
return;
}

// if the proposed federation exists and the validation period ended,
// we can conclude that the svp failed
Federation proposedFederation = proposedFederationOpt.get();
if (!validationPeriodIsOngoing(proposedFederation)) {
logger.info(
"[updateSvpState] Proposed federation validation failed at block {}. SVP failure will be processed",
rskExecutionBlock.getNumber()
);
processSvpFailure(proposedFederation);
return;
}

Keccak256 rskTxHash = rskTx.getHash();

if (shouldCreateAndProcessSvpFundTransaction()) {
logger.info(
"[updateSvpState] No svp values were found, so fund tx creation will be processed."
);
processSvpFundTransactionUnsigned(rskTxHash, proposedFederation);
}

// if the fund tx signed is present, then the fund transaction change was registered,
// meaning we can create the spend tx.
Optional<BtcTransaction> svpFundTxSigned = provider.getSvpFundTxSigned();
if (svpFundTxSigned.isPresent()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also be checking that there is no spend tx created? Just in case.

I know there should only be one at a time so if both are found perhaps we have a problem

logger.info(
"[updateSvpState] Fund tx signed was found, so spend tx creation will be processed."
);
processSvpSpendTransactionUnsigned(rskTxHash, proposedFederation, svpFundTxSigned.get());
apancorb marked this conversation as resolved.
Show resolved Hide resolved
}
}

private boolean shouldCreateAndProcessSvpFundTransaction() {
// the fund tx will be created when the svp starts,
// so we must ensure all svp values are clear to proceed with its creation
Optional<Sha256Hash> svpFundTxHashUnsigned = provider.getSvpFundTxHashUnsigned();
Optional<BtcTransaction> svpFundTxSigned = provider.getSvpFundTxSigned();
Optional<Sha256Hash> svpSpendTxHashUnsigned = provider.getSvpSpendTxHashUnsigned(); // spendTxHash will be removed the last, after spendTxWFS, so is enough checking just this value

return svpFundTxHashUnsigned.isEmpty()
&& svpFundTxSigned.isEmpty()
&& svpSpendTxHashUnsigned.isEmpty();
}
julia-zack marked this conversation as resolved.
Show resolved Hide resolved

private void processSvpFailure(Federation proposedFederation) {
eventLogger.logCommitFederationFailure(rskExecutionBlock, proposedFederation);
logger.warn(
"[processSVPFailure] Proposed federation validation failed at block {}, so federation election will be allowed again.",
rskExecutionBlock.getNumber()
);

logger.info("[processSVPFailure] Federation election will be allowed again.");
allowFederationElectionAgain();
}

Expand All @@ -1045,21 +1095,24 @@ private boolean validationPeriodIsOngoing(Federation proposedFederation) {
return rskExecutionBlock.getNumber() < validationPeriodEndBlock;
}

protected void processSvpFundTransactionUnsigned(Transaction rskTx) throws IOException, InsufficientMoneyException {
Optional<Federation> proposedFederationOpt = federationSupport.getProposedFederation();
if (proposedFederationOpt.isEmpty()) {
String message = "Proposed federation should be present when processing SVP fund transaction.";
logger.warn(message);
throw new IllegalStateException(message);
}
Federation proposedFederation = proposedFederationOpt.get();

private void processSvpFundTransactionUnsigned(Keccak256 rskTxHash, Federation proposedFederation) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call this create rather than process?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i named it process to be consistent with processPegoutOrMigration method. But no big deal, I can change it :)

Coin spendableValueFromProposedFederation = bridgeConstants.getSpendableValueFromProposedFederation();
BtcTransaction svpFundTransactionUnsigned = createSvpFundTransaction(proposedFederation, spendableValueFromProposedFederation);

provider.setSvpFundTxHashUnsigned(svpFundTransactionUnsigned.getHash());
PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations = provider.getPegoutsWaitingForConfirmations();
settleReleaseRequest(pegoutsWaitingForConfirmations, svpFundTransactionUnsigned, rskTx.getHash(), spendableValueFromProposedFederation);
try {
BtcTransaction svpFundTransactionUnsigned = createSvpFundTransaction(proposedFederation, spendableValueFromProposedFederation);
provider.setSvpFundTxHashUnsigned(svpFundTransactionUnsigned.getHash());
PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations = provider.getPegoutsWaitingForConfirmations();
settleReleaseRequest(pegoutsWaitingForConfirmations, svpFundTransactionUnsigned, rskTxHash, spendableValueFromProposedFederation);
} catch (InsufficientMoneyException e) {
logger.error(
"[processSvpFundTransactionUnsigned] Insufficient funds for creating the fund transaction. Error message: {}",
e.getMessage()
julia-zack marked this conversation as resolved.
Show resolved Hide resolved
);
} catch (IOException e) {
logger.error(
"[processSvpFundTransactionUnsigned] IOException getting the pegouts waiting for confirmations. Error message: {}",
e.getMessage()
Comment on lines +1111 to +1113
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

);
}
}

private BtcTransaction createSvpFundTransaction(Federation proposedFederation, Coin spendableValueFromProposedFederation) throws InsufficientMoneyException {
Expand Down Expand Up @@ -1092,19 +1145,13 @@ private SendRequest createSvpFundTransactionSendRequest(BtcTransaction transacti
return sendRequest;
}

protected void processSvpSpendTransactionUnsigned(Transaction rskTx) {
federationSupport.getProposedFederation()
.ifPresent(proposedFederation -> provider.getSvpFundTxSigned()
.ifPresent(svpFundTxSigned -> {
BtcTransaction svpSpendTransactionUnsigned = createSvpSpendTransaction(svpFundTxSigned, proposedFederation);

Keccak256 rskTxHash = rskTx.getHash();
updateSvpSpendTransactionValues(rskTxHash, svpSpendTransactionUnsigned);
private void processSvpSpendTransactionUnsigned(Keccak256 rskTxHash, Federation proposedFederation, BtcTransaction svpFundTxSigned) {
BtcTransaction svpSpendTransactionUnsigned = createSvpSpendTransaction(svpFundTxSigned, proposedFederation);
updateSvpSpendTransactionValues(rskTxHash, svpSpendTransactionUnsigned);

Coin amountSentToActiveFed = svpSpendTransactionUnsigned.getOutput(0).getValue();
logReleaseRequested(rskTxHash, svpSpendTransactionUnsigned, amountSentToActiveFed);
logPegoutTransactionCreated(svpSpendTransactionUnsigned);
}));
Coin amountSentToActiveFed = svpSpendTransactionUnsigned.getOutput(0).getValue();
logReleaseRequested(rskTxHash, svpSpendTransactionUnsigned, amountSentToActiveFed);
logPegoutTransactionCreated(svpSpendTransactionUnsigned);
}

private BtcTransaction createSvpSpendTransaction(BtcTransaction svpFundTxSigned, Federation proposedFederation) {
Expand Down
Loading