Gas calculation first draft
This commit is contained in:
parent
63a87f36a8
commit
c6dd4f31f9
|
@ -1,6 +1,7 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.vm.Program;
|
||||
import org.ethereum.vm.ProgramInvokeImpl;
|
||||
import org.ethereum.vm.VM;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -32,7 +33,14 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
|||
VM vm = new VM();
|
||||
// Program program = new Program(Hex.decode("630000000060445960CC60DD611234600054615566602054630000000060445960CC60DD611234600054615566602054630000000060445960CC60DD611234600054615566602054"));
|
||||
// Program program = new Program(Hex.decode("60016023576000605f556014600054601e60205463abcddcba6040545b51602001600a5254516040016014525451606001601e5254516080016028525460a052546016604860003960166000f26000603f556103e75660005460005360200235602054"), null);
|
||||
Program program = new Program(Hex.decode("620f424073cd2a3d9f938e13cd947ec05abc7fe734df8dd826576086602660003960866000f26001602036040e0f630000002159600060200235600054600053565b525b54602052f263000000765833602054602053566040546000602002356060546001602002356080546080536040530a0f0f630000006c59608053604053036020535760805360605356016060535760015b525b54602052f263000000765860005b525b54602052f2"), null);
|
||||
|
||||
String code = "60016000546006601160003960066000f261778e600054";
|
||||
// String code = "620f424073cd2a3d9f938e13cd947ec05abc7fe734df8dd826576086602660003960866000f26001602036040e0f630000002159600060200235600054600053565b525b54602052f263000000765833602054602053566040546000602002356060546001602002356080546080536040530a0f0f630000006c59608053604053036020535760805360605356016060535760015b525b54602052f263000000765860005b525b54602052f2";
|
||||
|
||||
byte[] codeBytes =
|
||||
Hex.decode(code);
|
||||
Program program = new Program(codeBytes ,
|
||||
new ProgramInvokeImpl(codeBytes));
|
||||
|
||||
program.addListener(this);
|
||||
program.fullTrace();
|
||||
|
|
|
@ -44,6 +44,9 @@ public class DataWord {
|
|||
public BigInteger value(){
|
||||
return new BigInteger(1, data);
|
||||
}
|
||||
public int intValue(){
|
||||
return new BigInteger(1, data).intValue();
|
||||
}
|
||||
|
||||
public BigInteger sValue(){
|
||||
return new BigInteger(data);
|
||||
|
|
|
@ -27,16 +27,19 @@ public class Program {
|
|||
|
||||
byte[] ops;
|
||||
int pc = 0;
|
||||
byte lastOp = 0;
|
||||
boolean stopped = false;
|
||||
|
||||
ProgramInvoke invokeData;
|
||||
|
||||
Map<byte[], DataWord> addressChange;
|
||||
int spendGas = 0;
|
||||
|
||||
|
||||
public Program(byte[] ops, ProgramInvoke invokeData) {
|
||||
|
||||
spendGas(GasCost.TRANSACTION);
|
||||
spendGas(GasCost.TXDATA * invokeData.getDataSize().intValue());
|
||||
|
||||
if (ops == null) throw new RuntimeException("program can not run with ops: null");
|
||||
|
||||
this.invokeData = invokeData;
|
||||
|
@ -47,6 +50,9 @@ public class Program {
|
|||
return ops[pc];
|
||||
}
|
||||
|
||||
public void setLastOp(byte op){
|
||||
this.lastOp = op;
|
||||
}
|
||||
|
||||
public void stackPush(byte[] data){
|
||||
DataWord stackWord = new DataWord(data);
|
||||
|
@ -203,7 +209,7 @@ public class Program {
|
|||
public void spendGas(int gasValue){
|
||||
// todo: check it against avail gas
|
||||
// todo: out of gas will revert the changes [YP 5, 6 ]
|
||||
spendGas += gasValue;
|
||||
result.spendGas(gasValue);
|
||||
}
|
||||
|
||||
public void storageSave(DataWord word1, DataWord word2){
|
||||
|
@ -276,9 +282,7 @@ public class Program {
|
|||
|
||||
public void fullTrace(){
|
||||
|
||||
// todo: add gas to full trace calc
|
||||
|
||||
if (logger.isDebugEnabled()){
|
||||
if (logger.isDebugEnabled() || listener != null){
|
||||
|
||||
StringBuilder stackData = new StringBuilder();
|
||||
for (int i = 0; i < stack.size(); ++i){
|
||||
|
@ -335,22 +339,26 @@ public class Program {
|
|||
logger.debug(" -- STORAGE -- {}\n", storageData);
|
||||
|
||||
|
||||
StringBuilder global = new StringBuilder("\n");
|
||||
StringBuilder globalOutput = new StringBuilder("\n");
|
||||
if (stackData.length() > 0) stackData.append("\n");
|
||||
|
||||
global.append(" -- OPS -- ").append(opsString).append("\n");
|
||||
global.append(" -- STACK -- ").append(stackData).append("\n");
|
||||
global.append(" -- MEMORY -- ").append(memoryData).append("\n");
|
||||
global.append(" -- STORAGE -- ").append(storageData).append("\n");
|
||||
if (pc != 0)
|
||||
globalOutput.append("[Op: ").append(OpCode.code(lastOp).name()).append("]\n");
|
||||
|
||||
globalOutput.append(" -- OPS -- ").append(opsString).append("\n");
|
||||
globalOutput.append(" -- STACK -- ").append(stackData).append("\n");
|
||||
globalOutput.append(" -- MEMORY -- ").append(memoryData).append("\n");
|
||||
globalOutput.append(" -- STORAGE -- ").append(storageData).append("\n");
|
||||
|
||||
if (result.gethReturn() != null){
|
||||
global.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array()));
|
||||
globalOutput.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array()));
|
||||
}
|
||||
|
||||
globalOutput.append("\n\n Spent Gas: ").append(result.getGasUsed());
|
||||
|
||||
if (listener != null){
|
||||
listener.output(global.toString());
|
||||
listener.output(globalOutput.toString());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 03/06/2014 15:00
|
||||
*/
|
||||
|
||||
public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
|
||||
byte[] msgData;
|
||||
|
||||
|
||||
public ProgramInvokeImpl(byte[] msgDataRaw){
|
||||
this.msgData = msgDataRaw;
|
||||
}
|
||||
|
||||
public ProgramInvokeImpl() {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,10 @@ public class ProgramResult {
|
|||
return exception;
|
||||
}
|
||||
|
||||
public int getGasUsed() {
|
||||
return gasUsed;
|
||||
}
|
||||
|
||||
public void setException(RuntimeException exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ public class VM {
|
|||
try {
|
||||
|
||||
byte op = program.getCurrentOp();
|
||||
program.setLastOp(op);
|
||||
logger.debug("Op: {}" ,OpCode.code(op).name());
|
||||
|
||||
int oldMemSize = program.getMemSize();
|
||||
|
@ -70,8 +71,6 @@ public class VM {
|
|||
program.spendGas(GasCost.SLOAD);
|
||||
break;
|
||||
case SSTORE:
|
||||
// todo: calc gas in the execution
|
||||
// todo: according to the size
|
||||
break;
|
||||
case BALANCE:
|
||||
program.spendGas(GasCost.BALANCE);
|
||||
|
@ -84,8 +83,9 @@ public class VM {
|
|||
break;
|
||||
case MSTORE8:
|
||||
case MSTORE:
|
||||
// todo: calc gas in the execution
|
||||
// todo: according to the size
|
||||
// TODO: [cpp impl] do this when [go impl] spend just the usage size
|
||||
// TODO: https://github.com/ethereum/cpp-ethereum/blob/develop/libevm/VM.h#L183
|
||||
program.spendGas(GasCost.STEP);
|
||||
break;
|
||||
default:
|
||||
program.spendGas(GasCost.STEP);
|
||||
|
@ -527,11 +527,12 @@ public class VM {
|
|||
} break;
|
||||
default:{
|
||||
}
|
||||
|
||||
// memory gas calc
|
||||
int newMemSize = program.getMemSize();
|
||||
program.spendGas(GasCost.MEMORY * (newMemSize - oldMemSize) /32);
|
||||
}
|
||||
|
||||
// memory gas calc
|
||||
int newMemSize = program.getMemSize();
|
||||
program.spendGas(GasCost.MEMORY * (newMemSize - oldMemSize) /32);
|
||||
|
||||
program.fullTrace();
|
||||
} catch (RuntimeException e) {
|
||||
program.stop();
|
||||
|
|
|
@ -14,7 +14,7 @@ log4j.logger.java.nio = WARN
|
|||
log4j.logger.io.netty = FATAL
|
||||
log4j.logger.org.ethereum.core = FATAL
|
||||
log4j.logger.wire = FATAL
|
||||
log4j.logger.VM = FATAL
|
||||
log4j.logger.VM = DEBUG
|
||||
log4j.logger.main = FATAL
|
||||
log4j.logger.state = FATAL
|
||||
log4j.logger.blockchain = FATAL
|
||||
|
|
Loading…
Reference in New Issue