Search in sources :

Example 1 with TxRecpt

use of org.aion.api.server.types.TxRecpt in project aion by aionnetwork.

the class ApiAion method getTransactionByHash.

public AionTransaction getTransactionByHash(byte[] hash) {
    TxRecpt txRecpt = this.getTransactionReceipt(hash);
    if (txRecpt == null) {
        if (LOG.isErrorEnabled()) {
            LOG.error("Can't find the transaction receipt by the txhash.");
        }
        return null;
    } else {
        AionTransaction atx = this.getTransactionByBlockNumberAndIndex(txRecpt.blockNumber, txRecpt.transactionIndex);
        if (atx == null) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Can't find the transaction by the blocknumber and the txIndex.");
            }
            return null;
        }
        atx.setNrgConsume(txRecpt.nrgUsed);
        return atx;
    }
}
Also used : TxRecpt(org.aion.api.server.types.TxRecpt) AionTransaction(org.aion.zero.types.AionTransaction)

Example 2 with TxRecpt

use of org.aion.api.server.types.TxRecpt in project aion by aionnetwork.

the class ApiWeb3Aion method ops_getTransactionReceiptByTransactionAndBlockHash.

/**
 * This function runs as fast as is possible with the on-disk data model Use this to retrieve
 * the Transaction Receipt if you know the block hash already
 */
public RpcMsg ops_getTransactionReceiptByTransactionAndBlockHash(Object _params) {
    String _transactionHash;
    String _blockHash;
    if (_params instanceof JSONArray) {
        _transactionHash = ((JSONArray) _params).get(0) + "";
        _blockHash = ((JSONArray) _params).get(1) + "";
    } else if (_params instanceof JSONObject) {
        _transactionHash = ((JSONObject) _params).get("transactionHash") + "";
        _blockHash = ((JSONObject) _params).get("blockHash") + "";
    } else {
        return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
    }
    byte[] transactionHash = StringUtils.StringHexToByteArray(_transactionHash);
    byte[] blockHash = StringUtils.StringHexToByteArray(_blockHash);
    // cast will cause issues after the PoW refactor goes in
    AionBlockchainImpl chain = (AionBlockchainImpl) this.ac.getAionHub().getBlockchain();
    AionTxInfo info = chain.getTransactionInfoLite(transactionHash, blockHash);
    if (info == null) {
        return new RpcMsg(JSONObject.NULL);
    }
    Block block = blockCache.get(ByteArrayWrapper.wrap(blockHash));
    AionTransaction t = block.getTransactionsList().get(info.getIndex());
    if (Arrays.compare(t.getTransactionHash(), transactionHash) != 0) {
        LOG.error("INCONSISTENT STATE: transaction info's transaction index is wrong.");
        return new RpcMsg(null, RpcError.INTERNAL_ERROR, "Database Error");
    }
    info.setTransaction(t);
    return new RpcMsg((new TxRecpt(block, info, 0L, true)).toJson());
}
Also used : TxRecpt(org.aion.api.server.types.TxRecpt) JSONObject(org.json.JSONObject) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) JSONArray(org.json.JSONArray) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) StakingBlock(org.aion.zero.impl.types.StakingBlock) AionTransaction(org.aion.base.AionTransaction) Hex.toHexString(org.aion.util.conversions.Hex.toHexString) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl)

Example 3 with TxRecpt

use of org.aion.api.server.types.TxRecpt in project aion by aionnetwork.

the class ApiWeb3Aion method ops_getTransactionReceiptListByBlockHash.

public RpcMsg ops_getTransactionReceiptListByBlockHash(Object _params) {
    String _blockHash;
    if (_params instanceof JSONArray) {
        _blockHash = ((JSONArray) _params).get(0) + "";
    } else if (_params instanceof JSONObject) {
        _blockHash = ((JSONObject) _params).get("blockHash") + "";
    } else {
        return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
    }
    byte[] blockHash = StringUtils.StringHexToByteArray(_blockHash);
    if (blockHash.length != 32) {
        return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
    }
    // ok to getUnchecked() since the load() implementation does not throw checked exceptions
    Block b;
    try {
        b = blockCache.get(ByteArrayWrapper.wrap(blockHash));
    } catch (Exception e) {
        // Catch errors if send an incorrect tx hash
        return new RpcMsg(null, RpcError.INVALID_REQUEST, "Invalid Request " + e + " " + e.getMessage() != null ? e.getMessage() : "");
    }
    // cast will cause issues after the PoW refactor goes in
    AionBlockchainImpl chain = (AionBlockchainImpl) this.ac.getAionHub().getBlockchain();
    Function<AionTransaction, JSONObject> extractTxReceipt = t -> {
        AionTxInfo info = chain.getTransactionInfoLite(t.getTransactionHash(), b.getHash());
        info.setTransaction(t);
        return ((new TxRecpt(b, info, 0L, true)).toJson());
    };
    List<JSONObject> receipts;
    // use the fork-join pool to parallelize receipt retrieval if necessary
    int PARALLELIZE_RECEIPT_COUNT = 20;
    if (b.getTransactionsList().size() > PARALLELIZE_RECEIPT_COUNT) {
        receipts = b.getTransactionsList().parallelStream().map(extractTxReceipt).collect(toList());
    } else {
        receipts = b.getTransactionsList().stream().map(extractTxReceipt).collect(toList());
    }
    return new RpcMsg(new JSONArray(receipts));
}
Also used : Arrays(java.util.Arrays) ApiTxResponse(org.aion.api.server.ApiTxResponse) ArgTxCall(org.aion.api.server.types.ArgTxCall) Seal(org.aion.zero.impl.types.BlockHeader.Seal) ListIterator(java.util.ListIterator) FltrTx(org.aion.api.server.types.FltrTx) Version(org.aion.zero.impl.Version) Tx(org.aion.api.server.types.Tx) NodeWrapper(org.aion.zero.impl.sync.NodeWrapper) LRUMap(org.apache.commons.collections4.map.LRUMap) CfgApiZmq(org.aion.zero.impl.config.CfgApiZmq) AionTxReceipt(org.aion.base.AionTxReceipt) AionImpl(org.aion.zero.impl.blockchain.AionImpl) FltrBlk(org.aion.api.server.types.FltrBlk) CfgApiNrg(org.aion.zero.impl.config.CfgApiNrg) BigDecimal(java.math.BigDecimal) JSONObject(org.json.JSONObject) AddressUtils(org.aion.util.types.AddressUtils) Map(java.util.Map) BigInteger(java.math.BigInteger) MiningBlock(org.aion.zero.impl.types.MiningBlock) ZoneOffset(java.time.ZoneOffset) Block(org.aion.zero.impl.types.Block) AionAddress(org.aion.types.AionAddress) RoundingMode(java.math.RoundingMode) FltrLg(org.aion.api.server.types.FltrLg) HexConvert.hexStringToBytes(org.aion.util.types.HexConvert.hexStringToBytes) LoadingCache(com.github.benmanes.caffeine.cache.LoadingCache) Fltr(org.aion.api.server.types.Fltr) Keystore(org.aion.zero.impl.keystore.Keystore) MiningBlockHeader(org.aion.zero.impl.types.MiningBlockHeader) Instant(java.time.Instant) ByteUtil(org.aion.util.bytes.ByteUtil) EventCallback(org.aion.evtmgr.impl.callback.EventCallback) TxRecpt(org.aion.api.server.types.TxRecpt) HashUtil(org.aion.crypto.HashUtil) TransactionTypes(org.aion.base.TransactionTypes) Base64(java.util.Base64) List(java.util.List) StringUtils(org.aion.util.string.StringUtils) CfgNet(org.aion.zero.impl.config.CfgNet) Entry(java.util.Map.Entry) Optional(java.util.Optional) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) Hex.toHexString(org.aion.util.conversions.Hex.toHexString) SyncInfo(org.aion.api.server.types.SyncInfo) ECKey(org.aion.crypto.ECKey) CfgAion(org.aion.zero.impl.config.CfgAion) BlockContext(org.aion.zero.impl.types.BlockContext) ArgFltr(org.aion.api.server.types.ArgFltr) CfgApiRpc(org.aion.zero.impl.config.CfgApiRpc) AccountState(org.aion.base.AccountState) CacheLoader(com.github.benmanes.caffeine.cache.CacheLoader) HashMap(java.util.HashMap) CfgApi(org.aion.zero.impl.config.CfgApi) CfgNetP2p(org.aion.zero.impl.config.CfgNetP2p) Function(java.util.function.Function) NumericalValue(org.aion.api.server.types.NumericalValue) ArrayList(java.util.ArrayList) DataWord(org.aion.util.types.DataWord) ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) AccountManager(org.aion.api.server.account.AccountManager) IEventMgr(org.aion.evtmgr.IEventMgr) CfgTx(org.aion.zero.impl.config.CfgTx) IAionChain(org.aion.zero.impl.blockchain.IAionChain) StakingBlock(org.aion.zero.impl.types.StakingBlock) CfgSsl(org.aion.zero.impl.config.CfgSsl) CfgSync(org.aion.zero.impl.config.CfgSync) LinkedList(java.util.LinkedList) CfgEnergyStrategy(org.aion.zero.impl.config.CfgEnergyStrategy) ApiAion(org.aion.api.server.ApiAion) IHandler(org.aion.evtmgr.IHandler) Caffeine(com.github.benmanes.caffeine.cache.Caffeine) Blk(org.aion.api.server.types.Blk) BLOCKS_QUERY_MAX(org.aion.api.server.types.FltrLg.BLOCKS_QUERY_MAX) Evt(org.aion.api.server.types.Evt) Log(org.aion.types.Log) ImportResult(org.aion.zero.impl.core.ImportResult) CompiledContr(org.aion.api.server.types.CompiledContr) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl) TimeUnit(java.util.concurrent.TimeUnit) Collectors.toList(java.util.stream.Collectors.toList) EMPTY_BYTE_ARRAY(org.aion.util.bytes.ByteUtil.EMPTY_BYTE_ARRAY) CfgConsensusUnity(org.aion.zero.impl.config.CfgConsensusUnity) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) StakingBlockHeader(org.aion.zero.impl.types.StakingBlockHeader) AionTransaction(org.aion.base.AionTransaction) Collections(java.util.Collections) JSONArray(org.json.JSONArray) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) JSONArray(org.json.JSONArray) AionTransaction(org.aion.base.AionTransaction) Hex.toHexString(org.aion.util.conversions.Hex.toHexString) TxRecpt(org.aion.api.server.types.TxRecpt) JSONObject(org.json.JSONObject) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) StakingBlock(org.aion.zero.impl.types.StakingBlock) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl)

Example 4 with TxRecpt

use of org.aion.api.server.types.TxRecpt in project aion by aionnetwork.

the class ApiWeb3Aion method eth_getTransactionReceipt.

public RpcMsg eth_getTransactionReceipt(Object _params) {
    String _hash;
    if (_params instanceof JSONArray) {
        _hash = ((JSONArray) _params).get(0) + "";
    } else if (_params instanceof JSONObject) {
        _hash = ((JSONObject) _params).get("hash") + "";
    } else {
        return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
    }
    byte[] txHash = StringUtils.StringHexToByteArray(_hash);
    TxRecpt r = getTransactionReceipt(txHash);
    if (r == null) {
        return new RpcMsg(// json rpc spec: 'or null when no receipt was found'
        JSONObject.NULL);
    }
    return new RpcMsg(r.toJson());
}
Also used : TxRecpt(org.aion.api.server.types.TxRecpt) JSONObject(org.json.JSONObject) JSONArray(org.json.JSONArray) Hex.toHexString(org.aion.util.conversions.Hex.toHexString)

Example 5 with TxRecpt

use of org.aion.api.server.types.TxRecpt in project aion by aionnetwork.

the class ApiAion0 method process.

public byte[] process(byte[] request, byte[] socketId) {
    if (request == null || (request.length < this.getApiHeaderLen())) {
        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_header_len_VALUE);
    }
    byte[] msgHash = ApiUtil.getApiMsgHash(request);
    if (request[0] < this.getApiVersion()) {
        return msgHash == null ? ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_api_version_VALUE) : ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_api_version_VALUE, msgHash);
    }
    short service = (short) request[1];
    switch((short) request[2]) {
        // General Module
        case Message.Funcs.f_protocolVersion_VALUE:
            {
                if (service != Message.Servs.s_net_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                // TODO : create query API for every module
                Message.rsp_protocolVersion rsp = Message.rsp_protocolVersion.newBuilder().setApi(String.valueOf(this.getApiVersion())).setDb(AionHub.getRepoVersion()).setKernel(Version.KERNEL_VERSION).setMiner(EquihashMiner.VERSION).setNet(this.p2pProtocolVersion()).setTxpool(this.ac.getAionHub().getPendingState().getVersion()).setVm("0.1.0").build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_minerAddress_VALUE:
            {
                if (service != Message.Servs.s_wallet_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                String cb = this.getCoinbase();
                if (cb == null) {
                    LOG.debug("ApiAion0.process.coinbase - null coinbase");
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_wallet_nullcb_VALUE);
                }
                Message.rsp_minerAddress rsp = Message.rsp_minerAddress.newBuilder().setMinerAddr(ByteString.copyFrom(StringUtils.StringHexToByteArray(cb))).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_contractDeploy_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
                }
                Message.req_contractDeploy req;
                byte[] data = parseMsgReq(request, msgHash);
                ApiTxResponse result;
                try {
                    req = Message.req_contractDeploy.parseFrom(data);
                    // TODO: the client api should send server binary code directly
                    // instead of str format like "0xhex".!
                    byte[] bytes = req.getData().toByteArray();
                    if (bytes == null || bytes.length <= 4) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_ct_bytecode_VALUE, msgHash);
                    }
                    ArgTxCall params = new ArgTxCall(new AionAddress(req.getFrom().toByteArray()), null, Hex.decode(new String(bytes).substring(2)), BigInteger.ZERO, BigInteger.ZERO, req.getNrgLimit(), req.getNrgPrice(), null);
                    LOG.debug("ApiAion0.process.ContractDeploy - ArgsTxCall: [{}] ", params.toString());
                    result = this.createContract(params);
                    if (!result.isFail()) {
                        getMsgIdMapping().put(ByteArrayWrapper.wrap(result.getTxHash()), new AbstractMap.SimpleEntry<>(ByteArrayWrapper.wrap(msgHash), ByteArrayWrapper.wrap(socketId)));
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("ApiAion0.process.ContractDeploy - msgIdMapping.put: [{}] ", ByteArrayWrapper.wrap(result.getTxHash()).toString());
                        }
                        Message.rsp_contractDeploy rsp = Message.rsp_contractDeploy.newBuilder().setContractAddress(ByteString.copyFrom(result.getContractAddress().toByteArray())).setTxHash(ByteString.copyFrom(result.getTxHash())).build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_tx_Recved_VALUE, msgHash);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    } else {
                        return processTxFail(result, msgHash);
                    }
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.ContractDeploy exception [{}] ", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
                }
            }
        // Authenication Module
        case Message.Funcs.f_accounts_VALUE:
            {
                if (service != Message.Servs.s_wallet_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                // noinspection unchecked
                List<String> accounts = this.getAccounts();
                ArrayList<ByteString> al = new ArrayList<>();
                for (String s : accounts) {
                    al.add(ByteString.copyFrom(StringUtils.StringHexToByteArray(s)));
                }
                Message.rsp_accounts rsp = Message.rsp_accounts.newBuilder().addAllAccout(al).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_blockNumber_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                Message.rsp_blockNumber rsp = Message.rsp_blockNumber.newBuilder().setBlocknumber(this.getBestBlock().getNumber()).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_unlockAccount_VALUE:
            {
                if (service != Message.Servs.s_wallet_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                boolean result;
                try {
                    Message.req_unlockAccount req = Message.req_unlockAccount.parseFrom(data);
                    result = this.unlockAccount(new AionAddress(req.getAccount().toByteArray()), req.getPassword(), req.getDuration());
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.unlockAccount exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, (byte) (result ? 0x01 : 0x00));
            }
        // Transaction Module
        case Message.Funcs.f_getBalance_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                BigInteger balance;
                try {
                    Message.req_getBalance req = Message.req_getBalance.parseFrom(data);
                    AionAddress addr = new AionAddress(req.getAddress().toByteArray());
                    balance = this.getBalance(addr);
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.getbalance exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                Message.rsp_getBalance rsp = Message.rsp_getBalance.newBuilder().setBalance(ByteString.copyFrom(balance.toByteArray())).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_getNonce_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Message.Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                BigInteger nonce;
                try {
                    Message.req_getNonce req = Message.req_getNonce.parseFrom(data);
                    AionAddress addr = new AionAddress(req.getAddress().toByteArray());
                    nonce = this.getNonce(addr);
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAionA0.process.getNonce exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Message.Retcode.r_fail_function_exception_VALUE);
                }
                Message.rsp_getNonce rsp = Message.rsp_getNonce.newBuilder().setNonce(ByteString.copyFrom(nonce.toByteArray())).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Message.Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_getNrgPrice_VALUE:
            {
                if (service != Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                long nrg = this.getRecommendedNrgPrice();
                try {
                    Message.rsp_getNrgPrice rsp = Message.rsp_getNrgPrice.newBuilder().setNrgPrice(nrg).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getEnergyPrice exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_compile_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                try {
                    Message.req_compile req = Message.req_compile.parseFrom(data);
                    String source = req.getCode();
                    if (source == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_null_compile_source_VALUE);
                    }
                    @SuppressWarnings("unchecked") Map<String, CompiledContr> _contrs = this.contract_compileSolidity(source);
                    if (_contrs != null && !_contrs.isEmpty()) {
                        Message.rsp_compile.Builder b = Message.rsp_compile.newBuilder();
                        for (Entry<String, CompiledContr> entry : _contrs.entrySet()) {
                            if (entry.getKey().contains("compile-error")) {
                                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_compile_contract_VALUE);
                                Message.t_Contract tc = Message.t_Contract.newBuilder().setError(entry.getValue().error).build();
                                return ApiUtil.combineRetMsg(retHeader, b.putConstracts(entry.getKey(), tc).build().toByteArray());
                            }
                            CompiledContr _contr = entry.getValue();
                            JSONArray abi = new JSONArray();
                            for (org.aion.solidity.Entry f : _contr.info.abiDefinition) {
                                abi.put(f.toJSON());
                            }
                            Message.t_Contract tc = Message.t_Contract.newBuilder().setCode(_contr.code).setAbiDef(ByteString.copyFrom(abi.toString().getBytes())).setSource(_contr.info.source).build();
                            b.putConstracts(entry.getKey(), tc);
                        }
                        Message.rsp_compile rsp = b.build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    } else {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                    }
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.compile exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Funcs.f_compileSolidityZip_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                try {
                    Message.req_compileSolidityZip req = Message.req_compileSolidityZip.parseFrom(data);
                    ByteString zipfile = req.getZipfile();
                    String entryPoint = req.getEntryPoint();
                    if (zipfile == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_null_compile_source_VALUE);
                    }
                    @SuppressWarnings("unchecked") Map<String, CompiledContr> _contrs = this.contract_compileSolidityZip(zipfile.toByteArray(), entryPoint);
                    if (_contrs != null && !_contrs.isEmpty()) {
                        Message.rsp_compile.Builder b = Message.rsp_compile.newBuilder();
                        for (Entry<String, CompiledContr> entry : _contrs.entrySet()) {
                            if (entry.getKey().contains("compile-error")) {
                                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_compile_contract_VALUE);
                                Message.t_Contract tc = Message.t_Contract.newBuilder().setError(entry.getValue().error).build();
                                return ApiUtil.combineRetMsg(retHeader, b.putConstracts(entry.getKey(), tc).build().toByteArray());
                            }
                            CompiledContr _contr = entry.getValue();
                            JSONArray abi = new JSONArray();
                            for (org.aion.solidity.Entry f : _contr.info.abiDefinition) {
                                abi.put(f.toJSON());
                            }
                            Message.t_Contract tc = Message.t_Contract.newBuilder().setCode(_contr.code).setAbiDef(ByteString.copyFrom(abi.toString().getBytes())).setSource(_contr.info.source).build();
                            b.putConstracts(entry.getKey(), tc);
                        }
                        Message.rsp_compile rsp = b.build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    } else {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                    }
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.compile exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_sendTransaction_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_sendTransaction req;
                ApiTxResponse result;
                try {
                    req = Message.req_sendTransaction.parseFrom(data);
                    ArgTxCall params = new ArgTxCall(new AionAddress(req.getFrom().toByteArray()), new AionAddress(req.getTo().toByteArray()), req.getData().toByteArray(), new BigInteger(req.getNonce().toByteArray()), new BigInteger(req.getValue().toByteArray()), req.getNrg(), req.getNrgPrice(), null);
                    result = this.sendTransaction(params);
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.sendTransaction exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
                }
                return processSendTxRsp(result, msgHash, socketId);
            }
        case Message.Funcs.f_getCode_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getCode req;
                try {
                    req = Message.req_getCode.parseFrom(data);
                    AionAddress to = new AionAddress(req.getAddress().toByteArray());
                    byte[] code = this.getCode(to);
                    if (code == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_null_rsp_VALUE);
                    }
                    Message.rsp_getCode rsp = Message.rsp_getCode.newBuilder().setCode(ByteString.copyFrom(code)).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getCode exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getTransactionReceipt_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getTransactionReceipt req;
                try {
                    req = Message.req_getTransactionReceipt.parseFrom(data);
                    TxRecpt result = this.getTransactionReceipt(req.getTxHash().toByteArray());
                    if (result == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_getTxReceipt_null_recp_VALUE);
                    }
                    List<Message.t_LgEle> logs = new ArrayList<>();
                    for (TxRecptLg log : result.logs) {
                        List<String> al = new ArrayList<>();
                        Collections.addAll(al, log.topics);
                        Message.t_LgEle msgLog = Message.t_LgEle.newBuilder().setAddress(ByteString.copyFrom(AddressUtils.wrapAddress(log.address).toByteArray())).setData(ByteString.copyFrom(ByteUtil.hexStringToBytes(log.data))).addAllTopics(al).build();
                        logs.add(msgLog);
                    }
                    Message.rsp_getTransactionReceipt rsp = Message.rsp_getTransactionReceipt.newBuilder().setFrom(ByteString.copyFrom(result.fromAddr.toByteArray())).setBlockNumber(result.blockNumber).setBlockHash(ByteString.copyFrom(result.blockHash != null ? ByteUtil.hexStringToBytes(result.blockHash) : EMPTY_BYTE_ARRAY)).setContractAddress(ByteString.copyFrom(result.contractAddress != null ? ByteUtil.hexStringToBytes(result.contractAddress) : EMPTY_BYTE_ARRAY)).setTxIndex(result.transactionIndex).setTxHash(ByteString.copyFrom(result.transactionHash != null ? ByteUtil.hexStringToBytes(result.transactionHash) : EMPTY_BYTE_ARRAY)).setTo(ByteString.copyFrom(result.toAddr == null ? EMPTY_BYTE_ARRAY : result.toAddr.toByteArray())).setNrgConsumed(result.nrgUsed).setCumulativeNrgUsed(result.cumulativeNrgUsed).addAllLogs(logs).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getTransactionReceipt exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_call_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_call req;
                try {
                    req = Message.req_call.parseFrom(data);
                    AionAddress from = new AionAddress(req.getFrom().toByteArray());
                    AionAddress to = new AionAddress(req.getTo().toByteArray());
                    BigInteger value = new BigInteger(req.getValue().toByteArray());
                    byte[] d = req.getData().toByteArray();
                    ArgTxCall params = new ArgTxCall(from, to, d, BigInteger.ZERO, value, req.getNrg(), req.getNrgPrice(), null);
                    Message.rsp_call rsp = Message.rsp_call.newBuilder().setResult(ByteString.copyFrom(this.doCall(params))).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.call exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockByNumber_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockByNumber req;
                try {
                    req = Message.req_getBlockByNumber.parseFrom(data);
                    long num = req.getBlockNumber();
                    Block blk = this.getBlock(num);
                    return createBlockMsg(blk);
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockByNumber exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockReward_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockReward req;
                BigInteger reward;
                try {
                    req = Message.req_getBlockReward.parseFrom(data);
                    reward = ac.getBlockchain().calculateBlockRewards(req.getBlockNumber());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockReward exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                Message.rsp_getBlockReward rsp = Message.rsp_getBlockReward.newBuilder().setReward(ByteString.copyFrom(reward.toByteArray())).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_getBlockByHash_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockByHash req;
                try {
                    req = Message.req_getBlockByHash.parseFrom(data);
                    byte[] hash = req.getBlockHash().toByteArray();
                    if (hash == null || hash.length != Hash256.BYTES) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    Block blk = this.getBlockByHash(hash);
                    return createBlockMsg(blk);
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockByHash exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getTransactionByBlockHashAndIndex_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getTransactionByBlockHashAndIndex req;
                try {
                    req = Message.req_getTransactionByBlockHashAndIndex.parseFrom(data);
                    long txIdx = req.getTxIndex();
                    byte[] hash = req.getBlockHash().toByteArray();
                    if (txIdx < -1 || hash == null || hash.length != Hash256.BYTES) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    TransactionWithBlockInfo txInfo = this.getTransactionByBlockHashAndIndex(hash, txIdx);
                    if (txInfo == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
                    }
                    Message.rsp_getTransaction rsp = getRsp_getTransaction(txInfo);
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getTransactionByBlockHashAndIndex exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getTransactionByBlockNumberAndIndex_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getTransactionByBlockNumberAndIndex req;
                try {
                    req = Message.req_getTransactionByBlockNumberAndIndex.parseFrom(data);
                    long blkNr = req.getBlockNumber();
                    long txIdx = req.getTxIndex();
                    if (blkNr < -1 || txIdx < -1) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    TransactionWithBlockInfo txInfo = this.getTransactionByBlockNumberAndIndex(blkNr, txIdx);
                    if (txInfo == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
                    }
                    Message.rsp_getTransaction rsp = getRsp_getTransaction(txInfo);
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getTransactionByBlockNumberAndIndex exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockTransactionCountByNumber_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockTransactionCountByNumber req;
                try {
                    req = Message.req_getBlockTransactionCountByNumber.parseFrom(data);
                    long blkNr = req.getBlockNumber();
                    if (blkNr < -1) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    long cnt = this.getBlockTransactionCountByNumber(blkNr);
                    if (cnt == -1) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
                    }
                    Message.rsp_getBlockTransactionCount rsp = Message.rsp_getBlockTransactionCount.newBuilder().setTxCount((int) cnt).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockTransactionCountByNumber exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getTransactionCount_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getTransactionCount req;
                try {
                    req = Message.req_getTransactionCount.parseFrom(data);
                    long blkNr = req.getBlocknumber();
                    AionAddress addr = new AionAddress(req.getAddress().toByteArray());
                    if (blkNr < -1) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    long cnt = this.getTransactionCount(addr, blkNr);
                    if (cnt == -1) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
                    }
                    Message.rsp_getTransactionCount rsp = Message.rsp_getTransactionCount.newBuilder().setTxCount((int) cnt).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getTransactionCount exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockTransactionCountByHash_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getTransactionCountByHash req;
                try {
                    req = Message.req_getTransactionCountByHash.parseFrom(data);
                    byte[] hash = req.getTxHash().toByteArray();
                    if (hash == null || hash.length != Hash256.BYTES) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    long cnt = this.getTransactionCountByHash(hash);
                    if (cnt == -1) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
                    }
                    Message.rsp_getTransactionCount rsp = Message.rsp_getTransactionCount.newBuilder().setTxCount((int) cnt).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getTransactionCount exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getTransactionByHash_VALUE:
            {
                if (service != Message.Servs.s_chain_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getTransactionByHash req;
                try {
                    req = Message.req_getTransactionByHash.parseFrom(data);
                    byte[] txHash = req.getTxHash().toByteArray();
                    if (txHash == null || txHash.length != this.getTxHashLen()) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    TransactionWithBlockInfo txInfo = this.getTransactionByHash(txHash);
                    if (txInfo == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
                    }
                    Message.rsp_getTransaction rsp = getRsp_getTransaction(txInfo);
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getTransactionCount exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getActiveNodes_VALUE:
            {
                if (service != Message.Servs.s_net_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                List<NodeWrapper> nodes = new ArrayList<>(this.ac.getAionHub().getActiveNodes().values());
                List<Message.t_Node> pl = new ArrayList<>();
                try {
                    for (NodeWrapper n : nodes) {
                        Message.t_Node node = Message.t_Node.newBuilder().setBlockNumber(n.getBestBlockNumber()).setNodeId(ByteArrayWrapper.wrap(n.getId()).toString()).setRemoteP2PIp(ByteArrayWrapper.wrap(n.getIp()).toString()).build();
                        pl.add(node);
                    }
                    Message.rsp_getActiveNodes rsp = Message.rsp_getActiveNodes.newBuilder().addAllNode(pl).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getActiveNodes exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getStaticNodes_VALUE:
            {
                if (service != Message.Servs.s_net_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                String[] al = this.getBootNodes();
                List<Message.t_Node> nl = new ArrayList<>();
                for (String s : al) {
                    // TODO : get more node info
                    Message.t_Node n = Message.t_Node.newBuilder().setRemoteP2PIp(s).build();
                    nl.add(n);
                }
                try {
                    Message.rsp_getStaticNodes rsp = Message.rsp_getStaticNodes.newBuilder().addAllNode(nl).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getStaticNodes exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getSolcVersion_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                String ver = this.solcVersion();
                try {
                    Message.rsp_getSolcVersion rsp = Message.rsp_getSolcVersion.newBuilder().setVer(ver).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getSolcVersion exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_isSyncing_VALUE:
            {
                if (service != Message.Servs.s_net_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                try {
                    Optional<Long> localBestBlockNumber = this.ac.getLocalBestBlockNumber();
                    Optional<Long> networkBestBlockNumber = this.ac.getNetworkBestBlockNumber();
                    // Check that we actually have real values in our hands.
                    if (!localBestBlockNumber.isPresent()) {
                        LOG.error("Unable to determine the local node's best block number!");
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
                    }
                    if (!networkBestBlockNumber.isPresent()) {
                        LOG.error("Unable to determine the network's best block number!");
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
                    }
                    SyncInfo syncInfo = this.getSyncInfo(localBestBlockNumber.get(), networkBestBlockNumber.get());
                    Message.rsp_isSyncing rsp = Message.rsp_isSyncing.newBuilder().setSyncing(!syncInfo.done).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.syncing exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_syncInfo_VALUE:
            {
                if (service != Message.Servs.s_net_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                Optional<Long> localBestBlockNumber = this.ac.getLocalBestBlockNumber();
                Optional<Long> networkBestBlockNumber = this.ac.getNetworkBestBlockNumber();
                // Check that we actually have real values in our hands.
                if (!localBestBlockNumber.isPresent()) {
                    LOG.error("Unable to determine the local node's best block number!");
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
                }
                if (!networkBestBlockNumber.isPresent()) {
                    LOG.error("Unable to determine the network's best block number!");
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
                }
                SyncInfo syncInfo = this.getSyncInfo(localBestBlockNumber.get(), networkBestBlockNumber.get());
                try {
                    Message.rsp_syncInfo rsp = Message.rsp_syncInfo.newBuilder().setChainBestBlock(syncInfo.chainBestBlkNumber).setNetworkBestBlock(syncInfo.networkBestBlkNumber).setSyncing(!syncInfo.done).setMaxImportBlocks(24).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.syncInfo exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_accountCreate_VALUE:
            {
                if (service != Message.Servs.s_account_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_accountCreate req;
                try {
                    req = Message.req_accountCreate.parseFrom(data);
                    List<ByteString> addressList = new ArrayList<>();
                    List<ByteString> pKeyList = new ArrayList<>();
                    for (int i = 0; i < req.getPasswordList().size() && i < ACCOUNT_CREATE_LIMIT; i++) {
                        String addr = Keystore.create(req.getPassword(i));
                        byte[] pKey;
                        if (req.getPrivateKey()) {
                            pKey = Keystore.getKey(addr, req.getPassword(i)).getPrivKeyBytes();
                            if (pKey == null) {
                                pKey = new byte[] { (byte) 0x0 };
                            }
                            pKeyList.add(ByteString.copyFrom(pKey));
                        }
                        addressList.add(ByteString.copyFrom(AddressUtils.wrapAddress(addr).toByteArray()));
                    }
                    Message.rsp_accountCreate rsp = Message.rsp_accountCreate.newBuilder().addAllAddress(addressList).addAllPrivateKey(pKeyList).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.accountCreate exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_accountLock_VALUE:
            {
                if (service != Message.Servs.s_wallet_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                if (data == null) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                }
                boolean result;
                try {
                    Message.req_accountlock req = Message.req_accountlock.parseFrom(data);
                    result = this.lockAccount(new AionAddress(req.getAccount().toByteArray()), req.getPassword());
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.lockAccount exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, (byte) (result ? 0x01 : 0x00));
            }
        case Message.Funcs.f_userPrivilege_VALUE:
            {
                if (service != Message.Servs.s_privilege_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_unsupport_api_VALUE);
            }
        case Message.Funcs.f_mining_VALUE:
            {
                if (service != Message.Servs.s_mine_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                Message.rsp_mining rsp = Message.rsp_mining.newBuilder().setMining(this.isMining()).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_estimateNrg_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_estimateNrg req;
                long result;
                try {
                    req = Message.req_estimateNrg.parseFrom(data);
                    ArgTxCall params = new ArgTxCall(new AionAddress(req.getFrom().toByteArray()), new AionAddress(req.getTo().toByteArray()), req.getData().toByteArray(), BigInteger.ZERO, new BigInteger(req.getValue().toByteArray()), req.getNrg(), req.getNrgPrice(), null);
                    result = this.estimateNrg(params);
                } catch (InvalidProtocolBufferException e) {
                    LOG.error("ApiAion0.process.estimateNrg exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
                }
                Message.rsp_estimateNrg rsp = Message.rsp_estimateNrg.newBuilder().setNrg(result).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_exportAccounts_VALUE:
        case Message.Funcs.f_backupAccounts_VALUE:
            {
                if (service != Message.Servs.s_account_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_exportAccounts req;
                try {
                    req = Message.req_exportAccounts.parseFrom(data);
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.exportAccounts exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                Map<AionAddress, String> addrMap = new HashMap<>();
                for (int i = 0; i < req.getKeyFileList().size() && i < ACCOUNT_CREATE_LIMIT; i++) {
                    addrMap.put(new AionAddress(req.getKeyFile(i).getAddress().toByteArray()), req.getKeyFile(i).getPassword());
                }
                Map<AionAddress, ByteArrayWrapper> res = ((short) request[2] == Message.Funcs.f_exportAccounts_VALUE) ? Keystore.exportAccount(addrMap) : Keystore.backupAccount(addrMap);
                List<ByteString> invalidKey = addrMap.keySet().parallelStream().filter(addr -> res.keySet().parallelStream().noneMatch(ad -> ad.equals(addr))).map(match -> ByteString.copyFrom(match.toByteArray())).collect(Collectors.toList());
                List<ByteString> keyBins = res.values().parallelStream().map(key -> ByteString.copyFrom(key.toBytes())).collect(Collectors.toList());
                Message.rsp_exportAccounts rsp = Message.rsp_exportAccounts.newBuilder().addAllKeyFile(keyBins).addAllFailedKey(invalidKey).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_importAccounts_VALUE:
            {
                if (service != Message.Servs.s_account_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_importAccounts req;
                try {
                    req = Message.req_importAccounts.parseFrom(data);
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.importAccount exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                Map<String, String> importKey = req.getPrivateKeyList().parallelStream().collect(Collectors.toMap(Message.t_PrivateKey::getPrivateKey, Message.t_PrivateKey::getPassword));
                if (importKey == null) {
                    LOG.error("ApiAion0.process.importAccount exception: [null importKey]");
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
                Set<String> res = Keystore.importAccount(importKey);
                if (res == null) {
                    throw new NullPointerException();
                }
                Message.rsp_importAccounts rsp = Message.rsp_importAccounts.newBuilder().addAllInvalidKey(res).build();
                byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
            }
        case Message.Funcs.f_signedTransaction_VALUE:
        case Message.Funcs.f_rawTransaction_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_rawTransaction req;
                ApiTxResponse result;
                try {
                    req = Message.req_rawTransaction.parseFrom(data);
                    byte[] encodedTx = req.getEncodedTx().toByteArray();
                    if (encodedTx == null) {
                        LOG.error("ApiAion0.process.rawTransaction exception: [null encodedTx]");
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    result = this.sendTransaction(encodedTx);
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.rawTransaction exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
                }
                return processSendTxRsp(result, msgHash, socketId);
            }
        case Message.Funcs.f_eventRegister_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_eventRegister req;
                try {
                    req = Message.req_eventRegister.parseFrom(data);
                    List<String> evtList = new ArrayList<>(req.getEventsList());
                    if (evtList.isEmpty()) {
                        LOG.error("ApiNucoNcp.process.eventRegister : [{}]", "empty event list");
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    Message.t_FilterCt fltr = req.getFilter();
                    List<byte[]> accList = new ArrayList<>();
                    fltr.getAddressesList().forEach(a -> accList.add(a.toByteArray()));
                    long lv = ByteUtil.byteArrayToLong(socketId);
                    FltrCt preFc = (FltrCt) installedFilters.get(lv);
                    if (Optional.ofNullable(preFc).isPresent()) {
                        preFc.getTopics().forEach(t -> {
                            if (!fltr.getTopicsList().contains(t)) {
                                evtList.add(t);
                            }
                        });
                    }
                    FltrCt fc = new FltrCt(fltr.getContractAddr().toByteArray(), fltr.getTo(), fltr.getFrom(), evtList, accList, fltr.getExpireTime());
                    installedFilters.put(lv, fc);
                    Message.rsp_eventRegister rsp = Message.rsp_eventRegister.newBuilder().setResult(true).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.eventRegister exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_eventDeregister_VALUE:
            {
                if (service != Message.Servs.s_tx_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_eventDeregister req;
                try {
                    req = Message.req_eventDeregister.parseFrom(data);
                    List<String> evtList = new ArrayList<>(req.getEventsList());
                    byte[] contractAddr;
                    if (req.getContractAddr() == null) {
                        contractAddr = null;
                    } else {
                        contractAddr = req.getContractAddr().toByteArray();
                    }
                    if (evtList.isEmpty()) {
                        LOG.error("ApiAion0.process.eventRegister : [{}]", "empty event list");
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    long lv = ByteUtil.byteArrayToLong(socketId);
                    FltrCt preFc = (FltrCt) installedFilters.get(lv);
                    boolean changed = false;
                    if (Optional.ofNullable(preFc).isPresent() && Arrays.equals(preFc.getContractAddr(), contractAddr)) {
                        evtList.forEach(ev -> preFc.getTopics().remove(ev));
                        installedFilters.put(lv, preFc);
                        changed = true;
                    }
                    Message.rsp_eventRegister rsp = Message.rsp_eventRegister.newBuilder().setResult(changed).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.eventDeregister exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockDetailsByNumber_VALUE:
            {
                if (service != Message.Servs.s_admin_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockDetailsByNumber req;
                try {
                    req = Message.req_getBlockDetailsByNumber.parseFrom(data);
                    long latestBlkNum = this.getBestBlock().getNumber();
                    List<Long> blkNum = req.getBlkNumbersList().parallelStream().filter(n -> n <= latestBlkNum).collect(Collectors.toSet()).parallelStream().sorted().collect(Collectors.toList());
                    if (blkNum.size() > 1000) {
                        blkNum = blkNum.subList(0, 1000);
                    }
                    List<Block> blks = getBlocksForBlkNumList(blkNum);
                    if (blks == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    } else {
                        List<Message.t_BlockDetail> bds = getRsp_getBlockDetails(blks);
                        Message.rsp_getBlockDetailsByNumber rsp = Message.rsp_getBlockDetailsByNumber.newBuilder().addAllBlkDetails(bds).build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    }
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockSqlByRange_VALUE:
            {
                if (service != Message.Servs.s_admin_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockSqlByRange req;
                try {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("BlockSqlByRange: start");
                    }
                    req = Message.req_getBlockSqlByRange.parseFrom(data);
                    long latestBlkNum = this.getBestBlock().getNumber();
                    Long _blkStart = req.getBlkNumberStart();
                    Long _blkEnd = req.getBlkNumberEnd();
                    // no null check here
                    long blkStart;
                    long blkEnd;
                    if (_blkStart < 0) {
                        blkStart = 0;
                    } else {
                        blkStart = _blkStart;
                    }
                    if (_blkEnd > latestBlkNum) {
                        blkEnd = latestBlkNum;
                    } else {
                        blkEnd = _blkEnd;
                    }
                    if (blkEnd < blkStart) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    // truncate the thing
                    if (blkEnd - blkStart > 1000) {
                        blkStart = blkEnd - 1000 + 1;
                        if (blkStart < 0) {
                            blkStart = 0;
                        }
                    }
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("BlockSqlByRange: range " + blkStart + "-" + blkEnd);
                    }
                    Long lastBlockTimestamp = null;
                    long listLength = blkEnd - blkStart + 1;
                    List<Message.t_BlockSql> bds = new ArrayList<>();
                    for (int i = 0; i < listLength; i++) {
                        long blkNum = blkStart + i;
                        Block b = getBlock(blkNum);
                        long blocktime;
                        if (blkNum != 0 && lastBlockTimestamp == null) {
                            lastBlockTimestamp = getBlock(blkNum - 1).getTimestamp();
                        }
                        if (blkNum == 0) {
                            blocktime = 0;
                        } else {
                            blocktime = b.getTimestamp() - lastBlockTimestamp;
                        }
                        lastBlockTimestamp = b.getTimestamp();
                        String blockSql = generateBlockSqlStatement(b, b.getTotalDifficulty(), blocktime);
                        List<String> transactionSql = new ArrayList<>();
                        AionBlockSummary bs = null;
                        if (explorerBlockCache != null) {
                            // remove from cache since after consumed, we're probably not gonna
                            // revisit it
                            bs = explorerBlockCache.remove(b.getHashWrapper());
                        }
                        if (bs != null) {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("BlockSqlByRange: cache HIT for #: " + b.getNumber());
                            }
                            Map<ByteArrayWrapper, AionTxReceipt> receipts = new HashMap<>();
                            for (AionTxReceipt r : bs.getReceipts()) {
                                receipts.put(ByteArrayWrapper.wrap(r.getTransaction().getTransactionHash()), r);
                            }
                            List<AionTransaction> txns = b.getTransactionsList();
                            for (int j = 0; j < txns.size(); j++) {
                                AionTransaction tx = txns.get(j);
                                AionTxReceipt r = receipts.get(ByteArrayWrapper.wrap(tx.getTransactionHash()));
                                if (r == null) {
                                    if (LOG.isDebugEnabled()) {
                                        LOG.debug("BlockSqlByRange: transaction not in Block Summary: " + b.getNumber() + "." + j);
                                    }
                                    AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
                                    r = ti.getReceipt();
                                }
                                if (r == null) {
                                    LOG.error("BlockSqlByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
                                } else {
                                    transactionSql.add(generateTransactionSqlStatement(b, tx, r.getLogInfoList(), j, r.getEnergyUsed()));
                                }
                            }
                        } else {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("BlockSqlByRange: cache MISS for #: " + b.getNumber());
                            }
                            List<AionTransaction> txs = b.getTransactionsList();
                            transactionSql = txs.parallelStream().filter(Objects::nonNull).map((AionTransaction tx) -> {
                                AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
                                if (ti == null) {
                                    LOG.error("BlockSqlByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
                                    return null;
                                } else {
                                    return generateTransactionSqlStatement(b, tx, ti.getReceipt().getLogInfoList(), ti.getIndex(), ti.getReceipt().getEnergyUsed());
                                }
                            }).filter(Objects::nonNull).collect(Collectors.toList());
                        }
                        Message.t_BlockSql sqlObj = Message.t_BlockSql.newBuilder().setBlockNumber(b.getNumber()).setBlockHash(ByteUtil.toHexString(b.getHash())).setParentHash(ByteUtil.toHexString(b.getParentHash())).setBlock(blockSql).addAllTx(transactionSql).build();
                        bds.add(sqlObj);
                    }
                    Message.rsp_getBlockSqlByRange rsp = Message.rsp_getBlockSqlByRange.newBuilder().addAllBlkSql(bds).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockDetailsByRange_VALUE:
            {
                if (service != Message.Servs.s_admin_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockDetailsByRange req;
                try {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("getBlockDetailsByRange: start");
                    }
                    req = Message.req_getBlockDetailsByRange.parseFrom(data);
                    long latestBlkNum = this.getBestBlock().getNumber();
                    Long _blkStart = req.getBlkNumberStart();
                    Long _blkEnd = req.getBlkNumberEnd();
                    // no null check here
                    long blkStart;
                    long blkEnd;
                    if (_blkStart < 0) {
                        blkStart = 0;
                    } else {
                        blkStart = _blkStart;
                    }
                    // blocks requested in the future. return empty result
                    if (blkStart > latestBlkNum) {
                        Message.rsp_getBlockDetailsByRange rsp = Message.rsp_getBlockDetailsByRange.newBuilder().addAllBlkDetails(new ArrayList<>()).build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    }
                    if (_blkEnd > latestBlkNum) {
                        blkEnd = latestBlkNum;
                    } else {
                        blkEnd = _blkEnd;
                    }
                    if (blkEnd < blkStart) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    // truncate at the beginning of range
                    if (blkEnd - blkStart > 1000) {
                        blkStart = blkEnd - 1000 + 1;
                        if (blkStart < 0) {
                            blkStart = 0;
                        }
                    }
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("getBlockDetailsByRange: range " + blkStart + "-" + blkEnd);
                    }
                    Long lastBlockTimestamp = null;
                    long listLength = blkEnd - blkStart + 1;
                    List<Message.t_BlockDetail> bds = new ArrayList<>();
                    for (int i = 0; i < listLength; i++) {
                        long blkNum = blkStart + i;
                        Block b = getBlockWithInfo(blkNum);
                        if (b == null) {
                            throw new NullPointerException("Can retrieve the block#" + blkNum + "in the database!");
                        }
                        long blocktime = 0;
                        if (b.getNumber() > 0 && lastBlockTimestamp == null) {
                            lastBlockTimestamp = getBlockByHash(b.getParentHash()).getTimestamp();
                        }
                        if (lastBlockTimestamp != null) {
                            blocktime = b.getTimestamp() - lastBlockTimestamp;
                        }
                        lastBlockTimestamp = b.getTimestamp();
                        Message.t_BlockDetail.Builder blockDetails = getBlockDetailsObj(b, blocktime);
                        List<Message.t_TxDetail> txDetails = new ArrayList<>();
                        AionBlockSummary bs = null;
                        if (explorerBlockCache != null) {
                            // remove from cache since after consumed, we're probably not gonna
                            // revisit it
                            bs = explorerBlockCache.remove(b.getHashWrapper());
                        }
                        if (bs != null) {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("getBlockDetailsByRange: cache HIT for #: " + b.getNumber());
                            }
                            Map<ByteArrayWrapper, AionTxReceipt> receipts = new HashMap<>();
                            for (AionTxReceipt r : bs.getReceipts()) {
                                receipts.put(ByteArrayWrapper.wrap(r.getTransaction().getTransactionHash()), r);
                            }
                            List<AionTransaction> txns = b.getTransactionsList();
                            for (int j = 0; j < txns.size(); j++) {
                                AionTransaction tx = txns.get(j);
                                AionTxReceipt r = receipts.get(ByteArrayWrapper.wrap(tx.getTransactionHash()));
                                if (r == null) {
                                    if (LOG.isDebugEnabled()) {
                                        LOG.debug("getBlockDetailsByRange: transaction not in Block Summary: " + b.getNumber() + "." + j);
                                    }
                                    AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
                                    r = ti.getReceipt();
                                }
                                if (r == null) {
                                    LOG.error("getBlockDetailsByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
                                } else {
                                    txDetails.add(getTxDetailsObj(tx, r.getLogInfoList(), j, r.getEnergyUsed(), r.getError()));
                                }
                            }
                        } else {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("getBlockDetailsByRange: cache MISS for #: " + b.getNumber());
                            }
                            List<AionTransaction> txs = b.getTransactionsList();
                            txDetails = txs.parallelStream().filter(Objects::nonNull).map((AionTransaction tx) -> {
                                AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
                                if (ti == null) {
                                    LOG.error("getBlockDetailsByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
                                    return null;
                                } else {
                                    return getTxDetailsObj(tx, ti.getReceipt().getLogInfoList(), ti.getIndex(), ti.getReceipt().getEnergyUsed(), ti.getReceipt().getError());
                                }
                            }).filter(Objects::nonNull).collect(Collectors.toList());
                        }
                        bds.add(blockDetails.addAllTx(txDetails).build());
                    }
                    Message.rsp_getBlockDetailsByRange rsp = Message.rsp_getBlockDetailsByRange.newBuilder().addAllBlkDetails(bds).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlockDetailsByLatest_VALUE:
            {
                if (service != Message.Servs.s_admin_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlockDetailsByLatest req;
                try {
                    req = Message.req_getBlockDetailsByLatest.parseFrom(data);
                    // clip the requested count up to 1000
                    Long count = req.getCount();
                    if (count > 1000) {
                        count = 1000L;
                    }
                    // clip start block to 0 at the bottom
                    Long endBlock = this.getBestBlock().getNumber();
                    Long startBlock = (endBlock - count + 1) >= 0 ? (endBlock - count + 1) : 0;
                    List<Long> blkNum = LongStream.rangeClosed(startBlock, endBlock).boxed().collect(Collectors.toList());
                    List<Block> blks = getBlocksForBlkNumList(blkNum);
                    if (blks == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    } else {
                        List<Message.t_BlockDetail> bds = getRsp_getBlockDetails(blks);
                        Message.rsp_getBlockDetailsByLatest rsp = Message.rsp_getBlockDetailsByLatest.newBuilder().addAllBlkDetails(bds).build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    }
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockDetailsByLatest exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getBlocksByLatest_VALUE:
            {
                if (service != Message.Servs.s_admin_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getBlocksByLatest req;
                try {
                    req = Message.req_getBlocksByLatest.parseFrom(data);
                    // clip the requested count up to 1000
                    Long count = req.getCount();
                    if (count > 1000) {
                        count = 1000L;
                    }
                    // clip start block to 0 at the bottom
                    Long endBlock = this.getBestBlock().getNumber();
                    Long startBlock = (endBlock - count + 1) >= 0 ? (endBlock - count + 1) : 0;
                    List<Long> blkNum = LongStream.rangeClosed(startBlock, endBlock).boxed().collect(Collectors.toList());
                    List<Block> blks = getBlocksForBlkNumList(blkNum);
                    if (blks == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    } else {
                        List<Message.t_Block> bs = getRsp_getBlocks(blks);
                        Message.rsp_getBlocksByLatest rsp = Message.rsp_getBlocksByLatest.newBuilder().addAllBlks(bs).build();
                        byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                        return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                    }
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlocksByLatest exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        case Message.Funcs.f_getAccountDetailsByAddressList_VALUE:
            {
                if (service != Message.Servs.s_admin_VALUE) {
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
                }
                byte[] data = parseMsgReq(request, msgHash);
                Message.req_getAccountDetailsByAddressList req;
                try {
                    req = Message.req_getAccountDetailsByAddressList.parseFrom(data);
                    List<ByteString> num = req.getAddressesList();
                    if (num.size() > 1000) {
                        num = num.subList(0, 1000);
                    }
                    List<Message.t_AccountDetail> accounts = num.parallelStream().map(a -> {
                        BigInteger b = this.getBalance(new AionAddress(a.toByteArray()));
                        Message.t_AccountDetail.Builder builder = Message.t_AccountDetail.newBuilder();
                        if (b != null) {
                            builder.setBalance(ByteString.copyFrom(b.toByteArray()));
                        }
                        builder.setAddress(a);
                        return builder.build();
                    }).collect(Collectors.toList());
                    if (accounts == null) {
                        return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
                    }
                    Message.rsp_getAccountDetailsByAddressList rsp = Message.rsp_getAccountDetailsByAddressList.newBuilder().addAllAccounts(accounts).build();
                    byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
                    return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
                } catch (Exception e) {
                    LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
                    return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
                }
            }
        // case Message.Funcs.f_getWork_VALUE:
        default:
            return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
    }
}
Also used : Funcs(org.aion.api.server.pb.Message.Funcs) Arrays(java.util.Arrays) ApiTxResponse(org.aion.api.server.ApiTxResponse) ArgTxCall(org.aion.api.server.types.ArgTxCall) Seal(org.aion.zero.impl.types.BlockHeader.Seal) Version(org.aion.zero.impl.Version) NodeWrapper(org.aion.zero.impl.sync.NodeWrapper) LRUMap(org.apache.commons.collections4.map.LRUMap) AionTxReceipt(org.aion.base.AionTxReceipt) ByteBuffer(java.nio.ByteBuffer) FltrCt(org.aion.api.server.types.FltrCt) AddressUtils(org.aion.util.types.AddressUtils) Map(java.util.Map) BigInteger(java.math.BigInteger) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) IApiAion(org.aion.api.server.IApiAion) AionAddress(org.aion.types.AionAddress) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) Fltr(org.aion.api.server.types.Fltr) Keystore(org.aion.zero.impl.keystore.Keystore) Set(java.util.Set) BlockingQueue(java.util.concurrent.BlockingQueue) ByteUtil(org.aion.util.bytes.ByteUtil) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) Collectors(java.util.stream.Collectors) EvtTx(org.aion.api.server.types.EvtTx) EventCallback(org.aion.evtmgr.impl.callback.EventCallback) TxRecpt(org.aion.api.server.types.TxRecpt) ByteString(com.google.protobuf.ByteString) Objects(java.util.Objects) TxUtil(org.aion.base.TxUtil) EquihashMiner(org.aion.equihash.EquihashMiner) List(java.util.List) StringUtils(org.aion.util.string.StringUtils) Entry(java.util.Map.Entry) PendingTransactionState(org.aion.zero.impl.pendingState.PendingTransactionState) Optional(java.util.Optional) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) SyncInfo(org.aion.api.server.types.SyncInfo) EvtContract(org.aion.api.server.types.EvtContract) CfgAion(org.aion.zero.impl.config.CfgAion) AionHub(org.aion.zero.impl.blockchain.AionHub) Hash256(org.aion.util.types.Hash256) Servs(org.aion.api.server.pb.Message.Servs) IEvent(org.aion.evtmgr.IEvent) HashMap(java.util.HashMap) EventBlock(org.aion.evtmgr.impl.evt.EventBlock) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) AccountManager(org.aion.api.server.account.AccountManager) IAionChain(org.aion.zero.impl.blockchain.IAionChain) Retcode(org.aion.api.server.pb.Message.Retcode) StakingBlock(org.aion.zero.impl.types.StakingBlock) ApiAion(org.aion.api.server.ApiAion) IHandler(org.aion.evtmgr.IHandler) LongStream(java.util.stream.LongStream) ApiUtil(org.aion.api.server.ApiUtil) Hex(org.aion.util.conversions.Hex) Log(org.aion.types.Log) TxRecptLg(org.aion.api.server.types.TxRecptLg) EventExecuteService(org.aion.evtmgr.impl.es.EventExecuteService) CompiledContr(org.aion.api.server.types.CompiledContr) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl) AbstractMap(java.util.AbstractMap) EMPTY_BYTE_ARRAY(org.aion.util.bytes.ByteUtil.EMPTY_BYTE_ARRAY) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) AionTransaction(org.aion.base.AionTransaction) Collections(java.util.Collections) TxPendingStatus(org.aion.api.server.types.TxPendingStatus) JSONArray(org.json.JSONArray) AionTxInfo(org.aion.zero.impl.types.AionTxInfo) ByteString(com.google.protobuf.ByteString) ArrayList(java.util.ArrayList) ByteString(com.google.protobuf.ByteString) CompiledContr(org.aion.api.server.types.CompiledContr) SyncInfo(org.aion.api.server.types.SyncInfo) TxRecptLg(org.aion.api.server.types.TxRecptLg) AionTxReceipt(org.aion.base.AionTxReceipt) LRUMap(org.apache.commons.collections4.map.LRUMap) Map(java.util.Map) HashMap(java.util.HashMap) AbstractMap(java.util.AbstractMap) Set(java.util.Set) HashSet(java.util.HashSet) Entry(java.util.Map.Entry) TxRecpt(org.aion.api.server.types.TxRecpt) NodeWrapper(org.aion.zero.impl.sync.NodeWrapper) ArgTxCall(org.aion.api.server.types.ArgTxCall) AionBlockSummary(org.aion.zero.impl.types.AionBlockSummary) List(java.util.List) ArrayList(java.util.ArrayList) AionAddress(org.aion.types.AionAddress) Optional(java.util.Optional) BigInteger(java.math.BigInteger) MiningBlock(org.aion.zero.impl.types.MiningBlock) Block(org.aion.zero.impl.types.Block) EventBlock(org.aion.evtmgr.impl.evt.EventBlock) StakingBlock(org.aion.zero.impl.types.StakingBlock) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) JSONArray(org.json.JSONArray) AionTransaction(org.aion.base.AionTransaction) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) FltrCt(org.aion.api.server.types.FltrCt) ApiTxResponse(org.aion.api.server.ApiTxResponse) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl)

Aggregations

TxRecpt (org.aion.api.server.types.TxRecpt)9 Block (org.aion.zero.impl.types.Block)7 MiningBlock (org.aion.zero.impl.types.MiningBlock)7 AionTransaction (org.aion.base.AionTransaction)6 AionTxInfo (org.aion.zero.impl.types.AionTxInfo)5 JSONArray (org.json.JSONArray)5 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)4 Hex.toHexString (org.aion.util.conversions.Hex.toHexString)4 StakingBlock (org.aion.zero.impl.types.StakingBlock)4 JSONObject (org.json.JSONObject)4 AionBlockchainImpl (org.aion.zero.impl.blockchain.AionBlockchainImpl)3 BigInteger (java.math.BigInteger)2 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Map (java.util.Map)2 Entry (java.util.Map.Entry)2 Optional (java.util.Optional)2