add JOSN-RPC methods.

many of them have questions to Roman, shh_ method must wait till Roman finish create whisper protocol.
Will try to schedule online meeting with Roman today to get answers / advice.
This commit is contained in:
Yaroslav Dmytrotsa 2015-06-16 16:45:28 +03:00
parent 34d98c9ea3
commit 40b0749304
47 changed files with 2068 additions and 59 deletions

View File

@ -28,6 +28,7 @@ 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.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
@ -48,11 +49,14 @@ public final class JsonRpcServer {
this.ethereum = ethereum;
this.dispatcher = new Dispatcher();
this.dispatcher.register(new web3_clientVersion(this.ethereum));
this.dispatcher.register(new web3_sha3(this.ethereum));
this.dispatcher.register(new net_version(this.ethereum));
this.dispatcher.register(new net_listening(this.ethereum));
this.dispatcher.register(new net_peerCount(this.ethereum));
this.dispatcher.register(new eth_protocolVersion(this.ethereum));
this.dispatcher.register(new eth_coinbase(this.ethereum));
this.dispatcher.register(new eth_mining(this.ethereum));
@ -70,6 +74,47 @@ public final class JsonRpcServer {
this.dispatcher.register(new eth_getCode(this.ethereum));
this.dispatcher.register(new eth_sign(this.ethereum));
this.dispatcher.register(new eth_sendTransaction(this.ethereum));
this.dispatcher.register(new eth_call(this.ethereum));
this.dispatcher.register(new eth_estimateGas(this.ethereum));
this.dispatcher.register(new eth_getBlockByHash(this.ethereum));
this.dispatcher.register(new eth_getBlockByNumber(this.ethereum));
this.dispatcher.register(new eth_getTransactionByHash(this.ethereum));
this.dispatcher.register(new eth_getTransactionByBlockHashAndIndex(this.ethereum));
this.dispatcher.register(new eth_getTransactionByBlockNumberAndIndex(this.ethereum));
this.dispatcher.register(new eth_getUncleByBlockHashAndIndex(this.ethereum));
this.dispatcher.register(new eth_getUncleByBlockNumberAndIndex(this.ethereum));
this.dispatcher.register(new eth_getCompilers(this.ethereum));
this.dispatcher.register(new eth_compileSolidity(this.ethereum));
this.dispatcher.register(new eth_compileLLL(this.ethereum));
this.dispatcher.register(new eth_compileSerpent(this.ethereum));
this.dispatcher.register(new eth_newFilter(this.ethereum));
this.dispatcher.register(new eth_newBlockFilter(this.ethereum));
this.dispatcher.register(new eth_newPendingTransactionFilter(this.ethereum));
this.dispatcher.register(new eth_uninstallFilter(this.ethereum));
this.dispatcher.register(new eth_getFilterChanges(this.ethereum));
this.dispatcher.register(new eth_getFilterLogs(this.ethereum));
this.dispatcher.register(new eth_getLogs(this.ethereum));
this.dispatcher.register(new eth_getWork(this.ethereum));
this.dispatcher.register(new eth_submitWork(this.ethereum));
this.dispatcher.register(new db_putString(this.ethereum));
this.dispatcher.register(new db_getString(this.ethereum));
this.dispatcher.register(new db_putHex(this.ethereum));
this.dispatcher.register(new db_getHex(this.ethereum));
this.dispatcher.register(new shh_version(this.ethereum));
this.dispatcher.register(new shh_post(this.ethereum));
this.dispatcher.register(new shh_newIdentity(this.ethereum));
this.dispatcher.register(new shh_hasIdentity(this.ethereum));
this.dispatcher.register(new shh_newGroup(this.ethereum));
this.dispatcher.register(new shh_addToGroup(this.ethereum));
this.dispatcher.register(new shh_newFilter(this.ethereum));
this.dispatcher.register(new shh_uninstallFilter(this.ethereum));
this.dispatcher.register(new shh_getFilterChanges(this.ethereum));
this.dispatcher.register(new shh_getMessages(this.ethereum));
FilterManager.getInstance();
org.ethereum.android.jsonrpc.whisper.FilterManager.getInstance();
}
public void start() throws Exception {

View File

@ -3,11 +3,18 @@ package org.ethereum.android.jsonrpc;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServer;
import org.ethereum.core.Account;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.core.BlockHeader;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.HashUtil;
import org.ethereum.facade.Ethereum;
import org.ethereum.util.RLP;
import org.ethereum.vm.DataWord;
import org.spongycastle.util.encoders.Hex;
@ -15,6 +22,8 @@ import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import static org.ethereum.core.Denomination.SZABO;
public abstract class JsonRpcServerMethod implements RequestHandler {
private String name = "";
@ -74,4 +83,175 @@ public abstract class JsonRpcServerMethod implements RequestHandler {
protected BigInteger jsToBigInteger(String data) {
return new BigInteger(data.substring(2), 16);
}
protected Transaction jsToTransaction(JSONObject obj) throws Exception {
if ((!obj.containsKey("to") || ((String)obj.get("to")).equals("")) && (!obj.containsKey("data") || ((String)obj.get("data")).equals(""))) {
throw new Exception("");
}
byte[] from = ((Account) ethereum.getWallet().getAccountCollection().toArray()[1]).getEcKey().getAddress();
if (obj.containsKey("from") && !((String)obj.get("from")).equals("")) {
from = jsToAddress((String) obj.get("from"));
}
Account acc = null;
for (Account ac : ethereum.getWallet().getAccountCollection()) {
if (Arrays.equals(ac.getAddress(), from)) {
acc = ac;
break;
}
}
if (acc == null) {
throw new Exception("");
}
byte[] senderPrivKey = acc.getEcKey().getPrivKeyBytes();
// default - from ethereumj-studio
byte[] to = null;
if (obj.containsKey("to") && !((String)obj.get("to")).equals("")) {
to = jsToAddress((String) obj.get("to"));
}
// default - from ethereumj-studio
BigInteger gasPrice = SZABO.value().multiply(BigInteger.TEN);
if (obj.containsKey("gasPrice") && !((String)obj.get("gasPrice")).equals("")) {
gasPrice = jsToBigInteger((String) obj.get("gasPrice"));
}
// default - from cpp-ethereum
BigInteger gas = acc.getBalance().divide(gasPrice);
BigInteger gasBBRemaining = new BigInteger(Long.toString((ethereum.getBlockchain().getBestBlock().getGasLimit() - ethereum.getBlockchain().getBestBlock().getGasUsed()) / 5));
if (gasBBRemaining.compareTo(gas) < 0)
gas = gasBBRemaining;
if (obj.containsKey("gas") && !((String)obj.get("gas")).equals("")) {
gas = jsToBigInteger((String) obj.get("gas"));
}
// default - from ethereumj-studio
BigInteger value = new BigInteger("1000");
if (obj.containsKey("value") && !((String)obj.get("value")).equals("")) {
value = jsToBigInteger((String) obj.get("value"));
}
// default - from ethereumj-studio
BigInteger nonce = ethereum.getRepository().getNonce(acc.getAddress());
if (obj.containsKey("nonce") && !((String)obj.get("nonce")).equals("")) {
nonce = jsToBigInteger((String) obj.get("nonce"));
}
// default - from ethereumj-studio
byte[] data = new byte[]{};
if (obj.containsKey("data") && !((String)obj.get("data")).equals("")) {
data = jsToAddress((String) obj.get("data"));
}
Transaction tx = ethereum.createTransaction(nonce, gasPrice, gas, to, value, data);
tx.sign(senderPrivKey);
return tx;
}
protected JSONObject blockToJS (Block block, Boolean detailed) {
JSONObject res = new JSONObject();
if (block == null)
return null;
res.put("number", "0x" + Long.toHexString(block.getNumber()));
res.put("hash", "0x" + Hex.toHexString(block.getHash()));
res.put("parentHash", "0x" + Hex.toHexString(block.getParentHash()));
res.put("nonce", "0x" + Hex.toHexString(block.getNonce()));
res.put("sha3Uncles", "0x" + Hex.toHexString(block.getUnclesHash()));
res.put("logsBloom", "0x" + Hex.toHexString(block.getLogBloom()));
res.put("transactionsRoot", "0x" + Hex.toHexString(block.getHeader().getTxTrieRoot()));
res.put("stateRoot", "0x" + Hex.toHexString(block.getStateRoot()));
res.put("miner", "0x" + Hex.toHexString(block.getCoinbase()));
res.put("difficulty", "0x" + block.getDifficultyBI().toString(16));
res.put("totalDifficulty", "0x" + block.getCumulativeDifficulty().toString(16));
res.put("extraData", "0x" + Hex.toHexString(block.getExtraData()));
// No way to get size of block in bytes, so I try calculate it using formula from getEncoded
byte[] header = block.getHeader().getEncoded();
byte[] transactions = RLP.encodeList();
byte[][] unclesEncoded = new byte[block.getUncleList().size()][];
int i = 0;
for (BlockHeader uncle : block.getUncleList()) {
unclesEncoded[i] = uncle.getEncoded();
++i;
}
byte[] uncles = RLP.encodeList(unclesEncoded);
byte[] rlpEncoded = RLP.encodeList(header, transactions, uncles);
res.put("size", "0x" + Integer.toHexString(rlpEncoded.length));
res.put("gasLimit", "0x" + Long.toHexString(block.getGasLimit()));
res.put("gasUsed", "0x" + Long.toHexString(block.getGasUsed()));
res.put("timestamp", "0x" + Long.toHexString(block.getTimestamp()));
JSONArray transactionsJA = new JSONArray();
i = 0;
for (Transaction transaction : block.getTransactionsList()) {
if (detailed) {
JSONObject tx = transactionToJS(transaction);
tx.put("transactionIndex", "0x" + Integer.toHexString(i));
tx.put("blockHash", "0x" + Hex.toHexString(block.getHash()));
tx.put("blockNumber", "0x" + Long.toHexString(block.getNumber()));
transactionsJA.add(tx);
} else {
transactionsJA.add("0x" + Hex.toHexString(transaction.getHash()));
}
++i;
}
res.put("transactions", transactionsJA);
//TODO: ask if I correctly get uncle's hash (takes form -core right now)
JSONArray unclesJA = new JSONArray();
for (BlockHeader uncle : block.getUncleList()) {
unclesJA.add("0x" + Hex.toHexString(HashUtil.sha3(uncle.getEncoded())));
}
res.put("uncles", unclesJA);
return res;
}
protected JSONObject transactionToJS (Transaction transaction) {
JSONObject res = new JSONObject();
res.put("hash", "0x" + Hex.toHexString(transaction.getHash()));
res.put("nonce", "0x" + Hex.toHexString(transaction.getNonce()));
res.put("from", "0x" + Hex.toHexString(transaction.getSender()));
res.put("to", "0x" + Hex.toHexString(transaction.getReceiveAddress()));
res.put("value", "0x" + Hex.toHexString(transaction.getValue()));
res.put("gasPrice", "0x" + Hex.toHexString(transaction.getGasPrice()));
res.put("gas", "0x" + Hex.toHexString(transaction.getGasLimit()));
res.put("input", "0x" + Hex.toHexString(transaction.getData()));
/*
No way to get this data from inside of transaction.
TODO: Ask roman to include it into transaction class.
res.put("transactionIndex", "0x" + "");
res.put("blockHash", "0x" + "");
res.put("blockNumber", "0x" + "");
*/
return res;
}
}

View File

@ -0,0 +1,30 @@
package org.ethereum.android.jsonrpc.filter;
import net.minidev.json.JSONArray;
import org.ethereum.facade.Ethereum;
public abstract class FilterBase {
protected int id;
protected long lastRequest = System.currentTimeMillis();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public long getLastRequestTime() {
return lastRequest;
}
protected void updateLastRequest() {
lastRequest = System.currentTimeMillis();
}
public abstract void processEvent(Object data);
public abstract JSONArray toJS();
public abstract JSONArray toJS(Ethereum ethereum);
}

View File

@ -0,0 +1,38 @@
package org.ethereum.android.jsonrpc.filter;
import net.minidev.json.JSONArray;
import org.ethereum.core.Block;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
public class FilterBlock extends FilterBase {
private ArrayList<String> blocks = new ArrayList<String>();
public void processEvent(Object data) {
if (data instanceof Block) {
synchronized (blocks) {
blocks.add("0x" + Hex.toHexString(((Block) data).getHash()));
}
}
}
public JSONArray toJS() {
updateLastRequest();
JSONArray res = new JSONArray();
synchronized (blocks) {
for(String item : blocks) {
res.add(item);
}
blocks.clear();
}
return res;
}
public JSONArray toJS(Ethereum ethereum) {
return null;
}
}

View File

@ -0,0 +1,199 @@
package org.ethereum.android.jsonrpc.filter;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.facade.Ethereum;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.LogInfo;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
import java.util.Arrays;
/*
Right now LogInfo not contains information about Transaction and Transaction not have information about block.
TODO: talk to Roman about create links between LogInfo and Transaction and between Transaction and Block.
*/
public class FilterLog extends FilterBase {
private ArrayList<LogInfo> logs = new ArrayList<LogInfo>();
long blockFrom;
long blockTo;
ArrayList<byte[]> addresses = new ArrayList<>();
ArrayList<byte[]> topics = new ArrayList<>();
public FilterLog (Ethereum ethereum, JSONObject data) {
blockFrom = ethereum.getBlockchain().getBestBlock().getNumber();
if (data.containsKey("fromBlock") && !((String)data.get("fromBlock")).equals("")) {
String fromS = (String)data.get("fromBlock");
if (fromS.equals("latest")) {
} else if (fromS.equals("pending") || fromS.equals("earliest")) {
blockFrom = -1;
} else {
blockFrom = Long.parseLong(fromS.substring(2), 16);
}
}
blockTo = ethereum.getBlockchain().getBestBlock().getNumber();
if (data.containsKey("toBlock") && !((String)data.get("toBlock")).equals("")) {
String fromS = (String)data.get("toBlock");
if (fromS.equals("latest")) {
} else if (fromS.equals("pending") || fromS.equals("earliest")) {
blockTo = -1;
} else {
blockTo = Long.parseLong(fromS.substring(2), 16);
}
}
if (data.containsKey("address")) {
if (data.get("address") instanceof String) {
addresses.add(Hex.decode(((String) data.get("address")).substring(2)));
} else if (data.get("address") instanceof JSONArray){
for (Object item : (JSONArray)data.get("address")) {
if (item instanceof String) {
addresses.add(Hex.decode(((String) item).substring(2)));
}
}
}
}
if (data.containsKey("topics")) {
if (data.get("topics") instanceof String) {
topics.add(Hex.decode(((String) data.get("topics")).substring(2)));
} else if (data.get("topics") instanceof JSONArray){
for (Object item : (JSONArray)data.get("topics")) {
if (item instanceof String) {
topics.add(Hex.decode(((String) item).substring(2)));
}
}
}
}
}
/*
TODO: Right now Bloom from -core can be used only to check total mach of 2 same class objects. Will be nice to have possibility to check contains.
*/
public void processEvent(Object data) {
if (data instanceof LogInfo) {
synchronized (logs) {
LogInfo li = (LogInfo)data;
//TODO: check if li inside blockFrom - blockTo
if (checkLogInfo(li))
logs.add(li);
}
}
}
public JSONArray toJS() {
updateLastRequest();
JSONArray res = new JSONArray();
synchronized (logs) {
for(LogInfo item : logs) {
res.add(logInfoToJS(item));
}
logs.clear();
}
return res;
}
public JSONArray toJS(Ethereum ethereum) {
JSONArray res = new JSONArray();
// Process mined blocks
if (blockFrom >= 0) {
long i = blockFrom;
while (true) {
Block block = ethereum.getBlockchain().getBlockByNumber(i);
if (block == null)
break;
for (Transaction tx : block.getTransactionsList()) {
TransactionReceipt txr = ethereum.getBlockchain().getTransactionReceiptByHash(tx.getHash());
if (txr != null) {
for (LogInfo li : txr.getLogInfoList()) {
if (checkLogInfo(li))
res.add(logInfoToJS(li));
}
}
}
i++;
}
}
/*
Process pending transactions. But not sure if BlockChain can return TransactionReceipt for pending transaction.
*/
if (blockFrom < 0 || blockTo < 0) {
for (Transaction tx : ethereum.getPendingTransactions()) {
TransactionReceipt txr = ethereum.getBlockchain().getTransactionReceiptByHash(tx.getHash());
if (txr != null) {
for (LogInfo li : txr.getLogInfoList()) {
if (checkLogInfo(li))
res.add(logInfoToJS(li));
}
}
}
}
return res;
}
private boolean checkLogInfo(LogInfo li) {
boolean found = false;
for (byte[] address : addresses) {
if (Arrays.equals(address, li.getAddress())) {
found = true;
break;
}
}
if (!found)
return false;
found = false;
for (byte[] topic : topics) {
for (DataWord litopic : li.getTopics()) {
if (Arrays.equals(topic, litopic.getData())) {
found = true;
break;
}
}
if (found)
break;
}
if (!found)
return false;
return true;
}
private JSONObject logInfoToJS(LogInfo li) {
JSONObject res = new JSONObject();
/*
TODO: check here if log's transaction / block mined or pending.
*/
res.put("type", "pending");
res.put("logIndex", null);
res.put("transactionIndex", null);
res.put("transactionHash", null);
res.put("blockHash", null);
res.put("blockNumber", null);
res.put("address", Hex.toHexString(li.getAddress()));
res.put("data", Hex.toHexString(li.getData()));
JSONArray topics = new JSONArray();
for (DataWord topic : li.getTopics()) {
topics.add(Hex.toHexString(topic.getData()));
}
res.put("topics", topics);
return res;
}
}

View File

@ -0,0 +1,98 @@
package org.ethereum.android.jsonrpc.filter;
import net.minidev.json.JSONArray;
import org.ethereum.facade.Ethereum;
import java.util.Hashtable;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
/*
This class must receive notification from -core about new log, Block, Transaction. Right now I not see the way todo that.
TODO: ask advice from Roman about how to send notification to this class.
*/
public class FilterManager {
protected static FilterManager instance = null;
public static FilterManager getInstance() {
if (instance == null)
instance = new FilterManager();
return instance;
}
private Timer timer = null;
private long filterAutoUninstall = TimeUnit.MINUTES.toMillis(5);
protected Hashtable<Integer, FilterBase> filters;
protected int last_id = 0;
private FilterManager() {
filters = new Hashtable<Integer, FilterBase>();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
long now = System.currentTimeMillis();
synchronized (filters) {
for (Map.Entry<Integer, FilterBase> item : filters.entrySet()) {
if (now - item.getValue().getLastRequestTime() >= filterAutoUninstall) {
filters.remove(item.getKey());
}
}
}
}
}, TimeUnit.MINUTES.toMillis(1));
}
public void processEvent(Object data) {
synchronized (filters) {
for (Map.Entry<Integer, FilterBase> item : filters.entrySet()) {
item.getValue().processEvent(data);
}
}
}
public int addFilter(FilterBase filter) {
filter.setId(++last_id);
filters.put(filter.getId(), filter);
return filter.getId();
}
public FilterBase getFilter(int id) {
if (filters.containsKey(id)) {
return filters.get(id);
}
return null;
}
public boolean uninstallFilter(int id) {
synchronized (filters) {
if (!filters.containsKey(id))
return false;
filters.remove(id);
}
return true;
}
public JSONArray toJS(int id) {
synchronized (filters) {
if (!filters.containsKey(id))
return null;
return filters.get(id).toJS();
}
}
public JSONArray toJS(int id, Ethereum ethereum) {
synchronized (filters) {
if (!filters.containsKey(id))
return null;
return filters.get(id).toJS(ethereum);
}
}
}

View File

@ -0,0 +1,38 @@
package org.ethereum.android.jsonrpc.filter;
import net.minidev.json.JSONArray;
import org.ethereum.core.Transaction;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
public class FilterTransaction extends FilterBase {
private ArrayList<String> transactions = new ArrayList<String>();
public void processEvent(Object data) {
if (data instanceof Transaction) {
synchronized (transactions) {
transactions.add("0x" + Hex.toHexString(((Transaction) data).getHash()));
}
}
}
public JSONArray toJS() {
updateLastRequest();
JSONArray res = new JSONArray();
synchronized (transactions) {
for(String item : transactions) {
res.add(item);
}
transactions.clear();
}
return res;
}
public JSONArray toJS(Ethereum ethereum) {
return null;
}
}

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
Deprecated
*/
public class db_getHex extends JsonRpcServerMethod {
public db_getHex (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
Deprecated
*/
public class db_getString extends JsonRpcServerMethod {
public db_getString (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
Deprecated
*/
public class db_putHex extends JsonRpcServerMethod {
public db_putHex (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
Deprecated
*/
public class db_putString extends JsonRpcServerMethod {
public db_putString (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,61 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.Transaction;
import org.ethereum.facade.Ethereum;
import org.ethereum.vm.Program;
import org.ethereum.vm.VM;
import org.spongycastle.util.encoders.Hex;
import java.util.List;
/*
It's magic here, not sure if -core have this possibility at all. I found this in test and studio. But not sure that getHReturn it's what specification mean.
TODO: get advice from Roman
*/
public class eth_call extends JsonRpcServerMethod {
public eth_call (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
Transaction tx;
try {
tx = jsToTransaction(obj);
} catch (Exception e) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
}
String height = (String)params.get(1);
long blockNumber = getBlockNumber(height);
byte[] root = ethereum.getBlockchain().getBestBlock().getStateRoot();
if (blockNumber >= 0) {
ethereum.getRepository().syncToRoot(ethereum.getBlockchain().getBlockByNumber(blockNumber).getStateRoot());
}
VM vm = new VM();
Program program = new Program(tx.getData(), null);
vm.play(program);
byte[] result = program.getResult().getHReturn();
if (blockNumber >= 0) {
ethereum.getRepository().syncToRoot(root);
}
String tmp = "0x" + Hex.toHexString(result);
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,33 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
/*
TODO: -core not have lll compiler
*/
public class eth_compileLLL extends JsonRpcServerMethod {
public eth_compileLLL (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String code = (String)params.get(0);
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}

View File

@ -0,0 +1,55 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.facade.Ethereum;
import org.ethereum.serpent.SerpentCompiler;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
Example taken from -studio. Not sure if we must call encodeMachineCodeForVMRun in end
TODO: get advice from Roman about encodeMachineCodeForVMRun
*/
public class eth_compileSerpent extends JsonRpcServerMethod {
public eth_compileSerpent (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String code = (String)params.get(0);
String asmResult = "";
byte[] machineCode = null;
try {
Pattern pattern = Pattern.compile("(.*?)init:(.*?)code:(.*?)", Pattern.DOTALL);
Matcher matcher = pattern.matcher(code);
if (matcher.find()) {
asmResult = SerpentCompiler.compileFullNotion(code);
machineCode = SerpentCompiler.compileFullNotionAssemblyToMachine(asmResult);
} else {
asmResult = SerpentCompiler.compile(code);
machineCode = SerpentCompiler.compileAssemblyToMachine(asmResult);
// machineCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
}
} catch (Throwable th) {
return new JSONRPC2Response(JSONRPC2Error.INTERNAL_ERROR, req.getID());
}
return new JSONRPC2Response("0x" + Hex.toHexString(machineCode), req.getID());
}
}
}

View File

@ -0,0 +1,33 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
/*
TODO: -core not have solidity compiler
*/
public class eth_compileSolidity extends JsonRpcServerMethod {
public eth_compileSolidity (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String code = (String)params.get(0);
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}

View File

@ -0,0 +1,61 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.Transaction;
import org.ethereum.facade.Ethereum;
import org.ethereum.vm.Program;
import org.ethereum.vm.VM;
import org.spongycastle.util.encoders.Hex;
import java.util.List;
/*
It's magic here, not sure if -core have this possibility at all. I found this in test and studio. But not sure that getHReturn it's what specification mean.
TODO: get advice from Roman
*/
public class eth_estimateGas extends JsonRpcServerMethod {
public eth_estimateGas (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
Transaction tx;
try {
tx = jsToTransaction(obj);
} catch (Exception e) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
}
String height = (String)params.get(1);
long blockNumber = getBlockNumber(height);
byte[] root = ethereum.getBlockchain().getBestBlock().getStateRoot();
if (blockNumber >= 0) {
ethereum.getRepository().syncToRoot(ethereum.getBlockchain().getBlockByNumber(blockNumber).getStateRoot());
}
VM vm = new VM();
Program program = new Program(tx.getData(), null);
vm.play(program);
long result = program.getResult().getGasUsed();
if (blockNumber >= 0) {
ethereum.getRepository().syncToRoot(root);
}
String tmp = "0x" + Long.toHexString(result);
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,39 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
/*
By specification this method can receive hash of pending block but from -core it's not possible.
TODO: get advice from Roman about pending block
*/
public class eth_getBlockByHash extends JsonRpcServerMethod {
public eth_getBlockByHash (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] address = jsToAddress((String) params.get(0));
Boolean detailed = (Boolean)params.get(1);
Block block = ethereum.getBlockchain().getBlockByHash(address);
JSONRPC2Response res = new JSONRPC2Response(blockToJS(block, detailed), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,47 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
/*
By specification this method can receive number of pending block but from -core it's not possible.
TODO: get advice from Roman about pending block
*/
public class eth_getBlockByNumber extends JsonRpcServerMethod {
public eth_getBlockByNumber (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String height = (String)params.get(0);
long blockNumber = getBlockNumber(height);
Boolean detailed = (Boolean)params.get(1);
if (blockNumber == -1) {
blockNumber = ethereum.getBlockchain().getBestBlock().getNumber();
}
// TODO: here we must load pending block but -core not "group" it.
if (blockNumber == -2) {
}
Block block = ethereum.getBlockchain().getBlockByNumber(blockNumber);
JSONRPC2Response res = new JSONRPC2Response(blockToJS(block, detailed), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,27 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
import java.util.ArrayList;
/*
As I see right now -core have only serpent compiler
*/
public class eth_getCompilers extends JsonRpcServerMethod {
public eth_getCompilers (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
ArrayList<String> tmp = new ArrayList<String>();
tmp.add("serpent");
//TODO: add lll and solidity when they will be implemented in -core
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}

View File

@ -0,0 +1,31 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterBase;
import org.ethereum.android.jsonrpc.filter.FilterLog;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_getFilterChanges extends JsonRpcServerMethod {
public eth_getFilterChanges (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
int id = jsToInt((String) params.get(0));
JSONRPC2Response res = new JSONRPC2Response(FilterManager.getInstance().toJS(id), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,31 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterBase;
import org.ethereum.android.jsonrpc.filter.FilterLog;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_getFilterLogs extends JsonRpcServerMethod {
public eth_getFilterLogs (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
int id = jsToInt((String) params.get(0));
JSONRPC2Response res = new JSONRPC2Response(FilterManager.getInstance().toJS(id, ethereum), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,30 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterLog;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_getLogs extends JsonRpcServerMethod {
public eth_getLogs (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
JSONRPC2Response res = new JSONRPC2Response((new FilterLog(ethereum, obj)).toJS(ethereum), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,49 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
public class eth_getTransactionByBlockHashAndIndex extends JsonRpcServerMethod {
public eth_getTransactionByBlockHashAndIndex (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] address = jsToAddress((String) params.get(0));
int index = jsToInt((String) params.get(1));
Block block = ethereum.getBlockchain().getBlockByHash(address);
if (block == null)
return new JSONRPC2Response(null, req.getID());
if (block.getTransactionsList().size() <= index)
return new JSONRPC2Response(null, req.getID());
JSONObject tx = transactionToJS(block.getTransactionsList().get(index));
tx.put("transactionIndex", "0x" + Integer.toHexString(index));
tx.put("blockHash", "0x" + Hex.toHexString(block.getHash()));
tx.put("blockNumber", "0x" + Long.toHexString(block.getNumber()));
JSONRPC2Response res = new JSONRPC2Response(tx, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,57 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
public class eth_getTransactionByBlockNumberAndIndex extends JsonRpcServerMethod {
public eth_getTransactionByBlockNumberAndIndex (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String height = (String)params.get(0);
long blockNumber = getBlockNumber(height);
int index = jsToInt((String) params.get(1));
if (blockNumber == -1) {
blockNumber = ethereum.getBlockchain().getBestBlock().getNumber();
}
// TODO: here we must load pending block but -core not "group" it.
if (blockNumber == -2) {
}
Block block = ethereum.getBlockchain().getBlockByNumber(blockNumber);
if (block == null)
return new JSONRPC2Response(null, req.getID());
if (block.getTransactionsList().size() <= index)
return new JSONRPC2Response(null, req.getID());
JSONObject tx = transactionToJS(block.getTransactionsList().get(index));
tx.put("transactionIndex", "0x" + Integer.toHexString(index));
tx.put("blockHash", "0x" + Hex.toHexString(block.getHash()));
tx.put("blockNumber", "0x" + Long.toHexString(block.getNumber()));
JSONRPC2Response res = new JSONRPC2Response(tx, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,37 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: get advice from Roman about get block from transaction.
*/
public class eth_getTransactionByHash extends JsonRpcServerMethod {
public eth_getTransactionByHash (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] address = jsToAddress((String) params.get(0));
TransactionReceipt transaction = ethereum.getBlockchain().getTransactionReceiptByHash(address);
if (transaction == null)
return new JSONRPC2Response(null, req.getID());
JSONRPC2Response res = new JSONRPC2Response(transactionToJS(transaction.getTransaction()), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,41 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.Block;
import org.ethereum.crypto.HashUtil;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_getUncleByBlockHashAndIndex extends JsonRpcServerMethod {
public eth_getUncleByBlockHashAndIndex (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] address = jsToAddress((String) params.get(0));
int index = jsToInt((String) params.get(1));
Block block = ethereum.getBlockchain().getBlockByHash(address);
if (block == null)
return new JSONRPC2Response(null, req.getID());
if (block.getUncleList().size() <= index)
return new JSONRPC2Response(null, req.getID());
Block uncle = ethereum.getBlockchain().getBlockByHash(HashUtil.sha3(block.getUncleList().get(index).getEncoded()));
JSONRPC2Response res = new JSONRPC2Response(blockToJS(uncle, false), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,49 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.core.Block;
import org.ethereum.crypto.HashUtil;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_getUncleByBlockNumberAndIndex extends JsonRpcServerMethod {
public eth_getUncleByBlockNumberAndIndex (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 2) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String height = (String)params.get(0);
long blockNumber = getBlockNumber(height);
int index = jsToInt((String) params.get(1));
if (blockNumber == -1) {
blockNumber = ethereum.getBlockchain().getBestBlock().getNumber();
}
// TODO: here we must load pending block but -core not "group" it.
if (blockNumber == -2) {
}
Block block = ethereum.getBlockchain().getBlockByNumber(blockNumber);
if (block == null)
return new JSONRPC2Response(null, req.getID());
if (block.getUncleList().size() <= index)
return new JSONRPC2Response(null, req.getID());
Block uncle = ethereum.getBlockchain().getBlockByHash(HashUtil.sha3(block.getUncleList().get(index).getEncoded()));
JSONRPC2Response res = new JSONRPC2Response(blockToJS(uncle, false), req.getID());
return res;
}
}
}

View File

@ -22,7 +22,7 @@ public class eth_getUncleCountByBlockNumber extends JsonRpcServerMethod {
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
String height = (String)params.get(1);
String height = (String)params.get(0);
long blockNumber = getBlockNumber(height);
if (blockNumber == -1)

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
TODO: right now -core not auto start mining so no way to get information about state
*/
public class eth_getWork extends JsonRpcServerMethod {
public eth_getWork (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,24 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterBlock;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
public class eth_newBlockFilter extends JsonRpcServerMethod {
public eth_newBlockFilter (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
int id = FilterManager.getInstance().addFilter(new FilterBlock());
String tmp = "0x" + Integer.toHexString(id);
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}

View File

@ -0,0 +1,32 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterLog;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_newFilter extends JsonRpcServerMethod {
public eth_newFilter (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
int id = FilterManager.getInstance().addFilter(new FilterLog(ethereum, obj));
String tmp = "0x" + Integer.toHexString(id);
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,25 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterBlock;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.android.jsonrpc.filter.FilterTransaction;
import org.ethereum.facade.Ethereum;
public class eth_newPendingTransactionFilter extends JsonRpcServerMethod {
public eth_newPendingTransactionFilter (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
int id = FilterManager.getInstance().addFilter(new FilterTransaction());
String tmp = "0x" + Integer.toHexString(id);
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}

View File

@ -32,67 +32,13 @@ public class eth_sendTransaction extends JsonRpcServerMethod {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
if (!obj.containsKey("from") || (!obj.containsKey("to") && !obj.containsKey("data"))) {
Transaction tx;
try {
tx = jsToTransaction(obj);
} catch (Exception e) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
}
byte[] from = jsToAddress((String)obj.get("from"));
Account acc = null;
for (Account ac : ethereum.getWallet().getAccountCollection()) {
if (Arrays.equals(ac.getAddress(), from)) {
acc = ac;
break;
}
}
if (acc == null) {
return new JSONRPC2Response(JSONRPC2Error.INTERNAL_ERROR, req.getID());
}
byte[] senderPrivKey = acc.getEcKey().getPrivKeyBytes();
// default - from ethereumj-studio
byte[] to = null;
if (obj.containsKey("to") && !((String)obj.get("to")).equals("")) {
to = jsToAddress((String) obj.get("to"));
}
// default - from ethereumj-studio
BigInteger gasPrice = SZABO.value().multiply(BigInteger.TEN);
if (obj.containsKey("gasPrice") && !((String)obj.get("gasPrice")).equals("")) {
gasPrice = jsToBigInteger((String) obj.get("gasPrice"));
}
// default - from cpp-ethereum
BigInteger gas = acc.getBalance().divide(gasPrice);
BigInteger gasBBLimit = new BigInteger(Long.toString(ethereum.getBlockchain().getBestBlock().getGasLimit() / 5));
if (gasBBLimit.compareTo(gas) < 0)
gas = gasBBLimit;
if (obj.containsKey("gas") && !((String)obj.get("gas")).equals("")) {
gas = jsToBigInteger((String) obj.get("gas"));
}
// default - from ethereumj-studio
BigInteger value = new BigInteger("1000");
if (obj.containsKey("value") && !((String)obj.get("value")).equals("")) {
value = jsToBigInteger((String) obj.get("value"));
}
// default - from ethereumj-studio
BigInteger nonce = ethereum.getRepository().getNonce(acc.getAddress());
if (obj.containsKey("nonce") && !((String)obj.get("nonce")).equals("")) {
nonce = jsToBigInteger((String) obj.get("nonce"));
}
// default - from ethereumj-studio
byte[] data = new byte[]{};
if (obj.containsKey("data") && !((String)obj.get("data")).equals("")) {
data = jsToAddress((String) obj.get("data"));
}
Transaction tx = ethereum.createTransaction(nonce, gasPrice, gas, to, value, data);
tx.sign(senderPrivKey);
try {
ethereum.submitTransaction(tx).get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS);
} catch (Exception e) {

View File

@ -0,0 +1,35 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: right now -core not auto start mining so no way to get information about state
*/
public class eth_submitWork extends JsonRpcServerMethod {
public eth_submitWork (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 3) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] nonce = jsToAddress((String) params.get(0));
byte[] powHash = jsToAddress((String) params.get(1));
byte[] mixDigest = jsToAddress((String) params.get(2));
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,31 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.filter.FilterBase;
import org.ethereum.android.jsonrpc.filter.FilterLog;
import org.ethereum.android.jsonrpc.filter.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
public class eth_uninstallFilter extends JsonRpcServerMethod {
public eth_uninstallFilter (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
int id = jsToInt((String) params.get(0));
JSONRPC2Response res = new JSONRPC2Response(FilterManager.getInstance().uninstallFilter(id), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,32 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: not present clear specification for this method, also cpp and go version not provide it.
*/
public class shh_addToGroup extends JsonRpcServerMethod {
public shh_addToGroup(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] identity = jsToAddress((String)params.get(0));
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,32 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.whisper.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_getFilterChanges extends JsonRpcServerMethod {
public shh_getFilterChanges(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
int id = jsToInt((String)params.get(0));
JSONRPC2Response res = new JSONRPC2Response(FilterManager.getInstance().toJS(id), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,32 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.whisper.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_getMessages extends JsonRpcServerMethod {
public shh_getMessages(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
int id = jsToInt((String)params.get(0));
JSONRPC2Response res = new JSONRPC2Response(FilterManager.getInstance().toJSAll(id), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,32 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_hasIdentity extends JsonRpcServerMethod {
public shh_hasIdentity(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
byte[] identity = jsToAddress((String)params.get(0));
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,38 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.whisper.Filter;
import org.ethereum.android.jsonrpc.whisper.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_newFilter extends JsonRpcServerMethod {
public shh_newFilter(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
int id = FilterManager.getInstance().addFilter(new Filter(obj));
String tmp = "0x" + Integer.toHexString(id);
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
TODO: not present clear specification for this method, also cpp and go version not provide it.
*/
public class shh_newGroup extends JsonRpcServerMethod {
public shh_newGroup(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,23 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_newIdentity extends JsonRpcServerMethod {
public shh_newIdentity(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}

View File

@ -0,0 +1,60 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
import java.util.List;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_post extends JsonRpcServerMethod {
public shh_post (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
JSONObject obj = (JSONObject)params.get(0);
byte[] from = null;
if (obj.containsKey("from"))
from = jsToAddress((String)obj.get("from"));
byte[] to = null;
if (obj.containsKey("to"))
to = jsToAddress((String)obj.get("to"));
ArrayList<byte[]> topics = new ArrayList<>();
for (Object item : (JSONArray)obj.get("topics")) {
if (item instanceof String) {
topics.add(jsToAddress((String)item));
}
}
byte[] payload = jsToAddress((String)obj.get("payload"));
int priority = jsToInt((String) obj.get("priority"));
int ttl = jsToInt((String)obj.get("ttl"));
//TODO:
JSONRPC2Response res = new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
return res;
}
}
}

View File

@ -0,0 +1,32 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.android.jsonrpc.whisper.FilterManager;
import org.ethereum.facade.Ethereum;
import java.util.List;
/*
TODO: done it when shh will be ready in -core
*/
public class shh_uninstallFilter extends JsonRpcServerMethod {
public shh_uninstallFilter(Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
List<Object> params = req.getPositionalParams();
if (params.size() != 1) {
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
} else {
int id = jsToInt((String)params.get(0));
JSONRPC2Response res = new JSONRPC2Response(FilterManager.getInstance().uninstallFilter(id), req.getID());
return res;
}
}
}

View File

@ -0,0 +1,22 @@
package org.ethereum.android.jsonrpc.method;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.JsonRpcServerMethod;
import org.ethereum.facade.Ethereum;
import org.ethereum.net.shh.ShhHandler;
public class shh_version extends JsonRpcServerMethod {
public shh_version (Ethereum ethereum) {
super(ethereum);
}
protected JSONRPC2Response worker(JSONRPC2Request req, MessageContext ctx) {
String tmp = "" + ShhHandler.VERSION;
JSONRPC2Response res = new JSONRPC2Response(tmp, req.getID());
return res;
}
}

View File

@ -0,0 +1,86 @@
package org.ethereum.android.jsonrpc.whisper;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import org.ethereum.facade.Ethereum;
import org.ethereum.net.shh.ShhMessage;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
/*
TODO: replace ShhMessage with real class when Roman finish Shh.
*/
public class Filter {
protected int id;
protected ArrayList<ShhMessage> messages;
byte[] to = null;
boolean isWildcard = false;
ArrayList<ArrayList<byte[]>> or;
ArrayList<byte[]> and;
int sendID = 0;
public Filter (JSONObject data) {
messages = new ArrayList<ShhMessage>();
if (data.containsKey("to")) {
to = Hex.decode(((String)data.get("to")).substring(2));
}
JSONArray topics = (JSONArray)data.get("topics");
for (Object item : topics) {
if (item == null) {
isWildcard = true;
}
else if (item instanceof JSONArray) {
ArrayList<byte[]> tmp = new ArrayList<byte[]>();
for (Object ori : (JSONArray)item) {
if (ori instanceof String) {
tmp.add(Hex.decode(((String)ori).substring(2)));
}
}
or.add(tmp);
} else if (item instanceof String) {
and.add(Hex.decode(((String)item).substring(2)));
}
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void processEvent(Object data) {
//TODO: parse incomming data when we will know what comes.
}
public JSONArray toJS() {
JSONArray res = new JSONArray();
synchronized (messages) {
for (int i = sendID; i < messages.size(); i++) {
res.add(toJS(messages.get(i)));
}
sendID = messages.size();
}
return res;
}
public JSONArray toJSAll() {
JSONArray res = new JSONArray();
synchronized (messages) {
for (int i = 0; i < messages.size(); i++) {
res.add(toJS(messages.get(i)));
}
sendID = messages.size();
}
return res;
}
private JSONObject toJS (ShhMessage data) {
JSONObject res = new JSONObject();
return res;
}
}

View File

@ -0,0 +1,80 @@
package org.ethereum.android.jsonrpc.whisper;
import net.minidev.json.JSONArray;
import org.ethereum.facade.Ethereum;
import java.util.Hashtable;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
/*
This class must receive notification from -core about new whisper message. Right now I not see the way todo that.
TODO: ask advice from Roman about how to send notification to this class.
*/
public class FilterManager {
protected static FilterManager instance = null;
public static FilterManager getInstance() {
if (instance == null)
instance = new FilterManager();
return instance;
}
protected Hashtable<Integer, Filter> filters;
protected int last_id = 0;
private FilterManager() {
filters = new Hashtable<Integer, Filter>();
}
public void processEvent(Object data) {
synchronized (filters) {
for (Map.Entry<Integer, Filter> item : filters.entrySet()) {
item.getValue().processEvent(data);
}
}
}
public int addFilter(Filter filter) {
filter.setId(++last_id);
filters.put(filter.getId(), filter);
return filter.getId();
}
public Filter getFilter(int id) {
if (filters.containsKey(id)) {
return filters.get(id);
}
return null;
}
public boolean uninstallFilter(int id) {
synchronized (filters) {
if (!filters.containsKey(id))
return false;
filters.remove(id);
}
return true;
}
public JSONArray toJS(int id) {
synchronized (filters) {
if (!filters.containsKey(id))
return null;
return filters.get(id).toJS();
}
}
public JSONArray toJSAll(int id) {
synchronized (filters) {
if (!filters.containsKey(id))
return null;
return filters.get(id).toJSAll();
}
}
}