From 1a73c8a7b7048d2143dbc072be77362efad66041 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 19 Nov 2018 13:18:17 -0500 Subject: [PATCH 1/3] add support for pending option --- .../org/aion/api/server/rpc/ApiWeb3Aion.java | 82 +++++++------------ 1 file changed, 28 insertions(+), 54 deletions(-) diff --git a/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java b/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java index a1399b1566..29c8ff028e 100644 --- a/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java +++ b/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java @@ -237,8 +237,9 @@ public ApiWeb3Aion(final IAionChain _ac) { public ChainHeadView load(Integer key) { // no checked exception return new ChainHeadView(OPS_RECENT_ENTITY_COUNT).update(); } - - // reload() executed asynchronously using ForkJoinPool.commonPool() + + // reload() executed asynchronously using + // ForkJoinPool.commonPool() public ChainHeadView reload( final Integer key, ChainHeadView prev) { return new ChainHeadView(prev).update(); @@ -272,8 +273,9 @@ public MinerStatsView load(String key) { // no checked exception STRATUM_RECENT_BLK_COUNT, miner.toBytes()) .update(); } - - // reload() executed asynchronously using ForkJoinPool.commonPool() + + // reload() executed asynchronously using + // ForkJoinPool.commonPool() public MinerStatsView reload( final String key, MinerStatsView prev) { return new MinerStatsView(prev).update(); @@ -426,13 +428,6 @@ public RpcMsg eth_getBalance(Object _params) { if (!JSONObject.NULL.equals(_bnOrId)) { bnOrId = _bnOrId + ""; } - /* - if (!bnOrId.equalsIgnoreCase("latest")) { - return new RpcMsg( - null, - RpcError.INVALID_PARAMS, - "Default block parameter temporarily unsupported"); - }*/ IRepository repo = getRepoByJsonBlockId(bnOrId); if (repo == null) // invalid bnOrId @@ -446,8 +441,6 @@ public RpcMsg eth_getBalance(Object _params) { + "State may have been pruned; please check your db pruning settings in the configuration file."); } - // IRepository repo = this.ac.getRepository(); - BigInteger balance = repo.getBalance(address); return new RpcMsg(TypeConverter.toJsonHex(balance)); } @@ -485,13 +478,6 @@ public RpcMsg eth_getStorageAt(Object _params) { return new RpcMsg( null, RpcError.INVALID_PARAMS, "Invalid storageIndex. Must be <= 16 bytes."); } - /* - if (!bnOrId.equalsIgnoreCase("latest")) { - return new RpcMsg( - null, - RpcError.INVALID_PARAMS, - "Default block parameter temporarily unsupported"); - }*/ IRepository repo = getRepoByJsonBlockId(bnOrId); if (repo == null) // invalid bnOrId @@ -505,8 +491,6 @@ public RpcMsg eth_getStorageAt(Object _params) { + "State may have been pruned; please check your db pruning settings in the configuration file."); } - // IRepository repo = this.ac.getRepository(); - @SuppressWarnings("unchecked") IDataWord storageValue = repo.getStorageValue(address, key); if (storageValue != null) { @@ -535,17 +519,6 @@ public RpcMsg eth_getTransactionCount(Object _params) { if (!JSONObject.NULL.equals(_bnOrId)) { bnOrId = _bnOrId + ""; } - /* - if (!bnOrId.equalsIgnoreCase("latest")) { - return new RpcMsg( - null, - RpcError.INVALID_PARAMS, - "Default block parameter temporarily unsupported"); - }*/ - - if (bnOrId.equalsIgnoreCase("pending")) { - return new RpcMsg(TypeConverter.toJsonHex(pendingState.bestPendingStateNonce(address))); - } IRepository repo = getRepoByJsonBlockId(bnOrId); if (repo == null) // invalid bnOrId @@ -559,8 +532,6 @@ public RpcMsg eth_getTransactionCount(Object _params) { + "State may have been pruned; please check your db pruning settings in the configuration file."); } - // IRepository repo = this.ac.getRepository(); - return new RpcMsg(TypeConverter.toJsonHex(repo.getNonce(address))); } @@ -635,13 +606,6 @@ public RpcMsg eth_getCode(Object _params) { if (!JSONObject.NULL.equals(_bnOrId)) { bnOrId = _bnOrId + ""; } - /* - if (!bnOrId.equalsIgnoreCase("latest")) { - return new RpcMsg( - null, - RpcError.INVALID_PARAMS, - "Default block parameter temporarily unsupported"); - }*/ IRepository repo = getRepoByJsonBlockId(bnOrId); if (repo == null) // invalid bnOrId @@ -655,8 +619,6 @@ public RpcMsg eth_getCode(Object _params) { + "State may have been pruned; please check your db pruning settings in the configuration file."); } - // IRepository repo = this.ac.getRepository(); - byte[] code = repo.getCode(address); return new RpcMsg(TypeConverter.toJsonHex(code)); } @@ -826,10 +788,12 @@ public RpcMsg eth_call(Object _params) { } Long bn = parseBnOrId(bnOrId); - if (bn == null || bn < 0) { + if (bn == null) { return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block id provided."); } + AionBlock b = getBlockByBN(bn); + AionTransaction tx = new AionTransaction( txParams.getNonce().toByteArray(), @@ -839,7 +803,6 @@ public RpcMsg eth_call(Object _params) { txParams.getNrg(), txParams.getNrgPrice()); - AionBlock b = this.ac.getBlockchain().getBlockByNumber(bn); AionTxReceipt receipt = this.ac.callConstant(tx, b); return new RpcMsg(TypeConverter.toJsonHex(receipt.getExecutionResult())); @@ -923,11 +886,11 @@ public RpcMsg eth_getBlockByNumber(Object _params) { Long bn = this.parseBnOrId(_bnOrId); - if (bn == null || bn < 0) { + if (bn == null) { return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block id provided."); } - AionBlock nb = this.ac.getBlockchain().getBlockByNumber(bn); + AionBlock nb = getBlockByBN(bn); if (nb == null) { LOG.debug("", bn); @@ -1025,11 +988,12 @@ public RpcMsg eth_getTransactionByBlockNumberAndIndex(Object _params) { } Long bn = parseBnOrId(_bnOrId); - if (bn == null || bn < 0) { + if (bn == null) { return null; } - AionBlock b = this.ac.getBlockchain().getBlockByNumber(bn); + AionBlock b = this.getBlockByBN(bn); + if (b == null) { return new RpcMsg( JSONObject.NULL); // json rpc spec: 'or null when no transaction was found' @@ -1131,13 +1095,13 @@ private FltrLg createFilter(ArgFltr rf) { Long bnFrom = parseBnOrId(rf.fromBlock); Long bnTo = parseBnOrId(rf.toBlock); - if (bnFrom == null || bnTo == null || bnFrom == -1 || bnTo == -1) { + if (bnFrom == null || bnTo == null) { LOG.debug("jsonrpc - eth_newFilter(): from, to block parse failed"); return null; } - final AionBlock fromBlock = this.ac.getBlockchain().getBlockByNumber(bnFrom); - AionBlock toBlock = this.ac.getBlockchain().getBlockByNumber(bnTo); + AionBlock fromBlock = this.getBlockByBN(bnFrom); + AionBlock toBlock = this.getBlockByBN(bnTo); if (fromBlock != null) { // need to add historical data @@ -2860,10 +2824,12 @@ public RpcMsg stratum_getMinerStats(Object _params) { private IRepository getRepoByJsonBlockId(String _bnOrId) { Long bn = parseBnOrId(_bnOrId); // if you passed in an invalid bnOrId, pending or it's an error - if (bn == null || bn < 0) { + if (bn == null) { return null; } + if (bn < 0) return pendingState.getRepository(); + AionBlock b = this.ac.getBlockchain().getBlockByNumber(bn); if (b == null) { return null; @@ -2872,6 +2838,14 @@ private IRepository getRepoByJsonBlockId(String _bnOrId) { return ac.getRepository().getSnapshotTo(b.getStateRoot()); } + private AionBlock getBlockByBN(Long bn) { + if (bn < 0) { + return pendingState.getBestBlock(); + } else { + return this.ac.getBlockchain().getBlockByNumber(bn); + } + } + private Long parseBnOrId(String _bnOrId) { if (_bnOrId == null) { return null; From a969e2e57739aa0bf6a7db42e6bf5383089d7a8e Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Mon, 19 Nov 2018 14:16:20 -0500 Subject: [PATCH 2/3] add tests for changes --- .../test/org/aion/api/server/ApiAionTest.java | 145 ----------- .../aion/api/server/rpc/ApiWeb3AionTest.java | 234 ++++++++++++++++++ 2 files changed, 234 insertions(+), 145 deletions(-) create mode 100644 modApiServer/test/org/aion/api/server/rpc/ApiWeb3AionTest.java diff --git a/modApiServer/test/org/aion/api/server/ApiAionTest.java b/modApiServer/test/org/aion/api/server/ApiAionTest.java index cd248afcd7..f80f3d7cfc 100644 --- a/modApiServer/test/org/aion/api/server/ApiAionTest.java +++ b/modApiServer/test/org/aion/api/server/ApiAionTest.java @@ -147,7 +147,6 @@ private void addEvents() { } private ApiAionImpl api; - private ApiWeb3Aion web3Api; private AionImpl impl; private AionRepositoryImpl repo; @@ -156,7 +155,6 @@ public void setup() { CfgAion.inst().getDb().setPath(DATABASE_PATH); impl = AionImpl.inst(); api = new ApiAionImpl(impl); - web3Api = new ApiWeb3Aion(impl); repo = AionRepositoryImpl.inst(); testStartTime = System.currentTimeMillis(); } @@ -519,147 +517,4 @@ public void testHashRate() { Double.parseDouble(api.getHashrate()), 0.001); } - - @Test - public void testEthSignTransaction() { - Address addr = new Address(Keystore.create("testPwd")); - - AccountManager.inst().unlockAccount(addr, "testPwd", 50000); - - Address toAddr = new Address(Keystore.create("testPwd")); - - JSONObject tx = new JSONObject(); - tx.put("from", "0x" + addr.toString()); - tx.put("to", "0x" + toAddr.toString()); - tx.put("gasPrice", "20000000000"); - tx.put("gas", "21000"); - tx.put("value", "500000"); - tx.put("data", ""); - - JSONArray jsonArray = new JSONArray(); - jsonArray.put(tx); - jsonArray.put(addr); - - RpcMsg rpcMsg = web3Api.eth_signTransaction(jsonArray); - assertNotNull(rpcMsg); - - JSONObject result = (JSONObject) rpcMsg.getResult(); - JSONObject outTx = (JSONObject) result.get("tx"); - String raw = (String) result.get("raw"); - - assertNotNull(result); - assertNotNull(raw); - assertNotNull(tx); - - assertEquals(tx.get("to"), outTx.get("to")); - assertEquals( - tx.get("value"), StringHexToBigInteger(outTx.get("value").toString()).toString()); - assertEquals( - tx.get("gasPrice"), - StringHexToBigInteger(outTx.get("gasPrice").toString()).toString()); - assertEquals( - tx.get("gasPrice"), - StringHexToBigInteger(outTx.get("nrgPrice").toString()).toString()); - assertEquals(tx.get("gas"), StringHexToBigInteger(outTx.get("gas").toString()).toString()); - assertEquals(tx.get("gas"), StringHexToBigInteger(outTx.get("nrg").toString()).toString()); - assertEquals("0x", outTx.get("input").toString()); - - JSONArray rawTxArray = new JSONArray(); - rawTxArray.put(raw); - assertNotNull(web3Api.eth_sendRawTransaction(rawTxArray)); - } - - @Test - public void testEthSignTransactionAddressParamIsNull() { - Address addr = new Address(Keystore.create("testPwd")); - - AccountManager.inst().unlockAccount(addr, "testPwd", 50000); - - Address toAddr = new Address(Keystore.create("testPwd")); - - JSONObject tx = new JSONObject(); - tx.put("from", addr.toString()); - tx.put("gasPrice", "20000000000"); - tx.put("gas", "21000"); - tx.put("to", toAddr.toString()); - tx.put("value", "500000"); - tx.put("data", ""); - - JSONArray jsonArray = new JSONArray(); - jsonArray.put(tx); - // don't pass address - - RpcMsg rpcMsg = web3Api.eth_signTransaction(jsonArray); - assertNotNull(rpcMsg); - - JSONObject result = (JSONObject) rpcMsg.getResult(); - assertNull(result); - assertEquals(RpcError.INTERNAL_ERROR, rpcMsg.getError()); - } - - @Test - public void testEthSignTransactionAccountNotUnlocked() { - Address addr = new Address(Keystore.create("testPwd")); - - Address toAddr = new Address(Keystore.create("testPwd")); - - JSONObject tx = new JSONObject(); - tx.put("from", addr.toString()); - tx.put("gasPrice", "20000000000"); - tx.put("gas", "21000"); - tx.put("to", toAddr.toString()); - tx.put("value", "500000"); - tx.put("data", ""); - - JSONArray jsonArray = new JSONArray(); - jsonArray.put(tx); - jsonArray.put(addr); - - RpcMsg rpcMsg = web3Api.eth_signTransaction(jsonArray); - assertNotNull(rpcMsg); - - JSONObject result = (JSONObject) rpcMsg.getResult(); - assertNull(result); - assertEquals(RpcError.INTERNAL_ERROR, rpcMsg.getError()); - } - - @Test - public void testEthSendTransactionAccountNotUnlocked() { - Address addr = new Address(Keystore.create("testPwd")); - - Address toAddr = new Address(Keystore.create("testPwd")); - - JSONObject tx = new JSONObject(); - tx.put("from", addr.toString()); - tx.put("gasPrice", "20000000000"); - tx.put("gas", "21000"); - tx.put("to", toAddr.toString()); - tx.put("value", "500000"); - tx.put("data", ""); - - JSONArray jsonArray = new JSONArray(); - jsonArray.put(tx); - jsonArray.put(addr); - - RpcMsg rpcMsg = web3Api.eth_sendTransaction(jsonArray); - assertNotNull(rpcMsg); - - JSONObject result = (JSONObject) rpcMsg.getResult(); - assertNull(result); - assertEquals(RpcError.NOT_ALLOWED, rpcMsg.getError()); - } - - @Test - public void testEthGetTransactionCountPending() { - JSONObject req = new JSONObject(); - req.put("address", Address.ZERO_ADDRESS().toString()); - req.put("block", "pending"); - - RpcMsg rsp = web3Api.eth_getTransactionCount(req); - assertNull(rsp.getError()); - - assertEquals( - impl.getPendingState().getNonce(Address.ZERO_ADDRESS()), - StringHexToBigInteger(rsp.getResult().toString())); - } } diff --git a/modApiServer/test/org/aion/api/server/rpc/ApiWeb3AionTest.java b/modApiServer/test/org/aion/api/server/rpc/ApiWeb3AionTest.java new file mode 100644 index 0000000000..f99f9be675 --- /dev/null +++ b/modApiServer/test/org/aion/api/server/rpc/ApiWeb3AionTest.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017-2018 Aion foundation. + * + * This file is part of the aion network project. + * + * The aion network project is free software: you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or any later version. + * + * The aion network project is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the aion network project source files. + * If not, see . + * + * Contributors: + * Aion foundation. + */ + +package org.aion.api.server.rpc; + +import static org.aion.base.util.TypeConverter.StringHexToBigInteger; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.aion.base.type.Address; +import org.aion.mcf.account.AccountManager; +import org.aion.mcf.account.Keystore; +import org.aion.zero.impl.blockchain.AionImpl; +import org.aion.zero.impl.blockchain.AionPendingStateImpl; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; + +public class ApiWeb3AionTest { + + private ApiWeb3Aion web3Api; + private AionImpl impl; + + @Before + public void setup() { + impl = AionImpl.inst(); + web3Api = new ApiWeb3Aion(impl); + } + + @Test + public void testEthSignTransaction() { + Address addr = new Address(Keystore.create("testPwd")); + + AccountManager.inst().unlockAccount(addr, "testPwd", 50000); + + Address toAddr = new Address(Keystore.create("testPwd")); + + JSONObject tx = new JSONObject(); + tx.put("from", "0x" + addr.toString()); + tx.put("to", "0x" + toAddr.toString()); + tx.put("gasPrice", "20000000000"); + tx.put("gas", "21000"); + tx.put("value", "500000"); + tx.put("data", ""); + + JSONArray jsonArray = new JSONArray(); + jsonArray.put(tx); + jsonArray.put(addr); + + RpcMsg rpcMsg = web3Api.eth_signTransaction(jsonArray); + assertNotNull(rpcMsg); + + JSONObject result = (JSONObject) rpcMsg.getResult(); + JSONObject outTx = (JSONObject) result.get("tx"); + String raw = (String) result.get("raw"); + + assertNotNull(result); + assertNotNull(raw); + assertNotNull(tx); + + assertEquals(tx.get("to"), outTx.get("to")); + assertEquals( + tx.get("value"), StringHexToBigInteger(outTx.get("value").toString()).toString()); + assertEquals( + tx.get("gasPrice"), + StringHexToBigInteger(outTx.get("gasPrice").toString()).toString()); + assertEquals( + tx.get("gasPrice"), + StringHexToBigInteger(outTx.get("nrgPrice").toString()).toString()); + assertEquals(tx.get("gas"), StringHexToBigInteger(outTx.get("gas").toString()).toString()); + assertEquals(tx.get("gas"), StringHexToBigInteger(outTx.get("nrg").toString()).toString()); + assertEquals("0x", outTx.get("input").toString()); + + JSONArray rawTxArray = new JSONArray(); + rawTxArray.put(raw); + assertNotNull(web3Api.eth_sendRawTransaction(rawTxArray)); + } + + @Test + public void testEthSignTransactionAddressParamIsNull() { + Address addr = new Address(Keystore.create("testPwd")); + + AccountManager.inst().unlockAccount(addr, "testPwd", 50000); + + Address toAddr = new Address(Keystore.create("testPwd")); + + JSONObject tx = new JSONObject(); + tx.put("from", addr.toString()); + tx.put("gasPrice", "20000000000"); + tx.put("gas", "21000"); + tx.put("to", toAddr.toString()); + tx.put("value", "500000"); + tx.put("data", ""); + + JSONArray jsonArray = new JSONArray(); + jsonArray.put(tx); + // don't pass address + + RpcMsg rpcMsg = web3Api.eth_signTransaction(jsonArray); + assertNotNull(rpcMsg); + + JSONObject result = (JSONObject) rpcMsg.getResult(); + assertNull(result); + assertEquals(RpcError.INTERNAL_ERROR, rpcMsg.getError()); + } + + @Test + public void testEthSignTransactionAccountNotUnlocked() { + Address addr = new Address(Keystore.create("testPwd")); + + Address toAddr = new Address(Keystore.create("testPwd")); + + JSONObject tx = new JSONObject(); + tx.put("from", addr.toString()); + tx.put("gasPrice", "20000000000"); + tx.put("gas", "21000"); + tx.put("to", toAddr.toString()); + tx.put("value", "500000"); + tx.put("data", ""); + + JSONArray jsonArray = new JSONArray(); + jsonArray.put(tx); + jsonArray.put(addr); + + RpcMsg rpcMsg = web3Api.eth_signTransaction(jsonArray); + assertNotNull(rpcMsg); + + JSONObject result = (JSONObject) rpcMsg.getResult(); + assertNull(result); + assertEquals(RpcError.INTERNAL_ERROR, rpcMsg.getError()); + } + + @Test + public void testEthSendTransactionAccountNotUnlocked() { + Address addr = new Address(Keystore.create("testPwd")); + + Address toAddr = new Address(Keystore.create("testPwd")); + + JSONObject tx = new JSONObject(); + tx.put("from", addr.toString()); + tx.put("gasPrice", "20000000000"); + tx.put("gas", "21000"); + tx.put("to", toAddr.toString()); + tx.put("value", "500000"); + tx.put("data", ""); + + JSONArray jsonArray = new JSONArray(); + jsonArray.put(tx); + jsonArray.put(addr); + + RpcMsg rpcMsg = web3Api.eth_sendTransaction(jsonArray); + assertNotNull(rpcMsg); + + JSONObject result = (JSONObject) rpcMsg.getResult(); + assertNull(result); + assertEquals(RpcError.NOT_ALLOWED, rpcMsg.getError()); + } + + @Test + public void testEthGetTransactionCountPending() { + JSONObject req = new JSONObject(); + req.put("address", Address.ZERO_ADDRESS().toString()); + req.put("block", "pending"); + + RpcMsg rsp = web3Api.eth_getTransactionCount(req); + assertNull(rsp.getError()); + + assertEquals( + impl.getPendingState().getNonce(Address.ZERO_ADDRESS()), + StringHexToBigInteger(rsp.getResult().toString())); + } + + @Test + public void testEthGetBalancePending() { + JSONObject req = new JSONObject(); + req.put("address", Address.ZERO_ADDRESS().toString()); + req.put("block", "pending"); + + RpcMsg rsp = web3Api.eth_getBalance(req); + assertNull(rsp.getError()); + + assertEquals( + impl.getPendingState().getBalance(Address.ZERO_ADDRESS()), + StringHexToBigInteger(rsp.getResult().toString())); + } + + @Test + public void testEthGetBlockByNumberPending() { + JSONObject req = new JSONObject(); + req.put("block", "pending"); + + RpcMsg rsp = web3Api.eth_getBlockByNumber(req); + assertNull(rsp.getError()); + + long rspNum = rsp.toJson().getJSONObject("result").getLong("number"); + + assertEquals( + AionPendingStateImpl.inst().getBestBlock().getNumber(), + rspNum); + } + + @Test + public void testEthGetTransactionFromBlockPending() { + JSONObject req = new JSONObject(); + req.put("index", "0"); + req.put("block", "pending"); + + RpcMsg rsp = web3Api.eth_getTransactionByBlockNumberAndIndex(req); + assertEquals(JSONObject.NULL, rsp.getResult()); + + } +} From 6f90eed6dd226bb46d760de3c996947637060667 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 20 Nov 2018 11:33:34 -0500 Subject: [PATCH 3/3] Reject negative block numbers, standardise logging --- .../org/aion/api/server/rpc/ApiWeb3Aion.java | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java b/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java index 29c8ff028e..1b8402a6ab 100644 --- a/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java +++ b/modApiServer/src/org/aion/api/server/rpc/ApiWeb3Aion.java @@ -135,6 +135,8 @@ public class ApiWeb3Aion extends ApiAion { private boolean isSeedMode; + private final long BEST_PENDING_BLOCK = -1L; + private final LoadingCache CachedRecentEntities; private final LoadingCache MinerStats; @@ -571,7 +573,7 @@ public RpcMsg eth_getBlockTransactionCountByNumber(Object _params) { } // pending transactions - if (bn < 0) { + if (bn == BEST_PENDING_BLOCK) { long pendingTxCount = this.ac.getAionHub().getPendingState().getPendingTxSize(); return new RpcMsg(TypeConverter.toJsonHex(pendingTxCount)); } @@ -789,7 +791,7 @@ public RpcMsg eth_call(Object _params) { Long bn = parseBnOrId(bnOrId); if (bn == null) { - return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block id provided."); + return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block number."); } AionBlock b = getBlockByBN(bn); @@ -887,7 +889,7 @@ public RpcMsg eth_getBlockByNumber(Object _params) { Long bn = this.parseBnOrId(_bnOrId); if (bn == null) { - return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block id provided."); + return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block number."); } AionBlock nb = getBlockByBN(bn); @@ -989,7 +991,7 @@ public RpcMsg eth_getTransactionByBlockNumberAndIndex(Object _params) { Long bn = parseBnOrId(_bnOrId); if (bn == null) { - return null; + return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block number."); } AionBlock b = this.getBlockByBN(bn); @@ -1100,6 +1102,11 @@ private FltrLg createFilter(ArgFltr rf) { return null; } + if (bnTo != BEST_PENDING_BLOCK && bnFrom > bnTo) { + LOG.debug("jsonrpc - eth_newFilter(): from block is after to block"); + return null; + } + AionBlock fromBlock = this.getBlockByBN(bnFrom); AionBlock toBlock = this.getBlockByBN(bnTo); @@ -1338,7 +1345,7 @@ public RpcMsg debug_getBlocksByNumber(Object _params) { Long bn = parseBnOrId(_bnOrId); if (bn == null || bn < 0) { - return null; + return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid block number."); } List>> blocks = @@ -2823,12 +2830,12 @@ public RpcMsg stratum_getMinerStats(Object _params) { // comment out until resolved private IRepository getRepoByJsonBlockId(String _bnOrId) { Long bn = parseBnOrId(_bnOrId); - // if you passed in an invalid bnOrId, pending or it's an error + if (bn == null) { return null; } - if (bn < 0) return pendingState.getRepository(); + if (bn == BEST_PENDING_BLOCK) return pendingState.getRepository(); AionBlock b = this.ac.getBlockchain().getBlockByNumber(bn); if (b == null) { @@ -2838,14 +2845,16 @@ private IRepository getRepoByJsonBlockId(String _bnOrId) { return ac.getRepository().getSnapshotTo(b.getStateRoot()); } - private AionBlock getBlockByBN(Long bn) { - if (bn < 0) { + private AionBlock getBlockByBN(long bn) { + if (bn == BEST_PENDING_BLOCK) { return pendingState.getBestBlock(); } else { return this.ac.getBlockchain().getBlockByNumber(bn); } } + // Note: If return is null, caller sometimes assumes no blockNumber was passed in + private Long parseBnOrId(String _bnOrId) { if (_bnOrId == null) { return null; @@ -2857,12 +2866,21 @@ private Long parseBnOrId(String _bnOrId) { } else if ("latest".equalsIgnoreCase(_bnOrId)) { return getBestBlock().getNumber(); } else if ("pending".equalsIgnoreCase(_bnOrId)) { - return -1L; + return BEST_PENDING_BLOCK; } else { + + Long ret; + if (_bnOrId.startsWith("0x")) { - return TypeConverter.StringHexToBigInteger(_bnOrId).longValue(); + ret = TypeConverter.StringHexToBigInteger(_bnOrId).longValue(); + } else { + ret = Long.parseLong(_bnOrId); + } + if (ret < 0) { + LOG.debug("block number cannot be negative" + _bnOrId); + return null; } else { - return Long.parseLong(_bnOrId); + return ret; } } } catch (Exception e) {