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

EIP-1153: Transient storage opcodes #4118

Merged
merged 67 commits into from Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
518a259
Exploratory changes
codyborn Jul 13, 2022
930066b
Add Shanghai fork
codyborn Jul 15, 2022
20a5c86
Multi-contract tests
codyborn Jul 15, 2022
b77a993
More tests; handle transient state across frames
codyborn Jul 16, 2022
4edfd8d
Moar tests
codyborn Jul 16, 2022
85d06e3
Backward sync exception improvements (#4092)
fab-10 Jul 13, 2022
6af79cb
Finalised blocks should not prevent reorgs in BWS (#4097)
gezero Jul 14, 2022
82d0cb6
delegate all the block checks and validation to the block import phas…
fab-10 Jul 14, 2022
4564178
Ignore 2 tests that assume that the system language is English, if th…
daniellehrner Jul 14, 2022
5b41dcf
Fix PR 4098 (#4106)
fab-10 Jul 14, 2022
0a65802
log execution errors at right level, stops transition message propaga…
jflo Jul 14, 2022
ad0890a
Add experimental config option to enable v5 discovery (#4103)
Gabriel-Trintinalia Jul 15, 2022
e520669
Move Taccat to Emeritus (#4033)
shemnon Jul 15, 2022
743fa0a
Remove hash to append from the queue only if the step succeeds (#4105)
fab-10 Jul 15, 2022
df43a9d
Create backward sync retries on demand (#4095)
fab-10 Jul 15, 2022
21a7054
Update checkpoint sync for merge (#4085)
matkt Jul 15, 2022
d61e457
Remove unintended changes
codyborn Jul 16, 2022
c126cd5
Organize bytecode enum
codyborn Jul 16, 2022
75d74aa
Remove extra space
codyborn Jul 16, 2022
b6bf7fc
Updates to address PR feedback
codyborn Jul 28, 2022
57f1fd2
TreeMap -> HashMap
codyborn Jul 28, 2022
188d201
Remove shanghai hf config
codyborn Jul 29, 2022
a1708a4
Merge with main
codyborn Jul 31, 2022
4f0a43b
Missed some changes in the merge
codyborn Jul 31, 2022
612ee73
Whitespace style fix
codyborn Jul 31, 2022
04ffcae
Remove eip from all_forks.json
codyborn Aug 1, 2022
8623f48
Clear transient storage after each transaction
codyborn Aug 2, 2022
0ad50e6
Style fixes
codyborn Aug 4, 2022
d1db3b2
Merge branch 'main' into eip1153
codyborn Aug 4, 2022
03ad001
Simple performance test
codyborn Aug 4, 2022
45f603c
javadoc ByteCodeBuilder, undo unintended change
codyborn Aug 6, 2022
42ce2ec
correct javadoc typos
codyborn Aug 6, 2022
2c24e18
style fix
codyborn Aug 6, 2022
9b3f8d8
Move transient performance test to jmh suite
codyborn Aug 8, 2022
114446d
Remove commented out line
codyborn Aug 8, 2022
7e108d5
Upgrade Web3J (#3752)
diega Aug 4, 2022
9d63c64
Fix ConcurrentModificationException on ReattemptPendingPeerRequests (…
Gabriel-Trintinalia Aug 4, 2022
c46b1bf
Log unexpected exceptions in execution engine rpc (#4222)
siladu Aug 5, 2022
b68a6a7
correct fallback ttd to correct value (#4223)
daniellehrner Aug 7, 2022
b937710
Enclave public key length constraint removed for private transactions…
freemanzMrojo Aug 8, 2022
26714f1
Merge branch 'main' into eip1153
codyborn Aug 8, 2022
34451ae
Merge branch 'main' into eip1153
codyborn Aug 9, 2022
7bf6470
Merge branch 'main' into eip1153
codyborn Aug 10, 2022
47b1f31
Merge branch 'main' into eip1153
codyborn Aug 10, 2022
4b1c2a7
Merge branch 'main' into eip1153
codyborn Aug 12, 2022
c0c3c92
Merge branch 'main' into eip1153
codyborn Aug 21, 2022
a0cc8df
Add 1153 as ExperimentalEIP cmd line
codyborn Aug 31, 2022
d184d71
Merge branch 'main' into eip1153
codyborn Aug 31, 2022
a950795
Merge upstream
codyborn Nov 30, 2022
ed3ccad
Merge upstream
codyborn Nov 30, 2022
1a0b0fd
Fix tests
codyborn Dec 3, 2022
dd3f4bd
Merge pull request #1 from codyborn/merge1153
codyborn Dec 3, 2022
ab4285d
Update tests
codyborn Nov 30, 2022
206923f
Merge branch 'eip1153' of https://github.com/codyborn/besu into eip1153
codyborn Dec 3, 2022
bed8c06
Fix merge issue
codyborn Dec 3, 2022
7e86124
Spotless fix
codyborn Dec 3, 2022
6cce1ce
Add experimental EIPs back into BesuCommand
codyborn Dec 4, 2022
aafce49
Fix merge artifacts
codyborn Dec 4, 2022
0cbedf4
Revert reference test external-resources
codyborn Dec 4, 2022
8eadf09
Merge branch 'main' into eip1153
codyborn Dec 5, 2022
82af1b8
ugly merge
shemnon Jan 26, 2023
0439c40
finish removing CLI feature flag
shemnon Jan 26, 2023
22b0cf1
Move transient storage to the MessageFrame
shemnon Jan 26, 2023
9580690
Merge remote-tracking branch 'upstream/main' into eip1153
shemnon Jan 26, 2023
6b8fa64
javadoc
shemnon Jan 26, 2023
56f04be
spotless
shemnon Jan 26, 2023
4ab15e6
Merge branch 'main' into eip1153
shemnon Feb 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,91 @@
/*
* Copyright Hyperledger Besu contributors.
*
* 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.ethereum.vm.operations;

import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive;
import static org.mockito.Mockito.mock;

import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.MessageFrameTestFixture;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
import org.hyperledger.besu.evm.operation.TLoadOperation;
import org.hyperledger.besu.evm.operation.TStoreOperation;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;

@State(Scope.Thread)
public class TransientStorageOperationBenchmark {

private OperationBenchmarkHelper operationBenchmarkHelper;
private TStoreOperation tstore;
private TLoadOperation tload;
private MessageFrame frame;

private MessageFrame createMessageFrame(final Address address) {
final Blockchain blockchain = mock(Blockchain.class);

final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive();
final WorldUpdater worldStateUpdater = worldStateArchive.getMutable().updater();
final BlockHeader blockHeader = new BlockHeaderTestFixture().buildHeader();
final MessageFrame benchmarkFrame =
new MessageFrameTestFixture()
.address(address)
.worldUpdater(worldStateUpdater)
.blockHeader(blockHeader)
.blockchain(blockchain)
.build();
worldStateUpdater.getOrCreate(address).getMutable().setBalance(Wei.of(1));
worldStateUpdater.commit();

return benchmarkFrame;
}

@Setup
public void prepare() throws Exception {
operationBenchmarkHelper = OperationBenchmarkHelper.create();
CancunGasCalculator gasCalculator = new CancunGasCalculator();
tstore = new TStoreOperation(gasCalculator);
tload = new TLoadOperation(gasCalculator);
frame = createMessageFrame(Address.fromHexString("0x18675309"));
}

@TearDown
public void cleanUp() throws Exception {
operationBenchmarkHelper.cleanUp();
}

@Benchmark
public Bytes executeOperation() {
frame.pushStackItem(UInt256.ONE);
frame.pushStackItem(UInt256.fromHexString("0x01"));
tstore.execute(frame, null);
frame.pushStackItem(UInt256.fromHexString("0x01"));
tload.execute(frame, null);
return frame.popStackItem();
}
}
24 changes: 22 additions & 2 deletions evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java
Expand Up @@ -16,6 +16,7 @@

import org.hyperledger.besu.evm.gascalculator.BerlinGasCalculator;
import org.hyperledger.besu.evm.gascalculator.ByzantiumGasCalculator;
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator;
import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
Expand Down Expand Up @@ -111,6 +112,8 @@
import org.hyperledger.besu.evm.operation.StopOperation;
import org.hyperledger.besu.evm.operation.SubOperation;
import org.hyperledger.besu.evm.operation.SwapOperation;
import org.hyperledger.besu.evm.operation.TLoadOperation;
import org.hyperledger.besu.evm.operation.TStoreOperation;
import org.hyperledger.besu.evm.operation.TimestampOperation;
import org.hyperledger.besu.evm.operation.XorOperation;

Expand Down Expand Up @@ -724,6 +727,15 @@ public static void registerShanghaiOperations(
registry.put(new Create2Operation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
}

/**
* Cancun evm.
*
* @param evmConfiguration the evm configuration
* @return the evm
*/
public static EVM cancun(final EvmConfiguration evmConfiguration) {
return cancun(DEV_NET_CHAIN_ID, evmConfiguration);
}
/**
* Cancun evm.
*
Expand All @@ -732,7 +744,7 @@ public static void registerShanghaiOperations(
* @return the evm
*/
public static EVM cancun(final BigInteger chainId, final EvmConfiguration evmConfiguration) {
return cancun(new ShanghaiGasCalculator(), chainId, evmConfiguration);
return cancun(new CancunGasCalculator(), chainId, evmConfiguration);
}

/**
Expand Down Expand Up @@ -780,12 +792,20 @@ public static void registerCancunOperations(
final GasCalculator gasCalculator,
final BigInteger chainID) {
registerShanghaiOperations(registry, gasCalculator, chainID);

// EIP-4844
registry.put(new DataHashOperation(gasCalculator));

// TSTORE/TLOAD
registry.put(new TStoreOperation(gasCalculator));
registry.put(new TLoadOperation(gasCalculator));

// EOFV1
registry.put(new RelativeJumpOperation(gasCalculator));
registry.put(new RelativeJumpIfOperation(gasCalculator));
registry.put(new RelativeJumpVectorOperation(gasCalculator));
registry.put(new CallFOperation(gasCalculator));
registry.put(new RetFOperation(gasCalculator));
registry.put(new DataHashOperation(gasCalculator));
}

/**
Expand Down
49 changes: 49 additions & 0 deletions evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java
Expand Up @@ -42,8 +42,10 @@
import java.util.function.Consumer;
import java.util.function.Function;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Table;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.MutableBytes;
Expand Down Expand Up @@ -240,6 +242,8 @@ public enum Type {
private final Map<String, Object> contextVariables;
private final Optional<List<Hash>> versionedHashes;

private final Table<Address, Bytes32, Bytes32> transientStorage = HashBasedTable.create();

// Miscellaneous fields.
private Optional<ExceptionalHaltReason> exceptionalHaltReason = Optional.empty();
private Operation currentOperation;
Expand Down Expand Up @@ -1287,6 +1291,7 @@ public void setCurrentOperation(final Operation currentOperation) {
public Multimap<Address, Bytes32> getWarmedUpStorage() {
return warmedUpStorage;
}

/**
* Gets maybe updated memory.
*
Expand All @@ -1305,6 +1310,50 @@ public Optional<StorageEntry> getMaybeUpdatedStorage() {
return maybeUpdatedStorage;
}

/**
* Gets the transient storage value, including values from parent frames if not set
*
* @param accountAddress The address of the executing context
* @param slot the slot to retrieve
* @return the data value read
*/
public Bytes32 getTransientStorageValue(final Address accountAddress, final Bytes32 slot) {
Bytes32 data = transientStorage.get(accountAddress, slot);

if (data != null) {
return data;
}

if (parentMessageFrame != null) {
data = parentMessageFrame.getTransientStorageValue(accountAddress, slot);
}
if (data == null) {
data = Bytes32.ZERO;
}
transientStorage.put(accountAddress, slot, data);

return data;
}

/**
* Gets the transient storage value, including values from parent frames if not set
*
* @param accountAddress The address of the executing context
* @param slot the slot to set
* @param value the value to set in the transient store
*/
public void setTransientStorageValue(
final Address accountAddress, final Bytes32 slot, final Bytes32 value) {
transientStorage.put(accountAddress, slot, value);
}

/** Writes the transient storage to the parent frame, if one exists */
public void commitTransientStorage() {
if (parentMessageFrame != null) {
parentMessageFrame.transientStorage.putAll(transientStorage);
}
}

/**
* Accessor for versionedHashes, if present.
*
Expand Down
Expand Up @@ -38,7 +38,9 @@ public class BerlinGasCalculator extends IstanbulGasCalculator {
// new constants for EIP-2929
private static final long COLD_SLOAD_COST = 2100L;
private static final long COLD_ACCOUNT_ACCESS_COST = 2600L;
private static final long WARM_STORAGE_READ_COST = 100L;
/** Warm storage read, defined in EIP-2929 */
protected static final long WARM_STORAGE_READ_COST = 100L;

private static final long ACCESS_LIST_ADDRESS_COST = 2400L;
/** The constant ACCESS_LIST_STORAGE_COST. */
protected static final long ACCESS_LIST_STORAGE_COST = 1900L;
Expand Down
@@ -0,0 +1,39 @@
/*
* Copyright Hyperledger Besu contributors.
*
* 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.gascalculator;

/**
* Gas Calculator for Cancun
*
* <UL>
* <LI>Gas costs for TSTORE/TLOAD
* </UL>
*/
public class CancunGasCalculator extends LondonGasCalculator {

private static final long TLOAD_GAS = WARM_STORAGE_READ_COST;
private static final long TSTORE_GAS = WARM_STORAGE_READ_COST;

// EIP-1153
@Override
public long getTransientLoadOperationGasCost() {
return TLOAD_GAS;
}

@Override
public long getTransientStoreOperationGasCost() {
return TSTORE_GAS;
}
}
Expand Up @@ -487,4 +487,22 @@ default long getMaxRefundQuotient() {
*/
// what would be the gas for a PMT with hash of all non-zeros
long getMaximumTransactionCost(int size);

/**
* Returns the cost of a loading from Transient Storage
*
* @return the cost of a TLOAD from a storage slot
*/
default long getTransientLoadOperationGasCost() {
return 0L;
}

/**
* Returns the cost of a storing to Transient Storage
*
* @return the cost of a TSTORE to a storage slot
*/
default long getTransientStoreOperationGasCost() {
return 0L;
}
}
@@ -0,0 +1,57 @@
/*
* Copyright Hyperledger Besu contributors.
*
* 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.operation;

import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.FixedStack.OverflowException;
import org.hyperledger.besu.evm.internal.FixedStack.UnderflowException;

import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;

/** Implements the TLOAD operation defined in EIP-1153 */
public class TLoadOperation extends AbstractOperation {
atoulme marked this conversation as resolved.
Show resolved Hide resolved

/**
* TLoad operation
*
* @param gasCalculator gas calculator for costing
*/
public TLoadOperation(final GasCalculator gasCalculator) {
super(0xb3, "TLOAD", 1, 1, gasCalculator);
}

@Override
public OperationResult execute(final MessageFrame frame, final EVM evm) {
final long cost = gasCalculator().getTransientLoadOperationGasCost();
try {
final Bytes32 slot = UInt256.fromBytes(frame.popStackItem());
if (frame.getRemainingGas() < cost) {
return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS);
} else {
frame.pushStackItem(frame.getTransientStorageValue(frame.getRecipientAddress(), slot));

return new OperationResult(cost, null);
}
} catch (final UnderflowException ufe) {
return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_STACK_ITEMS);
} catch (final OverflowException ofe) {
return new OperationResult(cost, ExceptionalHaltReason.TOO_MANY_STACK_ITEMS);
}
}
}