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);
Program program = new Program(tx.getData() ,
ProgramInvokeFactory.createProgramInvoke(tx));
ProgramInvokeFactory.createProgramInvoke(tx, null));
program.addListener(this);
program.fullTrace();

View File

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

View File

@ -31,6 +31,14 @@ public class DataWord {
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) {
if (data == null){

View File

@ -242,11 +242,17 @@ public class Program {
return invokeData.getCallerAddress();
}
public DataWord getMinGasPrice(){
public DataWord getGasPrice(){
if (invokeData == null) return new DataWord( new byte[0]);
return invokeData.getMinGasPrice();
}
public DataWord getGas(){
if (invokeData == null) return new DataWord( new byte[0]);
return invokeData.getGas();
}
public DataWord getCallValue(){
if (invokeData == null) return new DataWord( new byte[0]);
return invokeData.getCallValue();
@ -271,6 +277,30 @@ public class Program {
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() {
return result;

View File

@ -14,11 +14,17 @@ public interface ProgramInvoke {
public DataWord getOriginAddress();
public DataWord getCallerAddress();
public DataWord getMinGasPrice();
public DataWord getGas();
public DataWord getCallValue();
public DataWord getDataSize();
public DataWord getDataValue(DataWord indexData);
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;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.spongycastle.util.encoders.Hex;
import org.ethereum.util.ByteUtil;
/**
* www.ethereumJ.com
@ -12,6 +10,7 @@ import org.spongycastle.util.encoders.Hex;
public class ProgramInvokeImpl implements ProgramInvoke {
/*** TRANSACTION env ***/
DataWord address;
DataWord origin;
DataWord caller;
@ -22,14 +21,22 @@ public class ProgramInvokeImpl implements ProgramInvoke {
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,
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.origin = new DataWord(origin);
this.caller = new DataWord(caller);
@ -37,8 +44,16 @@ public class ProgramInvokeImpl implements ProgramInvoke {
this.gasPrice = new DataWord(gasPrice);
this.gas = new DataWord(gas);
this.callValue = new DataWord(callValue);
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 */
@ -67,6 +82,12 @@ public class ProgramInvokeImpl implements ProgramInvoke {
return gasPrice;
}
/* GAS op */
public DataWord getGas(){
return gas;
}
/* CALLVALUE op */
public DataWord getCallValue(){
@ -120,4 +141,34 @@ public class ProgramInvokeImpl implements ProgramInvoke {
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;
case CALLDATASIZE:{
DataWord dataSize = program.getDataSize();
program.stackPush(dataSize);
program.step();
} break;
@ -370,34 +369,47 @@ public class VM {
program.memorySave(memOffsetData.getData(), code);
program.step();
} break;
case GASPRICE:
case GASPRICE:{
DataWord gasPrice = program.getGasPrice();
program.stackPush(gasPrice);
program.step();
break;
} break;
/**
* Block Information
*/
case PREVHASH:
case PREVHASH: {
DataWord prevHash = program.getPrevHash();
program.stackPush(prevHash);
program.step();
break;
case COINBASE:
} break;
case COINBASE: {
DataWord coinbase = program.getCoinbase();
program.stackPush(coinbase);
program.step();
break;
case TIMESTAMP:
} break;
case TIMESTAMP:{
DataWord timestamp = program.getTimestamp();
program.stackPush(timestamp);
program.step();
break;
case NUMBER:
} break;
case NUMBER:{
DataWord number = program.getNumber();
program.stackPush(number);
program.step();
break;
case DIFFICULTY:
} break;
case DIFFICULTY:{
DataWord difficulty = program.getDifficulty();
program.stackPush(difficulty);
program.step();
break;
case GASLIMIT:
} break;
case GASLIMIT:{
DataWord gaslimit = program.getGaslimit();
program.stackPush(gaslimit);
program.step();
break;
} break;
case POP:{
program.stackPop();
program.step();
@ -485,9 +497,12 @@ public class VM {
program.stackPush(wordMemSize);
program.step();
} break;
case GAS:
case GAS:{
DataWord gas = program.getGas();
program.stackPush(gas);
program.step();
break;
} 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:

View File

@ -56,7 +56,6 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return new DataWord(addr);
}
/* GASPRICE op */
public DataWord getMinGasPrice(){
@ -64,6 +63,11 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return new DataWord(minGasPrice);
}
/* GAS op */
public DataWord getGas() {
byte[] minGasPrice = Hex.decode("03E8");
return new DataWord(minGasPrice);
}
/* CALLVALUE op */
public DataWord getCallValue(){
@ -118,4 +122,40 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
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();
}
@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 */
@ -2827,16 +2952,6 @@ public class VMTest {
/**
* todo:
*
* 15) PREVHASH:
* 16) COINBASE:
* 17) TIMESTAMP:
* 18) NUMBER:
* 19) DIFFICULTY:
* 20) GASPRICE
* 20) GASLIMIT
* 20) GAS
*
* 22) CREATE:
* 23) CALL:
*
@ -2846,8 +2961,8 @@ public class VMTest {
/**
contract creation
-----------------
contract creation (gas usage)
-----------------------------
G_TRANSACTION = (500)
60016000546006601160003960066000f261778e600054 (115)
PUSH1 6001 (1)