VM Block env included:
+ OPs: PREVHASH, PREVHASH, TIMESTAMP, NUMBER, DIFFICULTY, GASPRICE, GAS, GASLIMIT + All OPs, Unit test
This commit is contained in:
parent
30459202c1
commit
54262dd1b9
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue