Document class and indentation to comply with convention http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html

This commit is contained in:
nicksavers 2014-06-07 21:11:44 +02:00
parent bf6693122d
commit 2e8d413817
1 changed files with 90 additions and 140 deletions

View File

@ -10,21 +10,47 @@ import java.nio.ByteBuffer;
import static org.ethereum.vm.OpCode.PUSH1; import static org.ethereum.vm.OpCode.PUSH1;
/** /**
* www.ethereumJ.com * The Ethereum Virtual Machine (EVM) is responsible for initialization
* User: Roman Mandeleil * and executing a transaction on a contract.
* Created on: 01/06/2014 10:44 *
* It is a quasi-Turing-complete machine; the quasi qualification
* comes from the fact that the computation is intrinsically bounded
* through a parameter, gas, which limits the total amount of computation done.
*
* The EVM is a simple stack-based architecture. The word size of the machine
* (and thus size of stack item) is 256-bit. This was chosen to facilitate
* the SHA3-256 hash scheme and elliptic-curve computations. The memory model
* is a simple word-addressed byte array. The stack has an unlimited size.
* The machine also has an independent storage model; this is similar in concept
* to the memory but rather than a byte array, it is a word-addressable word array.
*
* Unlike memory, which is volatile, storage is non volatile and is
* maintained as part of the system state. All locations in both storage
* and memory are well-defined initially as zero.
*
* The machine does not follow the standard von Neumann architecture.
* Rather than storing program code in generally-accessible memory or storage,
* it is stored separately in a virtual ROM interactable only though
* a specialised instruction.
*
* The machine can have exceptional execution for several reasons,
* including stack underflows and invalid instructions. These unambiguously
* and validly result in immediate halting of the machine with all state changes
* left intact. The one piece of exceptional execution that does not leave
* state changes intact is the out-of-gas (OOG) exception.
*
* Here, the machine halts immediately and reports the issue to
* the execution agent (either the transaction processor or, recursively,
* the spawning execution environment) and which will deal with it separately.
*/ */
public class VM { public class VM {
static private BigInteger _32_ = BigInteger.valueOf(32); static private BigInteger _32_ = BigInteger.valueOf(32);
Logger logger = LoggerFactory.getLogger("VM"); private Logger logger = LoggerFactory.getLogger("VM");
public void step(Program program) { public void step(Program program) {
try { try {
byte op = program.getCurrentOp(); byte op = program.getCurrentOp();
@ -62,46 +88,36 @@ public class VM {
break; break;
} }
switch (OpCode.code(op)) { switch (OpCode.code(op)) {
/** /**
* Stop and Arithmetic Operations * Stop and Arithmetic Operations
*/ */
case STOP:{ case STOP:{
program.setHReturn(ByteBuffer.allocate(0)); program.setHReturn(ByteBuffer.allocate(0));
program.stop(); program.stop();
} } break;
break;
case ADD:{ case ADD:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.add(word2); word1.add(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case MUL:{ case MUL:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.mul(word2); word1.mul(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case SUB:{ case SUB:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.sub(word2); word1.sub(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case DIV:{ case DIV:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
@ -109,8 +125,7 @@ public class VM {
word1.div(word2); word1.div(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case SDIV:{ case SDIV:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
@ -118,44 +133,35 @@ public class VM {
word1.sDiv(word2); word1.sDiv(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case MOD:{ case MOD:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.mod(word2); word1.mod(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case SMOD:{ case SMOD:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.sMod(word2); word1.sMod(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case EXP:{ case EXP:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.exp(word2); word1.exp(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case NEG:{ case NEG:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
word1.negate(); word1.negate();
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case LT:{ case LT:{
// todo: can be improved by not using BigInteger // todo: can be improved by not using BigInteger
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
@ -167,10 +173,8 @@ public class VM {
} }
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case SLT:{ case SLT:{
// todo: can be improved by not using BigInteger // todo: can be improved by not using BigInteger
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
@ -182,9 +186,8 @@ public class VM {
} }
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
}break; } break;
case SGT:{ case SGT:{
// todo: can be improved by not using BigInteger // todo: can be improved by not using BigInteger
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
@ -196,9 +199,8 @@ public class VM {
} }
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
}break; } break;
case GT:{ case GT:{
// todo: can be improved by not using BigInteger // todo: can be improved by not using BigInteger
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
@ -210,7 +212,7 @@ public class VM {
} }
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
}break; } break;
case EQ:{ case EQ:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
@ -222,8 +224,7 @@ public class VM {
} }
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case NOT: { case NOT: {
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
if (word1.isZero()){ if (word1.isZero()){
@ -233,42 +234,35 @@ public class VM {
} }
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
/** /**
* Bitwise Logic Operations * Bitwise Logic Operations
*/ */
case AND:{ case AND:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.and(word2); word1.and(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case OR: { case OR: {
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.or(word2); word1.or(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case XOR: { case XOR: {
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
word1.xor(word2); word1.xor(word2);
program.stackPush(word1); program.stackPush(word1);
program.step(); program.step();
} } break;
break;
case BYTE:{ case BYTE:{
DataWord word1 = program.stackPop(); DataWord word1 = program.stackPop();
DataWord word2 = program.stackPop(); DataWord word2 = program.stackPop();
DataWord result = null; DataWord result = null;
if (word1.value().compareTo(_32_) == -1){ if (word1.value().compareTo(_32_) == -1){
byte tmp = word2.getData()[word1.value().intValue()]; byte tmp = word2.getData()[word1.value().intValue()];
@ -280,13 +274,11 @@ public class VM {
} }
program.stackPush(result); program.stackPush(result);
program.step(); program.step();
} } break;
break;
/** /**
* SHA3 * SHA3
*/ */
case SHA3:{ case SHA3:{
DataWord memOffsetData = program.stackPop(); DataWord memOffsetData = program.stackPop();
DataWord lengthData = program.stackPop(); DataWord lengthData = program.stackPop();
@ -297,60 +289,50 @@ public class VM {
program.stackPush(word); program.stackPush(word);
program.step(); program.step();
} } break;
break;
/** /**
* Environmental Information * Environmental Information
*/ */
case ADDRESS:{ case ADDRESS:{
DataWord address = program.getOwnerAddress(); DataWord address = program.getOwnerAddress();
program.stackPush(address); program.stackPush(address);
program.step(); program.step();
} } break;
break;
case BALANCE:{ case BALANCE:{
DataWord balance = program.getBalance(); DataWord balance = program.getBalance();
program.stackPush(balance); program.stackPush(balance);
program.step(); program.step();
} } break;
break;
case ORIGIN:{ case ORIGIN:{
DataWord originAddress = program.getOriginAddress(); DataWord originAddress = program.getOriginAddress();
program.stackPush(originAddress); program.stackPush(originAddress);
program.step(); program.step();
} } break;
break;
case CALLER:{ case CALLER:{
DataWord callerAddress = program.getCallerAddress(); DataWord callerAddress = program.getCallerAddress();
program.stackPush(callerAddress); program.stackPush(callerAddress);
program.step(); program.step();
} } break;
break;
case CALLVALUE:{ case CALLVALUE:{
DataWord callValue = program.getCallValue(); DataWord callValue = program.getCallValue();
program.stackPush(callValue); program.stackPush(callValue);
program.step(); program.step();
} } break;
break;
case CALLDATALOAD:{ case CALLDATALOAD:{
DataWord dataOffs = program.stackPop(); DataWord dataOffs = program.stackPop();
DataWord value = program.getDataValue(dataOffs); DataWord value = program.getDataValue(dataOffs);
program.stackPush(value); program.stackPush(value);
program.step(); program.step();
} } break;
break;
case CALLDATASIZE:{ case CALLDATASIZE:{
DataWord dataSize = program.getDataSize(); DataWord dataSize = program.getDataSize();
program.stackPush(dataSize); program.stackPush(dataSize);
program.step(); program.step();
} } break;
break;
case CALLDATACOPY:{ case CALLDATACOPY:{
DataWord memOffsetData = program.stackPop(); DataWord memOffsetData = program.stackPop();
DataWord dataOffsetData = program.stackPop(); DataWord dataOffsetData = program.stackPop();
DataWord lengthData = program.stackPop(); DataWord lengthData = program.stackPop();
@ -358,15 +340,12 @@ public class VM {
byte[] msgData = program.getDataCopy(dataOffsetData, lengthData); byte[] msgData = program.getDataCopy(dataOffsetData, lengthData);
program.memorySave(memOffsetData.data, msgData); program.memorySave(memOffsetData.data, msgData);
program.step(); program.step();
} break; } break;
case CODESIZE:{ case CODESIZE:{
DataWord length = new DataWord(program.ops.length); DataWord length = new DataWord(program.ops.length);
program.stackPush(length); program.stackPush(length);
program.step(); program.step();
} } break;
break;
case CODECOPY:{ case CODECOPY:{
DataWord memOffsetData = program.stackPop(); DataWord memOffsetData = program.stackPop();
DataWord codeOffsetData = program.stackPop(); DataWord codeOffsetData = program.stackPop();
@ -377,7 +356,6 @@ public class VM {
int memOffset = memOffsetData.value().intValue(); int memOffset = memOffsetData.value().intValue();
if (program.ops.length < length + codeOffset){ if (program.ops.length < length + codeOffset){
program.stop(); program.stop();
break; break;
} }
@ -387,8 +365,7 @@ public class VM {
program.memorySave(memOffsetData.getData(), code); program.memorySave(memOffsetData.getData(), code);
program.step(); program.step();
} } break;
break;
case GASPRICE: case GASPRICE:
break; break;
@ -408,52 +385,43 @@ public class VM {
break; break;
case GASLIMIT: case GASLIMIT:
break; break;
case POP:{ case POP:{
program.stackPop(); program.stackPop();
program.step(); program.step();
} } break;
break;
case DUP:{ case DUP:{
DataWord word_1 = program.stackPop(); DataWord word_1 = program.stackPop();
DataWord word_2 = word_1.clone(); DataWord word_2 = word_1.clone();
program.stackPush(word_1); program.stackPush(word_1);
program.stackPush(word_2); program.stackPush(word_2);
program.step(); program.step();
} } break;
break;
case SWAP:{ case SWAP:{
DataWord word_1 = program.stackPop(); DataWord word_1 = program.stackPop();
DataWord word_2 = program.stackPop(); DataWord word_2 = program.stackPop();
program.stackPush(word_1); program.stackPush(word_1);
program.stackPush(word_2); program.stackPush(word_2);
program.step(); program.step();
} } break;
break;
case MLOAD:{ case MLOAD:{
DataWord addr = program.stackPop(); DataWord addr = program.stackPop();
DataWord data = program.memoryLoad(addr); DataWord data = program.memoryLoad(addr);
program.stackPush(data); program.stackPush(data);
program.step(); program.step();
} } break;
break;
case MSTORE:{ case MSTORE:{
DataWord addr = program.stackPop(); DataWord addr = program.stackPop();
DataWord value = program.stackPop(); DataWord value = program.stackPop();
program.memorySave(addr, value); program.memorySave(addr, value);
program.step(); program.step();
} } break;
break;
case MSTORE8:{ case MSTORE8:{
DataWord addr = program.stackPop(); DataWord addr = program.stackPop();
DataWord value = program.stackPop(); DataWord value = program.stackPop();
byte[] byteVal = {value.getData()[31]}; byte[] byteVal = {value.getData()[31]};
program.memorySave(addr.getData(), byteVal); program.memorySave(addr.getData(), byteVal);
program.step(); program.step();
} } break;
break;
case SLOAD:{ case SLOAD:{
DataWord key = program.stackPop(); DataWord key = program.stackPop();
DataWord val = program.storageLoad(key); DataWord val = program.storageLoad(key);
@ -462,8 +430,7 @@ public class VM {
} }
program.stackPush(val); program.stackPush(val);
program.step(); program.step();
} } break;
break;
case SSTORE:{ case SSTORE:{
DataWord addr = program.stackPop(); DataWord addr = program.stackPop();
DataWord value = program.stackPop(); DataWord value = program.stackPop();
@ -477,15 +444,12 @@ public class VM {
program.spendGas(GasCost.SSTORE * 0); program.spendGas(GasCost.SSTORE * 0);
} else } else
program.spendGas(GasCost.SSTORE); program.spendGas(GasCost.SSTORE);
program.step(); program.step();
} } break;
break;
case JUMP:{ case JUMP:{
DataWord pos = program.stackPop(); DataWord pos = program.stackPop();
program.setPC(pos); program.setPC(pos);
} } break;
break;
case JUMPI:{ case JUMPI:{
DataWord pos = program.stackPop(); DataWord pos = program.stackPop();
DataWord cond = program.stackPop(); DataWord cond = program.stackPop();
@ -495,23 +459,19 @@ public class VM {
} else{ } else{
program.step(); program.step();
} }
} } break;
break;
case PC:{ case PC:{
int pc = program.getPC(); int pc = program.getPC();
DataWord pcWord = new DataWord(pc); DataWord pcWord = new DataWord(pc);
program.stackPush(pcWord); program.stackPush(pcWord);
program.step(); program.step();
} } break;
break;
case MSIZE:{ case MSIZE:{
int memSize = program.getMemSize(); int memSize = program.getMemSize();
DataWord wordMemSize = new DataWord(memSize); DataWord wordMemSize = new DataWord(memSize);
program.stackPush(wordMemSize); program.stackPush(wordMemSize);
program.step(); program.step();
} } break;
break;
case GAS: case GAS:
break; break;
@ -519,14 +479,12 @@ public class VM {
case PUSH9: case PUSH10: case PUSH11: case PUSH12: case PUSH13: case PUSH14: case PUSH15: case PUSH16: case PUSH9: case PUSH10: case PUSH11: case PUSH12: case PUSH13: case PUSH14: case PUSH15: case PUSH16:
case PUSH17: case PUSH18: case PUSH19: case PUSH20: case PUSH21: case PUSH22: case PUSH23: case PUSH24: case PUSH17: case PUSH18: case PUSH19: case PUSH20: case PUSH21: case PUSH22: case PUSH23: case PUSH24:
case PUSH25: case PUSH26: case PUSH27: case PUSH28: case PUSH29: case PUSH30: case PUSH31: case PUSH32:{ case PUSH25: case PUSH26: case PUSH27: case PUSH28: case PUSH29: case PUSH30: case PUSH31: case PUSH32:{
program.step(); program.step();
int nPush = op - PUSH1.val() + 1; int nPush = op - PUSH1.val() + 1;
byte[] data = program.sweep(nPush); byte[] data = program.sweep(nPush);
program.stackPush(data); program.stackPush(data);
} } break;
break;
case CREATE:{ case CREATE:{
DataWord gas = program.stackPop(); DataWord gas = program.stackPop();
DataWord inOffset = program.stackPop(); DataWord inOffset = program.stackPop();
@ -535,8 +493,7 @@ public class VM {
// todo: implement contract creation // todo: implement contract creation
program.step(); program.step();
} } break;
break;
case CALL:{ case CALL:{
DataWord gas = program.stackPop(); DataWord gas = program.stackPop();
DataWord toAddress = program.stackPop(); DataWord toAddress = program.stackPop();
@ -548,10 +505,8 @@ public class VM {
// todo: the contract for real // todo: the contract for real
program.step(); program.step();
} } break;
break;
case RETURN:{ case RETURN:{
DataWord offset = program.stackPop(); DataWord offset = program.stackPop();
DataWord size = program.stackPop(); DataWord size = program.stackPop();
@ -560,14 +515,12 @@ public class VM {
program.step(); program.step();
program.stop(); program.stop();
} } break;
break;
case SUICIDE:{ case SUICIDE:{
DataWord address = program.stackPop(); DataWord address = program.stackPop();
// todo: transfer left balance to the address // todo: transfer left balance to the address
program.stop(); program.stop();
} } break;
break;
default:{ default:{
} }
@ -583,15 +536,12 @@ public class VM {
} }
public void play(Program program) {
public void play(Program program){
try { try {
while(!program.isStopped()) while(!program.isStopped())
this.step(program); this.step(program);
} catch (RuntimeException e) { } catch (RuntimeException e) {
program.setRuntimeFailure(e); program.setRuntimeFailure(e);
} }
} }
} }