Skip to content

Commit

Permalink
EOF Optimization - don't spit code sections (hyperledger#4898)
Browse files Browse the repository at this point in the history
Optimize the EOF Functions implementation by not splitting code sections
into separate Bytes object.  Instead the EOF evaluation occurs on a
single container space.  When a function is called the PC (relative to
container start, not section start) is moved.

EOF lacks PC introspection and absolute jumps, so where "PC=0" starts is
not observable to the code.  "PC=0" is still respected in the traces.

Signed-off-by: Danno Ferrin <danno.ferrin@swirldslabs.com>
  • Loading branch information
shemnon authored Jan 11, 2023
1 parent bb3c755 commit 2a30dfb
Show file tree
Hide file tree
Showing 27 changed files with 944 additions and 922 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ The final form of the Ethereum Panda will appear when the first finalized block
- Updated besu-native to version 0.4.3 [#3331](https://github.com/hyperledger/besu/pull/3331)
- Refactor synchronizer to asynchronously retrieve blocks from peers, and to change peer when retrying to get a block. [#3326](https://github.com/hyperledger/besu/pull/3326)
- Disable RocksDB TTL compactions [#3356](https://github.com/hyperledger/besu/pull/3356)
- add a websocket frame size configuration CLI parameter [3386][https://github.com/hyperledger/besu/pull/3386]
- add a websocket frame size configuration CLI parameter [#3386](https://github.com/hyperledger/besu/pull/3386)
- Add `--ec-curve` parameter to export/export-address public-key subcommands [#3333](https://github.com/hyperledger/besu/pull/3333)

### Bug Fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ private static FlatTrace.Context handleReturn(

// set value for contract creation TXes, CREATE, and CREATE2
if (actionBuilder.getCallType() == null && traceFrame.getMaybeCode().isPresent()) {
actionBuilder.init(traceFrame.getMaybeCode().get().getContainerBytes().toHexString());
actionBuilder.init(traceFrame.getMaybeCode().get().getBytes().toHexString());
resultBuilder.code(outputData.toHexString());
if (currentContext.isCreateOp()) {
// this is from a CREATE/CREATE2, so add code deposit cost.
Expand Down Expand Up @@ -460,7 +460,7 @@ private static FlatTrace.Context handleCreateOperation(

traceFrame
.getMaybeCode()
.map(Code::getContainerBytes)
.map(Code::getBytes)
.map(Bytes::toHexString)
.ifPresent(subTraceActionBuilder::init);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,7 @@ private void handleDepthIncreased(
code ->
op.setSub(
new VmTrace(
currentTraceFrame
.getMaybeCode()
.get()
.getContainerBytes()
.toHexString())));
currentTraceFrame.getMaybeCode().get().getBytes().toHexString())));
} else {
op.setCost(op.getCost());
op.setSub(null);
Expand Down Expand Up @@ -291,11 +287,7 @@ private void initStep(final TraceFrame frame) {
// set smart contract code
if (currentTrace != null && "0x".equals(currentTrace.getCode())) {
currentTrace.setCode(
currentTraceFrame
.getMaybeCode()
.orElse(CodeV0.EMPTY_CODE)
.getContainerBytes()
.toHexString());
currentTraceFrame.getMaybeCode().orElse(CodeV0.EMPTY_CODE).getBytes().toHexString());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.evm.code.CodeFactory;
import org.hyperledger.besu.evm.code.CodeInvalid;
import org.hyperledger.besu.evm.code.CodeSection;
import org.hyperledger.besu.evm.code.EOFLayout;

import java.io.BufferedReader;
Expand Down Expand Up @@ -126,7 +125,7 @@ public String considerCode(final String hexCode) {
return "OK "
+ IntStream.range(0, code.getCodeSectionCount())
.mapToObj(code::getCodeSection)
.map(CodeSection::getCode)
.map(cs -> layout.getContainer().slice(cs.getEntryPoint(), cs.getLength()))
.map(Bytes::toUnprefixedHexString)
.collect(Collectors.joining(","))
+ "\n";
Expand Down
11 changes: 1 addition & 10 deletions evm/src/main/java/org/hyperledger/besu/evm/Code.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,13 @@ public interface Code {
*/
int getSize();

/**
* Gets the code bytes. For legacy code only section 0 exists at address `0`. For V1/EOF it is the
* corresponding code section from the container header.
*
* @param section the section number to retrieve.
* @return the code bytes, or null of there is no code for that section number.
*/
Bytes getCodeBytes(final int section);

/**
* Get the bytes for the entire container, for example what EXTCODECOPY would want. For V0 it is
* the same as getCodeBytes, for V1 it is the entire container, not just the data section.
*
* @return container bytes.
*/
Bytes getContainerBytes();
Bytes getBytes();

/**
* Hash of the entire container
Expand Down
15 changes: 1 addition & 14 deletions evm/src/main/java/org/hyperledger/besu/evm/EVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public class EVM {

// Optimized operation flags
private final boolean enableShanghai;
private final boolean enableCancun;

public EVM(
final OperationRegistry operations,
Expand All @@ -88,7 +87,6 @@ public EVM(
this.evmSpecVersion = evmSpecVersion;

enableShanghai = EvmSpecVersion.SHANGHAI.ordinal() <= evmSpecVersion.ordinal();
enableCancun = EvmSpecVersion.CANCUN.ordinal() <= evmSpecVersion.ordinal();
}

public GasCalculator getGasCalculator() {
Expand All @@ -107,7 +105,7 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) {
evmSpecVersion.maybeWarnVersion();

var operationTracer = tracing == OperationTracer.NO_TRACING ? null : tracing;
byte[] code = frame.getCode().getCodeBytes(frame.getSection()).toArrayUnsafe();
byte[] code = frame.getCode().getBytes().toArrayUnsafe();
Operation[] operationArray = operations.getOperations();
while (frame.getState() == MessageFrame.State.CODE_EXECUTING) {
Operation currentOperation;
Expand Down Expand Up @@ -277,17 +275,6 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) {
case 0x9f:
result = SwapOperation.staticOperation(frame, opcode - SWAP_BASE);
break;
case 0xb0: // CALLF
case 0xb1: // RETF
// Function operations reset code
if (enableCancun) {
frame.setCurrentOperation(currentOperation);
result = currentOperation.execute(frame, this);
code = frame.getCode().getCodeSection(frame.getSection()).getCode().toArrayUnsafe();
} else {
result = InvalidOperation.INVALID_RESULT;
}
break;
default: // unoptimized operations
frame.setCurrentOperation(currentOperation);
result = currentOperation.execute(frame, this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ public static Code createCode(
codeHash, bytes, "Invalid EOF Layout: " + layout.getInvalidReason());
}

final String codeValidationError = CodeV1.validateCode(layout);
final String codeValidationError = CodeV1Validation.validateCode(layout);
if (codeValidationError != null) {
return new CodeInvalid(codeHash, bytes, "EOF Code Invalid : " + codeValidationError);
}

final String stackValidationError = CodeV1.validateStack(layout);
final String stackValidationError = CodeV1Validation.validateStack(layout);
if (stackValidationError != null) {
return new CodeInvalid(codeHash, bytes, "EOF Code Invalid : " + stackValidationError);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,7 @@ public int getSize() {
}

@Override
public Bytes getCodeBytes(final int function) {
return null;
}

@Override
public Bytes getContainerBytes() {
public Bytes getBytes() {
return codeBytes;
}

Expand Down
32 changes: 21 additions & 11 deletions evm/src/main/java/org/hyperledger/besu/evm/code/CodeSection.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,31 @@

import java.util.Objects;

import org.apache.tuweni.bytes.Bytes;

//// java17 convert to record
public final class CodeSection {
final Bytes code;

final int length;
final int inputs;
final int outputs;
final int maxStackHeight;
/** The byte offset from the begining of the container that the section starts at */
final int entryPoint;

public CodeSection(
final Bytes code, final int inputs, final int outputs, final int maxStackHeight) {
this.code = code;
final int length,
final int inputs,
final int outputs,
final int maxStackHeight,
final int entryPoint) {
this.length = length;
this.inputs = inputs;
this.outputs = outputs;
this.maxStackHeight = maxStackHeight;
this.entryPoint = entryPoint;
}

public Bytes getCode() {
return code;
public int getLength() {
return length;
}

public int getInputs() {
Expand All @@ -51,19 +57,23 @@ public int getMaxStackHeight() {
return maxStackHeight;
}

public int getEntryPoint() {
return entryPoint;
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CodeSection that = (CodeSection) o;
return inputs == that.inputs
return length == that.length
&& inputs == that.inputs
&& outputs == that.outputs
&& maxStackHeight == that.maxStackHeight
&& code.equals(that.code);
&& maxStackHeight == that.maxStackHeight;
}

@Override
public int hashCode() {
return Objects.hash(code, inputs, outputs, maxStackHeight);
return Objects.hash(length, inputs, outputs, maxStackHeight);
}
}
22 changes: 10 additions & 12 deletions evm/src/main/java/org/hyperledger/besu/evm/code/CodeV0.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public class CodeV0 implements Code {
/** Used to cache valid jump destinations. */
private long[] validJumpDestinations;

/** Code section info for the legacy code */
private final CodeSection codeSectionZero;

/**
* Public constructor.
*
Expand All @@ -46,6 +49,7 @@ public class CodeV0 implements Code {
CodeV0(final Bytes bytes, final Hash codeHash) {
this.bytes = bytes;
this.codeHash = codeHash;
this.codeSectionZero = new CodeSection(bytes.size(), 0, -1, -1, 0);
}

/**
Expand Down Expand Up @@ -80,17 +84,7 @@ public int getSize() {
}

@Override
public Bytes getCodeBytes(final int function) {

if (function == 0) {
return getContainerBytes();
} else {
return null;
}
}

@Override
public Bytes getContainerBytes() {
public Bytes getBytes() {
return bytes;
}

Expand Down Expand Up @@ -125,7 +119,11 @@ public boolean isValid() {

@Override
public CodeSection getCodeSection(final int section) {
return null;
if (section == 0) {
return codeSectionZero;
} else {
return null;
}
}

@Override
Expand Down
Loading

0 comments on commit 2a30dfb

Please sign in to comment.