VM Block env included:

+ OPs: PREVHASH, PREVHASH, TIMESTAMP, NUMBER, DIFFICULTY, GASPRICE, GAS, GASLIMIT
+ All OPs, Unit test
This commit is contained in:
romanman 2014-06-09 03:07:03 +01:00
parent 30459202c1
commit 54262dd1b9
9 changed files with 314 additions and 45 deletions

View File

@ -47,7 +47,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
// Hex.decode(code); // Hex.decode(code);
Program program = new Program(tx.getData() , Program program = new Program(tx.getData() ,
ProgramInvokeFactory.createProgramInvoke(tx)); ProgramInvokeFactory.createProgramInvoke(tx, null));
program.addListener(this); program.addListener(this);
program.fullTrace(); program.fullTrace();

View File

@ -2,6 +2,7 @@ package org.ethereum.manager;
import org.ethereum.core.AccountState; import org.ethereum.core.AccountState;
import org.ethereum.core.Block; import org.ethereum.core.Block;
import org.ethereum.core.Blockchain;
import org.ethereum.core.Transaction; import org.ethereum.core.Transaction;
import org.ethereum.crypto.HashUtil; import org.ethereum.crypto.HashUtil;
import org.ethereum.db.Database; import org.ethereum.db.Database;
@ -105,8 +106,11 @@ public class WorldManager {
byte[] initCode = tx.getData(); byte[] initCode = tx.getData();
Block lastBlock =
MainData.instance.getBlockchain().getLastBlock();
ProgramInvoke programInvoke = ProgramInvoke programInvoke =
ProgramInvokeFactory.createProgramInvoke(tx); ProgramInvokeFactory.createProgramInvoke(tx, lastBlock);
VM vm = new VM(); VM vm = new VM();
Program program = new Program(initCode, programInvoke); Program program = new Program(initCode, programInvoke);

View File

@ -31,6 +31,14 @@ public class DataWord {
this.data = data.array(); this.data = data.array();
} }
public DataWord(long num) {
ByteBuffer bLong = ByteBuffer.allocate(8).putLong(num);
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bLong.array(), 0, data.array(), 24, 8);
this.data = data.array();
}
public DataWord(byte[] data) { public DataWord(byte[] data) {
if (data == null){ if (data == null){

View File

@ -242,11 +242,17 @@ public class Program {
return invokeData.getCallerAddress(); return invokeData.getCallerAddress();
} }
public DataWord getMinGasPrice(){ public DataWord getGasPrice(){
if (invokeData == null) return new DataWord( new byte[0]); if (invokeData == null) return new DataWord( new byte[0]);
return invokeData.getMinGasPrice(); return invokeData.getMinGasPrice();
} }
public DataWord getGas(){
if (invokeData == null) return new DataWord( new byte[0]);
return invokeData.getGas();
}
public DataWord getCallValue(){ public DataWord getCallValue(){
if (invokeData == null) return new DataWord( new byte[0]); if (invokeData == null) return new DataWord( new byte[0]);
return invokeData.getCallValue(); return invokeData.getCallValue();
@ -271,6 +277,30 @@ public class Program {
return storage.get(key); return storage.get(key);
} }
public DataWord getPrevHash(){
return invokeData.getPrevHash();
}
public DataWord getCoinbase(){
return invokeData.getCoinbase();
}
public DataWord getTimestamp(){
return invokeData.getTimestamp();
}
public DataWord getNumber(){
return invokeData.getNumber();
}
public DataWord getDifficulty(){
return invokeData.getDifficulty();
}
public DataWord getGaslimit(){
return invokeData.getGaslimit();
}
public ProgramResult getResult() { public ProgramResult getResult() {
return result; return result;

View File

@ -14,11 +14,17 @@ public interface ProgramInvoke {
public DataWord getOriginAddress(); public DataWord getOriginAddress();
public DataWord getCallerAddress(); public DataWord getCallerAddress();
public DataWord getMinGasPrice(); public DataWord getMinGasPrice();
public DataWord getGas();
public DataWord getCallValue(); public DataWord getCallValue();
public DataWord getDataSize(); public DataWord getDataSize();
public DataWord getDataValue(DataWord indexData); public DataWord getDataValue(DataWord indexData);
public byte[] getDataCopy(DataWord offsetData, DataWord lengthData); public byte[] getDataCopy(DataWord offsetData, DataWord lengthData);
public DataWord getPrevHash();
public DataWord getCoinbase();
public DataWord getTimestamp();
public DataWord getNumber();
public DataWord getDifficulty();
public DataWord getGaslimit();
} }

View File

@ -1,8 +1,6 @@
package org.ethereum.vm; package org.ethereum.vm;
import org.ethereum.crypto.ECKey; import org.ethereum.util.ByteUtil;
import org.ethereum.crypto.HashUtil;
import org.spongycastle.util.encoders.Hex;
/** /**
* www.ethereumJ.com * www.ethereumJ.com
@ -12,6 +10,7 @@ import org.spongycastle.util.encoders.Hex;
public class ProgramInvokeImpl implements ProgramInvoke { public class ProgramInvokeImpl implements ProgramInvoke {
/*** TRANSACTION env ***/
DataWord address; DataWord address;
DataWord origin; DataWord origin;
DataWord caller; DataWord caller;
@ -22,14 +21,22 @@ public class ProgramInvokeImpl implements ProgramInvoke {
byte[] msgData; byte[] msgData;
/*** BLOCK env ***/
DataWord prevHash;
DataWord coinbase;
DataWord timestamp;
DataWord number;
DataWord difficulty;
DataWord gaslimit;
public ProgramInvokeImpl(byte[] msgDataRaw){
this.msgData = msgDataRaw;
}
public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] balance, public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] balance,
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData) { byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
long gaslimit) {
// Transaction env
this.address = new DataWord(address); this.address = new DataWord(address);
this.origin = new DataWord(origin); this.origin = new DataWord(origin);
this.caller = new DataWord(caller); this.caller = new DataWord(caller);
@ -37,8 +44,16 @@ public class ProgramInvokeImpl implements ProgramInvoke {
this.gasPrice = new DataWord(gasPrice); this.gasPrice = new DataWord(gasPrice);
this.gas = new DataWord(gas); this.gas = new DataWord(gas);
this.callValue = new DataWord(callValue); this.callValue = new DataWord(callValue);
this.msgData = msgData; this.msgData = msgData;
// last Block env
this.prevHash = new DataWord(lastHash);
this.coinbase = new DataWord(coinbase);
this.timestamp = new DataWord(timestamp);
this.number = new DataWord(number);
this.difficulty = new DataWord(difficulty);
this.gaslimit = new DataWord(gaslimit);
} }
/* ADDRESS op */ /* ADDRESS op */
@ -67,6 +82,12 @@ public class ProgramInvokeImpl implements ProgramInvoke {
return gasPrice; return gasPrice;
} }
/* GAS op */
public DataWord getGas(){
return gas;
}
/* CALLVALUE op */ /* CALLVALUE op */
public DataWord getCallValue(){ public DataWord getCallValue(){
@ -120,4 +141,34 @@ public class ProgramInvokeImpl implements ProgramInvoke {
return data; return data;
} }
/* PREVHASH op */
public DataWord getPrevHash() {
return prevHash;
}
/* COINBASE op */
public DataWord getCoinbase() {
return coinbase;
}
/* TIMESTAMP op */
public DataWord getTimestamp() {
return timestamp;
}
/* NUMBER op */
public DataWord getNumber() {
return number;
}
/* DIFFICULTY op */
public DataWord getDifficulty() {
return difficulty;
}
/* GASLIMIT op */
public DataWord getGaslimit() {
return gaslimit;
}
} }

View File

@ -332,7 +332,6 @@ public class VM {
} 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;
@ -370,34 +369,47 @@ public class VM {
program.memorySave(memOffsetData.getData(), code); program.memorySave(memOffsetData.getData(), code);
program.step(); program.step();
} break; } break;
case GASPRICE: case GASPRICE:{
DataWord gasPrice = program.getGasPrice();
program.stackPush(gasPrice);
program.step(); program.step();
break; } break;
/** /**
* Block Information * Block Information
*/ */
case PREVHASH: case PREVHASH: {
DataWord prevHash = program.getPrevHash();
program.stackPush(prevHash);
program.step(); program.step();
break; } break;
case COINBASE: case COINBASE: {
DataWord coinbase = program.getCoinbase();
program.stackPush(coinbase);
program.step(); program.step();
break; } break;
case TIMESTAMP: case TIMESTAMP:{
DataWord timestamp = program.getTimestamp();
program.stackPush(timestamp);
program.step(); program.step();
break; } break;
case NUMBER: case NUMBER:{
DataWord number = program.getNumber();
program.stackPush(number);
program.step(); program.step();
break; } break;
case DIFFICULTY: case DIFFICULTY:{
DataWord difficulty = program.getDifficulty();
program.stackPush(difficulty);
program.step(); program.step();
break; } break;
case GASLIMIT: case GASLIMIT:{
DataWord gaslimit = program.getGaslimit();
program.stackPush(gaslimit);
program.step(); program.step();
break; } break;
case POP:{ case POP:{
program.stackPop(); program.stackPop();
program.step(); program.step();
@ -485,9 +497,12 @@ public class VM {
program.stackPush(wordMemSize); program.stackPush(wordMemSize);
program.step(); program.step();
} break; } break;
case GAS: case GAS:{
DataWord gas = program.getGas();
program.stackPush(gas);
program.step(); program.step();
break; } break;
case PUSH1: case PUSH2: case PUSH3: case PUSH4: case PUSH5: case PUSH6: case PUSH7: case PUSH8: 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 PUSH9: case PUSH10: case PUSH11: case PUSH12: case PUSH13: case PUSH14: case PUSH15: case PUSH16:

View File

@ -56,7 +56,6 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return new DataWord(addr); return new DataWord(addr);
} }
/* GASPRICE op */ /* GASPRICE op */
public DataWord getMinGasPrice(){ public DataWord getMinGasPrice(){
@ -64,6 +63,11 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return new DataWord(minGasPrice); return new DataWord(minGasPrice);
} }
/* GAS op */
public DataWord getGas() {
byte[] minGasPrice = Hex.decode("03E8");
return new DataWord(minGasPrice);
}
/* CALLVALUE op */ /* CALLVALUE op */
public DataWord getCallValue(){ public DataWord getCallValue(){
@ -118,4 +122,40 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return data; return data;
} }
@Override
public DataWord getPrevHash() {
byte[] prevHash = Hex.decode("961CB117ABA86D1E596854015A1483323F18883C2D745B0BC03E87F146D2BB1C");
return new DataWord(prevHash);
}
@Override
public DataWord getCoinbase() {
byte[] coinBase = Hex.decode("E559DE5527492BCB42EC68D07DF0742A98EC3F1E");
return new DataWord(coinBase);
}
@Override
public DataWord getTimestamp() {
long timestamp = 1401421348;
return new DataWord(timestamp);
}
@Override
public DataWord getNumber() {
long number = 33;
return new DataWord(number);
}
@Override
public DataWord getDifficulty() {
byte[] difficulty = Hex.decode("3ED290");
return new DataWord(difficulty);
}
@Override
public DataWord getGaslimit() {
long gasLimit = 968269;
return new DataWord(gasLimit);
}
} }

View File

@ -2802,6 +2802,131 @@ public class VMTest {
fail(); fail();
} }
@Test // PREVHASH OP
public void testPREVHASH_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("40"),
createProgramInvoke_1());
String s_expected_1 = "961CB117ABA86D1E596854015A1483323F18883C2D745B0BC03E87F146D2BB1C";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // COINBASE OP
public void testCOINBASE_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("41"),
createProgramInvoke_1());
String s_expected_1 = "000000000000000000000000E559DE5527492BCB42EC68D07DF0742A98EC3F1E";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // TIMESTAMP OP
public void testTIMESTAMP_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("42"),
createProgramInvoke_1());
String s_expected_1 = "000000000000000000000000000000000000000000000000000000005387FE24";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // NUMBER OP
public void testNUMBER_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("43"),
createProgramInvoke_1());
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000021";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // DIFFICULTY OP
public void testDIFFICULTY_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("44"),
createProgramInvoke_1());
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000003ED290";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // GASPRICE OP
public void testGASPRICE_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("3A"),
createProgramInvoke_1());
String s_expected_1 = "000000000000000000000000000000000000000000000000000009184E72A000";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // GAS OP
public void testGAS_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("5C"),
createProgramInvoke_1());
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000003E8";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
@Test // GASLIMIT OP
public void testGASLIMIT_1(){
VM vm = new VM();
Program program =
new Program(Hex.decode("45"),
createProgramInvoke_1());
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000EC64D";
vm.step(program);
DataWord item1 = program.stack.pop();
assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase());
}
/* TEST CASE LIST END */ /* TEST CASE LIST END */
@ -2827,16 +2952,6 @@ public class VMTest {
/** /**
* todo: * todo:
* *
* 15) PREVHASH:
* 16) COINBASE:
* 17) TIMESTAMP:
* 18) NUMBER:
* 19) DIFFICULTY:
* 20) GASPRICE
* 20) GASLIMIT
* 20) GAS
*
* 22) CREATE: * 22) CREATE:
* 23) CALL: * 23) CALL:
* *
@ -2846,8 +2961,8 @@ public class VMTest {
/** /**
contract creation contract creation (gas usage)
----------------- -----------------------------
G_TRANSACTION = (500) G_TRANSACTION = (500)
60016000546006601160003960066000f261778e600054 (115) 60016000546006601160003960066000f261778e600054 (115)
PUSH1 6001 (1) PUSH1 6001 (1)