Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.v2.operation;

import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.operation.Operation;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;

import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes32;

/** The Chain id operation. */
public class ChainIdOperationV2 extends AbstractFixedCostOperationV2 {

private static final VarHandle LONG_BE =
MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);

/** The CHAINID Opcode number */
public static final int OPCODE = 0x46;

private final Bytes32 chainId;

// Cached big-endian limbs of the chainId for zero-allocation pushes to the EVM v2 stack.
private final long chainIdU3;
private final long chainIdU2;
private final long chainIdU1;
private final long chainIdU0;

/**
* Instantiates a new Chain id operation.
*
* @param gasCalculator the gas calculator
* @param chainId the chain id
*/
public ChainIdOperationV2(final GasCalculator gasCalculator, final Bytes32 chainId) {
super(OPCODE, "CHAINID", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost());
this.chainId = chainId;
final byte[] b = chainId.toArrayUnsafe();
this.chainIdU3 = (long) LONG_BE.get(b, 0);
this.chainIdU2 = (long) LONG_BE.get(b, 8);
this.chainIdU1 = (long) LONG_BE.get(b, 16);
this.chainIdU0 = (long) LONG_BE.get(b, 24);
}

/**
* Returns the chain ID this operation uses.
*
* @return the chain id
*/
@VisibleForTesting
Bytes32 getChainId() {
return chainId;
}

@Override
public Operation.OperationResult executeFixedCostOperation(
final MessageFrame frame, final EVM evm) {
if (!frame.stackHasSpaceV2(1)) return OVERFLOW_RESPONSE;
final long[] stack = frame.stackDataV2();
final int top = frame.stackTopV2();
final int offset = top << 2;
stack[offset] = chainIdU3;
stack[offset + 1] = chainIdU2;
stack[offset + 2] = chainIdU1;
stack[offset + 3] = chainIdU0;
frame.setTopV2(top + 1);
return successResponse;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.v2.operation;

import static org.hyperledger.besu.evm.v2.operation.StackUtil.pushAddress;

import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.operation.Operation;

/** The Coinbase operation. */
public class CoinbaseOperationV2 extends AbstractFixedCostOperationV2 {

/**
* Instantiates a new Coinbase operation.
*
* @param gasCalculator the gas calculator
*/
public CoinbaseOperationV2(final GasCalculator gasCalculator) {
super(0x41, "COINBASE", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost());
}

@Override
public Operation.OperationResult executeFixedCostOperation(
final MessageFrame frame, final EVM evm) {
if (!frame.stackHasSpaceV2(1)) return OVERFLOW_RESPONSE;
final long[] stack = frame.stackDataV2();
final int top = frame.stackTopV2();
pushAddress(frame.getMiningBeneficiary(), stack, top);
frame.setTopV2(top + 1);
return successResponse;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.v2.operation;

import static org.hyperledger.besu.evm.v2.operation.StackUtil.pushLong;

import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.operation.Operation;

/** The Gas limit operation. */
public class GasLimitOperationV2 extends AbstractFixedCostOperationV2 {

/**
* Instantiates a new Gas limit operation.
*
* @param gasCalculator the gas calculator
*/
public GasLimitOperationV2(final GasCalculator gasCalculator) {
super(0x45, "GASLIMIT", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost());
}

@Override
public Operation.OperationResult executeFixedCostOperation(
final MessageFrame frame, final EVM evm) {
if (!frame.stackHasSpaceV2(1)) return OVERFLOW_RESPONSE;
final long[] stack = frame.stackDataV2();
final int top = frame.stackTopV2();
pushLong(frame.getBlockValues().getGasLimit(), stack, top);
frame.setTopV2(top + 1);
return successResponse;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.v2.operation;

import static org.hyperledger.besu.evm.v2.operation.StackUtil.pushBytes32;

import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.operation.Operation;

/** The Prev randao operation. */
public class PrevRanDaoOperationV2 extends AbstractFixedCostOperationV2 {

/**
* Instantiates a new Prev randao operation.
*
* @param gasCalculator the gas calculator
*/
public PrevRanDaoOperationV2(final GasCalculator gasCalculator) {
super(0x44, "PREVRANDAO", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost());
}

@Override
public Operation.OperationResult executeFixedCostOperation(
final MessageFrame frame, final EVM evm) {
if (!frame.stackHasSpaceV2(1)) return OVERFLOW_RESPONSE;
final long[] stack = frame.stackDataV2();
final int top = frame.stackTopV2();
pushBytes32(frame.getBlockValues().getMixHashOrPrevRandao(), stack, top);
frame.setTopV2(top + 1);
return successResponse;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.nio.ByteOrder;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.jspecify.annotations.Nullable;

/**
* Static utility for reading/writing typed values on the flat {@code long[]} V2 operand stack. Each
Expand Down Expand Up @@ -70,6 +72,65 @@ static void pushWei(final Wei wei, final long[] stack, final int top) {
stack[offset + 3] = (long) LONG_BE.get(b, 24);
}

/**
* Writes a primitive {@code long} as a zero-extended 256-bit word at the given stack slot. The
* three most-significant limbs are set to zero and the value is written as the least-significant
* limb {@code u0}.
*
* @param value the unsigned long value to write
* @param stack the flat limb array
* @param top the slot index to write to
*/
static void pushLong(final long value, final long[] stack, final int top) {
final int offset = top << 2;
stack[offset] = 0L;
stack[offset + 1] = 0L;
stack[offset + 2] = 0L;
stack[offset + 3] = value;
}

/**
* Writes a 160-bit {@link Address} as a right-aligned 256-bit word at the given stack slot. The
* upper 96 bits are zero-padded so the address occupies the low 160-bit of the word, matching the
* layout expected by {@link #readAddressAt(long[], int, int)}.
*
* @param address the address to write
* @param stack the flat limb array
* @param top the slot index to write to
*/
static void pushAddress(final Address address, final long[] stack, final int top) {
final int offset = top << 2;
final byte[] b = address.getBytes().toArrayUnsafe();
stack[offset] = 0L;
stack[offset + 1] = ((int) INT_BE.get(b, 0)) & 0xFFFFFFFFL;
stack[offset + 2] = (long) LONG_BE.get(b, 4);
stack[offset + 3] = (long) LONG_BE.get(b, 12);
}

/**
* Writes a {@link Bytes32} value as four big-endian limbs at the given stack slot. A {@code null}
* value is written as a zero word.
*
* @param value the 32-byte value to write, or {@code null} for zero
* @param stack the flat limb array
* @param top the slot index to write to
*/
static void pushBytes32(final @Nullable Bytes32 value, final long[] stack, final int top) {
final int offset = top << 2;
if (value == null) {
stack[offset] = 0L;
stack[offset + 1] = 0L;
stack[offset + 2] = 0L;
stack[offset + 3] = 0L;
return;
}
final byte[] b = value.toArrayUnsafe();
stack[offset] = (long) LONG_BE.get(b, 0);
stack[offset + 1] = (long) LONG_BE.get(b, 8);
stack[offset + 2] = (long) LONG_BE.get(b, 16);
stack[offset + 3] = (long) LONG_BE.get(b, 24);
}

/**
* Extracts a 160-bit {@link Address} from a 256-bit stack word at the given depth below the top
* of stack.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,35 @@

import java.util.Optional;

import org.apache.tuweni.bytes.Bytes32;

public class FakeBlockValues implements BlockValues {
final long number;
final Optional<Wei> baseFee;
final long gasLimit;
final Bytes32 mixHashOrPrevRandao;

public FakeBlockValues(final long number) {
this(number, Optional.empty());
this(number, Optional.empty(), 0L, null);
}

public FakeBlockValues(final Optional<Wei> baseFee) {
this(1337, baseFee);
this(1337, baseFee, 0L, null);
}

public FakeBlockValues(final long number, final Optional<Wei> baseFee) {
this(number, baseFee, 0L, null);
}

public FakeBlockValues(
final long number,
final Optional<Wei> baseFee,
final long gasLimit,
final Bytes32 mixHashOrPrevRandao) {
this.number = number;
this.baseFee = baseFee;
this.gasLimit = gasLimit;
this.mixHashOrPrevRandao = mixHashOrPrevRandao;
}

@Override
Expand All @@ -45,4 +59,14 @@ public long getNumber() {
public Optional<Wei> getBaseFee() {
return baseFee;
}

@Override
public long getGasLimit() {
return gasLimit;
}

@Override
public Bytes32 getMixHashOrPrevRandao() {
return mixHashOrPrevRandao;
}
}
Loading
Loading