[PAN-2829] Add accountVersion to MessageFrame (#1675)

* [PAN-2829] Add accountVersion to MessageFrame

Add the current contract's version to the message frame.

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Danno Ferrin 5 years ago committed by GitHub
parent 2509680026
commit bbbb5af404
  1. 1
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/Account.java
  2. 42
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java
  3. 10
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetTransactionProcessor.java
  4. 9
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionProcessor.java
  5. 2
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/AbstractCallOperation.java
  6. 17
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/MessageFrame.java
  7. 1
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/AbstractCreateOperation.java
  8. 7
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/MessageFrameTestFixture.java
  9. 6
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java
  10. 4
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetTransactionProcessorTest.java
  11. 21
      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. 2
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ConstantinopleSStoreOperationGasCostTest.java

@ -39,6 +39,7 @@ public interface Account {
long DEFAULT_NONCE = 0L;
Wei DEFAULT_BALANCE = Wei.ZERO;
int DEFAULT_VERSION = 0;
int ISTANBUL_VERSION = 1;
/**
* The Keccak-256 hash of the account address.

@ -16,6 +16,7 @@ import static tech.pegasys.pantheon.ethereum.vm.MessageFrame.DEFAULT_MAX_STACK_S
import tech.pegasys.pantheon.ethereum.MainnetBlockValidator;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Account;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.MutableAccount;
@ -97,7 +98,8 @@ public abstract class MainnetProtocolSpecs {
contractCreationProcessor,
messageCallProcessor,
false,
stackSizeLimit))
stackSizeLimit,
Account.DEFAULT_VERSION))
.privateTransactionProcessorBuilder(
(gasCalculator,
transactionValidator,
@ -109,7 +111,8 @@ public abstract class MainnetProtocolSpecs {
contractCreationProcessor,
messageCallProcessor,
false,
stackSizeLimit))
stackSizeLimit,
Account.DEFAULT_VERSION))
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::create)
.ommerHeaderValidatorBuilder(MainnetBlockHeaderValidator::createOmmerValidator)
@ -215,7 +218,8 @@ public abstract class MainnetProtocolSpecs {
contractCreationProcessor,
messageCallProcessor,
true,
stackSizeLimit))
stackSizeLimit,
Account.DEFAULT_VERSION))
.privateTransactionProcessorBuilder(
(gasCalculator,
transactionValidator,
@ -227,7 +231,8 @@ public abstract class MainnetProtocolSpecs {
contractCreationProcessor,
messageCallProcessor,
false,
stackSizeLimit))
stackSizeLimit,
Account.DEFAULT_VERSION))
.name("SpuriousDragon");
}
@ -280,8 +285,35 @@ public abstract class MainnetProtocolSpecs {
final boolean enableRevertReason) {
final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return constantinopleFixDefinition(
chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason)
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new MainnetTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
true,
stackSizeLimit,
Account.ISTANBUL_VERSION))
.privateTransactionProcessorBuilder(
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
false,
stackSizeLimit,
Account.ISTANBUL_VERSION))
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
new MainnetContractCreationProcessor(
@ -291,7 +323,7 @@ public abstract class MainnetProtocolSpecs {
Collections.singletonList(MaxCodeSizeRule.of(contractSizeLimit)),
1,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES,
1))
Account.ISTANBUL_VERSION))
.name("Istanbul");
}

@ -48,8 +48,11 @@ public class MainnetTransactionProcessor implements TransactionProcessor {
private final AbstractMessageProcessor contractCreationProcessor;
private final AbstractMessageProcessor messageCallProcessor;
private final int maxStackSize;
private final int createContractAccountVersion;
public static class Result implements TransactionProcessor.Result {
private final Status status;
@ -150,13 +153,15 @@ public class MainnetTransactionProcessor implements TransactionProcessor {
final AbstractMessageProcessor contractCreationProcessor,
final AbstractMessageProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final int maxStackSize) {
final int maxStackSize,
final int createContractAccountVersion) {
this.gasCalculator = gasCalculator;
this.transactionValidator = transactionValidator;
this.contractCreationProcessor = contractCreationProcessor;
this.messageCallProcessor = messageCallProcessor;
this.clearEmptyAccounts = clearEmptyAccounts;
this.maxStackSize = maxStackSize;
this.createContractAccountVersion = createContractAccountVersion;
}
@Override
@ -229,6 +234,7 @@ public class MainnetTransactionProcessor implements TransactionProcessor {
.address(contractAddress)
.originator(senderAddress)
.contract(contractAddress)
.contractAccountVersion(createContractAccountVersion)
.gasPrice(transaction.getGasPrice())
.inputData(BytesValue.EMPTY)
.sender(senderAddress)
@ -258,6 +264,8 @@ public class MainnetTransactionProcessor implements TransactionProcessor {
.address(to)
.originator(senderAddress)
.contract(to)
.contractAccountVersion(
contract != null ? contract.getVersion() : Account.DEFAULT_VERSION)
.gasPrice(transaction.getGasPrice())
.inputData(transaction.getPayload())
.sender(senderAddress)

@ -59,6 +59,8 @@ public class PrivateTransactionProcessor {
private final int maxStackSize;
private final int createContractAccountVersion;
public static class Result implements TransactionProcessor.Result {
private final Status status;
@ -160,13 +162,15 @@ public class PrivateTransactionProcessor {
final AbstractMessageProcessor contractCreationProcessor,
final AbstractMessageProcessor messageCallProcessor,
final boolean clearEmptyAccounts,
final int maxStackSize) {
final int maxStackSize,
final int createContractAccountVersion) {
this.gasCalculator = gasCalculator;
this.transactionValidator = transactionValidator;
this.contractCreationProcessor = contractCreationProcessor;
this.messageCallProcessor = messageCallProcessor;
this.clearEmptyAccounts = clearEmptyAccounts;
this.maxStackSize = maxStackSize;
this.createContractAccountVersion = createContractAccountVersion;
}
@SuppressWarnings("unused")
@ -227,6 +231,7 @@ public class PrivateTransactionProcessor {
.address(privateContractAddress)
.originator(senderAddress)
.contract(privateContractAddress)
.contractAccountVersion(createContractAccountVersion)
.initialGas(Gas.MAX_VALUE)
.gasPrice(transaction.getGasPrice())
.inputData(BytesValue.EMPTY)
@ -255,6 +260,8 @@ public class PrivateTransactionProcessor {
.address(to)
.originator(senderAddress)
.contract(to)
.contractAccountVersion(
contract != null ? contract.getVersion() : Account.DEFAULT_VERSION)
.initialGas(Gas.MAX_VALUE)
.gasPrice(transaction.getGasPrice())
.inputData(transaction.getPayload())

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

@ -12,6 +12,7 @@
*/
package tech.pegasys.pantheon.ethereum.vm;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
@ -206,6 +207,7 @@ public class MessageFrame {
private final Address recipient;
private final Address originator;
private final Address contract;
private final int contractAccountVersion;
private final Wei gasPrice;
private final BytesValue inputData;
private final Address sender;
@ -238,6 +240,7 @@ public class MessageFrame {
final Address recipient,
final Address originator,
final Address contract,
final int contractAccountVersion,
final Wei gasPrice,
final BytesValue inputData,
final Address sender,
@ -271,6 +274,7 @@ public class MessageFrame {
this.recipient = recipient;
this.originator = originator;
this.contract = contract;
this.contractAccountVersion = contractAccountVersion;
this.gasPrice = gasPrice;
this.inputData = inputData;
this.sender = sender;
@ -846,6 +850,10 @@ public class MessageFrame {
this.currentOperation = currentOperation;
}
public int getContractAccountVersion() {
return contractAccountVersion;
}
public static class Builder {
private Type type;
@ -856,6 +864,7 @@ public class MessageFrame {
private Address address;
private Address originator;
private Address contract;
private int contractAccountVersion = -1;
private Wei gasPrice;
private BytesValue inputData;
private Address sender;
@ -912,6 +921,12 @@ public class MessageFrame {
return this;
}
public Builder contractAccountVersion(final int contractAccountVersion) {
checkArgument(contractAccountVersion >= 0, "Contract account version cannot be negative");
this.contractAccountVersion = contractAccountVersion;
return this;
}
public Builder gasPrice(final Wei gasPrice) {
this.gasPrice = gasPrice;
return this;
@ -1008,6 +1023,7 @@ public class MessageFrame {
checkState(miningBeneficiary != null, "Missing mining beneficiary");
checkState(blockHashLookup != null, "Missing block hash lookup");
checkState(isPersistingState != null, "Missing isPersistingState");
checkState(contractAccountVersion != -1, "Missing contractAccountVersion");
}
public MessageFrame build() {
@ -1022,6 +1038,7 @@ public class MessageFrame {
address,
originator,
contract,
contractAccountVersion,
gasPrice,
inputData,
sender,

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

@ -42,6 +42,7 @@ public class MessageFrameTestFixture {
private Address sender = DEFAUT_ADDRESS;
private Address originator = DEFAUT_ADDRESS;
private Address contract = DEFAUT_ADDRESS;
private int contractAccountVersion = Account.DEFAULT_VERSION;
private Wei gasPrice = Wei.ZERO;
private Wei value = Wei.ZERO;
private BytesValue inputData = BytesValue.EMPTY;
@ -108,6 +109,11 @@ public class MessageFrameTestFixture {
return this;
}
public MessageFrameTestFixture contractAccountVersion(final int contractAccountVersion) {
this.contractAccountVersion = contractAccountVersion;
return this;
}
public MessageFrameTestFixture gasPrice(final Wei gasPrice) {
this.gasPrice = gasPrice;
return this;
@ -167,6 +173,7 @@ public class MessageFrameTestFixture {
.value(value)
.apparentValue(value)
.contract(contract)
.contractAccountVersion(contractAccountVersion)
.code(code)
.blockHeader(blockHeader)
.depth(depth)

@ -39,7 +39,10 @@ public class TestCodeExecutor {
}
public MessageFrame executeCode(
final String code, final long gasLimit, final Consumer<MutableAccount> accountSetup) {
final String code,
final int accountVersion,
final long gasLimit,
final Consumer<MutableAccount> accountSetup) {
final ProtocolSpec<Void> protocolSpec = fixture.getProtocolSchedule().getByBlockNumber(0);
final WorldUpdater worldState =
createInitialWorldState(accountSetup, fixture.getStateArchive());
@ -68,6 +71,7 @@ public class TestCodeExecutor {
.address(SENDER_ADDRESS)
.originator(SENDER_ADDRESS)
.contract(SENDER_ADDRESS)
.contractAccountVersion(accountVersion)
.gasPrice(transaction.getGasPrice())
.inputData(transaction.getPayload())
.sender(SENDER_ADDRESS)

@ -19,6 +19,7 @@ import static tech.pegasys.pantheon.ethereum.mainnet.ValidationResult.invalid;
import static tech.pegasys.pantheon.ethereum.mainnet.ValidationResult.valid;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Account;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.ProcessableBlockHeader;
import tech.pegasys.pantheon.ethereum.core.Transaction;
@ -61,7 +62,8 @@ public class MainnetTransactionProcessorTest {
contractCreationProcessor,
messageCallProcessor,
false,
MAX_STACK_SIZE);
MAX_STACK_SIZE,
Account.DEFAULT_VERSION);
}
@Test

@ -12,6 +12,7 @@
*/
package tech.pegasys.pantheon.ethereum.vm;
import tech.pegasys.pantheon.ethereum.core.Account;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Gas;
@ -39,6 +40,8 @@ public class EnvironmentInformation {
private final Code code;
private final int version;
private final BytesValue data;
private final int depth;
@ -72,7 +75,8 @@ public class EnvironmentInformation {
@JsonProperty("gas") final String gas,
@JsonProperty("gasPrice") final String gasPrice,
@JsonProperty("origin") final String origin,
@JsonProperty("value") final String value) {
@JsonProperty("value") final String value,
@JsonProperty("version") final String version) {
this(
code,
0,
@ -82,7 +86,8 @@ public class EnvironmentInformation {
data == null ? null : BytesValue.fromHexString(data),
value == null ? null : Wei.fromHexString(value),
gasPrice == null ? null : Wei.fromHexString(gasPrice),
gas == null ? null : Gas.fromHexString(gas));
gas == null ? null : Gas.fromHexString(gas),
version == null ? Account.DEFAULT_VERSION : Integer.decode(version));
}
private EnvironmentInformation(
@ -94,7 +99,8 @@ public class EnvironmentInformation {
final BytesValue data,
final Wei value,
final Wei gasPrice,
final Gas gas) {
final Gas gas,
final int version) {
this.code = code;
this.depth = depth;
this.accountAddress = accountAddress;
@ -104,6 +110,7 @@ public class EnvironmentInformation {
this.value = value;
this.gasPrice = gasPrice;
this.gas = gas;
this.version = version;
}
/**
@ -165,6 +172,10 @@ public class EnvironmentInformation {
return originAddress;
}
public int getVersion() {
return version;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
@ -180,7 +191,9 @@ public class EnvironmentInformation {
.append("\nBlock header: \n ")
.append(blockHeader.toString().replaceAll("\n", "\n "))
.append("\nCaller: ")
.append(callerAddress);
.append(callerAddress)
.append("\nVersion: ")
.append(version);
return builder.toString();
}

@ -143,6 +143,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
.code(execEnv.getCode())
.blockHeader(execEnv.getBlockHeader())
.depth(execEnv.getDepth())
.contractAccountVersion(execEnv.getVersion())
.completer(c -> {})
.miningBeneficiary(execEnv.getBlockHeader().getCoinbase())
.blockHashLookup(new BlockHashLookup(execEnv.getBlockHeader(), blockchain))

@ -15,6 +15,7 @@ package tech.pegasys.pantheon.ethereum.vm.operations;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.config.StubGenesisConfigOptions;
import tech.pegasys.pantheon.ethereum.core.Account;
import tech.pegasys.pantheon.ethereum.core.Gas;
import tech.pegasys.pantheon.ethereum.core.TestCodeExecutor;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
@ -84,6 +85,7 @@ public class ConstantinopleSStoreOperationGasCostTest {
final MessageFrame frame =
codeExecutor.executeCode(
code,
Account.DEFAULT_VERSION,
gasLimit,
account -> account.setStorageValue(UInt256.ZERO, UInt256.of(originalValue)));
assertThat(frame.getState()).isEqualTo(State.COMPLETED_SUCCESS);

Loading…
Cancel
Save