VM impl, go on:
ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD, CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY implementation and unittest
This commit is contained in:
parent
d348b552b3
commit
9bec5d6885
|
@ -109,7 +109,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
|||
new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
submitContract();
|
||||
submitContractCall();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -215,7 +215,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
|||
this.statusMsg.setText(text);
|
||||
}
|
||||
|
||||
public void submitContract(){
|
||||
public void submitContractCall(){
|
||||
|
||||
ClientPeer peer = MainData.instance.getActivePeer();
|
||||
if (peer == null) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.ethereum.vm.Program;
|
||||
import org.ethereum.vm.ProgramInvoke;
|
||||
import org.ethereum.vm.VM;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -24,13 +26,15 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
|
||||
public List<String> outputList;
|
||||
public JTextArea console;
|
||||
public JSlider stepSlider;
|
||||
|
||||
public ProgramPlayDialog() {
|
||||
|
||||
outputList = new ArrayList<String>();
|
||||
|
||||
VM vm = new VM();
|
||||
Program program = new Program(Hex.decode("630000000060445960CC60DD611234600054615566602054630000000060445960CC60DD611234600054615566602054630000000060445960CC60DD611234600054615566602054"));
|
||||
// Program program = new Program(Hex.decode("630000000060445960CC60DD611234600054615566602054630000000060445960CC60DD611234600054615566602054630000000060445960CC60DD611234600054615566602054"));
|
||||
Program program = new Program(Hex.decode("6000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e75660005460005360200235602054"), null);
|
||||
|
||||
program.addListener(this);
|
||||
program.fullTrace();
|
||||
|
||||
|
@ -40,7 +44,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
||||
|
||||
//Create the slider.
|
||||
JSlider stepSlider = new JSlider(JSlider.HORIZONTAL,
|
||||
stepSlider = new JSlider(JSlider.HORIZONTAL,
|
||||
0, outputList.size() - 1, 0);
|
||||
|
||||
|
||||
|
@ -64,16 +68,22 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
int i = stepSlider.getValue();
|
||||
console = new JTextArea(outputList.get(i));
|
||||
console.setFont(new Font("Courier New", Font.PLAIN, 13));
|
||||
console.setForeground(new Color(143, 170, 220));
|
||||
console.setForeground(new Color(183, 209, 253));
|
||||
console.setBackground(Color.BLACK);
|
||||
console.setLineWrap(true);
|
||||
|
||||
stepSlider.setFocusable(true);
|
||||
|
||||
add(console);
|
||||
JScrollPane scrollPane = new JScrollPane(console);
|
||||
|
||||
add(scrollPane);
|
||||
add(stepSlider);
|
||||
|
||||
|
||||
this.setPreferredSize(new Dimension(600, 300));
|
||||
}
|
||||
|
||||
public void setFocus(){
|
||||
stepSlider.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,6 +102,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
String out = outputList.get(i);
|
||||
|
||||
console.setText(out);
|
||||
console.setCaretPosition(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -110,12 +121,18 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL
|
|||
JFrame frame = new JFrame("SliderDemo");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
frame.setPreferredSize(new Dimension(600, 500));
|
||||
frame.setLocation(400, 200);
|
||||
|
||||
|
||||
//Add content to the window.
|
||||
frame.add(ppd, BorderLayout.CENTER);
|
||||
|
||||
//Display the window.
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
ppd.setFocus();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -58,7 +58,7 @@ public enum OpCode {
|
|||
CALLDATASIZE(0x36),
|
||||
CALLDATACOPY(0x37),
|
||||
CODESIZE(0x38),
|
||||
CODECOPY(0x39), // [len src_start target_start CODECOPY]
|
||||
CODECOPY(0x39), // [len code_start mem_start CODECOPY]
|
||||
GASPRICE(0x3a),
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,14 +26,19 @@ public class Program {
|
|||
Map<DataWord, DataWord> storage = new HashMap<DataWord, DataWord>();
|
||||
ByteBuffer memory = null;
|
||||
|
||||
ByteBuffer hReturn = null;
|
||||
|
||||
byte[] ops;
|
||||
int pc = 0;
|
||||
boolean stopped = false;
|
||||
|
||||
public Program(byte[] ops) {
|
||||
ProgramInvoke invokeData;
|
||||
|
||||
public Program(byte[] ops, ProgramInvoke invokeData) {
|
||||
|
||||
if (ops == null) throw new RuntimeException("program can not run with ops: null");
|
||||
|
||||
this.invokeData = invokeData;
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
|
@ -58,7 +63,10 @@ public class Program {
|
|||
public void setPC(DataWord pc) {
|
||||
this.pc = pc.value().intValue();
|
||||
|
||||
if (this.pc > ops.length) throw new RuntimeException("pc overflow pc: " + pc);
|
||||
if (this.pc > ops.length) {
|
||||
stop();
|
||||
throw new RuntimeException("pc overflow pc: " + pc);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPC(int pc) {
|
||||
|
@ -73,6 +81,10 @@ public class Program {
|
|||
stopped = true;
|
||||
}
|
||||
|
||||
public void setHReturn(ByteBuffer buff){
|
||||
hReturn = buff;
|
||||
}
|
||||
|
||||
public void step(){
|
||||
++pc;
|
||||
if (pc >= ops.length) stop();
|
||||
|
@ -80,7 +92,10 @@ public class Program {
|
|||
|
||||
public byte[] sweep(int n){
|
||||
|
||||
if (pc + n > ops.length) throw new RuntimeException("pc overflow sweep n: " + n + " pc: " + pc);
|
||||
if (pc + n > ops.length) {
|
||||
stop();
|
||||
throw new RuntimeException("pc overflow sweep n: " + n + " pc: " + pc);
|
||||
}
|
||||
|
||||
byte[] data = Arrays.copyOfRange(ops, pc, pc + n);
|
||||
pc += n;
|
||||
|
@ -89,9 +104,12 @@ public class Program {
|
|||
return data;
|
||||
}
|
||||
|
||||
public DataWord stackPull(){
|
||||
public DataWord stackPop(){
|
||||
|
||||
if (stack.size() == 0) throw new RuntimeException("attempted pull action for empty stack");
|
||||
if (stack.size() == 0){
|
||||
stop();
|
||||
throw new RuntimeException("attempted pull action for empty stack");
|
||||
}
|
||||
return stack.pop();
|
||||
};
|
||||
|
||||
|
@ -125,6 +143,21 @@ public class Program {
|
|||
return new DataWord(data);
|
||||
}
|
||||
|
||||
public ByteBuffer memoryChunk(DataWord offsetData, DataWord sizeData){
|
||||
|
||||
int offset = offsetData.value().intValue();
|
||||
int size = sizeData.value().intValue();
|
||||
|
||||
byte[] chunk = new byte[size];
|
||||
|
||||
if (memory.limit() < offset + size) size = memory.limit() - offset;
|
||||
|
||||
System.arraycopy(memory.array(), offset, chunk, 0, size);
|
||||
|
||||
return ByteBuffer.wrap(chunk);
|
||||
}
|
||||
|
||||
|
||||
private void allocateMemory(int address, byte[] value){
|
||||
|
||||
int memSize = 0;
|
||||
|
@ -166,6 +199,52 @@ public class Program {
|
|||
}
|
||||
|
||||
|
||||
public DataWord getOwnerAddress(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getOwnerAddress();
|
||||
}
|
||||
|
||||
public DataWord getBalance(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getBalance();
|
||||
}
|
||||
|
||||
public DataWord getOriginAddress(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getOriginAddress();
|
||||
}
|
||||
|
||||
public DataWord getCallerAddress(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getCallerAddress();
|
||||
}
|
||||
|
||||
public DataWord getMinGasPrice(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getMinGasPrice();
|
||||
}
|
||||
|
||||
public DataWord getCallValue(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getCallValue();
|
||||
}
|
||||
|
||||
|
||||
public DataWord getDataSize(){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getDataSize();
|
||||
}
|
||||
|
||||
public DataWord getDataValue(DataWord index){
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getDataValue(index);
|
||||
}
|
||||
|
||||
public byte[] getDataCopy(DataWord offset, DataWord length){
|
||||
if (invokeData == null) return new byte[0];
|
||||
return invokeData.getDataCopy(offset, length);
|
||||
}
|
||||
|
||||
public DataWord storageLoad(DataWord key){
|
||||
return storage.get(key);
|
||||
}
|
||||
|
@ -237,6 +316,10 @@ public class Program {
|
|||
global.append(" -- MEMORY -- ").append(memoryData).append("\n");
|
||||
global.append(" -- STORAGE -- ").append(storageData).append("\n");
|
||||
|
||||
if (hReturn != null){
|
||||
global.append("\n HReturn: ").append(Hex.toHexString( hReturn.array()));
|
||||
}
|
||||
|
||||
if (listener != null){
|
||||
listener.output(global.toString());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 03/06/2014 14:59
|
||||
*/
|
||||
|
||||
public interface ProgramInvoke {
|
||||
|
||||
|
||||
public DataWord getOwnerAddress();
|
||||
public DataWord getBalance();
|
||||
public DataWord getOriginAddress();
|
||||
public DataWord getCallerAddress();
|
||||
public DataWord getMinGasPrice();
|
||||
public DataWord getCallValue();
|
||||
|
||||
|
||||
public DataWord getDataSize();
|
||||
public DataWord getDataValue(DataWord indexData);
|
||||
public byte[] getDataCopy(DataWord offsetData, DataWord lengthData);
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.ethereum.vm.OpCode.PUSH1;
|
||||
|
||||
|
@ -37,13 +38,14 @@ public class VM {
|
|||
|
||||
case STOP:{
|
||||
|
||||
program.setHReturn(ByteBuffer.allocate(0));
|
||||
program.stop();
|
||||
}
|
||||
break;
|
||||
case ADD:{
|
||||
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.add(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -51,8 +53,8 @@ public class VM {
|
|||
break;
|
||||
case MUL:{
|
||||
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.mull(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -60,8 +62,8 @@ public class VM {
|
|||
break;
|
||||
case SUB:{
|
||||
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.sub(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -69,8 +71,8 @@ public class VM {
|
|||
break;
|
||||
case DIV:{
|
||||
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.div(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -84,22 +86,22 @@ public class VM {
|
|||
break;
|
||||
case EXP:{
|
||||
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.exp(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case NEG:{
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
word1.negate();
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
}break;
|
||||
case LT:{
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
if (word1.value().compareTo(word2.value()) == -1){
|
||||
word1.and(DataWord.ZERO);
|
||||
word1.getData()[31] = 1;
|
||||
|
@ -114,8 +116,8 @@ public class VM {
|
|||
case SGT:
|
||||
break;
|
||||
case GT:{
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
if (word1.value().compareTo(word2.value()) == 1){
|
||||
word1.and(DataWord.ZERO);
|
||||
word1.getData()[31] = 1;
|
||||
|
@ -126,8 +128,8 @@ public class VM {
|
|||
program.step();
|
||||
}break;
|
||||
case EQ:{
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
if (word1.xor(word2).isZero()){
|
||||
word1.and(DataWord.ZERO);
|
||||
word1.getData()[31] = 1;
|
||||
|
@ -139,7 +141,7 @@ public class VM {
|
|||
}
|
||||
break;
|
||||
case NOT: {
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
if (word1.isZero()){
|
||||
word1.getData()[31] = 1;
|
||||
} else {
|
||||
|
@ -150,31 +152,29 @@ public class VM {
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bitwise Logic Operations
|
||||
*/
|
||||
|
||||
case AND:{
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.and(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case OR: {
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.or(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case XOR: {
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
word1.xor(word2);
|
||||
program.stackPush(word1);
|
||||
program.step();
|
||||
|
@ -182,8 +182,8 @@ public class VM {
|
|||
break;
|
||||
case BYTE:{
|
||||
|
||||
DataWord word1 = program.stackPull();
|
||||
DataWord word2 = program.stackPull();
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
|
||||
DataWord result = null;
|
||||
if (word1.value().compareTo(_32_) == -1){
|
||||
|
@ -210,25 +210,90 @@ public class VM {
|
|||
* Environmental Information
|
||||
*/
|
||||
|
||||
case ADDRESS:
|
||||
case ADDRESS:{
|
||||
DataWord address = program.getOwnerAddress();
|
||||
program.stackPush(address);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case BALANCE:
|
||||
case BALANCE:{
|
||||
DataWord balance = program.getBalance();
|
||||
program.stackPush(balance);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case ORIGIN:
|
||||
case ORIGIN:{
|
||||
DataWord originAddress = program.getOriginAddress();
|
||||
program.stackPush(originAddress);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case CALLER:
|
||||
case CALLER:{
|
||||
DataWord callerAddress = program.getCallerAddress();
|
||||
program.stackPush(callerAddress);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case CALLVALUE:
|
||||
case CALLVALUE:{
|
||||
DataWord callValue = program.getCallValue();
|
||||
program.stackPush(callValue);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case CALLDATALOAD:
|
||||
case CALLDATALOAD:{
|
||||
DataWord dataOffs = program.stackPop();
|
||||
DataWord value = program.getDataValue(dataOffs);
|
||||
|
||||
program.stackPush(value);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case CALLDATASIZE:
|
||||
case CALLDATASIZE:{
|
||||
DataWord dataSize = program.getDataSize();
|
||||
|
||||
program.stackPush(dataSize);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case CALLDATACOPY:
|
||||
case CALLDATACOPY:{
|
||||
|
||||
DataWord memOffsetData = program.stackPop();
|
||||
DataWord dataOffsetData = program.stackPop();
|
||||
DataWord lengthData = program.stackPop();
|
||||
|
||||
byte[] msgData = program.getDataCopy(dataOffsetData, lengthData);
|
||||
program.memorySave(memOffsetData.data, msgData);
|
||||
program.step();
|
||||
|
||||
} break;
|
||||
case CODESIZE:{
|
||||
|
||||
DataWord length = new DataWord(program.ops.length);
|
||||
program.stackPush(length);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case CODESIZE:
|
||||
case CODECOPY:{
|
||||
DataWord memOffsetData = program.stackPop();
|
||||
DataWord codeOffsetData = program.stackPop();
|
||||
DataWord lengthData = program.stackPop();
|
||||
|
||||
int length = lengthData.value().intValue();
|
||||
int codeOffset = codeOffsetData.value().intValue();
|
||||
int memOffset = memOffsetData.value().intValue();
|
||||
|
||||
if (program.ops.length < length + codeOffset){
|
||||
|
||||
program.stop();
|
||||
break;
|
||||
case CODECOPY:
|
||||
}
|
||||
|
||||
byte[] code = new byte[length];
|
||||
System.arraycopy(program.ops, codeOffset, code, memOffset, length);
|
||||
|
||||
program.memorySave(memOffsetData.getData(), code);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case GASPRICE:
|
||||
break;
|
||||
|
@ -252,12 +317,12 @@ public class VM {
|
|||
|
||||
|
||||
case POP:{
|
||||
program.stackPull();
|
||||
program.stackPop();
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case DUP:{
|
||||
DataWord word_1 = program.stackPull();
|
||||
DataWord word_1 = program.stackPop();
|
||||
DataWord word_2 = word_1.clone();
|
||||
program.stackPush(word_1);
|
||||
program.stackPush(word_2);
|
||||
|
@ -265,8 +330,8 @@ public class VM {
|
|||
}
|
||||
break;
|
||||
case SWAP:{
|
||||
DataWord word_1 = program.stackPull();
|
||||
DataWord word_2 = program.stackPull();
|
||||
DataWord word_1 = program.stackPop();
|
||||
DataWord word_2 = program.stackPop();
|
||||
|
||||
program.stackPush(word_1);
|
||||
program.stackPush(word_2);
|
||||
|
@ -274,15 +339,15 @@ public class VM {
|
|||
}
|
||||
break;
|
||||
case MLOAD:{
|
||||
DataWord addr = program.stackPull();
|
||||
DataWord addr = program.stackPop();
|
||||
DataWord data = program.memoryLoad(addr);
|
||||
program.stackPush(data);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case MSTORE:{
|
||||
DataWord addr = program.stackPull();
|
||||
DataWord value = program.stackPull();
|
||||
DataWord addr = program.stackPop();
|
||||
DataWord value = program.stackPop();
|
||||
|
||||
program.memorySave(addr, value);
|
||||
program.step();
|
||||
|
@ -290,15 +355,15 @@ public class VM {
|
|||
break;
|
||||
case MSTORE8:{
|
||||
|
||||
DataWord addr = program.stackPull();
|
||||
DataWord value = program.stackPull();
|
||||
DataWord addr = program.stackPop();
|
||||
DataWord value = program.stackPop();
|
||||
byte[] byteVal = {value.getData()[31]};
|
||||
program.memorySave(addr.getData(), byteVal);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case SLOAD:{
|
||||
DataWord key = program.stackPull();
|
||||
DataWord key = program.stackPop();
|
||||
DataWord val = program.storageLoad(key);
|
||||
|
||||
if (val == null){
|
||||
|
@ -309,21 +374,21 @@ public class VM {
|
|||
}
|
||||
break;
|
||||
case SSTORE:{
|
||||
DataWord addr = program.stackPull();
|
||||
DataWord value = program.stackPull();
|
||||
DataWord addr = program.stackPop();
|
||||
DataWord value = program.stackPop();
|
||||
|
||||
program.storageSave(addr, value);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case JUMP:{
|
||||
DataWord pos = program.stackPull();
|
||||
DataWord pos = program.stackPop();
|
||||
program.setPC(pos);
|
||||
}
|
||||
break;
|
||||
case JUMPI:{
|
||||
DataWord pos = program.stackPull();
|
||||
DataWord cond = program.stackPull();
|
||||
DataWord pos = program.stackPop();
|
||||
DataWord cond = program.stackPop();
|
||||
|
||||
if (!cond.isZero()){
|
||||
program.setPC(pos);
|
||||
|
@ -345,6 +410,7 @@ public class VM {
|
|||
int memSize = program.getMemSize();
|
||||
DataWord wordMemSize = new DataWord(memSize);
|
||||
program.stackPush(wordMemSize);
|
||||
program.step();
|
||||
}
|
||||
break;
|
||||
case GAS:
|
||||
|
@ -394,7 +460,17 @@ public class VM {
|
|||
break;
|
||||
case CALL:
|
||||
break;
|
||||
case RETURN:
|
||||
case RETURN:{
|
||||
|
||||
DataWord offset = program.stackPop();
|
||||
DataWord size = program.stackPop();
|
||||
|
||||
ByteBuffer hReturn = program.memoryChunk(offset, size);
|
||||
program.hReturn = hReturn;
|
||||
|
||||
program.step();
|
||||
program.stop();
|
||||
}
|
||||
break;
|
||||
case SUICIDE:
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 03/06/2014 15:00
|
||||
*/
|
||||
|
||||
public class ProgramInvokeMockImpl implements ProgramInvoke{
|
||||
|
||||
byte[] msgData;
|
||||
|
||||
|
||||
public ProgramInvokeMockImpl(byte[] msgDataRaw){
|
||||
this.msgData = msgDataRaw;
|
||||
}
|
||||
|
||||
ProgramInvokeMockImpl() {
|
||||
}
|
||||
|
||||
/* ADDRESS op */
|
||||
public DataWord getOwnerAddress(){
|
||||
|
||||
byte[] cowPrivKey = HashUtil.sha3("cow".getBytes());
|
||||
byte[] addr = ECKey.fromPrivate(cowPrivKey).getAddress();
|
||||
|
||||
return new DataWord(addr);
|
||||
}
|
||||
|
||||
/* BALANCE op */
|
||||
public DataWord getBalance(){
|
||||
byte[] balance = Hex.decode("0DE0B6B3A7640000");
|
||||
return new DataWord(balance);
|
||||
}
|
||||
|
||||
|
||||
/* ORIGIN op */
|
||||
public DataWord getOriginAddress(){
|
||||
|
||||
byte[] cowPrivKey = HashUtil.sha3("horse".getBytes());
|
||||
byte[] addr = ECKey.fromPrivate(cowPrivKey).getAddress();
|
||||
|
||||
return new DataWord(addr);
|
||||
}
|
||||
|
||||
/* CALLER op */
|
||||
public DataWord getCallerAddress(){
|
||||
|
||||
byte[] cowPrivKey = HashUtil.sha3("monkey".getBytes());
|
||||
byte[] addr = ECKey.fromPrivate(cowPrivKey).getAddress();
|
||||
|
||||
return new DataWord(addr);
|
||||
}
|
||||
|
||||
|
||||
/* GASPRICE op */
|
||||
public DataWord getMinGasPrice(){
|
||||
|
||||
byte[] minGasPrice = Hex.decode("09184e72a000");
|
||||
return new DataWord(minGasPrice);
|
||||
}
|
||||
|
||||
|
||||
/* CALLVALUE op */
|
||||
public DataWord getCallValue(){
|
||||
byte[] balance = Hex.decode("0DE0B6B3A7640000");
|
||||
return new DataWord(balance);
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/*** msg data ***/
|
||||
/*****************/
|
||||
|
||||
/* CALLDATALOAD op */
|
||||
public DataWord getDataValue(DataWord indexData){
|
||||
|
||||
byte[] data = new byte[32];
|
||||
|
||||
int index = indexData.value().intValue();
|
||||
int size = 32;
|
||||
|
||||
if (msgData == null) return new DataWord(data);
|
||||
if (index > msgData.length) return new DataWord(data);
|
||||
if (index + 32 > msgData.length) size = msgData.length - index ;
|
||||
|
||||
System.arraycopy(msgData, index, data, 0, size);
|
||||
|
||||
return new DataWord(data);
|
||||
}
|
||||
|
||||
/* CALLDATASIZE */
|
||||
public DataWord getDataSize(){
|
||||
|
||||
if (msgData == null || msgData.length == 0) return new DataWord(new byte[32]);
|
||||
int size = msgData.length;
|
||||
return new DataWord(size);
|
||||
}
|
||||
|
||||
/* CALLDATACOPY */
|
||||
public byte[] getDataCopy(DataWord offsetData, DataWord lengthData){
|
||||
|
||||
int offset = offsetData.value().intValue();
|
||||
int length = lengthData.value().intValue();
|
||||
|
||||
byte[] data = new byte[length];
|
||||
|
||||
if (msgData == null) return data;
|
||||
if (offset > msgData.length) return data;
|
||||
if (offset + length > msgData.length) length = msgData.length - offset ;
|
||||
|
||||
System.arraycopy(msgData, offset, data, 0, length);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue