mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-02-17 22:27:13 +00:00
VM enhance:
+ LOG0..LOG4 implemented and tested
This commit is contained in:
parent
8bf61332ae
commit
23a7f75266
@ -10,18 +10,18 @@ public class GasCost {
|
|||||||
|
|
||||||
/** Cost 1 gas */
|
/** Cost 1 gas */
|
||||||
public static int STEP = 1;
|
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 */
|
/** Cost 0 gas */
|
||||||
public static int STOP = 0;
|
public static int STOP = 0;
|
||||||
/** Cost 0 gas */
|
/** Cost 0 gas */
|
||||||
public static int SUICIDE = 0;
|
public static int SUICIDE = 0;
|
||||||
/** Cost 20 gas */
|
|
||||||
public static int SLOAD = 20;
|
|
||||||
/** Cost 20 gas */
|
|
||||||
public static int SHA3 = 20;
|
|
||||||
/** Cost 100 gas */
|
/** Cost 100 gas */
|
||||||
public static int SSTORE = 100;
|
public static int SSTORE = 100;
|
||||||
/** Cost 20 gas */
|
|
||||||
public static int BALANCE = 20;
|
|
||||||
/** Cost 100 gas */
|
/** Cost 100 gas */
|
||||||
public static int CREATE = 100;
|
public static int CREATE = 100;
|
||||||
/** Cost 20 gas */
|
/** Cost 20 gas */
|
||||||
@ -32,4 +32,10 @@ public class GasCost {
|
|||||||
public static int TXDATA = 5;
|
public static int TXDATA = 5;
|
||||||
/** Cost 500 gas */
|
/** Cost 500 gas */
|
||||||
public static int TRANSACTION = 500;
|
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;
|
||||||
}
|
}
|
60
ethereumj-core/src/main/java/org/ethereum/vm/LogInfo.java
Normal file
60
ethereumj-core/src/main/java/org/ethereum/vm/LogInfo.java
Normal file
@ -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 */
|
/** (0x9f) Exchange 17th item from stack with the top */
|
||||||
SWAP16(0x9f, 17),
|
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 */
|
/* System operations */
|
||||||
|
|
||||||
/** (0xf0) Create a new account with associated code */
|
/** (0xf0) Create a new account with associated code */
|
||||||
|
@ -316,6 +316,7 @@ public class Program {
|
|||||||
vm.play(program);
|
vm.play(program);
|
||||||
result = program.getResult();
|
result = program.getResult();
|
||||||
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
||||||
|
this.result.addLogInfos(result.getLogInfoList());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != null &&
|
if (result != null &&
|
||||||
@ -415,6 +416,7 @@ public class Program {
|
|||||||
result = program.getResult();
|
result = program.getResult();
|
||||||
this.getProgramTrace().merge(program.getProgramTrace());
|
this.getProgramTrace().merge(program.getProgramTrace());
|
||||||
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
||||||
|
this.result.addLogInfos(result.getLogInfoList());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != null &&
|
if (result != null &&
|
||||||
|
@ -17,6 +17,7 @@ public class ProgramResult {
|
|||||||
private ByteBuffer hReturn = null;
|
private ByteBuffer hReturn = null;
|
||||||
private RuntimeException exception;
|
private RuntimeException exception;
|
||||||
private List<DataWord> deleteAccounts;
|
private List<DataWord> deleteAccounts;
|
||||||
|
private List<LogInfo> logInfoList;
|
||||||
|
|
||||||
private Repository repository = null;
|
private Repository repository = null;
|
||||||
|
|
||||||
@ -69,6 +70,20 @@ public class ProgramResult {
|
|||||||
deleteAccounts.add(address);
|
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) {
|
public void addDeleteAccounts(List<DataWord> accounts) {
|
||||||
if (accounts == null) return;
|
if (accounts == null) return;
|
||||||
if (deleteAccounts == null)
|
if (deleteAccounts == null)
|
||||||
|
@ -73,8 +73,6 @@ public class VM {
|
|||||||
|
|
||||||
public void step(Program program) {
|
public void step(Program program) {
|
||||||
|
|
||||||
program.fullTrace();
|
|
||||||
|
|
||||||
if (CONFIG.vmTrace())
|
if (CONFIG.vmTrace())
|
||||||
program.saveOpTrace();
|
program.saveOpTrace();
|
||||||
|
|
||||||
@ -160,6 +158,16 @@ public class VM {
|
|||||||
gasCost = GasCost.CREATE;
|
gasCost = GasCost.CREATE;
|
||||||
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-3));
|
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-3));
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -717,6 +725,32 @@ public class VM {
|
|||||||
stack.set(stack.size() - n, word_1);
|
stack.set(stack.size() - n, word_1);
|
||||||
program.step();
|
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;
|
} break;
|
||||||
case MLOAD:{
|
case MLOAD:{
|
||||||
DataWord addr = program.stackPop();
|
DataWord addr = program.stackPop();
|
||||||
|
@ -321,5 +321,16 @@ public class ProgramMemoryTest {
|
|||||||
int size = 16;
|
int size = 16;
|
||||||
program.allocateMemory(offset, size);
|
program.allocateMemory(offset, size);
|
||||||
assertEquals(32,program.getMemSize());
|
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.junit.runners.MethodSorters;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1211,6 +1213,125 @@ public class VMTest {
|
|||||||
assertEquals(expected, Hex.toHexString(program.getMemory().array()));
|
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
|
@Test // MSTORE OP
|
||||||
public void testMSTORE_2() {
|
public void testMSTORE_2() {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user