use of org.aion.util.bytes.ByteUtil.EMPTY_BYTE_ARRAY 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);
}
}
Aggregations