Search in sources :

Example 1 with AionBlockchainImpl

use of org.aion.zero.impl.blockchain.AionBlockchainImpl 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)

Example 2 with AionBlockchainImpl

use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.

the class ApiAion0 method getRsp_getBlockDetails.

private List<Message.t_BlockDetail> getRsp_getBlockDetails(List<Block> blks) {
    return blks.parallelStream().filter(Objects::nonNull).map(blk -> {
        Message.t_BlockDetail.Builder builder;
        if (blk.getHeader().getSealType() == Seal.PROOF_OF_WORK) {
            MiningBlock b = (MiningBlock) blk;
            builder = Message.t_BlockDetail.newBuilder().setBlockNumber(b.getNumber()).setDifficulty(ByteString.copyFrom(b.getDifficulty())).setExtraData(ByteString.copyFrom(b.getExtraData())).setHash(ByteString.copyFrom(b.getHash())).setLogsBloom(ByteString.copyFrom(b.getLogBloom())).setMinerAddress(ByteString.copyFrom(b.getCoinbase().toByteArray())).setNonce(ByteString.copyFrom(b.getNonce())).setNrgConsumed(b.getNrgConsumed()).setNrgLimit(b.getNrgLimit()).setParentHash(ByteString.copyFrom(b.getParentHash())).setTimestamp(b.getTimestamp()).setTxTrieRoot(ByteString.copyFrom(b.getTxTrieRoot())).setReceiptTrieRoot(ByteString.copyFrom(b.getReceiptsRoot())).setStateRoot(ByteString.copyFrom(b.getStateRoot())).setSize(b.size()).setSolution(ByteString.copyFrom(b.getHeader().getSolution())).setTotalDifficulty(ByteString.copyFrom(blk.getTotalDifficulty().toByteArray()));
        } else if (blk.getHeader().getSealType() == Seal.PROOF_OF_STAKE) {
            StakingBlock b = (StakingBlock) blk;
            builder = Message.t_BlockDetail.newBuilder().setBlockNumber(b.getNumber()).setDifficulty(ByteString.copyFrom(b.getDifficulty())).setExtraData(ByteString.copyFrom(b.getExtraData())).setHash(ByteString.copyFrom(b.getHash())).setLogsBloom(ByteString.copyFrom(b.getLogBloom())).setMinerAddress(ByteString.copyFrom(b.getCoinbase().toByteArray())).setNonce(ByteString.copyFrom(new byte[0])).setNrgConsumed(b.getNrgConsumed()).setNrgLimit(b.getNrgLimit()).setParentHash(ByteString.copyFrom(b.getParentHash())).setTimestamp(b.getTimestamp()).setTxTrieRoot(ByteString.copyFrom(b.getTxTrieRoot())).setReceiptTrieRoot(ByteString.copyFrom(b.getReceiptsRoot())).setStateRoot(ByteString.copyFrom(b.getStateRoot())).setSize(b.size()).setSolution(ByteString.copyFrom(new byte[0])).setTotalDifficulty(ByteString.copyFrom(blk.getTotalDifficulty().toByteArray()));
        } else {
            throw new IllegalStateException("Invalid block type!");
        }
        List<AionTransaction> txs = blk.getTransactionsList();
        List<Message.t_TxDetail> tds = txs.parallelStream().filter(Objects::nonNull).map((AionTransaction tx) -> {
            AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), blk.getHeader().getHash());
            List<Message.t_LgEle> tles = ti.getReceipt().getLogInfoList().parallelStream().map(log -> {
                List<String> topics = new ArrayList<>();
                for (int i = 0; i < log.copyOfTopics().size(); i++) {
                    topics.add(StringUtils.toJsonHex(log.copyOfTopics().get(i)));
                }
                return Message.t_LgEle.newBuilder().setData(ByteString.copyFrom(log.copyOfData())).setAddress(ByteString.copyFrom(log.copyOfAddress())).addAllTopics(topics).build();
            }).filter(Objects::nonNull).collect(Collectors.toList());
            Message.t_TxDetail.Builder tdBuilder = Message.t_TxDetail.newBuilder().setData(ByteString.copyFrom(tx.getData())).setTo(ByteString.copyFrom(tx.getDestinationAddress() == null ? EMPTY_BYTE_ARRAY : tx.getDestinationAddress().toByteArray())).setFrom(ByteString.copyFrom(tx.getSenderAddress().toByteArray())).setNonce(ByteString.copyFrom(tx.getNonce())).setValue(ByteString.copyFrom(tx.getValue())).setNrgConsumed(ti.getReceipt().getEnergyUsed()).setNrgPrice(tx.getEnergyPrice()).setTxHash(ByteString.copyFrom(tx.getTransactionHash())).setTxIndex(ti.getIndex()).setType(ByteString.copyFrom(new byte[] { tx.getType() })).addAllLogs(tles);
            return tdBuilder.build();
        }).filter(Objects::nonNull).collect(Collectors.toList());
        return builder.addAllTx(tds).build();
    }).filter(Objects::nonNull).collect(Collectors.toList());
}
Also used : AionTxInfo(org.aion.zero.impl.types.AionTxInfo) ArrayList(java.util.ArrayList) AionTransaction(org.aion.base.AionTransaction) ByteString(com.google.protobuf.ByteString) MiningBlock(org.aion.zero.impl.types.MiningBlock) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl) StakingBlock(org.aion.zero.impl.types.StakingBlock)

Example 3 with AionBlockchainImpl

use of org.aion.zero.impl.blockchain.AionBlockchainImpl 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 4 with AionBlockchainImpl

use of org.aion.zero.impl.blockchain.AionBlockchainImpl 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 5 with AionBlockchainImpl

use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.

the class Cli method call.

private ReturnType call(final String[] args, CfgAion cfg, boolean initializeAvm) {
    final CommandLine.ParseResult parseResult;
    try {
        // the pre-process method handles arguments that are separated by space
        // parsing populates the options object
        parseResult = parser.parseArgs(Arguments.preProcess(args));
    } catch (Exception e) {
        System.out.println("Unable to parse the input arguments due to: ");
        if (e.getMessage() != null) {
            System.out.println(e.getMessage());
        } else {
            e.printStackTrace();
        }
        System.out.println();
        printHelp();
        return ERROR;
    }
    // make sure that there is no conflicting arguments; otherwise send warning
    checkArguments(options, parseResult);
    try {
        if (options.isHelp()) {
            printHelp();
            return EXIT;
        }
        if (options.isVersion() || options.isVersionTag()) {
            if (options.isVersion()) {
                System.out.println("\nVersion");
                System.out.println("--------------------------------------------");
            }
            System.out.println(Version.KERNEL_VERSION);
            return EXIT;
        }
        if (options.getNetwork() != null || (options.getConfig() != null && !options.getConfig().isEmpty())) {
            String strNet = options.getNetwork();
            // the network given in config overwrites the -n option
            if (options.getConfig() != null && !options.getConfig().isEmpty()) {
                strNet = options.getConfig();
            }
            setNetwork(strNet, cfg);
        // no return -> allow for other parameters combined with -n
        }
        if (options.getDirectory() != null) {
            if (!setDirectory(options.getDirectory(), cfg)) {
                return ERROR;
            }
        // no return -> allow for other parameters combined with -d
        }
        // reading from correct config file
        File configFile = cfg.getExecConfigFile();
        if (!configFile.exists()) {
            configFile = cfg.getInitialConfigFile();
        } else {
            cfg.setReadConfigFile(configFile);
        }
        // reading from correct fork file
        File forkFile = cfg.getForkFile();
        if (forkFile != null && forkFile.exists()) {
            cfg.setForkProperties(cfg.getNetwork(), forkFile);
        }
        // true means the UUID must be set
        boolean overwrite = cfg.fromXML(configFile);
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ initialize the avm ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (initializeAvm) {
            try {
                // Grab the project root directory.
                String projectRootDirectory = System.getProperty("user.dir") + File.separator;
                // Create the multi-version schedule. Note that avm version 1 is always enabled, from block zero
                // because it handles balance transfers. The kernel is responsible for ensuring it is not called
                // with anything else.
                Properties forkProperties = CfgAion.inst().getFork().getProperties();
                String fork2 = forkProperties.getProperty("fork1.0");
                AvmVersionSchedule schedule;
                if (fork2 != null) {
                    schedule = AvmVersionSchedule.newScheduleForBothVersions(0, Long.valueOf(fork2), 100);
                } else {
                    schedule = AvmVersionSchedule.newScheduleForOnlySingleVersionSupport(0, 100);
                }
                AvmConfigurations.initializeConfigurationsAsReadOnly(schedule, projectRootDirectory);
            } catch (Exception e) {
                System.out.println("A fatal error occurred attempting to configure the AVM: " + e.getMessage());
                System.exit(SystemExitCodes.INITIALIZATION_ERROR);
            }
        }
        // determine the port configuration, can be combined with the -n, -d, -c, -i arguments
        if (parseResult.subcommand() != null && parseResult.subcommand().commandSpec().userObject().getClass() == EditCli.class && editCli.runCommand(cfg)) {
            overwrite = true;
        }
        if (editCli.help) {
            return ReturnType.EXIT;
        }
        if (options.getPort() != null) {
            int currentPort = cfg.getNet().getP2p().getPort();
            int portNumber = currentPort;
            boolean validPort = true;
            try {
                portNumber = Integer.parseInt(options.getPort());
            } catch (NumberFormatException e) {
                validPort = false;
                System.out.println("Port must be a positive integer value");
            }
            if (portNumber < 0 || portNumber > 0xFFFF) {
                validPort = false;
                System.out.println("Port out of range: " + portNumber);
            }
            if (validPort && portNumber != currentPort) {
                // update port in config
                cfg.getNet().getP2p().setPort(portNumber);
                overwrite = true;
                System.out.println("Port set to: " + portNumber);
            } else {
                System.out.println("Using the current port configuration: " + currentPort);
            }
        // no return, allow for other parameters combined with -p
        }
        if (options.getConfig() != null) {
            // if the directory was set we generate a new file
            if (options.getDirectory() != null) {
                configFile = cfg.getExecConfigFile();
                // ensure path exists
                File dir = cfg.getExecConfigDirectory();
                if (!dir.exists()) {
                    if (!dir.mkdirs()) {
                        System.out.println("ERROR: Unable to create directory: " + getRelativePath(dir.getAbsolutePath()));
                        return ERROR;
                    }
                }
                try {
                    configFile.createNewFile();
                } catch (IOException e) {
                    System.out.println("ERROR: Unable to create file: " + getRelativePath(configFile.getAbsolutePath()));
                    return ERROR;
                }
            }
            // save to disk
            cfg.toXML(null, configFile);
            System.out.println("\nNew config generated at: " + getRelativePath(configFile.getAbsolutePath()));
            return ReturnType.EXIT;
        }
        if (options.isInfo()) {
            System.out.println("Reading config file from: " + getRelativePath(configFile.getAbsolutePath()));
            if (overwrite) {
                // updating the file in case the user id was not set; overwrite port
                cfg.toXML(null, configFile);
            }
            printInfo(cfg);
            return ReturnType.EXIT;
        }
        // make directories for kernel execution
        makeDirs(configFile, forkFile, cfg);
        if (overwrite) {
            // updating the file in case the user id was not set; overwrite port
            cfg.toXML(null, cfg.getExecConfigFile());
        }
        // set correct keystore directory
        Keystore.setKeystorePath(cfg.getKeystoreDir().getAbsolutePath());
        CommandSpec commandSpec = findCommandSpec(parseResult, AccountCli.class);
        if (commandSpec != null) {
            return ((AccountCli) commandSpec.userObject()).runCommand(passwordReader);
        }
        if (options.getSsl() != null) {
            String[] parameters = options.getSsl();
            if (parameters.length == 0 || parameters.length == 2) {
                createKeystoreDirIfMissing();
                Console console = System.console();
                checkConsoleExists(console);
                List<String> scriptArgs = new ArrayList<>();
                scriptArgs.add("/bin/bash");
                scriptArgs.add("script/generateSslCert.sh");
                scriptArgs.add(getCertName(console));
                scriptArgs.add(getCertPass(console));
                // add the hostname and ip optionally passed in as cli args
                scriptArgs.addAll(Arrays.asList(parameters));
                new ProcessBuilder(scriptArgs).inheritIO().start().waitFor();
                return EXIT;
            } else {
                System.out.println("Incorrect usage of -s create command.\n" + "Command must enter both hostname AND ip or else neither one.");
                return ERROR;
            }
        }
        if (options.isRebuildBlockInfo()) {
            System.out.println("Starting database clean-up.");
            CfgAion.inst().dbFromXML();
            Map<LogEnum, LogLevel> cfgLog = new HashMap<>();
            cfgLog.put(LogEnum.GEN, LogLevel.INFO);
            AionLoggerFactory.initAll(cfgLog);
            // get the current blockchain
            AionRepositoryImpl repository = AionRepositoryImpl.inst();
            repository.pruneAndCorrectBlockStore(AionLoggerFactory.getLogger(LogEnum.GEN.name()));
            repository.close();
            System.out.println("Finished database clean-up.");
            return EXIT;
        }
        if (options.getRevertToBlock() != null) {
            String block = options.getRevertToBlock();
            if (revertTo(block)) {
                System.out.println("Blockchain successfully reverted to block number " + block + ".");
                return EXIT;
            } else {
                System.out.println("Unable to revert to block number " + block + ".");
                return ERROR;
            }
        }
        if (options.getPruneStateOption() != null) {
            String pruning_type = options.getPruneStateOption();
            try {
                // ensure mining is disabled
                CfgAion localCfg = CfgAion.inst();
                localCfg.fromXML();
                localCfg.getConsensus().setMining(false);
                // setting pruning to the version requested
                CfgDb.PruneOption option = CfgDb.PruneOption.fromValue(pruning_type);
                localCfg.getDb().setPrune(option.toString());
                AionLoggerFactory.initAll(Map.of(LogEnum.GEN, LogLevel.INFO));
                final Logger log = AionLoggerFactory.getLogger(LogEnum.GEN.name());
                log.info("Reorganizing the state storage to " + option + " mode ...");
                AionBlockchainImpl chain = new AionBlockchainImpl(localCfg, null, false);
                chain.pruneOrRecoverState(pruning_type.equals("spread"), localCfg.getGenesis(), log);
                chain.close();
                return EXIT;
            } catch (Exception e) {
                System.out.println("Reorganizing the state storage FAILED due to:");
                e.printStackTrace();
                return ERROR;
            }
        }
        CommandLine.Model.CommandSpec spec = findCommandSpec(parseResult, DevCLI.class);
        if (spec != null) {
            ReturnType returnType = ((DevCLI) spec.userObject()).runCommand();
            if (returnType != RUN) {
                return returnType;
            }
        }
        if (options.isDbCompact()) {
            // read database configuration
            CfgAion.inst().dbFromXML();
            AionLoggerFactory.initAll(Map.of(LogEnum.DB, LogLevel.INFO));
            // get the current blockchain
            AionRepositoryImpl repository = AionRepositoryImpl.inst();
            // compact database after the changes were applied
            repository.compact();
            repository.close();
            return EXIT;
        }
        if (options.isRedoImport() != null) {
            long height = 0L;
            String parameter = options.isRedoImport();
            // ensure mining is disabled
            CfgAion localCfg = CfgAion.inst();
            localCfg.dbFromXML();
            localCfg.getConsensus().setMining(false);
            AionLoggerFactory.initAll(Map.of(LogEnum.GEN, LogLevel.INFO));
            final Logger log = AionLoggerFactory.getLogger(LogEnum.GEN.name());
            if (height < 0) {
                log.error("Negative values are not valid as starting height. Nothing to do.");
                return ERROR;
            }
            log.info("Importing stored blocks INITIATED...");
            AionBlockchainImpl chain = new AionBlockchainImpl(localCfg, null, false);
            if (parameter.isEmpty()) {
                chain.redoMainChainImport(height, localCfg.getGenesis(), log);
                chain.close();
                return EXIT;
            } else {
                try {
                    height = Long.parseLong(parameter);
                } catch (NumberFormatException e) {
                    log.error("The given argument «" + parameter + "» cannot be converted to a number.");
                    chain.close();
                    return ERROR;
                }
                chain.redoMainChainImport(height, localCfg.getGenesis(), log);
                chain.close();
                return EXIT;
            }
        }
        // if no return happened earlier, run the kernel
        return RUN;
    } catch (Exception e) {
        // TODO: should be moved to individual procedures
        System.out.println();
        e.printStackTrace();
        return ERROR;
    }
}
Also used : CfgDb(org.aion.zero.impl.config.CfgDb) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AionRepositoryImpl(org.aion.zero.impl.db.AionRepositoryImpl) Properties(java.util.Properties) Logger(org.slf4j.Logger) LogLevel(org.aion.log.LogLevel) LogEnum(org.aion.log.LogEnum) CommandSpec(picocli.CommandLine.Model.CommandSpec) Console(java.io.Console) CommandSpec(picocli.CommandLine.Model.CommandSpec) AvmVersionSchedule(org.aion.zero.impl.vm.avm.schedule.AvmVersionSchedule) IOException(java.io.IOException) IOException(java.io.IOException) CfgAion(org.aion.zero.impl.config.CfgAion) CommandLine(picocli.CommandLine) AionBlockchainImpl(org.aion.zero.impl.blockchain.AionBlockchainImpl) File(java.io.File)

Aggregations

AionBlockchainImpl (org.aion.zero.impl.blockchain.AionBlockchainImpl)10 MiningBlock (org.aion.zero.impl.types.MiningBlock)7 StakingBlock (org.aion.zero.impl.types.StakingBlock)7 Block (org.aion.zero.impl.types.Block)6 AionTransaction (org.aion.base.AionTransaction)5 ArrayList (java.util.ArrayList)4 CfgAion (org.aion.zero.impl.config.CfgAion)4 AionTxInfo (org.aion.zero.impl.types.AionTxInfo)4 JSONArray (org.json.JSONArray)4 BigInteger (java.math.BigInteger)3 HashMap (java.util.HashMap)3 TxRecpt (org.aion.api.server.types.TxRecpt)3 Hex.toHexString (org.aion.util.conversions.Hex.toHexString)3 ByteString (com.google.protobuf.ByteString)2 IOException (java.io.IOException)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 List (java.util.List)2 Map (java.util.Map)2 Entry (java.util.Map.Entry)2