-
Notifications
You must be signed in to change notification settings - Fork 267
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
Mark invalid pegin as processed #2910
Mark invalid pegin as processed #2910
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Manifest Files |
…jected pegin should be marked as processed - Update BridgeSupportRegisterBtcTransactionTest to assert rejected pegin are marked as processed since RSKIP459 - Add tests asserting rejected pegin are marked as processed once RSKIP459 is active
d8f72bb
to
208b14f
Compare
private static final NetworkParameters btcMainnetParams = bridgeMainnetConstants.getBtcParams(); | ||
private static final ActivationConfig.ForBlock arrowHeadActivations = ActivationConfigsForTest.arrowhead600().forBlock(0); | ||
private static final ActivationConfig.ForBlock lovellActivations = ActivationConfigsForTest.lovell700().forBlock(0); | ||
/*private static final ActivationConfig.ForBlock activations = ActivationConfigsForTest.all().forBlock(0);*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we ever need this line? If not, maybe we can remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! It can be removed. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
logger.debug("[{}] Rejected peg-in, reason {}", METHOD_NAME, rejectedPeginReason); | ||
eventLogger.logRejectedPegin(btcTx, rejectedPeginReason); | ||
|
||
switch (peginProcessAction) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can use here the new switch expression with arrow labels
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
// If the peg-in cannot be registered means it should be rejected | ||
Optional<RejectedPeginReason> rejectedPeginReasonOptional = peginEvaluationResult.getRejectedPeginReason(); | ||
if (rejectedPeginReasonOptional.isEmpty()) { | ||
// This flow should never be reached. There should always be a rejected pegin reason. | ||
String message = "Invalid state. No rejected reason was returned for an invalid pegin."; | ||
logger.error("[{}] {}", METHOD_NAME, message); | ||
throw new IllegalStateException(message); | ||
} | ||
RejectedPeginReason rejectedPeginReason = rejectedPeginReasonOptional.get(); | ||
logger.debug("[{}] Rejected peg-in, reason {}", METHOD_NAME, rejectedPeginReason); | ||
eventLogger.logRejectedPegin(btcTx, rejectedPeginReason); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this can be made more functional since we are using the Optional API as:
reason = peginEvaluationResult.getRejectedPeginReason()
.map(rejectedPeginReason -> {
logger.debug("[{}] Rejected peg-in, reason {}", METHOD_NAME, rejectedPeginReason);
eventLogger.logRejectedPegin(btcTx, rejectedPeginReason);
return rejectedPeginReason; // Placeholder if further processing is needed
})
.orElseThrow(() -> {
String message = "Invalid state. No rejected reason was returned for an invalid pegin.";
logger.error("[{}] {}", METHOD_NAME, message);
return new IllegalStateException(message);
});
Also would it make sense to abstract this logic to a private method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just this part regarding getting the rejected pegin reason? If so, to me looks clear how it is now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
@@ -1543,12 +1555,11 @@ void pegin_legacy_from_segwit_to_active_fed_cannot_be_processed( | |||
); | |||
|
|||
// assert | |||
|
|||
// SINCE RSKIP379 ONLY TRANSACTIONS THAT REALLY ARE PROCESSED, REFUNDS OR REGISTER WILL BE MARK AS PROCESSED. | |||
if (activations == fingerrootActivations){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (activations == fingerrootActivations){ | |
if (activations == fingerrootActivations) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
btcHeightWhenPegoutTxIndexActivates + pegoutTxIndexGracePeriodInBtcBlocks; | ||
} | ||
|
||
private PartialMerkleTree createPmtAndMockBlockStore(BtcTransaction btcTransaction) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't there a method in utils already for this? Maybe I am wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intend to remove this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this method is needed to recreate a valid chain for the given tx to satisfy the checks in registerBtcTransaction
method
This is a hypothetical case, which is not realistic with the implementation of the svp. | ||
A btc tx hash that is not saved as a spend tx, is identified as a pegin, and will be | ||
rejected due to invalid amount. This is because the pegin amount is below the minimum. | ||
Therefore, this tx should be rejected as pegin and mark as processed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a hypothetical case, which is not realistic with the implementation of the svp. | |
A btc tx hash that is not saved as a spend tx, is identified as a pegin, and will be | |
rejected due to invalid amount. This is because the pegin amount is below the minimum. | |
Therefore, this tx should be rejected as pegin and mark as processed | |
This is a hypothetical case, which is not realistic with the implementation of the svp. | |
A btc tx hash that is not saved as a spend tx is identified as a pegin and will be | |
rejected due to invalid amount, since the pegin amount is below the minimum. | |
Therefore, this tx should be rejected as pegin and mark as processed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
- Make logic handling rejected pegin functional using the Optional API - Fix formatting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
private void handleUnprocessableBtcTx( | ||
private RejectedPeginReason handleRejectedPegin(BtcTransaction btcTx, | ||
PeginEvaluationResult peginEvaluationResult) { | ||
return peginEvaluationResult.getRejectedPeginReason().map(reason -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's a good idea to return the rejected peg-in reason here. The method is called handle
so I would expect it to do something but not to return anything.
The rejected reason is obtained from PeginEvaluationResult
that is received by param. So it's basically returning something that was passed by parameter. Why can't the caller simply get that info from the object?
Maybe this method should renamed to logRejectedPegin
? That's what it's doing right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed and rearrange
}); | ||
} | ||
|
||
private void handleNonRefundablePegin( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps the same renaming idea could apply here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -3,5 +3,5 @@ | |||
public enum PeginProcessAction { | |||
CAN_BE_REGISTERED, | |||
CAN_BE_REFUNDED, | |||
CANNOT_BE_PROCESSED | |||
CANNOT_BE_REFUNDED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an idea, to rename this for clarity
REGISTER,
REFUND,
NO_REFUND
What do you think? A bit more straightforward. Last one could also be IGNORE
perhaps, not sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks simpler. I'll update it.
private static final NetworkParameters btcMainnetParams = bridgeMainnetConstants.getBtcParams(); | ||
private static final ActivationConfig.ForBlock arrowHeadActivations = ActivationConfigsForTest.arrowhead600() | ||
.forBlock(0); | ||
private static final ActivationConfig.ForBlock lovellActivations = ActivationConfigsForTest.lovell700() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we use all
activations? To make sure this keeps working in future network upgrades
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
btcHeightWhenPegoutTxIndexActivates + pegoutTxIndexGracePeriodInBtcBlocks; | ||
} | ||
|
||
private PartialMerkleTree createPmtAndMockBlockStore(BtcTransaction btcTransaction) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intend to remove this method?
@@ -1,13 +1,13 @@ | |||
package co.rsk.peg.utils; | |||
|
|||
public enum UnrefundablePeginReason { | |||
public enum NoRefundPeginReason { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public enum NoRefundPeginReason { | |
public enum NonRefundablePeginReason { |
I think that sounds better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed
@@ -212,7 +212,7 @@ public void logRejectedPegin(BtcTransaction btcTx, RejectedPeginReason reason) { | |||
} | |||
|
|||
@Override | |||
public void logUnrefundablePegin(BtcTransaction btcTx, UnrefundablePeginReason reason) { | |||
public void logNoRefundPegin(BtcTransaction btcTx, NoRefundPeginReason reason) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public void logNoRefundPegin(BtcTransaction btcTx, NoRefundPeginReason reason) { | |
public void logNonRefundablePegin(BtcTransaction btcTx, NoRefundPeginReason reason) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed
logger.debug("[{}] Unprocessable transaction {}.", METHOD_NAME, btcTx.getHash()); | ||
handleUnprocessableBtcTx(btcTx, peginInformation.getProtocolVersion(), rejectedPeginReason); | ||
} | ||
case NO_REFUND -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case NO_REFUND -> { | |
case NO_REFUND -> |
See Sonar report
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
peginEvaluationResult.getRejectedPeginReason() | ||
.map(reason -> { | ||
logger.debug("[{}] Rejected peg-in, reason {}", METHOD_NAME, reason); | ||
eventLogger.logRejectedPegin(btcTx, reason); | ||
return reason; | ||
}).orElseThrow(() -> { | ||
// This flow should never be reached. There should always be a rejected pegin reason. | ||
String message = "Invalid state. No rejected reason was returned for an invalid pegin."; | ||
logger.error("[{}] {}", METHOD_NAME, message); | ||
return new IllegalStateException(message); | ||
}); | ||
|
||
logger.debug("[{}] Refunding to address {} ", | ||
METHOD_NAME, peginInformation.getBtcRefundAddress()); | ||
generateRejectionRelease(btcTx, peginInformation.getBtcRefundAddress(), rskTxHash, | ||
totalAmount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looked better when all this logic was in its own method, why move it all here? It creates a code smell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the number of parameters that needs to be passed.
handleRefundablePegin(BtcTransaction btcTx, Keccak256 rskTxHash,
PeginEvaluationResult peginEvaluationResult, Address btcRefundAddress, Coin totalAmount)
.map(reason -> { | ||
logger.debug("[{}] Rejected peg-in, reason {}", METHOD_NAME, reason); | ||
eventLogger.logRejectedPegin(btcTx, reason); | ||
return reason; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need this return here? Nobody is storing that value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You right. It can be removed.
39a23fd
to
38f7bf2
Compare
- Enhance switch for processing each PeginProcessAction
38f7bf2
to
bf15222
Compare
Quality Gate passedIssues Measures |
ac0df42
into
invalid-pegin-as-processed-integration
Mark rejected pegins as processed once RSKIP459 is active.
Motivation and Context
Peg-in transactions rejected by the Bridge should be marked as processed to ensure that the
rejected_pegin
event is emitted only once per transaction.How Has This Been Tested?
Unit tests
Types of changes
Checklist: