parent
43905b99a2
commit
92f2c29f69
|
@ -179,15 +179,15 @@ public class MainActivity extends ActionBarActivity implements OnClickListener,
|
|||
Log.v(TAG, "333");
|
||||
//ethereumManager.startPeerDiscovery();
|
||||
while(true) {
|
||||
/*
|
||||
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
|
||||
if (quit == 1) {
|
||||
return "All Done!";
|
||||
//return "All Done!";
|
||||
}
|
||||
|
||||
//publishProgress(1111);
|
||||
|
|
|
@ -104,7 +104,7 @@ dependencies {
|
|||
//compile "com.octo.android.robospice:robospice-spring-android:1.4.14"
|
||||
|
||||
//compile 'com.octo.android.robospice:robospice-ormlite:1.4.14'
|
||||
compile('io.netty:netty-all:4.0.26.Final') {
|
||||
compile('io.netty:netty-all:4.1.0.Beta5') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
compile "com.madgag.spongycastle:core:${scastleVersion}"
|
||||
|
@ -129,6 +129,7 @@ dependencies {
|
|||
|
||||
//compile 'org.javassist:javassist:3.15.0-GA'
|
||||
compile 'org.slf4j:slf4j-android:1.7.12'
|
||||
compile 'de.mindpipe.android:android-logging-log4j:1.0.3'
|
||||
//compile "org.slf4j:slf4j-api:${slf4jVersion}"
|
||||
|
||||
//compile "log4j:log4j:${log4jVersion}"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package org.ethereum;
|
||||
|
||||
import org.ethereum.cli.CLIInterface;
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.facade.Ethereum;
|
||||
import org.ethereum.facade.EthereumFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 14.11.2014
|
||||
*/
|
||||
public class Start {
|
||||
|
||||
public static void main(String args[]) throws IOException, URISyntaxException {
|
||||
CLIInterface.call(args);
|
||||
Ethereum ethereum = EthereumFactory.createEthereum();
|
||||
|
||||
if (CONFIG.blocksLoader().equals(""))
|
||||
ethereum.connect(
|
||||
CONFIG.activePeerIP(),
|
||||
CONFIG.activePeerPort(),
|
||||
CONFIG.activePeerNodeid());
|
||||
else
|
||||
ethereum.getBlockLoader().loadBlocks();
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@ public class SystemProperties {
|
|||
|
||||
private final static int DEFAULT_TX_APPROVE_TIMEOUT = 10;
|
||||
private final static String DEFAULT_DISCOVERY_PEER_LIST = "poc-9.ethdev.com:30303";
|
||||
private final static String DEFAULT_ACTIVE_PEER_NODEID = "bf01b54b6bc7faa203286dfb8359ce11d7b1fe822968fb4991f508d6f5a36ab7d9ae8af9b0d61c0467fb08567e0fb71cfb9925a370b69f9ede97927db473d1f5"; // FIXME
|
||||
private final static String DEFAULT_ACTIVE_PEER_NODEID = ""; // FIXME
|
||||
private final static String DEFAULT_ACTIVE_PEER_IP = "poc-9.ethdev.com";
|
||||
private final static int DEFAULT_ACTIVE_PORT = 30303;
|
||||
private final static String DEFAULT_SAMPLES_DIR = "samples";
|
||||
|
|
|
@ -250,11 +250,12 @@ public class BlockchainImpl implements Blockchain {
|
|||
@Override
|
||||
public void add(Block block) {
|
||||
|
||||
if (exitOn < block.getNumber()) {
|
||||
if (exitOn < block.getNumber()){
|
||||
System.out.print("Exiting after block.number: " + getBestBlock().getNumber());
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
|
||||
if(!isValid(block)){
|
||||
logger.warn("Invalid block with number: {}", block.getNumber());
|
||||
return;
|
||||
|
@ -299,6 +300,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
track.commit();
|
||||
repository.flush(); // saving to the disc
|
||||
|
||||
|
||||
storeBlock(block, receipts);
|
||||
|
||||
// Remove all wallet transactions as they already approved by the net
|
||||
|
@ -474,7 +476,6 @@ public class BlockchainImpl implements Blockchain {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return receipts;
|
||||
}
|
||||
|
||||
|
@ -740,5 +741,4 @@ public class BlockchainImpl implements Blockchain {
|
|||
public void setExitOn(long exitOn) {
|
||||
this.exitOn = exitOn;
|
||||
}
|
||||
|
||||
}
|
|
@ -499,10 +499,11 @@ public class TransactionExecutor {
|
|||
}
|
||||
|
||||
*/
|
||||
/**
|
||||
/**
|
||||
* After any contract code finish the run the certain result should take place,
|
||||
* according to the given circumstances.
|
||||
*//*
|
||||
|
||||
private long applyProgramResult(ProgramResult result, BigInteger gasDebit,
|
||||
BigInteger gasPrice, Repository repository, byte[] senderAddress,
|
||||
byte[] contractAddress, byte[] coinbase, boolean initResults) {
|
||||
|
|
|
@ -84,9 +84,8 @@ public class Wallet {
|
|||
this.accountProvider = accountProvider;
|
||||
}
|
||||
|
||||
|
||||
public void addNewAccount() {
|
||||
Account account = accountProvider.get();
|
||||
Account account = new Account(this.repository);
|
||||
account.init();
|
||||
String address = Hex.toHexString(account.getEcKey().getAddress());
|
||||
rows.put(address, account);
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package org.ethereum.datasource;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
|
||||
import org.iq80.leveldb.CompressionType;
|
||||
import org.iq80.leveldb.DB;
|
||||
import org.iq80.leveldb.DBIterator;
|
||||
import org.iq80.leveldb.Options;
|
||||
import org.iq80.leveldb.WriteBatch;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 18.01.2015
|
||||
*/
|
||||
public class AndroidLevelDbDataSource implements KeyValueDataSource {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("db");
|
||||
|
||||
String name;
|
||||
private DB db;
|
||||
private Context context;
|
||||
|
||||
public AndroidLevelDbDataSource() {
|
||||
}
|
||||
|
||||
public AndroidLevelDbDataSource(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setContext(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
if (name == null) throw new NullPointerException("no name set to the db");
|
||||
|
||||
Options options = new Options();
|
||||
options.createIfMissing(true);
|
||||
options.compressionType(CompressionType.NONE);
|
||||
org.iq80.leveldb.Logger logger1 = new org.iq80.leveldb.Logger() {
|
||||
public void log(String message) {
|
||||
logger.debug(message);
|
||||
}
|
||||
};
|
||||
options.logger(logger1);
|
||||
try {
|
||||
logger.debug("Opening database");
|
||||
File dbLocation = context.getDir(SystemProperties.CONFIG.databaseDir(), 0);
|
||||
File fileLocation = new File(dbLocation, name);
|
||||
|
||||
if (SystemProperties.CONFIG.databaseReset()) {
|
||||
destroyDB(fileLocation);
|
||||
}
|
||||
|
||||
logger.debug("Initializing new or existing database: '{}'", fileLocation.getAbsolutePath());
|
||||
db = factory.open(fileLocation, options);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
logger.error(ioe.getMessage(), ioe);
|
||||
throw new RuntimeException("Can't initialize database");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void destroyDB(File fileLocation) {
|
||||
logger.debug("Destroying existing database");
|
||||
Options options = new Options();
|
||||
try {
|
||||
factory.destroy(fileLocation, options);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
return db.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] put(byte[] key, byte[] value) {
|
||||
db.put(key, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(byte[] key) {
|
||||
db.delete(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> keys() {
|
||||
|
||||
DBIterator dbIterator = db.iterator();
|
||||
Set<byte[]> keys = new HashSet<>();
|
||||
while (dbIterator.hasNext()) {
|
||||
|
||||
Map.Entry<byte[], byte[]> entry = dbIterator.next();
|
||||
keys.add(entry.getKey());
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBatch(Map<byte[], byte[]> rows) {
|
||||
|
||||
WriteBatch batch = db.createWriteBatch();
|
||||
|
||||
for (Map.Entry<byte[], byte[]> row : rows.entrySet())
|
||||
batch.put(row.getKey(), row.getValue());
|
||||
|
||||
db.write(batch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
logger.info("Close db: {}", name);
|
||||
db.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to find the db file on the close: {} ", name);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
|
@ -31,7 +30,6 @@ public class LevelDbDataSource implements KeyValueDataSource {
|
|||
|
||||
String name;
|
||||
private DB db;
|
||||
private Context context;
|
||||
|
||||
public LevelDbDataSource() {
|
||||
}
|
||||
|
@ -40,10 +38,6 @@ public class LevelDbDataSource implements KeyValueDataSource {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public void setContext(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
|
@ -52,22 +46,17 @@ public class LevelDbDataSource implements KeyValueDataSource {
|
|||
Options options = new Options();
|
||||
options.createIfMissing(true);
|
||||
options.compressionType(CompressionType.NONE);
|
||||
org.iq80.leveldb.Logger logger1 = new org.iq80.leveldb.Logger() {
|
||||
public void log(String message) {
|
||||
logger.debug(message);
|
||||
}
|
||||
};
|
||||
options.logger(logger1);
|
||||
try {
|
||||
logger.debug("Opening database");
|
||||
File dbLocation = context.getDir(SystemProperties.CONFIG.databaseDir(), 0);
|
||||
File dbLocation = new File(System.getProperty("user.dir") + "/" +
|
||||
SystemProperties.CONFIG.databaseDir() + "/");
|
||||
File fileLocation = new File(dbLocation, name);
|
||||
|
||||
if (SystemProperties.CONFIG.databaseReset()) {
|
||||
destroyDB(fileLocation);
|
||||
}
|
||||
|
||||
logger.debug("Initializing new or existing database: '{}'", fileLocation.getAbsolutePath());
|
||||
logger.debug("Initializing new or existing database: '{}'", name);
|
||||
db = factory.open(fileLocation, options);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
|
|
|
@ -2,8 +2,10 @@ package org.ethereum.di.modules;
|
|||
|
||||
import android.content.Context;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.core.BlockchainImpl;
|
||||
import org.ethereum.core.Wallet;
|
||||
import org.ethereum.datasource.AndroidLevelDbDataSource;
|
||||
import org.ethereum.datasource.KeyValueDataSource;
|
||||
import org.ethereum.datasource.LevelDbDataSource;
|
||||
import org.ethereum.db.BlockStore;
|
||||
|
@ -58,8 +60,8 @@ public class EthereumModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
WorldManager provideWorldManager(Blockchain blockchain, Repository repository, Wallet wallet, PeerDiscovery peerDiscovery
|
||||
,BlockStore blockStore, ChannelManager channelManager, EthereumListener listener) {
|
||||
return new WorldManager(blockchain, repository, wallet, peerDiscovery, blockStore, channelManager, listener);
|
||||
,BlockStore blockStore, ChannelManager channelManager, AdminInfo adminInfo, EthereumListener listener) {
|
||||
return new WorldManager(blockchain, repository, wallet, peerDiscovery, blockStore, channelManager, adminInfo, listener);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -79,9 +81,9 @@ public class EthereumModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
Repository provideRepository() {
|
||||
LevelDbDataSource detailsDS = new LevelDbDataSource();
|
||||
AndroidLevelDbDataSource detailsDS = new AndroidLevelDbDataSource();
|
||||
detailsDS.setContext(context);
|
||||
LevelDbDataSource stateDS = new LevelDbDataSource();
|
||||
AndroidLevelDbDataSource stateDS = new AndroidLevelDbDataSource();
|
||||
stateDS.setContext(context);
|
||||
return new RepositoryImpl(detailsDS, stateDS);
|
||||
}
|
||||
|
@ -139,7 +141,7 @@ public class EthereumModule {
|
|||
|
||||
@Provides
|
||||
MessageCodec provideMessageCodec(EthereumListener listener) {
|
||||
return new MessageCodec(listener);
|
||||
return new MessageCodec();
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -165,11 +167,11 @@ public class EthereumModule {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@Provides
|
||||
String provideRemoteId() {
|
||||
return "bf01b54b6bc7faa203286dfb8359ce11d7b1fe822968fb4991f508d6f5a36ab7d9ae8af9b0d61c0467fb08567e0fb71cfb9925a370b69f9ede97927db473d1f5";
|
||||
return SystemProperties.CONFIG.activePeerNodeid();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.slf4j.LoggerFactory;
|
|||
//import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
|
||||
//import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
|
@ -88,9 +87,7 @@ public class CommonConfig {
|
|||
|
||||
Properties prop = new Properties();
|
||||
|
||||
if (SystemProperties.CONFIG.databaseReset())
|
||||
prop.put("hibernate.hbm2ddl.auto", "create");
|
||||
|
||||
prop.put("hibernate.hbm2ddl.auto", "update");
|
||||
prop.put("hibernate.format_sql", "true");
|
||||
|
||||
// todo: useful but annoying consider define by system.properties
|
||||
|
@ -116,10 +113,9 @@ public class CommonConfig {
|
|||
|
||||
String url =
|
||||
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
|
||||
"create=%s;hsqldb.default_table_type=cached",
|
||||
"create=true;hsqldb.default_table_type=cached",
|
||||
|
||||
SystemProperties.CONFIG.databaseDir(),
|
||||
SystemProperties.CONFIG.databaseReset());
|
||||
SystemProperties.CONFIG.databaseDir());
|
||||
|
||||
DriverManagerDataSource ds = new DriverManagerDataSource();
|
||||
ds.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||
|
@ -127,7 +123,6 @@ public class CommonConfig {
|
|||
ds.setUsername("sa");
|
||||
|
||||
|
||||
|
||||
return ds;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,7 @@ import javax.inject.Provider;
|
|||
|
||||
import static org.ethereum.jsontestsuite.Utils.parseData;
|
||||
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
import static org.ethereum.vm.VMUtils.saveProgramTraceFile;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
|
@ -216,7 +217,7 @@ public class TestRunner {
|
|||
e = ex;
|
||||
}
|
||||
String content = program.getProgramTrace().asJsonString(true);
|
||||
//program.saveProgramTraceToFile(testCase.getName(), content);
|
||||
saveProgramTraceFile(testCase.getName(), content);
|
||||
|
||||
if (testCase.getPost().size() == 0) {
|
||||
if (vmDidThrowAnEception != true) {
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.List;
|
|||
public class AdminInfo {
|
||||
|
||||
|
||||
private long startupTimeStamp = System.currentTimeMillis();;
|
||||
private long startupTimeStamp;
|
||||
private boolean consensus = true;
|
||||
private List<Long> blockExecTime = new LinkedList<>();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
|||
//@Component
|
||||
public class BlockLoader {
|
||||
|
||||
Blockchain blockchain;
|
||||
private Blockchain blockchain;
|
||||
|
||||
Scanner scanner = null;
|
||||
|
||||
|
@ -65,4 +65,6 @@ public class BlockLoader {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -59,14 +59,14 @@ public class WorldManager {
|
|||
|
||||
private ChannelManager channelManager;
|
||||
|
||||
// TODO: What is this doing here ?
|
||||
private AdminInfo adminInfo;
|
||||
|
||||
|
||||
private EthereumListener listener;
|
||||
|
||||
@Inject
|
||||
public WorldManager(Blockchain blockchain, Repository repository, Wallet wallet, PeerDiscovery peerDiscovery
|
||||
,BlockStore blockStore, ChannelManager channelManager, EthereumListener listener) {
|
||||
,BlockStore blockStore, ChannelManager channelManager, AdminInfo adminInfo, EthereumListener listener) {
|
||||
logger.info("World manager instantiated");
|
||||
this.blockchain = blockchain;
|
||||
this.repository = repository;
|
||||
|
@ -74,6 +74,7 @@ public class WorldManager {
|
|||
this.peerDiscovery = peerDiscovery;
|
||||
this.blockStore = blockStore;
|
||||
this.channelManager = channelManager;
|
||||
this.adminInfo = adminInfo;
|
||||
this.listener = listener;
|
||||
|
||||
this.init();
|
||||
|
|
|
@ -34,6 +34,7 @@ public enum ReasonCode {
|
|||
*/
|
||||
TOO_MANY_PEERS(0x04),
|
||||
|
||||
|
||||
/**
|
||||
* [0x05] Already have a running connection with this peer
|
||||
*/
|
||||
|
|
|
@ -38,12 +38,12 @@ public class EthereumChannelInitializer extends ChannelInitializer<NioSocketChan
|
|||
Provider<Channel> channelProvider;
|
||||
|
||||
@Inject
|
||||
public EthereumChannelInitializer(Blockchain blockchain, ChannelManager channelManager, Provider<Channel> channelProvider) {
|
||||
public EthereumChannelInitializer(Blockchain blockchain, ChannelManager channelManager, Provider<Channel> channelProvider, String remoteId) {
|
||||
logger.info("Channel initializer instantiated");
|
||||
this.blockchain = blockchain;
|
||||
this.channelManager = channelManager;
|
||||
this.channelProvider = channelProvider;
|
||||
this.remoteId = "";
|
||||
this.remoteId = remoteId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -61,8 +61,28 @@ public class MessageCodec extends ByteToMessageCodec<Message> {
|
|||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
initiate(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
|
||||
super.channelReadComplete(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
}
|
||||
/*
|
||||
EthereumListener listener;
|
||||
|
||||
@Inject
|
||||
|
@ -70,7 +90,7 @@ public class MessageCodec extends ByteToMessageCodec<Message> {
|
|||
super();
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
*/
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
if (!isHandshakeDone)
|
||||
|
@ -99,7 +119,7 @@ public class MessageCodec extends ByteToMessageCodec<Message> {
|
|||
if (loggerNet.isInfoEnabled())
|
||||
loggerNet.info("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), msg);
|
||||
|
||||
listener.onRecvMessage(msg);
|
||||
//listener.onRecvMessage(msg);
|
||||
|
||||
out.add(msg);
|
||||
}
|
||||
|
@ -108,7 +128,7 @@ public class MessageCodec extends ByteToMessageCodec<Message> {
|
|||
protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
|
||||
|
||||
String output = String.format("To: \t%s \tSend: \t%s", ctx.channel().remoteAddress(), msg);
|
||||
listener.trace(output);
|
||||
//listener.trace(output);
|
||||
|
||||
if (loggerNet.isInfoEnabled())
|
||||
loggerNet.info("To: \t{} \tSend: \t{}", ctx.channel().remoteAddress(), msg);
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.vmtrace.ProgramTraceListener;
|
||||
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Math.ceil;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.String.format;
|
||||
import static org.ethereum.util.ByteUtil.oneByteToHexString;
|
||||
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
public class Memory implements ProgramTraceListenerAware {
|
||||
|
||||
private static final int CHUNK_SIZE = 1024;
|
||||
private static final int WORD_SIZE = 32;
|
||||
|
||||
private List<byte[]> chunks = new LinkedList<>();
|
||||
private int softSize;
|
||||
private ProgramTraceListener traceListener;
|
||||
|
||||
@Override
|
||||
public void setTraceListener(ProgramTraceListener traceListener) {
|
||||
this.traceListener = traceListener;
|
||||
}
|
||||
|
||||
public byte[] read(int address, int size) {
|
||||
if (size <= 0) return EMPTY_BYTE_ARRAY;
|
||||
|
||||
extend(address, size);
|
||||
byte[] data = new byte[size];
|
||||
|
||||
int chunkIndex = address / CHUNK_SIZE;
|
||||
int chunkOffset = address % CHUNK_SIZE;
|
||||
|
||||
int toGrab = data.length;
|
||||
int start = 0;
|
||||
|
||||
while (toGrab > 0) {
|
||||
int copied = grabMax(chunkIndex, chunkOffset, toGrab, data, start);
|
||||
|
||||
// read next chunk from the start
|
||||
++chunkIndex;
|
||||
chunkOffset = 0;
|
||||
|
||||
// mark remind
|
||||
toGrab -= copied;
|
||||
start += copied;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public void write(int address, byte[] data) {
|
||||
extend(address, data.length);
|
||||
|
||||
int chunkIndex = address / CHUNK_SIZE;
|
||||
int chunkOffset = address % CHUNK_SIZE;
|
||||
|
||||
int toCapture = data.length;
|
||||
int start = 0;
|
||||
|
||||
while (toCapture > 0) {
|
||||
int captured = captureMax(chunkIndex, chunkOffset, toCapture, data, start);
|
||||
|
||||
// capture next chunk
|
||||
++chunkIndex;
|
||||
chunkOffset = 0;
|
||||
|
||||
// mark remind
|
||||
toCapture -= captured;
|
||||
start += captured;
|
||||
}
|
||||
|
||||
if (traceListener != null) traceListener.onMemoryWrite(address, data);
|
||||
}
|
||||
|
||||
public void extendAndWrite(int address, int allocSize, byte[] data) {
|
||||
extend(address, allocSize);
|
||||
write(address, data);
|
||||
}
|
||||
|
||||
public void extend(int address, int size) {
|
||||
if (size <= 0) return;
|
||||
|
||||
final int newSize = address + size;
|
||||
|
||||
int toAllocate = newSize - internalSize();
|
||||
if (toAllocate > 0) {
|
||||
addChunks((int) ceil((double) toAllocate / CHUNK_SIZE));
|
||||
}
|
||||
|
||||
toAllocate = newSize - softSize;
|
||||
if (toAllocate > 0) {
|
||||
toAllocate = (int) ceil((double) toAllocate / WORD_SIZE) * WORD_SIZE;
|
||||
softSize += toAllocate;
|
||||
|
||||
if (traceListener != null) traceListener.onMemoryExtend(toAllocate);
|
||||
}
|
||||
}
|
||||
|
||||
public DataWord readWord(int address) {
|
||||
return new DataWord(read(address, 32));
|
||||
}
|
||||
|
||||
// just access expecting all data valid
|
||||
public byte readByte(int address) {
|
||||
|
||||
int chunkIndex = address / CHUNK_SIZE;
|
||||
int chunkOffset = address % CHUNK_SIZE;
|
||||
|
||||
byte[] chunk = chunks.get(chunkIndex);
|
||||
|
||||
return chunk[chunkOffset];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuilder memoryData = new StringBuilder();
|
||||
StringBuilder firstLine = new StringBuilder();
|
||||
StringBuilder secondLine = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < softSize; ++i) {
|
||||
|
||||
byte value = readByte(i);
|
||||
|
||||
// Check if value is ASCII
|
||||
String character = ((byte) 0x20 <= value && value <= (byte) 0x7e) ? new String(new byte[]{value}) : "?";
|
||||
firstLine.append(character).append("");
|
||||
secondLine.append(oneByteToHexString(value)).append(" ");
|
||||
|
||||
if ((i + 1) % 8 == 0) {
|
||||
String tmp = format("%4s", Integer.toString(i - 7, 16)).replace(" ", "0");
|
||||
memoryData.append("").append(tmp).append(" ");
|
||||
memoryData.append(firstLine).append(" ");
|
||||
memoryData.append(secondLine);
|
||||
if (i + 1 < softSize) memoryData.append("\n");
|
||||
firstLine.setLength(0);
|
||||
secondLine.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
return memoryData.toString();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return softSize;
|
||||
}
|
||||
|
||||
public int internalSize() {
|
||||
return chunks.size() * CHUNK_SIZE;
|
||||
}
|
||||
|
||||
public List<byte[]> getChunks() {
|
||||
return new LinkedList<>(chunks);
|
||||
}
|
||||
|
||||
private int captureMax(int chunkIndex, int chunkOffset, int size, byte[] src, int srcPos) {
|
||||
|
||||
byte[] chunk = chunks.get(chunkIndex);
|
||||
int toCapture = min(size, chunk.length - chunkOffset);
|
||||
|
||||
System.arraycopy(src, srcPos, chunk, chunkOffset, toCapture);
|
||||
return toCapture;
|
||||
}
|
||||
|
||||
private int grabMax(int chunkIndex, int chunkOffset, int size, byte[] dest, int destPos) {
|
||||
|
||||
byte[] chunk = chunks.get(chunkIndex);
|
||||
int toGrab = min(size, chunk.length - chunkOffset);
|
||||
|
||||
System.arraycopy(chunk, chunkOffset, dest, destPos, toGrab);
|
||||
|
||||
return toGrab;
|
||||
}
|
||||
|
||||
private void addChunks(int num) {
|
||||
for (int i = 0; i < num; ++i) {
|
||||
chunks.add(new byte[CHUNK_SIZE]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -350,7 +350,6 @@ public class Program {
|
|||
newBalance, null, track, this.invokeData.getBlockStore(), invokeData.byTestingSuite());
|
||||
|
||||
ProgramResult result = new ProgramResult();
|
||||
|
||||
if (programCode.length != 0) {
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode, programInvoke);
|
||||
|
@ -409,6 +408,7 @@ public class Program {
|
|||
|
||||
/**
|
||||
* That method is for internal code invocations
|
||||
*
|
||||
* - Normal calls invoke a specified contract which updates itself
|
||||
* - Stateless calls invoke code from another contract, within the context of the caller
|
||||
*
|
||||
|
@ -799,7 +799,6 @@ public class Program {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static String stringify(byte[] code, int index, String result) {
|
||||
if (code == null || code.length == 0)
|
||||
return result;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.vmtrace.ProgramTraceListener;
|
||||
|
||||
public interface ProgramTraceListenerAware {
|
||||
|
||||
void setTraceListener(ProgramTraceListener listener);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.vmtrace.ProgramTraceListener;
|
||||
|
||||
public class Stack extends java.util.Stack<DataWord> implements ProgramTraceListenerAware {
|
||||
|
||||
private ProgramTraceListener traceListener;
|
||||
|
||||
@Override
|
||||
public void setTraceListener(ProgramTraceListener listener) {
|
||||
this.traceListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized DataWord pop() {
|
||||
if (traceListener != null) traceListener.onStackPop();
|
||||
return super.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataWord push(DataWord item) {
|
||||
if (traceListener != null) traceListener.onStackPush(item);
|
||||
return super.push(item);
|
||||
}
|
||||
|
||||
public void swap(int from, int to) {
|
||||
if (isAccessible(from) && isAccessible(to) && (from != to)) {
|
||||
if (traceListener != null) traceListener.onStackSwap(from, to);
|
||||
DataWord tmp = get(from);
|
||||
set(from, set(to, tmp));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAccessible(int from) {
|
||||
return from >= 0 && from < size();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.db.ByteArrayWrapper;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.vmtrace.ProgramTraceListener;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Storage implements Repository, ProgramTraceListenerAware {
|
||||
|
||||
private final Repository repository;
|
||||
private final DataWord address;
|
||||
private ProgramTraceListener traceListener;
|
||||
|
||||
public Storage(DataWord address, Repository repository) {
|
||||
this.address = address;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTraceListener(ProgramTraceListener listener) {
|
||||
this.traceListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountState createAccount(byte[] addr) {
|
||||
return repository.createAccount(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExist(byte[] addr) {
|
||||
return repository.isExist(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountState getAccountState(byte[] addr) {
|
||||
return repository.getAccountState(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(byte[] addr) {
|
||||
if (canListenTrace(addr)) traceListener.onStorageClear();
|
||||
repository.delete(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger increaseNonce(byte[] addr) {
|
||||
return repository.increaseNonce(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getNonce(byte[] addr) {
|
||||
return repository.getNonce(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContractDetails getContractDetails(byte[] addr) {
|
||||
return repository.getContractDetails(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveCode(byte[] addr, byte[] code) {
|
||||
repository.saveCode(addr, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getCode(byte[] addr) {
|
||||
return repository.getCode(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStorageRow(byte[] addr, DataWord key, DataWord value) {
|
||||
if (canListenTrace(addr)) traceListener.onStoragePut(key, value);
|
||||
repository.addStorageRow(addr, key, value);
|
||||
}
|
||||
|
||||
private boolean canListenTrace(byte[] address) {
|
||||
return this.address.equals(new DataWord(address)) && (traceListener != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataWord getStorageValue(byte[] addr, DataWord key) {
|
||||
return repository.getStorageValue(addr, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getBalance(byte[] addr) {
|
||||
return repository.getBalance(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger addBalance(byte[] addr, BigInteger value) {
|
||||
return repository.addBalance(addr, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> getAccountsKeys() {
|
||||
return repository.getAccountsKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpState(Block block, long gasUsed, int txNumber, byte[] txHash) {
|
||||
repository.dumpState(block, gasUsed, txNumber, txHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repository startTracking() {
|
||||
return repository.startTracking();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
repository.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
repository.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
repository.rollback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncToRoot(byte[] root) {
|
||||
repository.syncToRoot(root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return repository.isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
repository.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBatch(HashMap<ByteArrayWrapper, AccountState> accountStates, HashMap<ByteArrayWrapper, ContractDetails> contractDetails) {
|
||||
for (ByteArrayWrapper address : contractDetails.keySet()) {
|
||||
if (!canListenTrace(address.getData())) return;
|
||||
|
||||
ContractDetails details = contractDetails.get(address);
|
||||
if (details.isDeleted()) {
|
||||
traceListener.onStorageClear();
|
||||
} else if (details.isDirty()) {
|
||||
for (Map.Entry<DataWord, DataWord> entry : details.getStorage().entrySet()) {
|
||||
traceListener.onStoragePut(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
repository.updateBatch(accountStates, contractDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getRoot() {
|
||||
return repository.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
|
||||
repository.loadAccount(addr, cacheAccounts, cacheDetails);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterOutputStream;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.lang.System.getProperty;
|
||||
//import static java.util.Base64.getDecoder;
|
||||
//import static java.util.Base64.getEncoder;
|
||||
//import static org.springframework.util.StringUtils.isEmpty;
|
||||
import static android.util.Base64.*;
|
||||
|
||||
public final class VMUtils {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("VM");
|
||||
private static final SystemProperties CONFIG = new SystemProperties();
|
||||
|
||||
private VMUtils() {
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable closeable) {
|
||||
try {
|
||||
if (closeable != null) {
|
||||
closeable.close();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private static File createProgramTraceFile(String txHash) {
|
||||
File result = null;
|
||||
|
||||
if (CONFIG.vmTrace() && !CONFIG.vmTraceDir().isEmpty()) {
|
||||
|
||||
String pathname = format("%s/%s/%s/%s.json", getProperty("user.dir"), CONFIG.databaseDir(), CONFIG.vmTraceDir(), txHash);
|
||||
File file = new File(pathname);
|
||||
|
||||
if (file.exists()) {
|
||||
if (file.isFile() && file.canWrite()) {
|
||||
result = file;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
result = file;
|
||||
} catch (IOException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void writeStringToFile(File file, String data) {
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(file);
|
||||
if (data != null) {
|
||||
out.write(data.getBytes("UTF-8"));
|
||||
}
|
||||
} catch (Exception e){
|
||||
LOGGER.error(format("Cannot write to file '%s': ", file.getAbsolutePath()), e);
|
||||
} finally {
|
||||
closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveProgramTraceFile(String txHash, String content) {
|
||||
File file = createProgramTraceFile(txHash);
|
||||
if (file != null) {
|
||||
writeStringToFile(file, content);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int BUF_SIZE = 4096;
|
||||
|
||||
private static void write(InputStream in, OutputStream out, int bufSize) throws IOException {
|
||||
try {
|
||||
byte[] buf = new byte[bufSize];
|
||||
for (int count = in.read(buf); count != -1; count = in.read(buf)) {
|
||||
out.write(buf, 0, count);
|
||||
}
|
||||
} finally {
|
||||
closeQuietly(in);
|
||||
closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] compress(String content) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes("UTF-8"));
|
||||
DeflaterOutputStream out = new DeflaterOutputStream(baos, new Deflater(), BUF_SIZE);
|
||||
|
||||
write(in, out, BUF_SIZE);
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
private static String decompress(byte[] data) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length);
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(data);
|
||||
InflaterOutputStream out = new InflaterOutputStream(baos, new Inflater(), BUF_SIZE);
|
||||
|
||||
write(in, out, BUF_SIZE);
|
||||
|
||||
return new String(baos.toByteArray(), "UTF-8");
|
||||
}
|
||||
|
||||
public static String zipAndEncode(String content) {
|
||||
try {
|
||||
return encodeToString(compress(content), DEFAULT);//getEncoder().encodeToString(compress(content));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Cannot zip or encode: ", e);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public static String unzipAndDecode(String content) {
|
||||
try {
|
||||
return decompress(decode(content, DEFAULT));//decompress(getDecoder().decode(content));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Cannot unzip or decode: ", e);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package org.ethereum.vmtrace;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import org.ethereum.vm.DataWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.ethereum.util.ByteUtil.toHexString;
|
||||
|
||||
public class OpActions {
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class Action {
|
||||
|
||||
public enum Name {
|
||||
pop,
|
||||
push,
|
||||
swap,
|
||||
extend,
|
||||
write,
|
||||
put,
|
||||
remove,
|
||||
clear;
|
||||
}
|
||||
|
||||
private Name name;
|
||||
private Map<String, Object> params;
|
||||
|
||||
public Name getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(Name name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Map<String, Object> params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
Action addParam(String name, Object value) {
|
||||
if (value != null) {
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
}
|
||||
params.put(name, value.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Action> stack = new ArrayList<>();
|
||||
private List<Action> memory = new ArrayList<>();
|
||||
private List<Action> storage = new ArrayList<>();
|
||||
|
||||
public List<Action> getStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public void setStack(List<Action> stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public List<Action> getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
public void setMemory(List<Action> memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
public List<Action> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public void setStorage(List<Action> storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
private static Action addAction(List<Action> container, Action.Name name) {
|
||||
Action action = new Action();
|
||||
action.setName(name);
|
||||
|
||||
container.add(action);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
public Action addStackPop() {
|
||||
return addAction(stack, Action.Name.pop);
|
||||
}
|
||||
|
||||
public Action addStackPush(DataWord value) {
|
||||
return addAction(stack, Action.Name.push)
|
||||
.addParam("value", value);
|
||||
}
|
||||
|
||||
public Action addStackSwap(int from, int to) {
|
||||
return addAction(stack, Action.Name.swap)
|
||||
.addParam("from", from)
|
||||
.addParam("to", to);
|
||||
}
|
||||
|
||||
public Action addMemoryExtend(long delta) {
|
||||
return addAction(memory, Action.Name.extend)
|
||||
.addParam("delta", delta);
|
||||
}
|
||||
|
||||
public Action addMemoryWrite(int address, byte[] data) {
|
||||
return addAction(memory, Action.Name.write)
|
||||
.addParam("address", address)
|
||||
.addParam("data", toHexString(data));
|
||||
}
|
||||
|
||||
public Action addStoragePut(DataWord key, DataWord value) {
|
||||
return addAction(storage, Action.Name.put)
|
||||
.addParam("key", key)
|
||||
.addParam("value", value);
|
||||
}
|
||||
|
||||
public Action addStorageRemove(DataWord key) {
|
||||
return addAction(storage, Action.Name.remove)
|
||||
.addParam("key", key);
|
||||
}
|
||||
|
||||
public Action addStorageClear() {
|
||||
return addAction(storage, Action.Name.clear);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package org.ethereum.vmtrace;
|
||||
|
||||
import org.ethereum.vm.DataWord;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
public class ProgramTraceListener {
|
||||
|
||||
private final boolean enabled = CONFIG.vmTrace();
|
||||
private OpActions actions = new OpActions();
|
||||
|
||||
public void onMemoryExtend(int delta) {
|
||||
if (enabled) actions.addMemoryExtend(delta);
|
||||
}
|
||||
|
||||
public void onMemoryWrite(int address, byte[] data) {
|
||||
if (enabled) actions.addMemoryWrite(address, data);
|
||||
}
|
||||
|
||||
public void onStackPop() {
|
||||
if (enabled) actions.addStackPop();
|
||||
}
|
||||
|
||||
public void onStackPush(DataWord value) {
|
||||
if (enabled) actions.addStackPush(value);
|
||||
}
|
||||
|
||||
public void onStackSwap(int from, int to) {
|
||||
if (enabled) actions.addStackSwap(from, to);
|
||||
}
|
||||
|
||||
public void onStoragePut(DataWord key, DataWord value) {
|
||||
if (enabled) {
|
||||
if (value.equals(DataWord.ZERO)) {
|
||||
actions.addStorageRemove(key);
|
||||
} else {
|
||||
actions.addStoragePut(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onStorageClear() {
|
||||
actions.addStorageClear();
|
||||
}
|
||||
|
||||
public OpActions resetActions() {
|
||||
OpActions actions = this.actions;
|
||||
this.actions = new OpActions();
|
||||
return actions;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@ peer.active.ip = 162.243.46.9
|
|||
peer.active.port = 30303
|
||||
peer.active.nodeid = e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e23717147073a7ce0b444d485fff5a0c34c4577251a7a990cf80d8542e21b95aa8c5e6c
|
||||
|
||||
|
||||
# heiko peer
|
||||
#peer.active.ip = 188.106.121.253
|
||||
#peer.active.port = 30303
|
||||
|
@ -45,7 +44,7 @@ peer.active.nodeid = e437a4836b77ad9d9ffe73ee782ef2614e6d8370fcf62191a6e488276e2
|
|||
# Peer for server to listen for incoming
|
||||
# connections
|
||||
|
||||
peer.listen.port = 30303
|
||||
peer.listen.port = 10101
|
||||
#peer.listen.port = 40304
|
||||
|
||||
# specify if the mechanism
|
||||
|
@ -127,6 +126,7 @@ vm.structured.trace = true
|
|||
vm.structured.dir = vmtrace
|
||||
vm.structured.compressed = true
|
||||
|
||||
|
||||
# make changes to tracing options
|
||||
# starting from certain block
|
||||
# -1 don't make any tracing changes
|
||||
|
|
Loading…
Reference in New Issue