[PAN-2989] EIP-1884 - Repricing for trie-size-dependent opcodes (#1795)

* [PAN-2989] EIP-1884 - Repricing for trie-size-dependent opcodes

Add the new gas costs and new operation to the EVM.
Add contract balance to message frame

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Danno Ferrin 5 years ago committed by GitHub
parent 59bf464c99
commit c4e7dcbe80
  1. 1
      ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java
  2. 21
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/IstanbulGasCalculator.java
  3. 5
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetEvmRegistries.java
  4. 2
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetTransactionProcessor.java
  5. 2
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionProcessor.java
  6. 1
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/AbstractCallOperation.java
  7. 20
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/MessageFrame.java
  8. 1
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/AbstractCreateOperation.java
  9. 35
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/SelfBalanceOperation.java
  10. 7
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/MessageFrameTestFixture.java
  11. 11
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/EnvironmentInformation.java
  12. 1
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java
  13. 9
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperationTest.java

@ -98,6 +98,7 @@ public class OperationBenchmarkHelper {
.address(messageFrame.getContractAddress())
.originator(messageFrame.getOriginatorAddress())
.contract(messageFrame.getRecipientAddress())
.contractBalance(messageFrame.getContractBalance())
.gasPrice(messageFrame.getGasPrice())
.inputData(messageFrame.getInputData())
.sender(messageFrame.getSenderAddress())

@ -25,6 +25,9 @@ public class IstanbulGasCalculator extends ConstantinopleFixGasCalculator {
private static final Gas TX_BASE_COST = Gas.of(21_000L);
private static final Gas SLOAD_GAS = Gas.of(800);
private static final Gas BALANCE_OPERATION_GAS_COST = Gas.of(700);
private static final Gas EXTCODE_HASH_COST = Gas.of(700);
private static final Gas SSTORE_SET_GAS = Gas.of(20_000);
private static final Gas SSTORE_RESET_GAS = Gas.of(5_000);
private static final Gas SSTORE_CLEARS_SCHEDULE = Gas.of(15_000);
@ -114,4 +117,22 @@ public class IstanbulGasCalculator extends ConstantinopleFixGasCalculator {
}
}
}
@Override
// As per https://eips.ethereum.org/EIPS/eip-1884
public Gas getSloadOperationGasCost() {
return SLOAD_GAS;
}
@Override
// As per https://eips.ethereum.org/EIPS/eip-1884
public Gas getBalanceOperationGasCost() {
return BALANCE_OPERATION_GAS_COST;
}
@Override
// As per https://eips.ethereum.org/EIPS/eip-1884
public Gas extCodeHashOperationGasCost() {
return EXTCODE_HASH_COST;
}
}

@ -81,6 +81,7 @@ import tech.pegasys.pantheon.ethereum.vm.operations.SLtOperation;
import tech.pegasys.pantheon.ethereum.vm.operations.SModOperation;
import tech.pegasys.pantheon.ethereum.vm.operations.SStoreOperation;
import tech.pegasys.pantheon.ethereum.vm.operations.SarOperation;
import tech.pegasys.pantheon.ethereum.vm.operations.SelfBalanceOperation;
import tech.pegasys.pantheon.ethereum.vm.operations.SelfDestructOperation;
import tech.pegasys.pantheon.ethereum.vm.operations.Sha3Operation;
import tech.pegasys.pantheon.ethereum.vm.operations.ShlOperation;
@ -266,12 +267,10 @@ abstract class MainnetEvmRegistries {
final int accountVersion,
final BigInteger chainId) {
registerConstantinopleOpcodes(registry, gasCalculator, accountVersion);
registry.put(
new SStoreOperation(gasCalculator, SStoreOperation.EIP_1706_MINIMUM),
Account.DEFAULT_VERSION);
registry.put(
new ChainIdOperation(gasCalculator, Bytes32.leftPad(BytesValue.of(chainId.toByteArray()))),
Account.DEFAULT_VERSION);
registry.put(new SelfBalanceOperation(gasCalculator), Account.DEFAULT_VERSION);
registry.put(
new SStoreOperation(gasCalculator, SStoreOperation.EIP_1706_MINIMUM),
Account.DEFAULT_VERSION);

@ -234,6 +234,7 @@ public class MainnetTransactionProcessor implements TransactionProcessor {
.address(contractAddress)
.originator(senderAddress)
.contract(contractAddress)
.contractBalance(sender.getBalance())
.contractAccountVersion(createContractAccountVersion)
.gasPrice(transaction.getGasPrice())
.inputData(BytesValue.EMPTY)
@ -264,6 +265,7 @@ public class MainnetTransactionProcessor implements TransactionProcessor {
.address(to)
.originator(senderAddress)
.contract(to)
.contractBalance(contract != null ? contract.getBalance() : Wei.ZERO)
.contractAccountVersion(
contract != null ? contract.getVersion() : Account.DEFAULT_VERSION)
.gasPrice(transaction.getGasPrice())

@ -230,6 +230,7 @@ public class PrivateTransactionProcessor {
.address(privateContractAddress)
.originator(senderAddress)
.contract(privateContractAddress)
.contractBalance(Wei.ZERO)
.contractAccountVersion(createContractAccountVersion)
.initialGas(Gas.MAX_VALUE)
.gasPrice(transaction.getGasPrice())
@ -259,6 +260,7 @@ public class PrivateTransactionProcessor {
.address(to)
.originator(senderAddress)
.contract(to)
.contractBalance(contract != null ? contract.getBalance() : Wei.ZERO)
.contractAccountVersion(
contract != null ? contract.getVersion() : Account.DEFAULT_VERSION)
.initialGas(Gas.MAX_VALUE)

@ -172,6 +172,7 @@ public abstract class AbstractCallOperation extends AbstractOperation {
.address(address(frame))
.originator(frame.getOriginatorAddress())
.contract(to)
.contractBalance(contract != null ? contract.getBalance() : Wei.ZERO)
.contractAccountVersion(
contract != null ? contract.getVersion() : Account.DEFAULT_VERSION)
.gasPrice(frame.getGasPrice())

@ -207,6 +207,7 @@ public class MessageFrame {
private final Address recipient;
private final Address originator;
private final Address contract;
private final Wei contractBalance;
private final int contractAccountVersion;
private final Wei gasPrice;
private final BytesValue inputData;
@ -240,6 +241,7 @@ public class MessageFrame {
final Address recipient,
final Address originator,
final Address contract,
final Wei contractBalance,
final int contractAccountVersion,
final Wei gasPrice,
final BytesValue inputData,
@ -274,6 +276,7 @@ public class MessageFrame {
this.recipient = recipient;
this.originator = originator;
this.contract = contract;
this.contractBalance = contractBalance;
this.contractAccountVersion = contractAccountVersion;
this.gasPrice = gasPrice;
this.inputData = inputData;
@ -753,6 +756,15 @@ public class MessageFrame {
return contract;
}
/**
* Returns the balance of the contract currently executing.
*
* @return the balance of the contract currently executing
*/
public Wei getContractBalance() {
return contractBalance;
}
/**
* Returns the current gas price.
*
@ -864,6 +876,7 @@ public class MessageFrame {
private Address address;
private Address originator;
private Address contract;
private Wei contractBalance;
private int contractAccountVersion = -1;
private Wei gasPrice;
private BytesValue inputData;
@ -921,6 +934,11 @@ public class MessageFrame {
return this;
}
public Builder contractBalance(final Wei contractBalance) {
this.contractBalance = contractBalance;
return this;
}
public Builder contractAccountVersion(final int contractAccountVersion) {
checkArgument(contractAccountVersion >= 0, "Contract account version cannot be negative");
this.contractAccountVersion = contractAccountVersion;
@ -1011,6 +1029,7 @@ public class MessageFrame {
checkState(address != null, "Missing message frame recipient");
checkState(originator != null, "Missing message frame originator");
checkState(contract != null, "Missing message frame contract");
checkState(contractBalance != null, "Missing message frame contractBalance");
checkState(gasPrice != null, "Missing message frame getGasRemaining price");
checkState(inputData != null, "Missing message frame input data");
checkState(sender != null, "Missing message frame sender");
@ -1038,6 +1057,7 @@ public class MessageFrame {
address,
originator,
contract,
contractBalance,
contractAccountVersion,
gasPrice,
inputData,

@ -111,6 +111,7 @@ public abstract class AbstractCreateOperation extends AbstractOperation {
.address(contractAddress)
.originator(frame.getOriginatorAddress())
.contract(contractAddress)
.contractBalance(account.getBalance())
.contractAccountVersion(frame.getContractAccountVersion())
.gasPrice(frame.getGasPrice())
.inputData(BytesValue.EMPTY)

@ -0,0 +1,35 @@
/*
* Copyright 2018 ConsenSys AG.
*
* 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.
*/
package tech.pegasys.pantheon.ethereum.vm.operations;
import tech.pegasys.pantheon.ethereum.core.Gas;
import tech.pegasys.pantheon.ethereum.vm.AbstractOperation;
import tech.pegasys.pantheon.ethereum.vm.GasCalculator;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
public class SelfBalanceOperation extends AbstractOperation {
public SelfBalanceOperation(final GasCalculator gasCalculator) {
super(0x47, "SELFBALANCE", 0, 1, false, 1, gasCalculator);
}
@Override
public Gas cost(final MessageFrame frame) {
return gasCalculator().getLowTierGasCost();
}
@Override
public void execute(final MessageFrame frame) {
frame.pushStackItem(frame.getContractBalance().getBytes());
}
}

@ -42,6 +42,7 @@ public class MessageFrameTestFixture {
private Address sender = DEFAUT_ADDRESS;
private Address originator = DEFAUT_ADDRESS;
private Address contract = DEFAUT_ADDRESS;
private Wei contractBalance = Wei.of(1);
private int contractAccountVersion = Account.DEFAULT_VERSION;
private Wei gasPrice = Wei.ZERO;
private Wei value = Wei.ZERO;
@ -109,6 +110,11 @@ public class MessageFrameTestFixture {
return this;
}
public MessageFrameTestFixture contractBalance(final Wei contractBalance) {
this.contractBalance = contractBalance;
return this;
}
public MessageFrameTestFixture contractAccountVersion(final int contractAccountVersion) {
this.contractAccountVersion = contractAccountVersion;
return this;
@ -173,6 +179,7 @@ public class MessageFrameTestFixture {
.value(value)
.apparentValue(value)
.contract(contract)
.contractBalance(contractBalance)
.contractAccountVersion(contractAccountVersion)
.code(code)
.blockHeader(blockHeader)

@ -34,6 +34,8 @@ public class EnvironmentInformation {
private final Address accountAddress;
private final Wei accountBalance;
private BlockHeader blockHeader;
private final Address callerAddress;
@ -69,6 +71,7 @@ public class EnvironmentInformation {
@JsonCreator
public EnvironmentInformation(
@JsonProperty("address") final String account,
@JsonProperty("balance") final String balance,
@JsonProperty("caller") final String caller,
@JsonProperty("code") final CodeMock code,
@JsonProperty("data") final String data,
@ -81,6 +84,7 @@ public class EnvironmentInformation {
code,
0,
account == null ? null : Address.fromHexString(account),
balance == null ? Wei.ZERO : Wei.fromHexString(balance),
caller == null ? null : Address.fromHexString(caller),
origin == null ? null : Address.fromHexString(origin),
data == null ? null : BytesValue.fromHexString(data),
@ -94,6 +98,7 @@ public class EnvironmentInformation {
final Code code,
final int depth,
final Address accountAddress,
final Wei accountBalance,
final Address callerAddress,
final Address originAddress,
final BytesValue data,
@ -104,6 +109,7 @@ public class EnvironmentInformation {
this.code = code;
this.depth = depth;
this.accountAddress = accountAddress;
this.accountBalance = accountBalance;
this.callerAddress = callerAddress;
this.originAddress = originAddress;
this.data = data;
@ -132,6 +138,11 @@ public class EnvironmentInformation {
return accountAddress;
}
/** @return The balance of the currently executing account */
public Wei getAccountBalance() {
return accountBalance;
}
/** @return Address of the caller. */
public Address getCallerAddress() {
return callerAddress;

@ -135,6 +135,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
.worldState(worldState.updater())
.initialGas(spec.getExec().getGas())
.contract(execEnv.getAccountAddress())
.contractBalance(execEnv.getAccountBalance())
.address(execEnv.getAccountAddress())
.originator(execEnv.getOriginAddress())
.gasPrice(execEnv.getGasPrice())

@ -29,6 +29,7 @@ import tech.pegasys.pantheon.ethereum.core.MutableAccount;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.core.WorldUpdater;
import tech.pegasys.pantheon.ethereum.mainnet.ConstantinopleGasCalculator;
import tech.pegasys.pantheon.ethereum.mainnet.IstanbulGasCalculator;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import tech.pegasys.pantheon.ethereum.vm.Words;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
@ -49,12 +50,20 @@ public class ExtCodeHashOperationTest {
private final ExtCodeHashOperation operation =
new ExtCodeHashOperation(new ConstantinopleGasCalculator());
private final ExtCodeHashOperation operationIstanbul =
new ExtCodeHashOperation(new IstanbulGasCalculator());
@Test
public void shouldCharge400Gas() {
assertThat(operation.cost(createMessageFrame(REQUESTED_ADDRESS))).isEqualTo(Gas.of(400));
}
@Test
public void istanbulShouldCharge700Gas() {
assertThat(operationIstanbul.cost(createMessageFrame(REQUESTED_ADDRESS)))
.isEqualTo(Gas.of(700));
}
@Test
public void shouldReturnZeroWhenAccountDoesNotExist() {
final Bytes32 result = executeOperation(REQUESTED_ADDRESS);

Loading…
Cancel
Save