Merge branch 'android-test-poc9-rlpx' of opulence.git.beanstalkapp.com:/opulence/ethereumj into android-test-poc9-rlpx

This commit is contained in:
Jarrad Hope 2015-06-10 20:17:55 +02:00
commit 51430d9032
15 changed files with 939 additions and 424 deletions

View File

@ -1,118 +1,165 @@
package org.ethereum.android_app;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import org.ethereum.android.EthereumManager;
public class MainActivity extends ActionBarActivity {
private static final String TAG = "MyActivity";
private static Integer quit = 0;
private Toolbar toolbar;
private ViewPager viewPager;
private SlidingTabLayout tabs;
private TabsPagerAdapter adapter;
public EthereumManager ethereumManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
ethereumManager = new EthereumManager(this);
adapter = new TabsPagerAdapter(getSupportFragmentManager(), ethereumManager);
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);;
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true);
tabs.setViewPager(viewPager);
//StrictMode.enableDefaults();
new PostTask().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//return super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
Log.v(TAG, Integer.valueOf(id).toString());
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
// The definition of our task class
private class PostTask extends AsyncTask<Context, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(Context... params) {
Log.v(TAG, "111");
Log.v(TAG, "222");
ethereumManager.connect();
Log.v(TAG, "333");
while(true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (quit == 1) {
Log.v(TAG, "Ending background process.");
return "All Done!";
}
//publishProgress(1111);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.v(TAG, values[0].toString());
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}
package org.ethereum.android_app;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.os.Build;
import org.ethereum.android.EthereumManager;
public class MainActivity extends ActionBarActivity {
private static final String TAG = "MyActivity";
private static Integer quit = 0;
private Toolbar toolbar;
private ViewPager viewPager;
private SlidingTabLayout tabs;
private TabsPagerAdapter adapter;
public EthereumManager ethereumManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
ethereumManager = new EthereumManager(this);
adapter = new TabsPagerAdapter(getSupportFragmentManager(), ethereumManager);
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);;
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true);
tabs.setViewPager(viewPager);
//StrictMode.enableDefaults();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new PostTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
new PostTask().execute();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new JsonRpcTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
new JsonRpcTask().execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//return super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
Log.v(TAG, Integer.valueOf(id).toString());
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
super.onDestroy();
ethereumManager.onDestroy();
}
// The definition of our task class
private class PostTask extends AsyncTask<Context, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(Context... params) {
Log.v(TAG, "111");
Log.v(TAG, "222");
ethereumManager.connect();
Log.v(TAG, "333");
while(true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (quit == 1) {
Log.v(TAG, "Ending background process.");
return "All Done!";
}
//publishProgress(1111);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.v(TAG, values[0].toString());
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
// The definition of our task class
private class JsonRpcTask extends AsyncTask<Context, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(Context... params) {
Log.v(TAG, "444");
try {
ethereumManager.startJsonRpc();
} catch (Exception e) {
}
Log.v(TAG, "555");
return "done";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.v(TAG, values[0].toString());
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
}

View File

@ -1,60 +1,62 @@
apply plugin: 'com.android.library'
apply plugin: 'com.neenbedankt.android-apt'
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
repositories {
jcenter()
mavenCentral()
}
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
tasks.withType(JavaCompile){
options.warnings = false
}
dependencies {
apt 'com.google.dagger:dagger-compiler:2.0'
compile fileTree(dir: 'libs', include: ['*.jar'])
compile (project(':ethereumj-core')) {
exclude group: "org.apache.commons", module: "commons-pool2"
exclude group: "org.slf4j", module: "slf4j-log4j12"
exclude group: "org.hibernate", module: "hibernate-core"
exclude group: "org.hibernate", module: "hibernate-entitymanager"
exclude group: "redis.clients", module: "jedis"
exclude group: "org.antlr", module: "antlr4-runtime"
}
//compile "com.google.dagger:dagger:2.1-SNAPSHOT"
compile "com.j256.ormlite:ormlite-android:4.48"
compile "org.glassfish:javax.annotation:10.0-b28"
compile "org.iq80.leveldb:leveldb:0.7"
compile 'org.slf4j:slf4j-android:1.7.12'
compile 'javax.persistence:persistence-api:1.0.2'
}
apply plugin: 'com.android.library'
apply plugin: 'com.neenbedankt.android-apt'
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
repositories {
jcenter()
mavenCentral()
}
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
tasks.withType(JavaCompile){
options.warnings = false
}
dependencies {
apt 'com.google.dagger:dagger-compiler:2.0'
compile fileTree(dir: 'libs', include: ['*.jar'])
compile (project(':ethereumj-core')) {
exclude group: "org.apache.commons", module: "commons-pool2"
exclude group: "org.slf4j", module: "slf4j-log4j12"
exclude group: "org.hibernate", module: "hibernate-core"
exclude group: "org.hibernate", module: "hibernate-entitymanager"
exclude group: "redis.clients", module: "jedis"
exclude group: "org.antlr", module: "antlr4-runtime"
}
//compile "com.google.dagger:dagger:2.1-SNAPSHOT"
compile "com.j256.ormlite:ormlite-android:4.48"
compile "org.glassfish:javax.annotation:10.0-b28"
compile "org.iq80.leveldb:leveldb:0.7"
compile 'org.slf4j:slf4j-android:1.7.12'
compile 'javax.persistence:persistence-api:1.0.2'
compile group: 'com.thetransactioncompany', name: 'jsonrpc2-server', version: '1.11'
}

View File

@ -1,50 +1,66 @@
package org.ethereum.android;
import android.content.Context;
import org.ethereum.android.di.modules.EthereumModule;
import org.ethereum.android.di.components.DaggerEthereumComponent;
import org.ethereum.config.SystemProperties;
import org.ethereum.facade.Ethereum;
import org.ethereum.listener.EthereumListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EthereumManager {
private static final Logger logger = LoggerFactory.getLogger("manager");
public static Ethereum ethereum = null;
public EthereumManager(Context context) {
System.setProperty("sun.arch.data.model", "32");
System.setProperty("leveldb.mmap", "false");
ethereum = DaggerEthereumComponent.builder()
.ethereumModule(new EthereumModule(context))
.build().ethereum();
}
public void start() {
}
public void connect() {
ethereum.connect(SystemProperties.CONFIG.activePeerIP(),
SystemProperties.CONFIG.activePeerPort(),
SystemProperties.CONFIG.activePeerNodeid());
//ethereum.getBlockchain();
}
public void startPeerDiscovery() {
ethereum.startPeerDiscovery();
}
public void addListener(EthereumListenerAdapter listener) {
ethereum.addListener(listener);
}
}
package org.ethereum.android;
import android.content.Context;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import org.ethereum.android.di.modules.EthereumModule;
import org.ethereum.android.di.components.DaggerEthereumComponent;
import org.ethereum.config.SystemProperties;
import org.ethereum.facade.Ethereum;
import org.ethereum.listener.EthereumListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ethereum.android.jsonrpc.JsonRpcServer;
public class EthereumManager {
private static final Logger logger = LoggerFactory.getLogger("manager");
public static Ethereum ethereum = null;
private JsonRpcServer jsonRpcServer;
public EthereumManager(Context context) {
System.setProperty("sun.arch.data.model", "32");
System.setProperty("leveldb.mmap", "false");
ethereum = DaggerEthereumComponent.builder()
.ethereumModule(new EthereumModule(context))
.build().ethereum();
jsonRpcServer = new JsonRpcServer(ethereum);
}
public void start() {
}
public void connect() {
ethereum.connect(SystemProperties.CONFIG.activePeerIP(),
SystemProperties.CONFIG.activePeerPort(),
SystemProperties.CONFIG.activePeerNodeid());
//ethereum.getBlockchain();
}
public void startPeerDiscovery() {
ethereum.startPeerDiscovery();
}
public void addListener(EthereumListenerAdapter listener) {
ethereum.addListener(listener);
}
public void startJsonRpc() throws Exception {
jsonRpcServer.start();
}
public void onDestroy() {
OpenHelperManager.releaseHelper();
}
}

View File

@ -1,84 +0,0 @@
package org.ethereum.android.db;
import java.sql.SQLException;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.ethereum.db.BlockVO;
/**
* Database helper class used to manage the creation and upgrading of your database. This class also usually provides
* the DAOs used by the other classes.
*/
public class BlockDatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "blocks.db";
private static final int DATABASE_VERSION = 1;
// the DAO object we use to access the SimpleData table
private Dao<BlockVO, Integer> blockDao = null;
public BlockDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should call createTable statements here to create
* the tables that will store your data.
*/
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, BlockVO.class);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher version number. This allows you to adjust
* the various data to match the new version number.
*/
@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, BlockVO.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached
* value.
*/
public Dao<BlockVO, Integer> getBlockDao() throws SQLException {
if (blockDao == null) {
blockDao = getDao(BlockVO.class);
}
return blockDao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
blockDao = null;
}
}

View File

@ -0,0 +1,34 @@
package org.ethereum.android.db;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import java.math.BigInteger;
import java.util.List;
public interface BlockStoreDatabase {
public List<BlockVO> getByNumber(Long number);
public List<BlockVO> getByHash(byte[] hash);
public List<byte[]> getHashListByNumberLimit(Long from, Long to);
public void deleteBlocksSince(long number);
public void save(BlockVO block);
public BigInteger getTotalDifficultySince(long number);
public BigInteger getTotalDifficulty();
public Block getBestBlock();
public List<Block> getAllBlocks();
public void reset();
public void save(TransactionReceiptVO transactionReceiptVO);
public TransactionReceipt getTransactionReceiptByHash(byte[] hash);
}

View File

@ -6,17 +6,16 @@ import org.ethereum.db.BlockStore;
import org.ethereum.util.ByteUtil;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class BlockStoreImpl implements BlockStore {
private BlockDatabaseHelper blockDao;
private TransactionDatabaseHelper transactionDao;
private BlockStoreDatabase database;
public BlockStoreImpl(BlockDatabaseHelper blockDao, TransactionDatabaseHelper transactionDao) {
public BlockStoreImpl(BlockStoreDatabase database) {
this.blockDao = blockDao;
this.transactionDao = transactionDao;
this.database = database;
}
public byte[] getBlockHashByNumber(long blockNumber) {
@ -29,65 +28,86 @@ public class BlockStoreImpl implements BlockStore {
public Block getBlockByNumber(long blockNumber) {
/*
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number").
setParameter("number", blockNumber).list();
List result = database.getByNumber(blockNumber);
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
public Block getBlockByHash(byte[] hash) {
List result = database.getByHash(hash);
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
*/
return null;
}
public Block getBlockByHash(byte[] hash) {
return null;
}
@SuppressWarnings("unchecked")
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
return null;
List<byte[]> hashes = new ArrayList<byte[]>();
// find block number of that block hash
Block block = getBlockByHash(hash);
if (block == null) return hashes;
hashes = database.getHashListByNumberLimit(block.getNumber(), block.getNumber() - qty);
return hashes;
}
public void deleteBlocksSince(long number) {
database.deleteBlocksSince(number);
}
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
block.getEncoded(), block.getCumulativeDifficulty());
for (TransactionReceipt receipt : receipts) {
byte[] hash = receipt.getTransaction().getHash();
byte[] rlp = receipt.getEncoded();
TransactionReceiptVO transactionReceiptVO = new TransactionReceiptVO(hash, rlp);
database.save(transactionReceiptVO);
}
database.save(blockVO);
}
public BigInteger getTotalDifficultySince(long number) {
return null;
return database.getTotalDifficultySince(number);
}
public BigInteger getTotalDifficulty() {
return null;
return database.getTotalDifficulty();
}
public Block getBestBlock() {
return null;
return database.getBestBlock();
}
@SuppressWarnings("unchecked")
public List<Block> getAllBlocks() {
return null;
return database.getAllBlocks();
}
public void reset() {
database.reset();
}
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
return null;
return database.getTransactionReceiptByHash(hash);
}
}

View File

@ -0,0 +1,66 @@
package org.ethereum.android.db;
import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import java.math.BigInteger;
@DatabaseTable(tableName = "block")
public class BlockVO {
@DatabaseField(index = true, dataType = DataType.BYTE_ARRAY)
byte[] hash;
@DatabaseField(index = true, dataType = DataType.LONG_OBJ)
Long number;
@DatabaseField(columnName = "cumulativedifficulty", dataType = DataType.BIG_INTEGER)
BigInteger cumulativeDifficulty;
@DatabaseField(dataType = DataType.BYTE_ARRAY)
byte[] rlp;
public BlockVO() {
}
public BlockVO(Long number, byte[] hash, byte[] rlp, BigInteger cumulativeDifficulty) {
this.number = number;
this.hash = hash;
this.rlp = rlp;
this.cumulativeDifficulty = cumulativeDifficulty;
}
public byte[] getHash() {
return hash;
}
public void setHash(byte[] hash) {
this.hash = hash;
}
public Long getIndex() {
return number;
}
public void setIndex(Long number) {
this.number = number;
}
public byte[] getRlp() {
return rlp;
}
public void setRlp(byte[] rlp) {
this.rlp = rlp;
}
public BigInteger getCumulativeDifficulty() {
return cumulativeDifficulty;
}
public void setCumulativeDifficulty(BigInteger cumulativeDifficulty) {
this.cumulativeDifficulty = cumulativeDifficulty;
}
}

View File

@ -0,0 +1,255 @@
package org.ethereum.android.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.GenericRawResults;
import com.j256.ormlite.stmt.DeleteBuilder;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import java.math.BigInteger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class OrmLiteBlockStoreDatabase extends OrmLiteSqliteOpenHelper implements BlockStoreDatabase {
private static final String DATABASE_NAME = "blockchain.db";
private static final int DATABASE_VERSION = 1;
private Dao<BlockVO, Integer> blockDao = null;
private Dao<TransactionReceiptVO, Integer> transactionDao = null;
public OrmLiteBlockStoreDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should call createTable statements here to create
* the tables that will store your data.
*/
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(OrmLiteBlockStoreDatabase.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, BlockVO.class);
TableUtils.createTable(connectionSource, TransactionReceiptVO.class);
} catch (SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher version number. This allows you to adjust
* the various data to match the new version number.
*/
@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(OrmLiteBlockStoreDatabase.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, BlockVO.class, true);
TableUtils.dropTable(connectionSource, TransactionReceiptVO.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached
* value.
*/
public Dao<BlockVO, Integer> getBlockDao() throws SQLException {
if (blockDao == null) {
blockDao = getDao(BlockVO.class);
}
return blockDao;
}
/**
* Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached
* value.
*/
public Dao<TransactionReceiptVO, Integer> getTransactionDao() throws SQLException {
if (transactionDao == null) {
transactionDao = getDao(TransactionReceiptVO.class);
}
return transactionDao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
blockDao = null;
transactionDao = null;
}
public List<BlockVO> getByNumber(Long number) {
List<BlockVO> list = new ArrayList<BlockVO>();
try {
list = getBlockDao().queryForEq("number", number);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error querying for number", e);
}
return list;
}
public List<BlockVO> getByHash(byte[] hash) {
List<BlockVO> list = new ArrayList<BlockVO>();
try {
list = getBlockDao().queryForEq("hash", hash);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error querying for hash", e);
}
return list;
}
public List<byte[]> getHashListByNumberLimit(Long from, Long to) {
List<byte[]> results = new ArrayList<byte[]>();
try {
List<BlockVO> list = new ArrayList<BlockVO>();
list = getBlockDao().queryBuilder().orderBy("number", false).limit(to - from).where().between("number", from, to).query();
for (BlockVO block : list) {
results.add(block.hash);
}
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error querying for hash list", e);
}
return results;
}
public void deleteBlocksSince(long number) {
try {
DeleteBuilder<BlockVO, Integer> deleteBuilder = getBlockDao().deleteBuilder();
deleteBuilder.where().gt("number", number);
deleteBuilder.delete();
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error deleting blocks since", e);
}
}
public void save(BlockVO block) {
try {
getBlockDao().create(block);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error saving block", e);
}
}
public BigInteger getTotalDifficultySince(long number) {
try {
GenericRawResults<String[]> rawResults = getBlockDao().queryRaw("select sum(cumulativedifficulty) from block where number > " + number);
List<String[]> results = rawResults.getResults();
return new BigInteger(results.get(0)[0]);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error getting total difficulty since", e);
}
return null;
}
public BigInteger getTotalDifficulty() {
try {
GenericRawResults<String[]> rawResults = getBlockDao().queryRaw("select sum(cumulativedifficulty) from block");
List<String[]> results = rawResults.getResults();
return new BigInteger(results.get(0)[0]);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error getting total difficulty", e);
}
return null;
}
public Block getBestBlock() {
Long bestNumber = null;
try {
GenericRawResults<String[]> rawResults = getBlockDao().queryRaw("select max(number) from block");
List<String[]> results = rawResults.getResults();
if (results.size() > 0 && results.get(0).length > 0) {
bestNumber = Long.valueOf(results.get(0)[0]);
}
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Sql Error getting best block", e);
} catch (Exception e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error getting best block", e);
}
if (bestNumber == null) return null;
List result = getByNumber(bestNumber);
if (result.isEmpty()) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
public List<Block> getAllBlocks() {
ArrayList<Block> blocks = new ArrayList<>();
try {
for (BlockVO blockVO : getBlockDao()) {
blocks.add(new Block(blockVO.getRlp()));
}
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error getting all blocks", e);
}
return blocks;
}
public void reset() {
deleteBlocksSince(Long.valueOf(0));
}
public void save(TransactionReceiptVO transactionReceiptVO) {
try {
getTransactionDao().create(transactionReceiptVO);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error saving transaction", e);
}
}
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
List<TransactionReceiptVO> list = new ArrayList<TransactionReceiptVO>();
try {
list = getTransactionDao().queryForEq("hash", hash);
} catch(java.sql.SQLException e) {
Log.e(OrmLiteBlockStoreDatabase.class.getName(), "Error querying for hash", e);
}
if (list.size() == 0) return null;
TransactionReceiptVO vo = list.get(0);
return new TransactionReceipt(vo.rlp);
}
}

View File

@ -1,84 +0,0 @@
package org.ethereum.android.db;
import java.sql.SQLException;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.ethereum.db.TransactionReceiptVO;
/**
* Database helper class used to manage the creation and upgrading of your database. This class also usually provides
* the DAOs used by the other classes.
*/
public class TransactionDatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "transactions.db";
private static final int DATABASE_VERSION = 1;
// the DAO object we use to access the SimpleData table
private Dao<TransactionReceiptVO, Integer> dao = null;
public TransactionDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should call createTable statements here to create
* the tables that will store your data.
*/
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, TransactionReceiptVO.class);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher version number. This allows you to adjust
* the various data to match the new version number.
*/
@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TransactionReceiptVO.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached
* value.
*/
public Dao<TransactionReceiptVO, Integer> getBlockDao() throws SQLException {
if (dao == null) {
dao = getDao(TransactionReceiptVO.class);
}
return dao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
dao = null;
}
}

View File

@ -0,0 +1,49 @@
package org.ethereum.android.db;
import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
/**
* @author Roman Mandeleil
* @since 14.11.2014
*/
@DatabaseTable(tableName = "transaction_receipt")
public class TransactionReceiptVO {
@DatabaseField(index = true, dataType = DataType.BYTE_ARRAY)
byte[] hash;
@DatabaseField(dataType = DataType.BYTE_ARRAY)
byte[] rlp;
public TransactionReceiptVO() {
}
public TransactionReceiptVO(byte[] hash, byte[] rlp) {
this.hash = hash;
this.rlp = rlp;
}
public byte[] getHash() {
return hash;
}
public void setHash(byte[] hash) {
this.hash = hash;
}
public byte[] getRlp() {
return rlp;
}
public void setRlp(byte[] rlp) {
this.rlp = rlp;
}
}

View File

@ -2,12 +2,15 @@ package org.ethereum.android.di.modules;
import android.content.Context;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import org.ethereum.android.datasource.LevelDbDataSource;
import org.ethereum.android.db.OrmLiteBlockStoreDatabase;
import org.ethereum.android.db.BlockStoreImpl;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.BlockchainImpl;
import org.ethereum.core.Wallet;
import org.ethereum.db.BlockStore;
import org.ethereum.db.InMemoryBlockStore;
import org.ethereum.db.RepositoryImpl;
import org.ethereum.facade.Blockchain;
import org.ethereum.facade.Ethereum;
@ -72,7 +75,8 @@ public class EthereumModule {
@Provides
@Singleton
BlockStore provideBlockStore() {
return new InMemoryBlockStore();
OrmLiteBlockStoreDatabase database = OpenHelperManager.getHelper(context, OrmLiteBlockStoreDatabase.class);
return new BlockStoreImpl(database);
}
@Provides

View File

@ -0,0 +1,159 @@
package org.ethereum.android.jsonrpc;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.HttpObject;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.channel.ChannelFuture;
import org.ethereum.facade.Ethereum;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import io.netty.handler.codec.http.HttpHeaders;
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
import org.ethereum.android.jsonrpc.method.*;
public final class JsonRpcServer {
static final int PORT = 8545;
private Ethereum ethereum;
private Dispatcher dispatcher;
public JsonRpcServer(Ethereum ethereum) {
this.ethereum = ethereum;
this.dispatcher = new Dispatcher();
this.dispatcher.register(new eth_coinbase(this.ethereum));
}
public void start() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
// b.localAddress(InetAddress.getLocalHost(), PORT);
b.localAddress(PORT);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new JsonRpcServerInitializer());
Channel ch = b.bind().sync().channel();
ch.closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
class JsonRpcServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec());
p.addLast(new JsonRpcServerHandler());
}
}
class JsonRpcServerHandler extends SimpleChannelInboundHandler<HttpObject> {
private HttpRequest request;
private final StringBuilder responseContent = new StringBuilder();
private HttpPostStandardRequestDecoder decoder;
private String postData;
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (decoder != null) {
decoder.destroy();
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest req = this.request = (HttpRequest) msg;
if (!req.getUri().equals("/") || !request.getMethod().equals(HttpMethod.POST)) {
responseContent.append("Hi, how are you?!!");
return;
} else {
decoder = new HttpPostStandardRequestDecoder(new DefaultHttpDataFactory(false), req);
postData = "";
}
}
if (decoder != null) {
if (msg instanceof HttpContent) {
HttpContent chunk = (HttpContent) msg;
decoder.offer(chunk);
postData += chunk.content().toString(0, chunk.content().capacity(), CharsetUtil.UTF_8);
if (chunk instanceof LastHttpContent) {
JSONRPC2Request req = JSONRPC2Request.parse(postData);
JSONRPC2Response resp = dispatcher.process(req, null);
responseContent.append(resp);
writeResponse(ctx);
request = null;
decoder.destroy();
decoder = null;
}
}
} else {
writeResponse(ctx);
}
}
private void writeResponse(ChannelHandlerContext ctx) {
ByteBuf buf = Unpooled.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
responseContent.setLength(0);
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION))
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION));
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
if (!close) {
response.headers().set(CONTENT_LENGTH, buf.readableBytes());
}
ChannelFuture future = ctx.writeAndFlush(response);
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
}

View File

@ -0,0 +1,29 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.facade.Ethereum;
public class eth_coinbase implements RequestHandler {
private String name = "";
private Ethereum ethereum;
public eth_coinbase(Ethereum ethereum) {
this.ethereum = ethereum;
name = this.getClass().getSimpleName();
}
public String[] handledRequests() {
return new String[]{name};
}
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals(name)) {
//TODO: place business logic here
return null;
} else {
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}

View File

@ -100,7 +100,7 @@ test {
logger.lifecycle("Running test: ${descriptor}")
}
jvmArgs '-Xss32m'
jvmArgs += [ "-Xss32m", "-XX:MaxPermSize=256m" ]
testLogging {
events "failed"

View File

@ -15,4 +15,6 @@
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# org.gradle.parallel=true
org.gradle.jvmargs=-XX:MaxPermSize=512m