Document class and indentation to comply with convention http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
This commit is contained in:
parent
bf6693122d
commit
2e8d413817
|
@ -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();
|
||||||
|
@ -35,73 +61,63 @@ public class VM {
|
||||||
switch (OpCode.code(op)) {
|
switch (OpCode.code(op)) {
|
||||||
case SHA3:
|
case SHA3:
|
||||||
program.spendGas(GasCost.SHA3);
|
program.spendGas(GasCost.SHA3);
|
||||||
break;
|
break;
|
||||||
case SLOAD:
|
case SLOAD:
|
||||||
program.spendGas(GasCost.SLOAD);
|
program.spendGas(GasCost.SLOAD);
|
||||||
break;
|
break;
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
// todo: calc gas in the execution
|
// todo: calc gas in the execution
|
||||||
// todo: according to the size
|
// todo: according to the size
|
||||||
break;
|
break;
|
||||||
case BALANCE:
|
case BALANCE:
|
||||||
program.spendGas(GasCost.BALANCE);
|
program.spendGas(GasCost.BALANCE);
|
||||||
break;
|
break;
|
||||||
case CREATE:
|
case CREATE:
|
||||||
program.spendGas(GasCost.CREATE);
|
program.spendGas(GasCost.CREATE);
|
||||||
break;
|
break;
|
||||||
case CALL:
|
case CALL:
|
||||||
program.spendGas(GasCost.CALL);
|
program.spendGas(GasCost.CALL);
|
||||||
break;
|
break;
|
||||||
case MSTORE8:
|
case MSTORE8:
|
||||||
case MSTORE:
|
case MSTORE:
|
||||||
// todo: calc gas in the execution
|
// todo: calc gas in the execution
|
||||||
// todo: according to the size
|
// todo: according to the size
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
program.spendGas(GasCost.STEP);
|
program.spendGas(GasCost.STEP);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue