Search in sources :

Example 96 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class PendingBlockStore method addBlockRange.

/**
 * Attempts to store a range of blocks in the pending block store for importing later when the
 * chain reaches the needed height and the parent blocks gets imported.
 *
 * @param blocks a range of blocks that cannot be imported due to height or lack of parent block
 * @param log external {@link Logger} for displaying messages
 * @return an integer value (ranging from zero to the number of given blocks) representing the
 *     number of blocks that were stored from the given input.
 * @implNote The functionality is optimized for calls providing consecutive blocks, but ensures
 *     correct behavior even when the blocks are not consecutive.
 */
public int addBlockRange(List<Block> blocks, Logger log) {
    List<Block> blockRange = new ArrayList<>(blocks);
    // nothing to do when 0 blocks given
    if (blockRange.isEmpty()) {
        return 0;
    }
    databaseLock.writeLock().lock();
    try {
        // first block determines the batch queue placement
        Block first = blockRange.remove(0);
        int stored = addBlockRange(first, blockRange);
        // save data to disk
        indexSource.commit();
        levelSource.commit();
        queueSource.commit();
        log.debug("<import-status: STORED {} out of {} blocks, starting with block #{} hash={}>", stored, blocks.size(), first.getNumber(), first.getShortHash());
        // the number of blocks added
        return stored;
    } catch (Exception e) {
        log.error("Unable to store range of blocks due to: ", e);
        return 0;
    } finally {
        databaseLock.writeLock().unlock();
    }
}
Also used : ArrayList(java.util.ArrayList) Block(org.aion.zero.impl.types.Block) IOException(java.io.IOException)

Example 97 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class PendingBlockStore method loadBlockRange.

/**
 * Retrieves blocks from storage based on the height of the first block in the range.
 *
 * @param level the height / number of the first block in the queues to be retrieved
 * @param log the logger used for messages
 * @return a map of queue identifiers and lists of blocks containing all the separate chain
 *     queues stored at that level.
 */
public Map<ByteArrayWrapper, List<Block>> loadBlockRange(long level, Logger log) {
    databaseLock.readLock().lock();
    try {
        // get the queue for the given level
        List<byte[]> queueHashes = levelSource.get(ByteUtil.longToBytes(level));
        if (queueHashes == null) {
            return Collections.emptyMap();
        }
        // get all the blocks in the given queues
        List<Block> list;
        Map<ByteArrayWrapper, List<Block>> blocks = new HashMap<>();
        for (byte[] queue : queueHashes) {
            list = queueSource.get(queue);
            if (list != null) {
                ByteArrayWrapper key = ByteArrayWrapper.wrap(queue);
                blocks.put(key, list);
                log.debug("Loaded {} blocks from disk from level={} queue={} before filtering.", list.size(), key, level);
            }
        }
        return blocks;
    } catch (Exception e) {
        log.error("Unable to retrieve stored blocks due to: ", e);
        return Collections.emptyMap();
    } finally {
        databaseLock.readLock().unlock();
    }
}
Also used : ByteArrayWrapper(org.aion.util.types.ByteArrayWrapper) HashMap(java.util.HashMap) Block(org.aion.zero.impl.types.Block) ArrayList(java.util.ArrayList) SharedRLPList(org.aion.rlp.SharedRLPList) RLPList(org.aion.rlp.RLPList) List(java.util.List) IOException(java.io.IOException)

Example 98 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class AionBlockStore method getListBlocksEndWith.

public List<Block> getListBlocksEndWith(byte[] hash, long qty) {
    if (hash == null || qty < 0) {
        return null;
    }
    Block block = this.blocks.get(hash);
    if (block == null) {
        return new ArrayList<>();
    }
    List<Block> result = new ArrayList<>((int) qty);
    for (int i = 0; i < qty; ++i) {
        result.add(block);
        block = this.blocks.get(block.getParentHash());
        if (block == null) {
            break;
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) Block(org.aion.zero.impl.types.Block)

Example 99 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class ApiAion0 method onBlock.

protected void onBlock(AionBlockSummary cbs) {
    Set<Long> keys = installedFilters.keySet();
    for (Long key : keys) {
        Fltr fltr = installedFilters.get(key);
        if (fltr.isExpired()) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("<fltr key={} expired removed>", key);
            }
            installedFilters.remove(key);
        } else {
            List<AionTxReceipt> txrs = cbs.getReceipts();
            if (fltr.getType() == Fltr.Type.EVENT && !Optional.ofNullable(txrs).orElse(Collections.emptyList()).isEmpty()) {
                FltrCt _fltr = (FltrCt) fltr;
                for (AionTxReceipt txr : txrs) {
                    AionTransaction tx = txr.getTransaction();
                    AionAddress contractAddress = Optional.ofNullable(tx.getDestinationAddress()).orElse(TxUtil.calculateContractAddress(tx));
                    Integer cnt = 0;
                    txr.getLogInfoList().forEach(bi -> bi.copyOfTopics().forEach(lg -> {
                        if (_fltr.isFor(contractAddress, ByteUtil.toHexString(lg))) {
                            Block blk = (cbs).getBlock();
                            List<AionTransaction> txList = blk.getTransactionsList();
                            int insideCnt = 0;
                            for (AionTransaction t : txList) {
                                if (Arrays.equals(t.getTransactionHash(), tx.getTransactionHash())) {
                                    break;
                                }
                                insideCnt++;
                            }
                            EvtContract ec = new EvtContract(bi.copyOfAddress(), bi.copyOfData(), blk.getHash(), blk.getNumber(), cnt, ByteUtil.toHexString(lg), false, insideCnt, tx.getTransactionHash());
                            _fltr.add(ec);
                        }
                    }));
                }
            }
        }
    }
}
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) AionAddress(org.aion.types.AionAddress) Fltr(org.aion.api.server.types.Fltr) EvtContract(org.aion.api.server.types.EvtContract) AionTransaction(org.aion.base.AionTransaction) FltrCt(org.aion.api.server.types.FltrCt) 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) List(java.util.List) ArrayList(java.util.ArrayList) AionTxReceipt(org.aion.base.AionTxReceipt)

Example 100 with Block

use of org.aion.zero.impl.types.Block in project aion by aionnetwork.

the class ApiAion0 method process.

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

Aggregations

Block (org.aion.zero.impl.types.Block)283 MiningBlock (org.aion.zero.impl.types.MiningBlock)155 Test (org.junit.Test)148 AionTransaction (org.aion.base.AionTransaction)106 ImportResult (org.aion.zero.impl.core.ImportResult)86 ArrayList (java.util.ArrayList)63 AionAddress (org.aion.types.AionAddress)61 StakingBlock (org.aion.zero.impl.types.StakingBlock)58 AionBlockSummary (org.aion.zero.impl.types.AionBlockSummary)57 BigInteger (java.math.BigInteger)55 AionRepositoryImpl (org.aion.zero.impl.db.AionRepositoryImpl)34 ByteArrayWrapper (org.aion.util.types.ByteArrayWrapper)30 AionTxReceipt (org.aion.base.AionTxReceipt)29 Hex.toHexString (org.aion.util.conversions.Hex.toHexString)28 AccountState (org.aion.base.AccountState)26 EventBlock (org.aion.evtmgr.impl.evt.EventBlock)26 JSONArray (org.json.JSONArray)26 JSONObject (org.json.JSONObject)26 MiningBlockHeader (org.aion.zero.impl.types.MiningBlockHeader)22 AionTxExecSummary (org.aion.base.AionTxExecSummary)20