Skip to content
This repository has been 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
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
Expand Up @@ -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
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 !!!
Expand Down
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
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
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
Expand Up @@ -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
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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;
Expand All @@ -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());
Expand Down Expand Up @@ -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: {

Expand Down Expand Up @@ -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();

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

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

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