Skip to content

Commit 0d5e99a

Browse files
usmansaleemgeorgereuben
authored andcommitted
feat: Soft failure reason for evm op results (besu-eth#9109)
Add soft failure reasons for evm operation results. Signed-off-by: Usman Saleem <usman@usmans.info> Signed-off-by: georgereuben <reubengeorge101@gmail.com>
1 parent c475246 commit 0d5e99a

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.evm.frame;
16+
17+
/** The enum Soft Failure reason. */
18+
public enum SoftFailureReason {
19+
20+
/** Soft failure due to insufficient balance. Mainly use to provide visibility to Tracers. */
21+
LEGACY_INSUFFICIENT_BALANCE("insufficient balance for transfer"),
22+
/** Soft failure due to max call depth. Mainly use to provide visibility to Tracers. */
23+
LEGACY_MAX_CALL_DEPTH("max call depth exceeded");
24+
25+
/** The Description of soft failure. */
26+
final String description;
27+
28+
/**
29+
* Enum constructor with description
30+
*
31+
* @param description to set
32+
*/
33+
SoftFailureReason(final String description) {
34+
this.description = description;
35+
}
36+
37+
/**
38+
* Returns Description
39+
*
40+
* @return description.
41+
*/
42+
public String getDescription() {
43+
return description;
44+
}
45+
}

evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
*/
1515
package org.hyperledger.besu.evm.operation;
1616

17+
import static org.hyperledger.besu.evm.frame.SoftFailureReason.LEGACY_INSUFFICIENT_BALANCE;
18+
import static org.hyperledger.besu.evm.frame.SoftFailureReason.LEGACY_MAX_CALL_DEPTH;
1719
import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
1820
import static org.hyperledger.besu.evm.internal.Words.clampedToLong;
1921
import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.getTarget;
@@ -29,6 +31,7 @@
2931
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
3032
import org.hyperledger.besu.evm.frame.MessageFrame;
3133
import org.hyperledger.besu.evm.frame.MessageFrame.State;
34+
import org.hyperledger.besu.evm.frame.SoftFailureReason;
3235
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
3336
import org.hyperledger.besu.evm.worldstate.CodeDelegationHelper;
3437

@@ -204,15 +207,19 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
204207

205208
// If the call is sending more value than the account has or the message frame is too deep
206209
// return a failed call
207-
if (value(frame).compareTo(balance) > 0 || frame.getDepth() >= 1024) {
210+
final boolean insufficientBalance = value(frame).compareTo(balance) > 0;
211+
final boolean isFrameDepthTooDeep = frame.getDepth() >= 1024;
212+
if (insufficientBalance || isFrameDepthTooDeep) {
208213
frame.expandMemory(inputDataOffset(frame), inputDataLength(frame));
209214
frame.expandMemory(outputDataOffset(frame), outputDataLength(frame));
210215
// For the following, we either increment the gas or return zero, so we don't get double
211216
// charged. If we return zero then the traces don't have the right per-opcode cost.
212217
frame.incrementRemainingGas(gasAvailableForChildCall(frame) + cost);
213218
frame.popStackItems(getStackItemsConsumed());
214219
frame.pushStackItem(LEGACY_FAILURE_STACK_ITEM);
215-
return new OperationResult(cost, null);
220+
final SoftFailureReason softFailureReason =
221+
insufficientBalance ? LEGACY_INSUFFICIENT_BALANCE : LEGACY_MAX_CALL_DEPTH;
222+
return new OperationResult(cost, 1, softFailureReason);
216223
}
217224

218225
final Bytes inputData = frame.readMutableMemory(inputDataOffset(frame), inputDataLength(frame));

evm/src/main/java/org/hyperledger/besu/evm/operation/Operation.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import org.hyperledger.besu.evm.EVM;
1818
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
1919
import org.hyperledger.besu.evm.frame.MessageFrame;
20+
import org.hyperledger.besu.evm.frame.SoftFailureReason;
21+
22+
import java.util.Optional;
2023

2124
/** The interface Operation. */
2225
public interface Operation {
@@ -32,6 +35,9 @@ class OperationResult {
3235
/** The increment. */
3336
final int pcIncrement;
3437

38+
/** Soft Failure Reason. Mainly used to provide visibility to tracers. */
39+
final SoftFailureReason softFailureReason;
40+
3541
/**
3642
* Instantiates a new Operation result.
3743
*
@@ -54,6 +60,22 @@ public OperationResult(
5460
this.gasCost = gasCost;
5561
this.haltReason = haltReason;
5662
this.pcIncrement = pcIncrement;
63+
this.softFailureReason = null;
64+
}
65+
66+
/**
67+
* Instantiate a new Operation Result with a Soft Failure Reason.
68+
*
69+
* @param gasCost Gas Cost
70+
* @param pcIncrement The increment
71+
* @param softFailureReason The Soft Failure Reason
72+
*/
73+
public OperationResult(
74+
final long gasCost, final int pcIncrement, final SoftFailureReason softFailureReason) {
75+
this.gasCost = gasCost;
76+
this.haltReason = null;
77+
this.pcIncrement = pcIncrement;
78+
this.softFailureReason = softFailureReason;
5779
}
5880

5981
/**
@@ -82,6 +104,15 @@ public ExceptionalHaltReason getHaltReason() {
82104
public int getPcIncrement() {
83105
return pcIncrement;
84106
}
107+
108+
/**
109+
* Returns optional Soft Failure Reason.
110+
*
111+
* @return Optional Soft Failure Reason
112+
*/
113+
public Optional<SoftFailureReason> getSoftFailureReason() {
114+
return Optional.ofNullable(this.softFailureReason);
115+
}
85116
}
86117

87118
/**

0 commit comments

Comments
 (0)