Merged latest develop changes.

This commit is contained in:
Adrian Tiberius 2015-07-08 14:23:41 +02:00
parent 805234deb7
commit 74eca228dc
38 changed files with 283 additions and 135 deletions

View File

@ -89,6 +89,11 @@ public class LevelDbDataSource implements KeyValueDataSource {
this.name = name; this.name = name;
} }
@Override
public String getName() {
return name;
}
@Override @Override
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
return db.get(key); return db.get(key);

View File

@ -46,6 +46,11 @@ public class MapDBDataSource implements KeyValueDataSource {
this.name = name; this.name = name;
} }
@Override
public String getName() {
return name;
}
@Override @Override
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
return map.get(wrap(key)); return map.get(wrap(key));

View File

@ -129,7 +129,7 @@ dependencies {
compile "com.h2database:h2:1.4.187" compile "com.h2database:h2:1.4.187"
// compile "org.mapdb:mapdb:1.0.7" // compile "org.mapdb:mapdb:1.0.7"
compile "org.mapdb:mapdb:2.0-alpha3" compile "org.mapdb:mapdb:2.0-beta1"
compile "org.slf4j:slf4j-log4j12:${slf4jVersion}" compile "org.slf4j:slf4j-log4j12:${slf4jVersion}"
compile "log4j:apache-log4j-extras:${log4jVersion}" compile "log4j:apache-log4j-extras:${log4jVersion}"

View File

@ -295,6 +295,12 @@ public class BlockchainImpl implements Blockchain {
track.commit(); track.commit();
storeBlock(block, receipts); storeBlock(block, receipts);
if (block.getNumber() == 650_000){
repository.flush();
blockStore.flush();
System.exit(-1);
}
if (needFlush(block)) { if (needFlush(block)) {
repository.flush(); repository.flush();
blockStore.flush(); blockStore.flush();
@ -322,13 +328,16 @@ public class BlockchainImpl implements Blockchain {
} }
private boolean needFlush(Block block) { private boolean needFlush(Block block) {
boolean possibleFlush = CONFIG.flushBlocksIgnoreConsensus() || adminInfo.isConsensus();
if (!possibleFlush)return false;
if (CONFIG.flushBlocksRepoSize() > 0 && repository.getClass().isAssignableFrom(RepositoryImpl.class)) { if (CONFIG.flushBlocksRepoSize() > 0 && repository.getClass().isAssignableFrom(RepositoryImpl.class)) {
return ((RepositoryImpl) repository).getAllocatedMemorySize() > CONFIG.flushBlocksRepoSize(); return ((RepositoryImpl) repository).getAllocatedMemorySize() > CONFIG.flushBlocksRepoSize();
} else { } else {
boolean isBatchReached = block.getNumber() % CONFIG.flushBlocksBatchSize() == 0; boolean isBatchReached = block.getNumber() % CONFIG.flushBlocksBatchSize() == 0;
boolean isConsensus = CONFIG.flushBlocksIgnoreConsensus() || adminInfo.isConsensus();
return isConsensus && isBatchReached; return isBatchReached;
} }
} }

View File

@ -8,6 +8,7 @@ import org.ethereum.util.ByteUtil;
import org.ethereum.util.RLP; import org.ethereum.util.RLP;
import org.ethereum.util.RLPList; import org.ethereum.util.RLPList;
import org.ethereum.vm.GasCost;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -108,6 +109,22 @@ public class Transaction {
this.signature = signature; this.signature = signature;
} }
public long transactionCost(){
if (!parsed) rlpParse();
long nonZeroes = nonZeroDataBytes();
long zeroVals = getDataSize() - nonZeroes;
return GasCost.TRANSACTION + zeroVals * GasCost.TX_ZERO_DATA + nonZeroes * GasCost.TX_NO_ZERO_DATA;
}
private int getDataSize(){
if (data == null)
return 0;
else
return data.length;
}
public void rlpParse() { public void rlpParse() {

View File

@ -237,6 +237,10 @@ public class TransactionExecutor {
if (vm == null) return; if (vm == null) return;
try { try {
// Charge basic cost of the transaction
program.spendGas(tx.transactionCost(), "TRANSACTION COST");
if (CONFIG.playVM()) if (CONFIG.playVM())
vm.play(program); vm.play(program);

View File

@ -1,21 +1,43 @@
package org.ethereum.datasource; package org.ethereum.datasource;
import java.util.Map; import org.slf4j.Logger;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.slf4j.LoggerFactory.getLogger;
public class DataSourcePool { public class DataSourcePool {
private static Map<String, KeyValueDataSource> pool = new ConcurrentHashMap<>(); private static Logger logger = getLogger("db");
private static ConcurrentMap<String, DataSource> pool = new ConcurrentHashMap<>();
public static KeyValueDataSource levelDbByName(String name) { public static KeyValueDataSource levelDbByName(String name) {
KeyValueDataSource dataSource = pool.get(name); return (KeyValueDataSource) getDataSourceFromPool(name, new LevelDbDataSource(name));
if (dataSource == null) { }
dataSource = new LevelDbDataSource(name);
dataSource.init(); private static DataSource getDataSourceFromPool(String name, DataSource dataSource) {
DataSource result = pool.putIfAbsent(name, dataSource);
pool.put(name, dataSource); if (result == null) {
synchronized (dataSource) {
dataSource.init();
result = dataSource;
}
logger.info("Data source '{}' created and added to pool.", dataSource.getName());
} else {
logger.info("Data source '{}' returned from pool.", dataSource.getName());
} }
return dataSource; return result;
}
public static void closeDataSource(String name){
DataSource dataSource = pool.remove(name);
if (dataSource != null){
synchronized (dataSource) {
dataSource.close();
logger.info("Data source '{}' closed and removed from pool.", dataSource.getName());
}
}
} }
} }

View File

@ -51,6 +51,11 @@ public class HashMapDB implements KeyValueDataSource {
} }
@Override
public String getName() {
return "in-memory";
}
@Override @Override
public Set<byte[]> keys() { public Set<byte[]> keys() {
Set<byte[]> keys = new HashSet<>(); Set<byte[]> keys = new HashSet<>();
@ -69,6 +74,6 @@ public class HashMapDB implements KeyValueDataSource {
@Override @Override
public void close() { public void close() {
this.storage.clear();
} }
} }

View File

@ -7,11 +7,7 @@ import java.util.Set;
* @author Roman Mandeleil * @author Roman Mandeleil
* @since 18.01.2015 * @since 18.01.2015
*/ */
public interface KeyValueDataSource { public interface KeyValueDataSource extends DataSource {
void init();
void setName(String name);
byte[] get(byte[] key); byte[] get(byte[] key);
@ -22,6 +18,4 @@ public interface KeyValueDataSource {
Set<byte[]> keys(); Set<byte[]> keys();
void updateBatch(Map<byte[], byte[]> rows); void updateBatch(Map<byte[], byte[]> rows);
void close();
} }

View File

@ -51,10 +51,6 @@ public class LevelDbDataSource implements KeyValueDataSource {
File dbLocation = fileLocation.getParentFile(); File dbLocation = fileLocation.getParentFile();
if (!dbLocation.exists()) dbLocation.mkdirs(); if (!dbLocation.exists()) dbLocation.mkdirs();
if (CONFIG.databaseReset()) {
destroyDB(fileLocation);
}
logger.debug("Initializing new or existing database: '{}'", name); logger.debug("Initializing new or existing database: '{}'", name);
db = factory.open(fileLocation, options); db = factory.open(fileLocation, options);
} catch (IOException ioe) { } catch (IOException ioe) {
@ -79,6 +75,11 @@ public class LevelDbDataSource implements KeyValueDataSource {
this.name = name; this.name = name;
} }
@Override
public String getName() {
return name;
}
@Override @Override
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
return db.get(key); return db.get(key);

View File

@ -42,6 +42,11 @@ public class MapDBDataSource implements KeyValueDataSource {
this.name = name; this.name = name;
} }
@Override
public String getName() {
return name;
}
@Override @Override
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
return map.get(key); return map.get(key);

View File

@ -53,6 +53,11 @@ public class RedisDataSource extends RedisMap<byte[], byte[]> implements KeyValu
super.setName(name); super.setName(name);
} }
@Override
public String getName() {
return new String(getNameBytes());
}
@Override @Override
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
return super.get(key); return super.get(key);

View File

@ -33,7 +33,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
return pooledWithResult(new Function<Jedis, Integer>() { return pooledWithResult(new Function<Jedis, Integer>() {
@Override @Override
public Integer apply(Jedis jedis) { public Integer apply(Jedis jedis) {
return jedis.hlen(getName()).intValue(); return jedis.hlen(getNameBytes()).intValue();
} }
}); });
} }
@ -48,7 +48,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
return pooledWithResult(new Function<Jedis, Boolean>() { return pooledWithResult(new Function<Jedis, Boolean>() {
@Override @Override
public Boolean apply(Jedis jedis) { public Boolean apply(Jedis jedis) {
return jedis.hexists(getName(), serializeKey((K) key)); return jedis.hexists(getNameBytes(), serializeKey((K) key));
} }
}); });
} }
@ -63,7 +63,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
return pooledWithResult(new Function<Jedis, V>() { return pooledWithResult(new Function<Jedis, V>() {
@Override @Override
public V apply(Jedis jedis) { public V apply(Jedis jedis) {
byte[] value = jedis.hget(getName(), serializeKey((K) key)); byte[] value = jedis.hget(getNameBytes(), serializeKey((K) key));
return deserialize(value); return deserialize(value);
} }
}); });
@ -75,8 +75,8 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
@Override @Override
public V apply(Jedis jedis) { public V apply(Jedis jedis) {
byte[] serializedKey = serializeKey(key); byte[] serializedKey = serializeKey(key);
byte[] oldValue = jedis.hget(getName(), serializedKey); byte[] oldValue = jedis.hget(getNameBytes(), serializedKey);
jedis.hset(getName(), serializedKey, serialize(value)); jedis.hset(getNameBytes(), serializedKey, serialize(value));
return deserialize(oldValue); return deserialize(oldValue);
} }
}); });
@ -88,8 +88,8 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
@Override @Override
public V apply(Jedis jedis) { public V apply(Jedis jedis) {
byte[] serializedKey = serializeKey((K) key); byte[] serializedKey = serializeKey((K) key);
byte[] oldValue = jedis.hget(getName(), serializedKey); byte[] oldValue = jedis.hget(getNameBytes(), serializedKey);
jedis.hdel(getName(), serializedKey); jedis.hdel(getNameBytes(), serializedKey);
return deserialize(oldValue); return deserialize(oldValue);
} }
}); });
@ -104,7 +104,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
for (Entry<? extends K, ? extends V> entry : m.entrySet()) { for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
map.put(serializeKey(entry.getKey()), serialize(entry.getValue())); map.put(serializeKey(entry.getKey()), serialize(entry.getValue()));
} }
jedis.hmset(getName(), map); jedis.hmset(getNameBytes(), map);
} }
}); });
} }
@ -114,7 +114,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
pooled(new Consumer<Jedis>() { pooled(new Consumer<Jedis>() {
@Override @Override
public void accept(Jedis jedis) { public void accept(Jedis jedis) {
jedis.del(getName()); jedis.del(getNameBytes());
} }
}); });
} }
@ -125,7 +125,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
@Override @Override
public Set<K> apply(Jedis jedis) { public Set<K> apply(Jedis jedis) {
Set<K> result = new HashSet<K>(); Set<K> result = new HashSet<K>();
collect(jedis.hkeys(getName()), new Transformer<byte[], K>() { collect(jedis.hkeys(getNameBytes()), new Transformer<byte[], K>() {
@Override @Override
public K transform(byte[] input) { public K transform(byte[] input) {
return deserializeKey(input); return deserializeKey(input);
@ -141,7 +141,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
return pooledWithResult(new Function<Jedis, Collection<V>>() { return pooledWithResult(new Function<Jedis, Collection<V>>() {
@Override @Override
public Collection<V> apply(Jedis jedis) { public Collection<V> apply(Jedis jedis) {
return deserialize(jedis.hvals(getName())); return deserialize(jedis.hvals(getNameBytes()));
} }
}); });
} }
@ -152,7 +152,7 @@ public class RedisMap<K, V> extends RedisStorage<V> implements Map<K, V> {
@Override @Override
public Set<Entry<K, V>> apply(Jedis jedis) { public Set<Entry<K, V>> apply(Jedis jedis) {
Set<Entry<K, V>> result = new HashSet<Entry<K, V>>(); Set<Entry<K, V>> result = new HashSet<Entry<K, V>>();
collect(jedis.hgetAll(getName()).entrySet(), new Transformer<Entry<byte[], byte[]>, Entry<K, V>>() { collect(jedis.hgetAll(getNameBytes()).entrySet(), new Transformer<Entry<byte[], byte[]>, Entry<K, V>>() {
@Override @Override
public Entry<K, V> transform(Entry<byte[], byte[]> input) { public Entry<K, V> transform(Entry<byte[], byte[]> input) {
K key = deserializeKey(input.getKey()); K key = deserializeKey(input.getKey());

View File

@ -23,7 +23,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
return pooledWithResult(new Function<Jedis, Integer>() { return pooledWithResult(new Function<Jedis, Integer>() {
@Override @Override
public Integer apply(Jedis jedis) { public Integer apply(Jedis jedis) {
return jedis.scard(getName()).intValue(); return jedis.scard(getNameBytes()).intValue();
} }
}); });
} }
@ -38,7 +38,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
return pooledWithResult(new Function<Jedis, Boolean>() { return pooledWithResult(new Function<Jedis, Boolean>() {
@Override @Override
public Boolean apply(Jedis jedis) { public Boolean apply(Jedis jedis) {
return jedis.sismember(getName(), serialize((T) o)); return jedis.sismember(getNameBytes(), serialize((T) o));
} }
}); });
} }
@ -52,7 +52,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
Set<byte[]> members = pooledWithResult(new Function<Jedis, Set<byte[]>>() { Set<byte[]> members = pooledWithResult(new Function<Jedis, Set<byte[]>>() {
@Override @Override
public Set<byte[]> apply(Jedis jedis) { public Set<byte[]> apply(Jedis jedis) {
return jedis.smembers(getName()); return jedis.smembers(getNameBytes());
} }
}); });
return deserialize(members); return deserialize(members);
@ -88,7 +88,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
return pooledWithResult(new Function<Jedis, Boolean>() { return pooledWithResult(new Function<Jedis, Boolean>() {
@Override @Override
public Boolean apply(Jedis jedis) { public Boolean apply(Jedis jedis) {
return jedis.sadd(getName(), serialize(c)) == c.size(); return jedis.sadd(getNameBytes(), serialize(c)) == c.size();
} }
}); });
} }
@ -101,7 +101,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
byte[] tempName = temporaryName(); byte[] tempName = temporaryName();
try { try {
jedis.sadd(tempName, serialize(c)); jedis.sadd(tempName, serialize(c));
return jedis.scard(getName()) != jedis.sinterstore(getName(), getName(), tempName); return jedis.scard(getNameBytes()) != jedis.sinterstore(getNameBytes(), getNameBytes(), tempName);
} finally { } finally {
jedis.del(tempName); jedis.del(tempName);
} }
@ -114,7 +114,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
return CollectionUtils.isEmpty(c) || pooledWithResult(new Function<Jedis, Boolean>() { return CollectionUtils.isEmpty(c) || pooledWithResult(new Function<Jedis, Boolean>() {
@Override @Override
public Boolean apply(Jedis jedis) { public Boolean apply(Jedis jedis) {
return jedis.srem(getName(), serialize(c)) == c.size(); return jedis.srem(getNameBytes(), serialize(c)) == c.size();
} }
}); });
} }
@ -124,7 +124,7 @@ public class RedisSet<T> extends RedisStorage<T> implements Set<T> {
pooled(new Consumer<Jedis>() { pooled(new Consumer<Jedis>() {
@Override @Override
public void accept(Jedis jedis) { public void accept(Jedis jedis) {
jedis.del(getName()); jedis.del(getNameBytes());
} }
}); });
} }

View File

@ -27,7 +27,7 @@ public abstract class RedisStorage<T> {
this.serializer = serializer; this.serializer = serializer;
} }
protected byte[] getName() { protected byte[] getNameBytes() {
return name; return name;
} }
@ -36,7 +36,7 @@ public abstract class RedisStorage<T> {
} }
protected byte[] formatName(String suffix) { protected byte[] formatName(String suffix) {
return Bytes.concat(getName(), suffix.getBytes()); return Bytes.concat(getNameBytes(), suffix.getBytes());
} }
protected byte[] temporaryName() { protected byte[] temporaryName() {

View File

@ -1,6 +1,7 @@
package org.ethereum.db; package org.ethereum.db;
import org.ethereum.config.SystemProperties; import org.ethereum.config.SystemProperties;
import org.ethereum.datasource.DataSourcePool;
import org.ethereum.datasource.KeyValueDataSource; import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.trie.SecureTrie; import org.ethereum.trie.SecureTrie;
import org.ethereum.util.RLP; import org.ethereum.util.RLP;
@ -52,13 +53,13 @@ public class ContractDetailsImpl implements ContractDetails {
keys.add(wrap(key)); keys.add(wrap(key));
keysSize += key.length; keysSize += key.length;
} }
private void removeKey(byte[] key) { private void removeKey(byte[] key) {
if (keys.remove(wrap(key))) { if (keys.remove(wrap(key))) {
keysSize -= key.length; keysSize -= key.length;
} }
} }
@Override @Override
public void put(DataWord key, DataWord value) { public void put(DataWord key, DataWord value) {
if (value.equals(DataWord.ZERO)) { if (value.equals(DataWord.ZERO)) {
@ -71,7 +72,7 @@ public class ContractDetailsImpl implements ContractDetails {
this.setDirty(true); this.setDirty(true);
this.rlpEncoded = null; this.rlpEncoded = null;
externalStorage = (keys.size() > SystemProperties.CONFIG.detailsInMemoryStorageLimit()) || externalStorage; externalStorage = (keys.size() > SystemProperties.CONFIG.detailsInMemoryStorageLimit()) || externalStorage;
} }
@ -123,7 +124,7 @@ public class ContractDetailsImpl implements ContractDetails {
for (RLPElement key : keys) { for (RLPElement key : keys) {
addKey(key.getRLPData()); addKey(key.getRLPData());
} }
if (externalStorage) { if (externalStorage) {
storageTrie.setRoot(storageRoot.getRLPData()); storageTrie.setRoot(storageRoot.getRLPData());
storageTrie.getCache().setDB(getExternalStorageDataSource()); storageTrie.getCache().setDB(getExternalStorageDataSource());
@ -215,6 +216,8 @@ public class ContractDetailsImpl implements ContractDetails {
if (externalStorage) { if (externalStorage) {
storageTrie.getCache().setDB(getExternalStorageDataSource()); storageTrie.getCache().setDB(getExternalStorageDataSource());
storageTrie.sync(); storageTrie.sync();
DataSourcePool.closeDataSource("details-storage/" + toHexString(address));
} }
} }
@ -250,14 +253,14 @@ public class ContractDetailsImpl implements ContractDetails {
return ret; return ret;
} }
@Override @Override
public int getAllocatedMemorySize() { public int getAllocatedMemorySize() {
int result = rlpEncoded == null ? 0 : rlpEncoded.length; int result = rlpEncoded == null ? 0 : rlpEncoded.length;
result += address.length; result += address.length;
result += code.length; result += code.length;
result += storageTrie.getCache().getAllocatedMemorySize(); result += storageTrie.getCache().getAllocatedMemorySize();
return result; return result;
} }
} }

View File

@ -135,7 +135,7 @@ public class RepositoryImpl implements Repository {
} else { } else {
if (!contractDetails.isDirty()) continue; if (!contractDetails.isDirty()) continue;
ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl)contractDetails; ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl)contractDetails;
if (contractDetailsCache.origContract == null){ if (contractDetailsCache.origContract == null){
contractDetailsCache.origContract = new ContractDetailsImpl(); contractDetailsCache.origContract = new ContractDetailsImpl();
@ -170,12 +170,26 @@ public class RepositoryImpl implements Repository {
detailsCache.clear(); detailsCache.clear();
} }
@Override
public void flushNoReconnect(){
gLogger.info("flushing to disk");
dds.flush();
worldState.sync();
}
@Override @Override
public void flush() { public void flush() {
gLogger.info("flushing to disk"); gLogger.info("flushing to disk");
dds.flush(); dds.flush();
worldState.sync(); worldState.sync();
byte[] root = worldState.getRootHash();
reset();
worldState.setRoot(root);
} }
public int getAllocatedMemorySize() { public int getAllocatedMemorySize() {

View File

@ -244,6 +244,10 @@ public class RepositoryTrack implements Repository {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public void flushNoReconnect() {
throw new UnsupportedOperationException();
}
@Override @Override
public void commit() { public void commit() {

View File

@ -24,6 +24,8 @@ public class CommonConfig {
private RedisConnection redisConnection; private RedisConnection redisConnection;
private MapDBFactory mapDBFactory;
Repository repository() { Repository repository() {
return new RepositoryImpl(keyValueDataSource(), keyValueDataSource()); return new RepositoryImpl(keyValueDataSource(), keyValueDataSource());
} }

View File

@ -6,9 +6,11 @@ import org.ethereum.di.components.DaggerEthereumComponent;
import org.ethereum.net.eth.EthHandler; import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.shh.ShhHandler; import org.ethereum.net.shh.ShhHandler;
import org.ethereum.util.FileUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static org.ethereum.config.SystemProperties.CONFIG;
/** /**
* @author Roman Mandeleil * @author Roman Mandeleil
@ -22,6 +24,16 @@ public class EthereumFactory {
public static Ethereum createEthereum() { public static Ethereum createEthereum() {
if (CONFIG.databaseReset()){
FileUtil.recursiveDelete(CONFIG.databaseDir());
logger.info("Database reset done");
}
return createEthereum(null);
}
public static Ethereum createEthereum(Class clazz) {
logger.info("capability eth version: [{}]", EthHandler.VERSION); logger.info("capability eth version: [{}]", EthHandler.VERSION);
logger.info("capability shh version: [{}]", ShhHandler.VERSION); logger.info("capability shh version: [{}]", ShhHandler.VERSION);

View File

@ -11,6 +11,8 @@ import org.hibernate.SessionFactory;
*/ */
public class RemoteConfig { public class RemoteConfig {
//@Autowired
CommonConfig commonConfig;
public BlockStore blockStore(SessionFactory sessionFactory){ public BlockStore blockStore(SessionFactory sessionFactory){

View File

@ -151,6 +151,7 @@ public interface Repository {
public Repository startTracking(); public Repository startTracking();
public void flush(); public void flush();
public void flushNoReconnect();
/** /**

View File

@ -71,7 +71,8 @@ public class TestProgramInvokeFactory implements ProgramInvokeFactory {
/*** CALLDATALOAD op ***/ /*** CALLDATALOAD op ***/
/*** CALLDATACOPY op ***/ /*** CALLDATACOPY op ***/
/*** CALLDATASIZE op ***/ /*** CALLDATASIZE op ***/
byte[] data = tx.getData() == null ? ByteUtil.EMPTY_BYTE_ARRAY : tx.getData(); byte[] data = tx.isContractCreation() ? ByteUtil.EMPTY_BYTE_ARRAY :( tx.getData() == null ? ByteUtil.EMPTY_BYTE_ARRAY : tx.getData() );
// byte[] data = tx.getData() == null ? ByteUtil.EMPTY_BYTE_ARRAY : tx.getData() ;
/*** PREVHASH op ***/ /*** PREVHASH op ***/
byte[] lastHash = env.getPreviousHash(); byte[] lastHash = env.getPreviousHash();

View File

@ -21,6 +21,8 @@ public class Utils {
data = data.substring(2); data = data.substring(2);
if (data.equals("")) return EMPTY_BYTE_ARRAY; if (data.equals("")) return EMPTY_BYTE_ARRAY;
if (data.length() % 2 == 1) data = "0" + data;
return Hex.decode(data); return Hex.decode(data);
} }

View File

@ -36,7 +36,7 @@ public class RepositoryBuilder {
RepositoryImpl repositoryDummy = new RepositoryImpl(new HashMapDB(), new HashMapDB()); RepositoryImpl repositoryDummy = new RepositoryImpl(new HashMapDB(), new HashMapDB());
repositoryDummy.updateBatch(stateBatch, detailsBatch); repositoryDummy.updateBatch(stateBatch, detailsBatch);
repositoryDummy.flush(); repositoryDummy.flushNoReconnect();
return repositoryDummy; return repositoryDummy;
} }

View File

@ -63,7 +63,7 @@ public class StateTestRunner {
} }
track.commit(); track.commit();
repository.flush(); repository.flushNoReconnect();
List<LogInfo> origLogs = executor.getResult().getLogInfoList(); List<LogInfo> origLogs = executor.getResult().getLogInfoList();
List<LogInfo> postLogs = LogBuilder.build(stateTestCase2.getLogs()); List<LogInfo> postLogs = LogBuilder.build(stateTestCase2.getLogs());

View File

@ -1,13 +1,11 @@
package org.ethereum.net.p2p; package org.ethereum.net.p2p;
import com.google.common.base.Joiner;
import org.ethereum.net.client.Capability; import org.ethereum.net.client.Capability;
import org.ethereum.util.ByteUtil; import org.ethereum.util.ByteUtil;
import org.ethereum.util.RLP; import org.ethereum.util.RLP;
import org.ethereum.util.RLPElement; import org.ethereum.util.RLPElement;
import org.ethereum.util.RLPList; import org.ethereum.util.RLPList;
import com.google.common.base.Joiner;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList; import java.util.ArrayList;
@ -64,33 +62,28 @@ public class HelloMessage extends P2pMessage {
byte[] p2pVersionBytes = paramsList.get(0).getRLPData(); byte[] p2pVersionBytes = paramsList.get(0).getRLPData();
this.p2pVersion = p2pVersionBytes != null ? p2pVersionBytes[0] : 0; this.p2pVersion = p2pVersionBytes != null ? p2pVersionBytes[0] : 0;
try { byte[] clientIdBytes = paramsList.get(1).getRLPData();
byte[] clientIdBytes = paramsList.get(1).getRLPData(); this.clientId = new String(clientIdBytes != null ? clientIdBytes : EMPTY_BYTE_ARRAY);
this.clientId = new String(clientIdBytes != null ? clientIdBytes : EMPTY_BYTE_ARRAY);
RLPList capabilityList = (RLPList) paramsList.get(2); RLPList capabilityList = (RLPList) paramsList.get(2);
this.capabilities = new ArrayList<>(); this.capabilities = new ArrayList<>();
for (Object aCapabilityList : capabilityList) { for (Object aCapabilityList : capabilityList) {
RLPElement capId = ((RLPList) aCapabilityList).get(0); RLPElement capId = ((RLPList) aCapabilityList).get(0);
RLPElement capVersion = ((RLPList) aCapabilityList).get(1); RLPElement capVersion = ((RLPList) aCapabilityList).get(1);
String name = new String(capId.getRLPData()); String name = new String(capId.getRLPData());
byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0]; byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0];
Capability cap = new Capability(name, version); Capability cap = new Capability(name, version);
this.capabilities.add(cap); this.capabilities.add(cap);
}
byte[] peerPortBytes = paramsList.get(3).getRLPData();
this.listenPort = ByteUtil.byteArrayToInt(peerPortBytes);
byte[] peerIdBytes = paramsList.get(4).getRLPData();
this.peerId = Hex.toHexString(peerIdBytes);
}
catch ( Exception e ) {
System.out.println(e.getMessage());
} }
byte[] peerPortBytes = paramsList.get(3).getRLPData();
this.listenPort = ByteUtil.byteArrayToInt(peerPortBytes);
byte[] peerIdBytes = paramsList.get(4).getRLPData();
this.peerId = Hex.toHexString(peerIdBytes);
this.parsed = true; this.parsed = true;
} }
@ -102,7 +95,7 @@ public class HelloMessage extends P2pMessage {
Capability capability = this.capabilities.get(i); Capability capability = this.capabilities.get(i);
capabilities[i] = RLP.encodeList( capabilities[i] = RLP.encodeList(
RLP.encodeElement(capability.getName().getBytes()), RLP.encodeElement(capability.getName().getBytes()),
RLP.encodeElement(new byte[]{capability.getVersion()})); RLP.encodeInt(capability.getVersion()));
} }
byte[] capabilityList = RLP.encodeList(capabilities); byte[] capabilityList = RLP.encodeList(capabilities);
byte[] peerPort = RLP.encodeInt(this.listenPort); byte[] peerPort = RLP.encodeInt(this.listenPort);

View File

@ -759,7 +759,7 @@ public class RLP {
if (isNullOrZeroArray(srcData)) if (isNullOrZeroArray(srcData))
return new byte[]{(byte) OFFSET_SHORT_ITEM}; return new byte[]{(byte) OFFSET_SHORT_ITEM};
else if (isSingleZero(srcData)) else if (isSingleZero(srcData))
return new byte[]{00}; return srcData;
else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) {
return srcData; return srcData;
} else if (srcData.length < SIZE_THRESHOLD) { } else if (srcData.length < SIZE_THRESHOLD) {

View File

@ -488,7 +488,7 @@ public class Program {
} }
if (result != null && if (result != null &&
result.getException() != null) { result.getException() != null) {
gasLogger.debug("contract run halted by Exception: contract: [{}], exception: [{}]", gasLogger.debug("contract run halted by Exception: contract: [{}], exception: [{}]",
Hex.toHexString(contextAddress), Hex.toHexString(contextAddress),
result.getException()); result.getException());

View File

@ -29,8 +29,6 @@ public interface ProgramInvoke {
public byte[] getDataCopy(DataWord offsetData, DataWord lengthData); public byte[] getDataCopy(DataWord offsetData, DataWord lengthData);
public int countNonZeroData();
public DataWord getPrevHash(); public DataWord getPrevHash();
public DataWord getCoinbase(); public DataWord getCoinbase();

View File

@ -66,7 +66,7 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
/*** CALLDATALOAD op ***/ /*** CALLDATALOAD op ***/
/*** CALLDATACOPY op ***/ /*** CALLDATACOPY op ***/
/*** CALLDATASIZE op ***/ /*** CALLDATASIZE op ***/
byte[] data = tx.getData() == null ? ByteUtil.EMPTY_BYTE_ARRAY : tx.getData(); byte[] data = tx.isContractCreation() ? ByteUtil.EMPTY_BYTE_ARRAY :( tx.getData() == null ? ByteUtil.EMPTY_BYTE_ARRAY : tx.getData() );
/*** PREVHASH op ***/ /*** PREVHASH op ***/
byte[] lastHash = lastBlock.getHash(); byte[] lastHash = lastBlock.getHash();

View File

@ -194,17 +194,6 @@ public class ProgramInvokeImpl implements ProgramInvoke {
} }
@Override
public int countNonZeroData() {
int counter = 0;
for (byte aMsgData : msgData) {
if (aMsgData != 0) ++counter;
}
return counter;
}
/* PREVHASH op */ /* PREVHASH op */
public DataWord getPrevHash() { public DataWord getPrevHash() {
return prevHash; return prevHash;

View File

@ -157,18 +157,6 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return new DataWord(prevHash); return new DataWord(prevHash);
} }
@Override
public int countNonZeroData() {
int counter = 0;
for (byte aMsgData : msgData) {
if (aMsgData != 0) ++counter;
}
return counter;
}
@Override @Override
public DataWord getCoinbase() { public DataWord getCoinbase() {
byte[] coinBase = Hex.decode("E559DE5527492BCB42EC68D07DF0742A98EC3F1E"); byte[] coinBase = Hex.decode("E559DE5527492BCB42EC68D07DF0742A98EC3F1E");

View File

@ -119,6 +119,12 @@ public class Storage implements Repository, ProgramTraceListenerAware {
repository.flush(); repository.flush();
} }
@Override
public void flushNoReconnect() {
throw new UnsupportedOperationException();
}
@Override @Override
public void commit() { public void commit() {
repository.commit(); repository.commit();

View File

@ -182,11 +182,11 @@ public class VM {
//check to see if account does not exist and is not a precompiled contract //check to see if account does not exist and is not a precompiled contract
if (op != CALLCODE && !program.result.getRepository().isExist(callAddressWord.getLast20Bytes())) if (op != CALLCODE && !program.result.getRepository().isExist(callAddressWord.getLast20Bytes()))
gasCost += GasCost.NEW_ACCT_CALL; gasCost += GasCost.NEW_ACCT_CALL;
//TODO #POC9 Make sure this is converted to BigInteger (256num support) //TODO #POC9 Make sure this is converted to BigInteger (256num support)
if (!stack.get(stack.size() - 3).isZero() ) if (!stack.get(stack.size() - 3).isZero() )
gasCost += GasCost.VT_CALL; gasCost += GasCost.VT_CALL;
BigInteger in = memNeeded(stack.get(stack.size() - 4), stack.get(stack.size() - 5)); // in offset+size BigInteger in = memNeeded(stack.get(stack.size() - 4), stack.get(stack.size() - 5)); // in offset+size
BigInteger out = memNeeded(stack.get(stack.size() - 6), stack.get(stack.size() - 7)); // out offset+size BigInteger out = memNeeded(stack.get(stack.size() - 6), stack.get(stack.size() - 7)); // out offset+size
@ -240,7 +240,7 @@ public class VM {
long memWordsOld = (oldMemSize / 32); long memWordsOld = (oldMemSize / 32);
//TODO #POC9 c_quadCoeffDiv = 512, this should be a constant, not magic number //TODO #POC9 c_quadCoeffDiv = 512, this should be a constant, not magic number
long memGas = ( GasCost.MEMORY * memWords + memWords * memWords / 512) long memGas = ( GasCost.MEMORY * memWords + memWords * memWords / 512)
- (GasCost.MEMORY * memWordsOld + memWordsOld * memWordsOld / 512); - (GasCost.MEMORY * memWordsOld + memWordsOld * memWordsOld / 512);
program.spendGas(memGas, op.name() + " (memory usage)"); program.spendGas(memGas, op.name() + " (memory usage)");
gasCost += memGas; gasCost += memGas;
} }
@ -1144,19 +1144,6 @@ public class VM {
public void play(Program program) { public void play(Program program) {
try { try {
// In case the program invoked by wire got
// transaction, this will be the gas cost,
// otherwise the call done by other contract
// charged by CALL op
if (program.invokeData.byTransaction()) {
program.spendGas(GasCost.TRANSACTION, "TRANSACTION");
int dataSize = program.invokeData.getDataSize().intValue();
int nonZeroesVals = program.invokeData.countNonZeroData();
int zeroVals = dataSize - nonZeroesVals;
program.spendGas(GasCost.TX_NO_ZERO_DATA * nonZeroesVals, "DATA");
program.spendGas(GasCost.TX_ZERO_DATA * zeroVals, "DATA");
}
if (program.invokeData.byTestingSuite()) return; if (program.invokeData.byTestingSuite()) return;

View File

@ -1,9 +1,18 @@
package org.ethereum; package org.ethereum;
import org.ethereum.db.IndexedBlockStore;
import org.ethereum.vm.DataWord; import org.ethereum.vm.DataWord;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Random; import java.util.Random;
import static org.ethereum.db.IndexedBlockStore.BLOCK_INFO_SERIALIZER;
public final class TestUtils { public final class TestUtils {
private TestUtils() { private TestUtils() {
@ -22,4 +31,30 @@ public final class TestUtils {
public static byte[] randomAddress() { public static byte[] randomAddress() {
return randomBytes(20); return randomBytes(20);
} }
public static Map<Long, List<IndexedBlockStore.BlockInfo>> createIndexMap(DB db){
Map<Long, List<IndexedBlockStore.BlockInfo>> index = db.hashMapCreate("index")
.keySerializer(Serializer.LONG)
.valueSerializer(BLOCK_INFO_SERIALIZER)
.makeOrGet();
return index;
}
public static DB createMapDB(String testDBDir){
String blocksIndexFile = testDBDir + "/blocks/index";
File dbFile = new File(blocksIndexFile);
if (!dbFile.getParentFile().exists()) dbFile.getParentFile().mkdirs();
DB db = DBMaker.fileDB(dbFile)
.transactionDisable()
.closeOnJvmShutdown()
.make();
return db;
}
} }

View File

@ -19,19 +19,22 @@ import static org.ethereum.jsontestsuite.JSONReader.getFileNamesForTreeSha;
public class GitHubStateTest { public class GitHubStateTest {
//SHACOMMIT of tested commit, ethereum/tests.git //SHACOMMIT of tested commit, ethereum/tests.git
public String shacommit = "baf4b8479c0b524560137d27e61d7e573dc4ab17"; public String shacommit = "cfae68e67aa922e08428c274d1ddbbc2741a975b";
@Ignore @Ignore
@Test // this method is mostly for hands-on convenient testing @Test // this method is mostly for hands-on convenient testing
public void stSingleTest() throws ParseException, IOException { public void stSingleTest() throws ParseException, IOException {
String json = JSONReader.loadJSONFromCommit("StateTests/stPreCompiledContracts.json", shacommit); // String shacommit = "cfae68e67aa922e08428c274d1ddbbc2741a975b";
GitHubJSONTestSuite.runStateTest(json, "CallEcrecover0_BonusGas");
String json = JSONReader.loadJSONFromCommit("StateTests/stCallCreateCallCodeTest.json", shacommit);
GitHubJSONTestSuite.runStateTest(json, "CallRecursiveBombPreCall");
} }
@Test @Test
public void stExample() throws ParseException, IOException { public void stExample() throws ParseException, IOException {
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("StateTests/stExample.json", shacommit); String json = JSONReader.loadJSONFromCommit("StateTests/stExample.json", shacommit);
GitHubJSONTestSuite.runStateTest(json, excluded); GitHubJSONTestSuite.runStateTest(json, excluded);
@ -39,6 +42,7 @@ public class GitHubStateTest {
@Test @Test
public void stCallCreateCallCodeTest() throws ParseException, IOException { public void stCallCreateCallCodeTest() throws ParseException, IOException {
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
excluded.add("createJS_ExampleContract"); //FIXME Bug on CPP testrunner, storage/SSTORE excluded.add("createJS_ExampleContract"); //FIXME Bug on CPP testrunner, storage/SSTORE
excluded.add("Callcode1024OOG"); excluded.add("Callcode1024OOG");
@ -46,7 +50,7 @@ public class GitHubStateTest {
excluded.add("callcodeWithHighValue"); excluded.add("callcodeWithHighValue");
excluded.add("callWithHighValue"); excluded.add("callWithHighValue");
excluded.add("Call1024PreCalls"); excluded.add("Call1024PreCalls");
excluded.add("CallRecursiveBombPreCall"); excluded.add("CallRecursiveBombPreCall"); // FIXME gas not BI limit
String json = JSONReader.loadJSONFromCommit("StateTests/stCallCreateCallCodeTest.json", shacommit); String json = JSONReader.loadJSONFromCommit("StateTests/stCallCreateCallCodeTest.json", shacommit);
GitHubJSONTestSuite.runStateTest(json, excluded); GitHubJSONTestSuite.runStateTest(json, excluded);
} }
@ -67,7 +71,7 @@ public class GitHubStateTest {
@Test @Test
public void stPreCompiledContracts() throws ParseException, IOException { public void stPreCompiledContracts() throws ParseException, IOException {
String shacommit = "baf4b8479c0b524560137d27e61d7e573dc4ab17";
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("StateTests/stPreCompiledContracts.json", shacommit); String json = JSONReader.loadJSONFromCommit("StateTests/stPreCompiledContracts.json", shacommit);
GitHubJSONTestSuite.runStateTest(json, excluded); GitHubJSONTestSuite.runStateTest(json, excluded);
@ -100,7 +104,6 @@ public class GitHubStateTest {
GitHubJSONTestSuite.runStateTest(json, excluded); GitHubJSONTestSuite.runStateTest(json, excluded);
} }
@Ignore
@Test @Test
public void stSolidityTest() throws ParseException, IOException { public void stSolidityTest() throws ParseException, IOException {
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
@ -126,11 +129,9 @@ public class GitHubStateTest {
@Test @Test
public void stSpecialTest() throws ParseException, IOException { public void stSpecialTest() throws ParseException, IOException {
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
excluded.add("txfrom0_deja"); // (!!!) FIXME fix them as soon as possible
excluded.add("JUMPDEST_AttackwithJump"); // (!!!) FIXME fix them as soon as possible excluded.add("JUMPDEST_AttackwithJump"); // (!!!) FIXME fix them as soon as possible
excluded.add("JUMPDEST_Attack"); // (!!!) FIXME fix them as soon as possible excluded.add("JUMPDEST_Attack"); // (!!!) FIXME fix them as soon as possible
String json = JSONReader.loadJSONFromCommit("StateTests/stSpecialTest.json", shacommit); String json = JSONReader.loadJSONFromCommit("StateTests/stSpecialTest.json", shacommit);
GitHubJSONTestSuite.runStateTest(json, excluded); GitHubJSONTestSuite.runStateTest(json, excluded);
} }
@ -141,7 +142,6 @@ public class GitHubStateTest {
GitHubJSONTestSuite.runStateTest(json); GitHubJSONTestSuite.runStateTest(json);
} }
//@Ignore
@Test @Test
public void stSystemOperationsTest() throws IOException { public void stSystemOperationsTest() throws IOException {
@ -155,6 +155,7 @@ public class GitHubStateTest {
@Test @Test
public void stTransactionTest() throws ParseException, IOException { public void stTransactionTest() throws ParseException, IOException {
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
excluded.add("OverflowGasRequire"); //FIXME wont work until we use gaslimit as long excluded.add("OverflowGasRequire"); //FIXME wont work until we use gaslimit as long
excluded.add("EmptyTransaction2"); // Buggy testcase excluded.add("EmptyTransaction2"); // Buggy testcase

View File

@ -5,6 +5,8 @@ import org.ethereum.crypto.HashUtil;
import com.cedarsoftware.util.DeepEquals; import com.cedarsoftware.util.DeepEquals;
import org.ethereum.db.ByteArrayWrapper; import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.net.client.Capability;
import org.ethereum.net.p2p.HelloMessage;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -1052,4 +1054,40 @@ public class RLPTest {
} }
@Test // capabilities: (eth:60, bzz:0, shh:2)
public void testEncodeHelloMessageCap0(){
List<Capability> capabilities = new ArrayList<>();
capabilities.add(new Capability("eth", (byte) 0x60));
capabilities.add(new Capability("shh", (byte) 0x02));
capabilities.add(new Capability("bzz", (byte) 0x00));
HelloMessage helloMessage = new HelloMessage((byte)4,
"Geth/v0.9.29-4182e20e/windows/go1.4.2",
capabilities , 30303,
"a52205ce10b39be86507e28f6c3dc08ab4c3e8250e062ec47c6b7fa13cf4a4312d68d6c340315ef953ada7e19d69123a1b902ea84ec00aa5386e5d550e6c550e");
byte[] rlp = helloMessage.getEncoded();
HelloMessage helloMessage_ = new HelloMessage(rlp);
String eth = helloMessage_.getCapabilities().get(0).getName();
byte eth_60 = helloMessage_.getCapabilities().get(0).getVersion();
assertEquals("eth", eth);
assertEquals(0x60, eth_60);
String shh = helloMessage_.getCapabilities().get(1).getName();
byte shh_02 = helloMessage_.getCapabilities().get(1).getVersion();
assertEquals("shh", shh);
assertEquals(0x02, shh_02);
String bzz = helloMessage_.getCapabilities().get(2).getName();
byte bzz_00 = helloMessage_.getCapabilities().get(2).getVersion();
assertEquals("bzz", bzz);
assertEquals(0x00, bzz_00);
}
} }