parent
8bf61332ae
commit
23a7f75266
|
@ -10,18 +10,18 @@ public class GasCost {
|
|||
|
||||
/** Cost 1 gas */
|
||||
public static int STEP = 1;
|
||||
/** Cost 20 gas */
|
||||
public static int BALANCE = 20;
|
||||
/** Cost 20 gas */
|
||||
public static int SHA3 = 20;
|
||||
/** Cost 20 gas */
|
||||
public static int SLOAD = 20;
|
||||
/** Cost 0 gas */
|
||||
public static int STOP = 0;
|
||||
/** Cost 0 gas */
|
||||
public static int SUICIDE = 0;
|
||||
/** Cost 20 gas */
|
||||
public static int SLOAD = 20;
|
||||
/** Cost 20 gas */
|
||||
public static int SHA3 = 20;
|
||||
/** Cost 100 gas */
|
||||
public static int SSTORE = 100;
|
||||
/** Cost 20 gas */
|
||||
public static int BALANCE = 20;
|
||||
/** Cost 100 gas */
|
||||
public static int CREATE = 100;
|
||||
/** Cost 20 gas */
|
||||
|
@ -32,4 +32,10 @@ public class GasCost {
|
|||
public static int TXDATA = 5;
|
||||
/** Cost 500 gas */
|
||||
public static int TRANSACTION = 500;
|
||||
/** Cost 32 gas */
|
||||
public static int LOG_GAS = 32;
|
||||
/** Cost 1 gas */
|
||||
public static int LOG_DATA_GAS = 1;
|
||||
/** Cost 32 gas */
|
||||
public static int LOG_TOPIC_GAS = 32;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.etherj.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 19/11/2014 22:03
|
||||
*/
|
||||
|
||||
public class LogInfo {
|
||||
|
||||
byte[] address;
|
||||
List<byte[]> topics;
|
||||
byte[] data;
|
||||
|
||||
public LogInfo(byte[] address, List<byte[]> topics, byte[] data) {
|
||||
this.address = address;
|
||||
this.topics = topics;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public List<byte[]> getTopics() {
|
||||
return topics;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuffer topicsStr = new StringBuffer();
|
||||
topicsStr.append("[");
|
||||
|
||||
for (byte[] topic: topics){
|
||||
String topicStr = Hex.toHexString(topic);
|
||||
topicsStr.append(topicStr).append(" ");
|
||||
}
|
||||
topicsStr.append("]");
|
||||
|
||||
|
||||
return "LogInfo{" +
|
||||
"address=" + Hex.toHexString(address) +
|
||||
", topics=" + topicsStr +
|
||||
", data=" + Hex.toHexString(data) +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -292,6 +292,13 @@ public enum OpCode {
|
|||
/** (0x9f) Exchange 17th item from stack with the top */
|
||||
SWAP16(0x9f, 17),
|
||||
|
||||
/** (0xa[n]) log some data for some addres with 0..n tags [addr [tag0..tagn] data] */
|
||||
LOG0(0xa0, 2),
|
||||
LOG1(0xa1, 3),
|
||||
LOG2(0xa2, 4),
|
||||
LOG3(0xa3, 5),
|
||||
LOG4(0xa4, 6),
|
||||
|
||||
/* System operations */
|
||||
|
||||
/** (0xf0) Create a new account with associated code */
|
||||
|
|
|
@ -316,6 +316,7 @@ public class Program {
|
|||
vm.play(program);
|
||||
result = program.getResult();
|
||||
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
||||
this.result.addLogInfos(result.getLogInfoList());
|
||||
}
|
||||
|
||||
if (result != null &&
|
||||
|
@ -415,6 +416,7 @@ public class Program {
|
|||
result = program.getResult();
|
||||
this.getProgramTrace().merge(program.getProgramTrace());
|
||||
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
||||
this.result.addLogInfos(result.getLogInfoList());
|
||||
}
|
||||
|
||||
if (result != null &&
|
||||
|
|
|
@ -17,6 +17,7 @@ public class ProgramResult {
|
|||
private ByteBuffer hReturn = null;
|
||||
private RuntimeException exception;
|
||||
private List<DataWord> deleteAccounts;
|
||||
private List<LogInfo> logInfoList;
|
||||
|
||||
private Repository repository = null;
|
||||
|
||||
|
@ -69,6 +70,20 @@ public class ProgramResult {
|
|||
deleteAccounts.add(address);
|
||||
}
|
||||
|
||||
public void addLogInfo(LogInfo logInfo){
|
||||
if (this.logInfoList == null) logInfoList = new ArrayList<>();
|
||||
this.logInfoList.add(logInfo);
|
||||
}
|
||||
|
||||
public void addLogInfos(List<LogInfo> logInfos){
|
||||
if (this.logInfoList == null) logInfoList = new ArrayList<>();
|
||||
this.logInfoList.addAll(logInfos);
|
||||
}
|
||||
|
||||
public List<LogInfo> getLogInfoList() {
|
||||
return logInfoList;
|
||||
}
|
||||
|
||||
public void addDeleteAccounts(List<DataWord> accounts) {
|
||||
if (accounts == null) return;
|
||||
if (deleteAccounts == null)
|
||||
|
|
|
@ -73,8 +73,6 @@ public class VM {
|
|||
|
||||
public void step(Program program) {
|
||||
|
||||
program.fullTrace();
|
||||
|
||||
if (CONFIG.vmTrace())
|
||||
program.saveOpTrace();
|
||||
|
||||
|
@ -160,6 +158,16 @@ public class VM {
|
|||
gasCost = GasCost.CREATE;
|
||||
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-3));
|
||||
break;
|
||||
case LOG0: case LOG1: case LOG2: case LOG3: case LOG4:
|
||||
|
||||
int nTopics = op.val() - OpCode.LOG0.val();
|
||||
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-2));
|
||||
gasCost = GasCost.LOG_GAS +
|
||||
GasCost.LOG_TOPIC_GAS * nTopics +
|
||||
GasCost.LOG_DATA_GAS * stack.get(stack.size()-2).longValue();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -717,6 +725,32 @@ public class VM {
|
|||
stack.set(stack.size() - n, word_1);
|
||||
program.step();
|
||||
|
||||
} break;
|
||||
case LOG0: case LOG1: case LOG2: case LOG3: case LOG4:{
|
||||
|
||||
DataWord address = program.programAddress;
|
||||
|
||||
DataWord memStart = stack.pop();
|
||||
DataWord memOffset = stack.pop();
|
||||
|
||||
int nTopics = op.val() - OpCode.LOG0.val();
|
||||
|
||||
List<byte[]> topics = new ArrayList<>();
|
||||
for (int i = 0; i < nTopics; ++i){
|
||||
DataWord topic = stack.pop();
|
||||
topics.add(topic.getData());
|
||||
}
|
||||
|
||||
ByteBuffer data = program.memoryChunk(memStart, memOffset);
|
||||
|
||||
LogInfo logInfo =
|
||||
new LogInfo(address.getLast20Bytes(), topics, data.array());
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = logInfo.toString();
|
||||
|
||||
program.getResult().addLogInfo(logInfo);
|
||||
|
||||
} break;
|
||||
case MLOAD:{
|
||||
DataWord addr = program.stackPop();
|
||||
|
|
|
@ -321,5 +321,16 @@ public class ProgramMemoryTest {
|
|||
int size = 16;
|
||||
program.allocateMemory(offset, size);
|
||||
assertEquals(32,program.getMemSize());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitialInsert() {
|
||||
|
||||
|
||||
// todo: fix the array out of bound here
|
||||
int offset = 32;
|
||||
int size = 00;
|
||||
program.memorySave(32, 0, new byte[0]);
|
||||
assertEquals(32,program.getMemSize());
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ import org.junit.Test;
|
|||
import org.junit.runners.MethodSorters;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
|
@ -1211,6 +1213,125 @@ public class VMTest {
|
|||
assertEquals(expected, Hex.toHexString(program.getMemory().array()));
|
||||
}
|
||||
|
||||
|
||||
@Test // LOG0 OP
|
||||
public void tesLog0(){
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("61123460005260206000A0"), invoke);
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
List<LogInfo> logInfoList = program.getResult().getLogInfoList();
|
||||
LogInfo logInfo = logInfoList.get(0);
|
||||
|
||||
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(logInfo.getAddress()));
|
||||
assertEquals(0, logInfo.getTopics().size());
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000001234", Hex.toHexString(logInfo.getData()));
|
||||
}
|
||||
|
||||
@Test // LOG1 OP
|
||||
public void tesLog1(){
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("61123460005261999960206000A1"), invoke);
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
List<LogInfo> logInfoList = program.getResult().getLogInfoList();
|
||||
LogInfo logInfo = logInfoList.get(0);
|
||||
|
||||
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(logInfo.getAddress()));
|
||||
assertEquals(1, logInfo.getTopics().size());
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000001234", Hex.toHexString(logInfo.getData()));
|
||||
}
|
||||
|
||||
@Test // LOG2 OP
|
||||
public void tesLog2(){
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("61123460005261999961666660206000A2"), invoke);
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
List<LogInfo> logInfoList = program.getResult().getLogInfoList();
|
||||
LogInfo logInfo = logInfoList.get(0);
|
||||
|
||||
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(logInfo.getAddress()));
|
||||
assertEquals(2, logInfo.getTopics().size());
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000001234", Hex.toHexString(logInfo.getData()));
|
||||
}
|
||||
|
||||
@Test // LOG3 OP
|
||||
public void tesLog3(){
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("61123460005261999961666661333360206000A3"), invoke);
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
List<LogInfo> logInfoList = program.getResult().getLogInfoList();
|
||||
LogInfo logInfo = logInfoList.get(0);
|
||||
|
||||
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(logInfo.getAddress()));
|
||||
assertEquals(3, logInfo.getTopics().size());
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000001234", Hex.toHexString(logInfo.getData()));
|
||||
}
|
||||
|
||||
|
||||
@Test // LOG4 OP
|
||||
public void tesLog4(){
|
||||
|
||||
VM vm = new VM();
|
||||
program = new Program(Hex.decode("61123460005261999961666661333361555560206000A4"), invoke);
|
||||
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
vm.step(program);
|
||||
|
||||
List<LogInfo> logInfoList = program.getResult().getLogInfoList();
|
||||
LogInfo logInfo = logInfoList.get(0);
|
||||
|
||||
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(logInfo.getAddress()));
|
||||
assertEquals(4, logInfo.getTopics().size());
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000001234", Hex.toHexString(logInfo.getData()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test // MSTORE OP
|
||||
public void testMSTORE_2() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue