VM impl go on:

ADD, MULL,  SUB, DIV, EXP, MEMSIZE, STOP ops implemented and unit tested
This commit is contained in:
romanman 2014-06-02 22:02:27 +03:00
parent c44920edd2
commit 926aa6f17f
5 changed files with 973 additions and 493 deletions

View File

@ -34,19 +34,8 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
program.addListener(this);
program.fullTrace();
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
while(!program.isStoped())
vm.step(program);
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

View File

@ -98,6 +98,69 @@ public class DataWord {
}
}
// todo: add can be done in more efficient way
// todo without BigInteger quick hack
public void add(DataWord word){
BigInteger result = value().add( word.value() );
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
}
// todo: mull can be done in more efficient way
// todo: with shift left shift right trick
// todo without BigInteger quick hack
public void mull(DataWord word){
BigInteger result = value().multiply( word.value() );
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
}
// todo: improve with no BigInteger
public void div(DataWord word){
if (word.isZero()){
this.and(ZERO);
return;
}
BigInteger result = value().divide( word.value() );
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
}
// todo: improve with no BigInteger
public void sub(DataWord word){
BigInteger result = value().subtract( word.value() );
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
}
// todo: improve with no BigInteger
public void exp(DataWord word){
BigInteger result = value().pow( word.value().intValue() );
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
}
public String toString(){
return Hex.toHexString(data);

View File

@ -26,8 +26,9 @@ public class Program {
Map<DataWord, DataWord> storage = new HashMap<DataWord, DataWord>();
ByteBuffer memory = null;
byte[] ops;
int pc = 0;
byte[] ops;
int pc = 0;
boolean stopped = false;
public Program(byte[] ops) {
@ -64,8 +65,17 @@ public class Program {
this.pc = pc;
}
public boolean isStoped(){
return stopped;
}
public void stop(){
stopped = true;
}
public void step(){
++pc;
if (pc >= ops.length) stop();
}
public byte[] sweep(int n){
@ -74,6 +84,8 @@ public class Program {
byte[] data = Arrays.copyOfRange(ops, pc, pc + n);
pc += n;
if (pc >= ops.length) stop();
return data;
}
@ -83,6 +95,13 @@ public class Program {
return stack.pop();
};
public int getMemSize(){
int memSize = 0;
if (memory != null) memSize = memory.limit();
return memSize;
}
public void memorySave(DataWord addrB, DataWord value){
memorySave(addrB.data, value.data);
}

View File

@ -3,9 +3,7 @@ package org.ethereum.vm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.crypto.Data;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import static org.ethereum.vm.OpCode.PUSH1;
@ -25,343 +23,389 @@ public class VM {
public void step(Program program){
byte op = program.getCurrentOp();
logger.debug("Op: {}" ,OpCode.code(op).name());
try {
switch (OpCode.code(op)){
byte op = program.getCurrentOp();
logger.debug("Op: {}" ,OpCode.code(op).name());
switch (OpCode.code(op)){
/**
* Stop and Arithmetic Operations
*/
/**
* Stop and Arithmetic Operations
*/
case STOP:
break;
case ADD:
break;
case MUL:
break;
case SUB:
break;
case DIV:
break;
case SDIV:
break;
case MOD:
break;
case SMOD:
break;
case EXP:
break;
case NEG:{
DataWord word1 = program.stackPull();
word1.negate();
program.stackPush(word1);
program.step();
}break;
case LT:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
if (word1.value().compareTo(word2.value()) == -1){
word1.and(DataWord.ZERO);
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
case STOP:{
program.stop();
}
program.stackPush(word1);
program.step();
}break;
case SLT:
break;
case SGT:
break;
case GT:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
if (word1.value().compareTo(word2.value()) == 1){
word1.and(DataWord.ZERO);
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}break;
case EQ:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
if (word1.xor(word2).isZero()){
word1.and(DataWord.ZERO);
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}
break;
case NOT: {
DataWord word1 = program.stackPull();
if (word1.isZero()){
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}
break;
case ADD:{
/**
* Bitwise Logic Operations
*/
case AND:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.and(word2);
program.stackPush(word1);
program.step();
}
break;
case OR: {
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.or(word2);
program.stackPush(word1);
program.step();
}
break;
case XOR: {
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.xor(word2);
program.stackPush(word1);
program.step();
}
break;
case BYTE:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
DataWord result = null;
if (word1.value().compareTo(_32_) == -1){
byte tmp = word2.getData()[word1.value().intValue()];
word2.and(DataWord.ZERO);
word2.getData()[31] = tmp;
result = word2;
} else
result = new DataWord();
program.stackPush(result);
program.step();
}
break;
/**
* SHA3
*/
case SHA3:
break;
/**
* Environmental Information
*/
case ADDRESS:
break;
case BALANCE:
break;
case ORIGIN:
break;
case CALLER:
break;
case CALLVALUE:
break;
case CALLDATALOAD:
break;
case CALLDATASIZE:
break;
case CALLDATACOPY:
break;
case CODESIZE:
break;
case CODECOPY:
break;
case GASPRICE:
break;
/**
* Block Information
*/
case PREVHASH:
break;
case COINBASE:
break;
case TIMESTAMP:
break;
case NUMBER:
break;
case DIFFICULTY:
break;
case GASLIMIT:
break;
case POP:{
program.stackPull();
program.step();
}
break;
case DUP:{
DataWord word_1 = program.stackPull();
DataWord word_2 = word_1.clone();
program.stackPush(word_1);
program.stackPush(word_2);
program.step();
}
break;
case SWAP:{
DataWord word_1 = program.stackPull();
DataWord word_2 = program.stackPull();
program.stackPush(word_1);
program.stackPush(word_2);
program.step();
}
break;
case MLOAD:{
DataWord addr = program.stackPull();
DataWord data = program.memoryLoad(addr);
program.stackPush(data);
program.step();
}
break;
case MSTORE:{
DataWord addr = program.stackPull();
DataWord value = program.stackPull();
program.memorySave(addr, value);
program.step();
}
break;
case MSTORE8:{
DataWord addr = program.stackPull();
DataWord value = program.stackPull();
byte[] byteVal = {value.getData()[31]};
program.memorySave(addr.getData(), byteVal);
program.step();
}
break;
case SLOAD:{
DataWord key = program.stackPull();
DataWord val = program.storageLoad(key);
if (val == null){
val = key.and(DataWord.ZERO);
}
program.stackPush(val);
program.step();
}
break;
case SSTORE:{
DataWord addr = program.stackPull();
DataWord value = program.stackPull();
program.storageSave(addr, value);
program.step();
}
break;
case JUMP:{
DataWord pos = program.stackPull();
program.setPC(pos);
}
break;
case JUMPI:{
DataWord pos = program.stackPull();
DataWord cond = program.stackPull();
if (!cond.isZero()){
program.setPC(pos);
} else{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.add(word2);
program.stackPush(word1);
program.step();
}
break;
case MUL:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.mull(word2);
program.stackPush(word1);
program.step();
}
break;
case SUB:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.sub(word2);
program.stackPush(word1);
program.step();
}
break;
case DIV:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.div(word2);
program.stackPush(word1);
program.step();
}
break;
case SDIV:
break;
case MOD:
break;
case SMOD:
break;
case EXP:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.exp(word2);
program.stackPush(word1);
program.step();
}
break;
case NEG:{
DataWord word1 = program.stackPull();
word1.negate();
program.stackPush(word1);
program.step();
}break;
case LT:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
if (word1.value().compareTo(word2.value()) == -1){
word1.and(DataWord.ZERO);
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}break;
case SLT:
break;
case SGT:
break;
case GT:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
if (word1.value().compareTo(word2.value()) == 1){
word1.and(DataWord.ZERO);
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}break;
case EQ:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
if (word1.xor(word2).isZero()){
word1.and(DataWord.ZERO);
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}
break;
case NOT: {
DataWord word1 = program.stackPull();
if (word1.isZero()){
word1.getData()[31] = 1;
} else {
word1.and(DataWord.ZERO);
}
program.stackPush(word1);
program.step();
}
break;
/**
* Bitwise Logic Operations
*/
case AND:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.and(word2);
program.stackPush(word1);
program.step();
}
break;
case OR: {
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.or(word2);
program.stackPush(word1);
program.step();
}
break;
case XOR: {
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
word1.xor(word2);
program.stackPush(word1);
program.step();
}
break;
case BYTE:{
DataWord word1 = program.stackPull();
DataWord word2 = program.stackPull();
DataWord result = null;
if (word1.value().compareTo(_32_) == -1){
byte tmp = word2.getData()[word1.value().intValue()];
word2.and(DataWord.ZERO);
word2.getData()[31] = tmp;
result = word2;
} else
result = new DataWord();
program.stackPush(result);
program.step();
}
break;
/**
* SHA3
*/
case SHA3:
break;
/**
* Environmental Information
*/
case ADDRESS:
break;
case BALANCE:
break;
case ORIGIN:
break;
case CALLER:
break;
case CALLVALUE:
break;
case CALLDATALOAD:
break;
case CALLDATASIZE:
break;
case CALLDATACOPY:
break;
case CODESIZE:
break;
case CODECOPY:
break;
case GASPRICE:
break;
/**
* Block Information
*/
case PREVHASH:
break;
case COINBASE:
break;
case TIMESTAMP:
break;
case NUMBER:
break;
case DIFFICULTY:
break;
case GASLIMIT:
break;
case POP:{
program.stackPull();
program.step();
}
break;
case DUP:{
DataWord word_1 = program.stackPull();
DataWord word_2 = word_1.clone();
program.stackPush(word_1);
program.stackPush(word_2);
program.step();
}
break;
case SWAP:{
DataWord word_1 = program.stackPull();
DataWord word_2 = program.stackPull();
program.stackPush(word_1);
program.stackPush(word_2);
program.step();
}
break;
case MLOAD:{
DataWord addr = program.stackPull();
DataWord data = program.memoryLoad(addr);
program.stackPush(data);
program.step();
}
break;
case MSTORE:{
DataWord addr = program.stackPull();
DataWord value = program.stackPull();
program.memorySave(addr, value);
program.step();
}
break;
case MSTORE8:{
DataWord addr = program.stackPull();
DataWord value = program.stackPull();
byte[] byteVal = {value.getData()[31]};
program.memorySave(addr.getData(), byteVal);
program.step();
}
break;
case SLOAD:{
DataWord key = program.stackPull();
DataWord val = program.storageLoad(key);
if (val == null){
val = key.and(DataWord.ZERO);
}
program.stackPush(val);
program.step();
}
break;
case SSTORE:{
DataWord addr = program.stackPull();
DataWord value = program.stackPull();
program.storageSave(addr, value);
program.step();
}
break;
case JUMP:{
DataWord pos = program.stackPull();
program.setPC(pos);
}
break;
case JUMPI:{
DataWord pos = program.stackPull();
DataWord cond = program.stackPull();
if (!cond.isZero()){
program.setPC(pos);
} else{
program.step();
}
}
break;
case PC:{
int pc = program.getPC();
DataWord pcWord = new DataWord(pc);
program.stackPush(pcWord);
program.step();
}
break;
case MEMSIZE:{
int memSize = program.getMemSize();
DataWord wordMemSize = new DataWord(memSize);
program.stackPush(wordMemSize);
}
break;
case GAS:
break;
case PUSH1:
case PUSH2:
case PUSH3:
case PUSH4:
case PUSH5:
case PUSH6:
case PUSH7:
case PUSH8:
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 PUSH25:
case PUSH26:
case PUSH27:
case PUSH28:
case PUSH29:
case PUSH30:
case PUSH31:
case PUSH32:{
program.step();
int nPush = op - PUSH1.val() + 1;
byte[] data = program.sweep(nPush);
program.stackPush(data);
}
break;
case CREATE:
break;
case CALL:
break;
case RETURN:
break;
case SUICIDE:
break;
default:
}
break;
case PC:{
int pc = program.getPC();
DataWord pcWord = new DataWord(pc);
program.stackPush(pcWord);
program.step();
}
break;
case MEMSIZE:
break;
case GAS:
break;
case PUSH1:
case PUSH2:
case PUSH3:
case PUSH4:
case PUSH5:
case PUSH6:
case PUSH7:
case PUSH8:
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 PUSH25:
case PUSH26:
case PUSH27:
case PUSH28:
case PUSH29:
case PUSH30:
case PUSH31:
case PUSH32:
program.step();
int nPush = op - PUSH1.val() + 1;
byte[] data = program.sweep(nPush);
program.stackPush(data);
break;
case CREATE:
break;
case CALL:
break;
case RETURN:
break;
case SUICIDE:
break;
default:
program.fullTrace();
} catch (RuntimeException e) {
program.stop();
throw e;
}
program.fullTrace();
}

File diff suppressed because it is too large Load Diff