Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Eip 211: New RETURNDATASIZE and RETURNDATACOPY opcodes #919

Merged
merged 8 commits into from
Aug 18, 2017
Merged
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
@@ -127,4 +127,14 @@ String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transac
* EIP155: https://github.com/ethereum/EIPs/issues/155
*/
Integer getChainId();

/**
* EIP206: https://github.com/ethereum/EIPs/pull/206
*/
boolean eip206();

/**
* EIP211: https://github.com/ethereum/EIPs/pull/211
*/
boolean eip211();
}
Original file line number Diff line number Diff line change
@@ -158,6 +158,16 @@ public Integer getChainId() {
return null;
}

@Override
public boolean eip206() {
return false;
}

@Override
public boolean eip211() {
return false;
}

@Override
public String toString() {
return getClass().getSimpleName();
Original file line number Diff line number Diff line change
@@ -62,4 +62,14 @@ public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader
long unclesAdj = parent.hasUncles() ? 2 : 1;
return BigInteger.valueOf(Math.max(unclesAdj - (curBlock.getTimestamp() - parent.getTimestamp()) / 9, -99));
}

@Override
public boolean eip206() {
return true;
}

@Override
public boolean eip211() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -146,4 +146,14 @@ public Constants getCommonConstants() {
public Integer getChainId() {
return null;
}

@Override
public boolean eip206() {
return false;
}

@Override
public boolean eip211() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -300,7 +300,7 @@ public void go() {
result = program.getResult();
m_endGas = toBI(tx.getGasLimit()).subtract(toBI(program.getResult().getGasUsed()));

if (tx.isContractCreation()) {
if (tx.isContractCreation() && !result.isRevert()) {
int returnDataGasValue = getLength(program.getResult().getHReturn()) *
blockchainConfig.getGasCost().getCREATE_DATA();
if (m_endGas.compareTo(BigInteger.valueOf(returnDataGasValue)) < 0) {
@@ -331,19 +331,24 @@ public void go() {
}


if (result.getException() != null) {
if (result.getException() != null || result.isRevert()) {
result.getDeleteAccounts().clear();
result.getLogInfoList().clear();
result.resetFutureRefund();
cacheTrack.rollback();

throw result.getException();
if (result.getException() != null) {
throw result.getException();
}
} else {
touchedAccounts.addAll(result.getTouchedAccounts());
cacheTrack.commit();
}

touchedAccounts.addAll(result.getTouchedAccounts());
} else {
cacheTrack.commit();
}

cacheTrack.commit();

} catch (Throwable e) {

// TODO: catch whatever they will throw on you !!!
10 changes: 10 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/vm/OpCode.java
Original file line number Diff line number Diff line change
@@ -188,6 +188,10 @@ public enum OpCode {
* environment to memory
*/
CODECOPY(0x39, 3, 0, VeryLowTier), // [len code_start mem_start CODECOPY]

RETURNDATASIZE(0x3d, 0, 1, BaseTier),

RETURNDATACOPY(0x3e, 3, 0, VeryLowTier),
/**
* (0x3a) Get price of gas in current
* environment
@@ -587,6 +591,12 @@ public enum OpCode {
* also the Value parameter is omitted for this opCode
*/
DELEGATECALL(0xf4, 6, 1, SpecialTier),
/**
* (0xfd) The `REVERT` instruction will stop execution, roll back all state changes done so far
* and provide a pointer to a memory section, which can be interpreted as an error code or message.
* While doing so, it will not consume all the remaining gas.
*/
REVERT(0xfd, 2, 0, ZeroTier),
/**
* (0xff) Halt execution and register account for
* later deletion
67 changes: 56 additions & 11 deletions ethereumj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
@@ -35,11 +35,7 @@

import static org.ethereum.crypto.HashUtil.sha3;
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
import static org.ethereum.vm.OpCode.CALL;
import static org.ethereum.vm.OpCode.CALLCODE;
import static org.ethereum.vm.OpCode.CREATE;
import static org.ethereum.vm.OpCode.DELEGATECALL;
import static org.ethereum.vm.OpCode.PUSH1;
import static org.ethereum.vm.OpCode.*;

/**
* The Ethereum Virtual Machine (EVM) is responsible for initialization
@@ -151,11 +147,25 @@ public void step(Program program) {
if (op == null) {
throw Program.Exception.invalidOpCode(program.getCurrentOp());
}
if (op == DELEGATECALL) {
// opcode since Homestead release only
if (!blockchainConfig.getConstants().hasDelegateCallOpcode()) {
throw Program.Exception.invalidOpCode(program.getCurrentOp());
}

switch (op) {
case DELEGATECALL:
if (!blockchainConfig.getConstants().hasDelegateCallOpcode()) {
// opcode since Homestead release only
throw Program.Exception.invalidOpCode(program.getCurrentOp());
}
break;
case REVERT:
if (!blockchainConfig.eip206()) {
throw Program.Exception.invalidOpCode(program.getCurrentOp());
}
break;
case RETURNDATACOPY:
case RETURNDATASIZE:
if (!blockchainConfig.eip211()) {
throw Program.Exception.invalidOpCode(program.getCurrentOp());
}
break;
}

program.setLastOp(op.val());
@@ -236,6 +246,7 @@ else if (oldValue != null && newValue.isZero()) {
gasCost += calcMemGas(gasCosts, oldMemSize, memNeeded(stack.peek(), new DataWord(32)), 0);
break;
case RETURN:
case REVERT:
gasCost = gasCosts.getSTOP() + calcMemGas(gasCosts, oldMemSize,
memNeeded(stack.peek(), stack.get(stack.size() - 2)), 0);
break;
@@ -246,6 +257,7 @@ else if (oldValue != null && newValue.isZero()) {
gasCost += chunkUsed * gasCosts.getSHA3_WORD();
break;
case CALLDATACOPY:
case RETURNDATACOPY:
gasCost += calcMemGas(gasCosts, oldMemSize,
memNeeded(stack.peek(), stack.get(stack.size() - 3)),
stack.get(stack.size() - 3).longValueSafe());
@@ -774,6 +786,34 @@ else if (oldValue != null && newValue.isZero()) {
program.step();
}
break;
case RETURNDATASIZE: {
DataWord dataSize = program.getReturnDataBufferSize();

if (logger.isInfoEnabled())
hint = "size: " + dataSize.value();

program.stackPush(dataSize);
program.step();
}
break;
case RETURNDATACOPY: {
DataWord memOffsetData = program.stackPop();
DataWord dataOffsetData = program.stackPop();
DataWord lengthData = program.stackPop();

byte[] msgData = program.getReturnDataBufferData(dataOffsetData, lengthData);

if (msgData == null) {
throw new Program.ReturnDataCopyIllegalBoundsException(dataOffsetData, lengthData, program.getReturnDataBufferSize().longValueSafe());
}

if (logger.isInfoEnabled())
hint = "data: " + Hex.toHexString(msgData);

program.memorySave(memOffsetData.intValueSafe(), msgData);
program.step();
}
break;
case CODESIZE:
case EXTCODESIZE: {

@@ -1190,7 +1230,8 @@ else if (oldValue != null && newValue.isZero()) {
program.step();
}
break;
case RETURN: {
case RETURN:
case REVERT: {
DataWord offset = program.stackPop();
DataWord size = program.stackPop();

@@ -1204,6 +1245,10 @@ else if (oldValue != null && newValue.isZero()) {

program.step();
program.stop();

if (op == REVERT) {
program.getResult().setRevert();
}
}
break;
case SUICIDE: {
Loading