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

Mark invalid pegin as processed #2929

Open
wants to merge 6 commits into
base: feature/powpeg_validation_protocol-integration
Choose a base branch
from
Open
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
99 changes: 62 additions & 37 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import static co.rsk.peg.ReleaseTransactionBuilder.BTC_TX_VERSION_2;
import static co.rsk.peg.bitcoin.BitcoinUtils.*;
import static co.rsk.peg.bitcoin.UtxoUtils.extractOutpointValues;
import static co.rsk.peg.pegin.RejectedPeginReason.INVALID_AMOUNT;
import static java.util.Objects.isNull;
import static org.ethereum.config.blockchain.upgrades.ConsensusRule.*;

Expand Down Expand Up @@ -503,48 +502,74 @@ protected void registerPegIn(
);

PeginProcessAction peginProcessAction = peginEvaluationResult.getPeginProcessAction();
if (peginProcessAction == PeginProcessAction.CAN_BE_REGISTERED) {
logger.debug("[{}] Peg-in is valid, going to register", METHOD_NAME);
executePegIn(btcTx, peginInformation, totalAmount);
} else {
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 from evaluatePegin method";
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);
if (peginProcessAction == PeginProcessAction.CAN_BE_REFUNDED) {
logger.debug("[{}] Refunding to address {} ", METHOD_NAME, peginInformation.getBtcRefundAddress());
generateRejectionRelease(btcTx, peginInformation.getBtcRefundAddress(), rskTxHash, totalAmount);
markTxAsProcessed(btcTx);
} else {
logger.debug("[{}] Unprocessable transaction {}.", METHOD_NAME, btcTx.getHash());
handleUnprocessableBtcTx(btcTx, peginInformation.getProtocolVersion(), rejectedPeginReason);
switch (peginProcessAction) {
case REGISTER -> {
logger.debug("[{}] Peg-in is valid, going to register", METHOD_NAME);
executePegIn(btcTx, peginInformation, totalAmount);
}
case REFUND -> handleRefundablePegin(btcTx, rskTxHash, peginEvaluationResult,
peginInformation.getBtcRefundAddress());
case NO_REFUND -> handleNonRefundablePegin(btcTx, peginInformation.getProtocolVersion(),
peginEvaluationResult);
}
}

private void handleUnprocessableBtcTx(
private void handleRefundablePegin(BtcTransaction btcTx, Keccak256 rskTxHash,
PeginEvaluationResult peginEvaluationResult, Address btcRefundAddress)
throws IOException {
RejectedPeginReason rejectedPeginReason = peginEvaluationResult.getRejectedPeginReason()
.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("[{handleRefundablePegin}] {}", message);
return new IllegalStateException(message);
});

logger.debug("[{handleRefundablePegin}] Rejected peg-in, reason {}", rejectedPeginReason);
eventLogger.logRejectedPegin(btcTx, rejectedPeginReason);

logger.debug("[{handleRefundablePegin}] Refunding to address {} ", btcRefundAddress);
Coin totalAmount = computeTotalAmountSent(btcTx);
generateRejectionRelease(btcTx, btcRefundAddress, rskTxHash,
totalAmount);
markTxAsProcessed(btcTx);
}

private void handleNonRefundablePegin(
BtcTransaction btcTx,
int protocolVersion,
RejectedPeginReason rejectedPeginReason
) {
UnrefundablePeginReason unrefundablePeginReason;
if (rejectedPeginReason == INVALID_AMOUNT) {
unrefundablePeginReason = UnrefundablePeginReason.INVALID_AMOUNT;
} else {
unrefundablePeginReason = protocolVersion == 1 ?
UnrefundablePeginReason.PEGIN_V1_REFUND_ADDRESS_NOT_SET :
UnrefundablePeginReason.LEGACY_PEGIN_UNDETERMINED_SENDER;
}
PeginEvaluationResult peginEvaluationResult
) throws IOException {
RejectedPeginReason rejectedPeginReason = peginEvaluationResult.getRejectedPeginReason()
.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("[{handleNonRefundablePegin}] {}", message);
return new IllegalStateException(message);
});

logger.debug("[{handleNonRefundablePegin}] Rejected peg-in, reason {}",
rejectedPeginReason);
eventLogger.logRejectedPegin(btcTx, rejectedPeginReason);

NonRefundablePeginReason nonRefundablePeginReason = switch (rejectedPeginReason) {
case INVALID_AMOUNT -> NonRefundablePeginReason.INVALID_AMOUNT;
case LEGACY_PEGIN_UNDETERMINED_SENDER, PEGIN_V1_INVALID_PAYLOAD ->
protocolVersion == 1 ? NonRefundablePeginReason.PEGIN_V1_REFUND_ADDRESS_NOT_SET
: NonRefundablePeginReason.LEGACY_PEGIN_UNDETERMINED_SENDER;
default -> throw new IllegalStateException("Unexpected value: " + rejectedPeginReason);
};

logger.debug("[handleNonRefundablePegin] Nonrefundable tx {}. Reason {}", btcTx.getHash(),
nonRefundablePeginReason);
eventLogger.logNonRefundablePegin(btcTx, nonRefundablePeginReason);

logger.debug("[handleUnprocessableBtcTx] Unprocessable tx {}. Reason {}", btcTx.getHash(), unrefundablePeginReason);
eventLogger.logUnrefundablePegin(btcTx, unrefundablePeginReason);
if (!activations.isActive(RSKIP459)) {
return;
}
// Since RSKIP459, rejected peg-ins should be marked as processed
markTxAsProcessed(btcTx);
}

/**
Expand Down Expand Up @@ -712,9 +737,9 @@ private void refundTxSender(

if (activations.isActive(ConsensusRule.RSKIP181)) {
if (peginInformation.getProtocolVersion() == 1) {
eventLogger.logUnrefundablePegin(btcTx, UnrefundablePeginReason.PEGIN_V1_REFUND_ADDRESS_NOT_SET);
eventLogger.logNonRefundablePegin(btcTx, NonRefundablePeginReason.PEGIN_V1_REFUND_ADDRESS_NOT_SET);
} else {
eventLogger.logUnrefundablePegin(btcTx, UnrefundablePeginReason.LEGACY_PEGIN_UNDETERMINED_SENDER);
eventLogger.logNonRefundablePegin(btcTx, NonRefundablePeginReason.LEGACY_PEGIN_UNDETERMINED_SENDER);
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions rskj-core/src/main/java/co/rsk/peg/PegUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ static PeginEvaluationResult evaluatePegin(

if(!allUTXOsToFedAreAboveMinimumPeginValue(btcTx, fedWallet, minimumPeginTxValue, activations)) {
logger.debug("[evaluatePegin] Peg-in contains at least one utxo below the minimum value");
return new PeginEvaluationResult(PeginProcessAction.CANNOT_BE_PROCESSED, INVALID_AMOUNT);
return new PeginEvaluationResult(PeginProcessAction.NO_REFUND, INVALID_AMOUNT);
}

try {
Expand All @@ -196,8 +196,8 @@ static PeginEvaluationResult evaluatePegin(
boolean hasRefundAddress = peginInformation.getBtcRefundAddress() != null;

PeginProcessAction peginProcessAction = hasRefundAddress ?
PeginProcessAction.CAN_BE_REFUNDED :
PeginProcessAction.CANNOT_BE_PROCESSED;
PeginProcessAction.REFUND :
PeginProcessAction.NO_REFUND;

return new PeginEvaluationResult(peginProcessAction, PEGIN_V1_INVALID_PAYLOAD);
}
Expand All @@ -207,7 +207,7 @@ static PeginEvaluationResult evaluatePegin(
case 0:
return evaluateLegacyPeginSender(peginInformation.getSenderBtcAddressType());
case 1:
return new PeginEvaluationResult(PeginProcessAction.CAN_BE_REGISTERED);
return new PeginEvaluationResult(PeginProcessAction.REGISTER);
default:
// This flow should never be reached.
String message = String.format("Invalid state. Unexpected pegin protocol %d", protocolVersion);
Expand All @@ -220,12 +220,12 @@ private static PeginEvaluationResult evaluateLegacyPeginSender(TxSenderAddressTy
switch (senderAddressType) {
case P2PKH:
case P2SHP2WPKH:
return new PeginEvaluationResult(PeginProcessAction.CAN_BE_REGISTERED);
return new PeginEvaluationResult(PeginProcessAction.REGISTER);
case P2SHMULTISIG:
case P2SHP2WSH:
return new PeginEvaluationResult(PeginProcessAction.CAN_BE_REFUNDED, LEGACY_PEGIN_MULTISIG_SENDER);
return new PeginEvaluationResult(PeginProcessAction.REFUND, LEGACY_PEGIN_MULTISIG_SENDER);
default:
return new PeginEvaluationResult(PeginProcessAction.CANNOT_BE_PROCESSED, LEGACY_PEGIN_UNDETERMINED_SENDER);
return new PeginEvaluationResult(PeginProcessAction.NO_REFUND, LEGACY_PEGIN_UNDETERMINED_SENDER);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package co.rsk.peg.pegin;

public enum PeginProcessAction {
CAN_BE_REGISTERED,
CAN_BE_REFUNDED,
CANNOT_BE_PROCESSED
REGISTER,
REFUND,
NO_REFUND
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ default void logRejectedPegin(BtcTransaction btcTx, RejectedPeginReason reason)
throw new UnsupportedOperationException();
}

default void logUnrefundablePegin(BtcTransaction btcTx, UnrefundablePeginReason reason) {
default void logNonRefundablePegin(BtcTransaction btcTx, NonRefundablePeginReason reason) {
throw new UnsupportedOperationException();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public void logRejectedPegin(BtcTransaction btcTx, RejectedPeginReason reason) {
}

@Override
public void logUnrefundablePegin(BtcTransaction btcTx, UnrefundablePeginReason reason) {
public void logNonRefundablePegin(BtcTransaction btcTx, NonRefundablePeginReason reason) {
CallTransaction.Function event = BridgeEvents.UNREFUNDABLE_PEGIN.getEvent();

byte[] btcTxHashSerialized = btcTx.getHash().getBytes();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package co.rsk.peg.utils;

public enum UnrefundablePeginReason {
public enum NonRefundablePeginReason {
LEGACY_PEGIN_UNDETERMINED_SENDER(1),
PEGIN_V1_REFUND_ADDRESS_NOT_SET(2),
INVALID_AMOUNT(3);

private final int value;

UnrefundablePeginReason(int value) {
NonRefundablePeginReason(int value) {
this.value = value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ public enum ConsensusRule {
RSKIP434("rskip434"),
RSKIP438("rskip438"),
RSKIP445("rskip445"), // From EIP-5656 MCOPY instruction
RSKIP446("rskip446") ,// Transient storage opcodes addition implementing EIP-1153
RSKIP446("rskip446"), // Transient storage opcodes addition implementing EIP-1153
RSKIP453("rskip453"),
RSKIP454("rskip454")
RSKIP454("rskip454"),
RSKIP459("rskip459"),
;

private final String configKey;
Expand Down
1 change: 1 addition & 0 deletions rskj-core/src/main/resources/expected.conf
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ blockchain = {
rskip446 = <hardforkName>
rskip453 = <hardforkName>
rskip454 = <hardforkName>
rskip459 = <hardforkName>
}
}
gc = {
Expand Down
1 change: 1 addition & 0 deletions rskj-core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ blockchain = {
rskip446 = lovell700
rskip453 = lovell700
rskip454 = lovell700
rskip459 = lovell700
}
}
gc = {
Expand Down
Loading
Loading