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

Commit

Permalink
Merge pull request #919 from ethereum/eip-211
Browse files Browse the repository at this point in the history
Eip 211 implementation
  • Loading branch information
mkalinin authored Aug 18, 2017
2 parents 4c0d48d + c4054c5 commit 4f97f27
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,13 @@ String validateTransactionChanges(BlockStore blockStore, Block curBlock, Transac
*/
Integer getChainId();

boolean eip140();
/**
* 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 @@ -159,7 +159,12 @@ public Integer getChainId() {
}

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ public BigInteger getCalcDifficultyMultiplier(BlockHeader curBlock, BlockHeader
}

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

@Override
public boolean eip211() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,12 @@ public Integer getChainId() {
}

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

@Override
public boolean eip211() {
return false;
}
}
4 changes: 4 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
59 changes: 49 additions & 10 deletions ethereumj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,16 +146,26 @@ public void step(Program program) {
OpCode op = OpCode.code(program.getCurrentOp());
if (op == null) {
throw Program.Exception.invalidOpCode(program.getCurrentOp());
} else if (op == DELEGATECALL) {
// opcode since Homestead release only
if (!blockchainConfig.getConstants().hasDelegateCallOpcode()) {
throw Program.Exception.invalidOpCode(program.getCurrentOp());
}
} else if (op == REVERT) {
// opcode since Bizantium HF only
if (!blockchainConfig.eip140()) {
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 @@ -247,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 @@ -775,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
33 changes: 31 additions & 2 deletions ethereumj-core/src/main/java/org/ethereum/vm/program/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
Expand Down Expand Up @@ -87,6 +86,7 @@ public class Program {
private Stack stack;
private Memory memory;
private Storage storage;
private byte[] returnDataBuffer;

private ProgramResult result = new ProgramResult();
private ProgramTrace trace = new ProgramTrace();
Expand Down Expand Up @@ -460,8 +460,9 @@ this, new DataWord(newAddress), getOwnerAddress(), value, gasLimit,
newBalance, null, track, this.invoke.getBlockStore(), byTestingSuite());

ProgramResult result = ProgramResult.empty();
if (isNotEmpty(programCode)) {
returnDataBuffer = null; // reset return buffer right before the call

if (isNotEmpty(programCode)) {
VM vm = new VM(config);
Program program = new Program(programCode, programInvoke, internalTx, config).withCommonConfig(commonConfig);
vm.play(program);
Expand All @@ -483,6 +484,8 @@ this, new DataWord(newAddress), getOwnerAddress(), value, gasLimit,

if (result.getException() != null) {
return;
} else {
returnDataBuffer = result.getHReturn();
}
} else {
// 4. CREATE THE CONTRACT OUT OF RETURN
Expand Down Expand Up @@ -583,6 +586,8 @@ public void callToAddress(MessageCall msg) {

ProgramResult result = null;
if (isNotEmpty(programCode)) {
returnDataBuffer = null; // reset return buffer right before the call

ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(contextAddress),
msg.getType() == MsgType.DELEGATECALL ? getCallerAddress() : getOwnerAddress(),
Expand Down Expand Up @@ -635,6 +640,8 @@ this, new DataWord(contextAddress),
int size = msg.getOutDataSize().intValue();

memorySaveLimited(offset, buffer, size);

returnDataBuffer = buffer;
}

// 5. REFUND THE REMAIN GAS
Expand Down Expand Up @@ -751,6 +758,20 @@ public byte[] getDataCopy(DataWord offset, DataWord length) {
return invoke.getDataCopy(offset, length);
}

public DataWord getReturnDataBufferSize() {
return new DataWord(getReturnDataBufferSizeI());
}

private int getReturnDataBufferSizeI() {
return returnDataBuffer == null ? 0 : returnDataBuffer.length;
}

public byte[] getReturnDataBufferData(DataWord off, DataWord size) {
if ((long) off.intValueSafe() + size.intValueSafe() > getReturnDataBufferSizeI()) return null;
return returnDataBuffer == null ? new byte[0] :
Arrays.copyOfRange(returnDataBuffer, off.intValueSafe(), off.intValueSafe() + size.intValueSafe());
}

public DataWord storageLoad(DataWord key) {
DataWord ret = getStorage().getStorageValue(getOwnerAddress().getLast20Bytes(), key.clone());
return ret == null ? null : ret.clone();
Expand Down Expand Up @@ -1206,6 +1227,14 @@ public StackTooSmallException(String message, Object... args) {
}
}

@SuppressWarnings("serial")
public static class ReturnDataCopyIllegalBoundsException extends BytecodeExecutionException {
public ReturnDataCopyIllegalBoundsException(DataWord off, DataWord size, long returnDataSize) {
super(String.format("Illegal RETURNDATACOPY arguments: offset (%s) + size (%s) > RETURNDATASIZE (%d)", off, size, returnDataSize));
}
}


public static class Exception {

public static OutOfGasException notEnoughOpGas(OpCode op, long opGas, long programGas) {
Expand Down

0 comments on commit 4f97f27

Please sign in to comment.