use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.
the class ApiAion0 method process.
public byte[] process(byte[] request, byte[] socketId) {
if (request == null || (request.length < this.getApiHeaderLen())) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_header_len_VALUE);
}
byte[] msgHash = ApiUtil.getApiMsgHash(request);
if (request[0] < this.getApiVersion()) {
return msgHash == null ? ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_api_version_VALUE) : ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_api_version_VALUE, msgHash);
}
short service = (short) request[1];
switch((short) request[2]) {
// General Module
case Message.Funcs.f_protocolVersion_VALUE:
{
if (service != Message.Servs.s_net_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
// TODO : create query API for every module
Message.rsp_protocolVersion rsp = Message.rsp_protocolVersion.newBuilder().setApi(String.valueOf(this.getApiVersion())).setDb(AionHub.getRepoVersion()).setKernel(Version.KERNEL_VERSION).setMiner(EquihashMiner.VERSION).setNet(this.p2pProtocolVersion()).setTxpool(this.ac.getAionHub().getPendingState().getVersion()).setVm("0.1.0").build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_minerAddress_VALUE:
{
if (service != Message.Servs.s_wallet_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
String cb = this.getCoinbase();
if (cb == null) {
LOG.debug("ApiAion0.process.coinbase - null coinbase");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_wallet_nullcb_VALUE);
}
Message.rsp_minerAddress rsp = Message.rsp_minerAddress.newBuilder().setMinerAddr(ByteString.copyFrom(StringUtils.StringHexToByteArray(cb))).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_contractDeploy_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
}
Message.req_contractDeploy req;
byte[] data = parseMsgReq(request, msgHash);
ApiTxResponse result;
try {
req = Message.req_contractDeploy.parseFrom(data);
// TODO: the client api should send server binary code directly
// instead of str format like "0xhex".!
byte[] bytes = req.getData().toByteArray();
if (bytes == null || bytes.length <= 4) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_ct_bytecode_VALUE, msgHash);
}
ArgTxCall params = new ArgTxCall(new AionAddress(req.getFrom().toByteArray()), null, Hex.decode(new String(bytes).substring(2)), BigInteger.ZERO, BigInteger.ZERO, req.getNrgLimit(), req.getNrgPrice(), null);
LOG.debug("ApiAion0.process.ContractDeploy - ArgsTxCall: [{}] ", params.toString());
result = this.createContract(params);
if (!result.isFail()) {
getMsgIdMapping().put(ByteArrayWrapper.wrap(result.getTxHash()), new AbstractMap.SimpleEntry<>(ByteArrayWrapper.wrap(msgHash), ByteArrayWrapper.wrap(socketId)));
if (LOG.isDebugEnabled()) {
LOG.debug("ApiAion0.process.ContractDeploy - msgIdMapping.put: [{}] ", ByteArrayWrapper.wrap(result.getTxHash()).toString());
}
Message.rsp_contractDeploy rsp = Message.rsp_contractDeploy.newBuilder().setContractAddress(ByteString.copyFrom(result.getContractAddress().toByteArray())).setTxHash(ByteString.copyFrom(result.getTxHash())).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_tx_Recved_VALUE, msgHash);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} else {
return processTxFail(result, msgHash);
}
} catch (Exception e) {
LOG.error("ApiAion0.process.ContractDeploy exception [{}] ", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
}
}
// Authenication Module
case Message.Funcs.f_accounts_VALUE:
{
if (service != Message.Servs.s_wallet_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
// noinspection unchecked
List<String> accounts = this.getAccounts();
ArrayList<ByteString> al = new ArrayList<>();
for (String s : accounts) {
al.add(ByteString.copyFrom(StringUtils.StringHexToByteArray(s)));
}
Message.rsp_accounts rsp = Message.rsp_accounts.newBuilder().addAllAccout(al).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_blockNumber_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
Message.rsp_blockNumber rsp = Message.rsp_blockNumber.newBuilder().setBlocknumber(this.getBestBlock().getNumber()).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_unlockAccount_VALUE:
{
if (service != Message.Servs.s_wallet_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
boolean result;
try {
Message.req_unlockAccount req = Message.req_unlockAccount.parseFrom(data);
result = this.unlockAccount(new AionAddress(req.getAccount().toByteArray()), req.getPassword(), req.getDuration());
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.unlockAccount exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, (byte) (result ? 0x01 : 0x00));
}
// Transaction Module
case Message.Funcs.f_getBalance_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
BigInteger balance;
try {
Message.req_getBalance req = Message.req_getBalance.parseFrom(data);
AionAddress addr = new AionAddress(req.getAddress().toByteArray());
balance = this.getBalance(addr);
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.getbalance exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
Message.rsp_getBalance rsp = Message.rsp_getBalance.newBuilder().setBalance(ByteString.copyFrom(balance.toByteArray())).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_getNonce_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Message.Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
BigInteger nonce;
try {
Message.req_getNonce req = Message.req_getNonce.parseFrom(data);
AionAddress addr = new AionAddress(req.getAddress().toByteArray());
nonce = this.getNonce(addr);
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAionA0.process.getNonce exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Message.Retcode.r_fail_function_exception_VALUE);
}
Message.rsp_getNonce rsp = Message.rsp_getNonce.newBuilder().setNonce(ByteString.copyFrom(nonce.toByteArray())).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Message.Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_getNrgPrice_VALUE:
{
if (service != Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
long nrg = this.getRecommendedNrgPrice();
try {
Message.rsp_getNrgPrice rsp = Message.rsp_getNrgPrice.newBuilder().setNrgPrice(nrg).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getEnergyPrice exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_compile_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
try {
Message.req_compile req = Message.req_compile.parseFrom(data);
String source = req.getCode();
if (source == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_null_compile_source_VALUE);
}
@SuppressWarnings("unchecked") Map<String, CompiledContr> _contrs = this.contract_compileSolidity(source);
if (_contrs != null && !_contrs.isEmpty()) {
Message.rsp_compile.Builder b = Message.rsp_compile.newBuilder();
for (Entry<String, CompiledContr> entry : _contrs.entrySet()) {
if (entry.getKey().contains("compile-error")) {
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_compile_contract_VALUE);
Message.t_Contract tc = Message.t_Contract.newBuilder().setError(entry.getValue().error).build();
return ApiUtil.combineRetMsg(retHeader, b.putConstracts(entry.getKey(), tc).build().toByteArray());
}
CompiledContr _contr = entry.getValue();
JSONArray abi = new JSONArray();
for (org.aion.solidity.Entry f : _contr.info.abiDefinition) {
abi.put(f.toJSON());
}
Message.t_Contract tc = Message.t_Contract.newBuilder().setCode(_contr.code).setAbiDef(ByteString.copyFrom(abi.toString().getBytes())).setSource(_contr.info.source).build();
b.putConstracts(entry.getKey(), tc);
}
Message.rsp_compile rsp = b.build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} else {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.compile exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Funcs.f_compileSolidityZip_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
try {
Message.req_compileSolidityZip req = Message.req_compileSolidityZip.parseFrom(data);
ByteString zipfile = req.getZipfile();
String entryPoint = req.getEntryPoint();
if (zipfile == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_null_compile_source_VALUE);
}
@SuppressWarnings("unchecked") Map<String, CompiledContr> _contrs = this.contract_compileSolidityZip(zipfile.toByteArray(), entryPoint);
if (_contrs != null && !_contrs.isEmpty()) {
Message.rsp_compile.Builder b = Message.rsp_compile.newBuilder();
for (Entry<String, CompiledContr> entry : _contrs.entrySet()) {
if (entry.getKey().contains("compile-error")) {
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_compile_contract_VALUE);
Message.t_Contract tc = Message.t_Contract.newBuilder().setError(entry.getValue().error).build();
return ApiUtil.combineRetMsg(retHeader, b.putConstracts(entry.getKey(), tc).build().toByteArray());
}
CompiledContr _contr = entry.getValue();
JSONArray abi = new JSONArray();
for (org.aion.solidity.Entry f : _contr.info.abiDefinition) {
abi.put(f.toJSON());
}
Message.t_Contract tc = Message.t_Contract.newBuilder().setCode(_contr.code).setAbiDef(ByteString.copyFrom(abi.toString().getBytes())).setSource(_contr.info.source).build();
b.putConstracts(entry.getKey(), tc);
}
Message.rsp_compile rsp = b.build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} else {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.compile exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_sendTransaction_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_sendTransaction req;
ApiTxResponse result;
try {
req = Message.req_sendTransaction.parseFrom(data);
ArgTxCall params = new ArgTxCall(new AionAddress(req.getFrom().toByteArray()), new AionAddress(req.getTo().toByteArray()), req.getData().toByteArray(), new BigInteger(req.getNonce().toByteArray()), new BigInteger(req.getValue().toByteArray()), req.getNrg(), req.getNrgPrice(), null);
result = this.sendTransaction(params);
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.sendTransaction exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
}
return processSendTxRsp(result, msgHash, socketId);
}
case Message.Funcs.f_getCode_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getCode req;
try {
req = Message.req_getCode.parseFrom(data);
AionAddress to = new AionAddress(req.getAddress().toByteArray());
byte[] code = this.getCode(to);
if (code == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_null_rsp_VALUE);
}
Message.rsp_getCode rsp = Message.rsp_getCode.newBuilder().setCode(ByteString.copyFrom(code)).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getCode exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getTransactionReceipt_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getTransactionReceipt req;
try {
req = Message.req_getTransactionReceipt.parseFrom(data);
TxRecpt result = this.getTransactionReceipt(req.getTxHash().toByteArray());
if (result == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_getTxReceipt_null_recp_VALUE);
}
List<Message.t_LgEle> logs = new ArrayList<>();
for (TxRecptLg log : result.logs) {
List<String> al = new ArrayList<>();
Collections.addAll(al, log.topics);
Message.t_LgEle msgLog = Message.t_LgEle.newBuilder().setAddress(ByteString.copyFrom(AddressUtils.wrapAddress(log.address).toByteArray())).setData(ByteString.copyFrom(ByteUtil.hexStringToBytes(log.data))).addAllTopics(al).build();
logs.add(msgLog);
}
Message.rsp_getTransactionReceipt rsp = Message.rsp_getTransactionReceipt.newBuilder().setFrom(ByteString.copyFrom(result.fromAddr.toByteArray())).setBlockNumber(result.blockNumber).setBlockHash(ByteString.copyFrom(result.blockHash != null ? ByteUtil.hexStringToBytes(result.blockHash) : EMPTY_BYTE_ARRAY)).setContractAddress(ByteString.copyFrom(result.contractAddress != null ? ByteUtil.hexStringToBytes(result.contractAddress) : EMPTY_BYTE_ARRAY)).setTxIndex(result.transactionIndex).setTxHash(ByteString.copyFrom(result.transactionHash != null ? ByteUtil.hexStringToBytes(result.transactionHash) : EMPTY_BYTE_ARRAY)).setTo(ByteString.copyFrom(result.toAddr == null ? EMPTY_BYTE_ARRAY : result.toAddr.toByteArray())).setNrgConsumed(result.nrgUsed).setCumulativeNrgUsed(result.cumulativeNrgUsed).addAllLogs(logs).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getTransactionReceipt exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_call_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_call req;
try {
req = Message.req_call.parseFrom(data);
AionAddress from = new AionAddress(req.getFrom().toByteArray());
AionAddress to = new AionAddress(req.getTo().toByteArray());
BigInteger value = new BigInteger(req.getValue().toByteArray());
byte[] d = req.getData().toByteArray();
ArgTxCall params = new ArgTxCall(from, to, d, BigInteger.ZERO, value, req.getNrg(), req.getNrgPrice(), null);
Message.rsp_call rsp = Message.rsp_call.newBuilder().setResult(ByteString.copyFrom(this.doCall(params))).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.call exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockByNumber_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockByNumber req;
try {
req = Message.req_getBlockByNumber.parseFrom(data);
long num = req.getBlockNumber();
Block blk = this.getBlock(num);
return createBlockMsg(blk);
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockByNumber exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockReward_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockReward req;
BigInteger reward;
try {
req = Message.req_getBlockReward.parseFrom(data);
reward = ac.getBlockchain().calculateBlockRewards(req.getBlockNumber());
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockReward exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
Message.rsp_getBlockReward rsp = Message.rsp_getBlockReward.newBuilder().setReward(ByteString.copyFrom(reward.toByteArray())).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_getBlockByHash_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockByHash req;
try {
req = Message.req_getBlockByHash.parseFrom(data);
byte[] hash = req.getBlockHash().toByteArray();
if (hash == null || hash.length != Hash256.BYTES) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
Block blk = this.getBlockByHash(hash);
return createBlockMsg(blk);
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockByHash exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getTransactionByBlockHashAndIndex_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getTransactionByBlockHashAndIndex req;
try {
req = Message.req_getTransactionByBlockHashAndIndex.parseFrom(data);
long txIdx = req.getTxIndex();
byte[] hash = req.getBlockHash().toByteArray();
if (txIdx < -1 || hash == null || hash.length != Hash256.BYTES) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
TransactionWithBlockInfo txInfo = this.getTransactionByBlockHashAndIndex(hash, txIdx);
if (txInfo == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
Message.rsp_getTransaction rsp = getRsp_getTransaction(txInfo);
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getTransactionByBlockHashAndIndex exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getTransactionByBlockNumberAndIndex_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getTransactionByBlockNumberAndIndex req;
try {
req = Message.req_getTransactionByBlockNumberAndIndex.parseFrom(data);
long blkNr = req.getBlockNumber();
long txIdx = req.getTxIndex();
if (blkNr < -1 || txIdx < -1) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
TransactionWithBlockInfo txInfo = this.getTransactionByBlockNumberAndIndex(blkNr, txIdx);
if (txInfo == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
Message.rsp_getTransaction rsp = getRsp_getTransaction(txInfo);
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getTransactionByBlockNumberAndIndex exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockTransactionCountByNumber_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockTransactionCountByNumber req;
try {
req = Message.req_getBlockTransactionCountByNumber.parseFrom(data);
long blkNr = req.getBlockNumber();
if (blkNr < -1) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
long cnt = this.getBlockTransactionCountByNumber(blkNr);
if (cnt == -1) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
Message.rsp_getBlockTransactionCount rsp = Message.rsp_getBlockTransactionCount.newBuilder().setTxCount((int) cnt).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockTransactionCountByNumber exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getTransactionCount_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getTransactionCount req;
try {
req = Message.req_getTransactionCount.parseFrom(data);
long blkNr = req.getBlocknumber();
AionAddress addr = new AionAddress(req.getAddress().toByteArray());
if (blkNr < -1) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
long cnt = this.getTransactionCount(addr, blkNr);
if (cnt == -1) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
Message.rsp_getTransactionCount rsp = Message.rsp_getTransactionCount.newBuilder().setTxCount((int) cnt).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getTransactionCount exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockTransactionCountByHash_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getTransactionCountByHash req;
try {
req = Message.req_getTransactionCountByHash.parseFrom(data);
byte[] hash = req.getTxHash().toByteArray();
if (hash == null || hash.length != Hash256.BYTES) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
long cnt = this.getTransactionCountByHash(hash);
if (cnt == -1) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
Message.rsp_getTransactionCount rsp = Message.rsp_getTransactionCount.newBuilder().setTxCount((int) cnt).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getTransactionCount exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getTransactionByHash_VALUE:
{
if (service != Message.Servs.s_chain_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getTransactionByHash req;
try {
req = Message.req_getTransactionByHash.parseFrom(data);
byte[] txHash = req.getTxHash().toByteArray();
if (txHash == null || txHash.length != this.getTxHashLen()) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
TransactionWithBlockInfo txInfo = this.getTransactionByHash(txHash);
if (txInfo == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
Message.rsp_getTransaction rsp = getRsp_getTransaction(txInfo);
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getTransactionCount exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getActiveNodes_VALUE:
{
if (service != Message.Servs.s_net_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
List<NodeWrapper> nodes = new ArrayList<>(this.ac.getAionHub().getActiveNodes().values());
List<Message.t_Node> pl = new ArrayList<>();
try {
for (NodeWrapper n : nodes) {
Message.t_Node node = Message.t_Node.newBuilder().setBlockNumber(n.getBestBlockNumber()).setNodeId(ByteArrayWrapper.wrap(n.getId()).toString()).setRemoteP2PIp(ByteArrayWrapper.wrap(n.getIp()).toString()).build();
pl.add(node);
}
Message.rsp_getActiveNodes rsp = Message.rsp_getActiveNodes.newBuilder().addAllNode(pl).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getActiveNodes exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getStaticNodes_VALUE:
{
if (service != Message.Servs.s_net_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
String[] al = this.getBootNodes();
List<Message.t_Node> nl = new ArrayList<>();
for (String s : al) {
// TODO : get more node info
Message.t_Node n = Message.t_Node.newBuilder().setRemoteP2PIp(s).build();
nl.add(n);
}
try {
Message.rsp_getStaticNodes rsp = Message.rsp_getStaticNodes.newBuilder().addAllNode(nl).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getStaticNodes exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getSolcVersion_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
String ver = this.solcVersion();
try {
Message.rsp_getSolcVersion rsp = Message.rsp_getSolcVersion.newBuilder().setVer(ver).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getSolcVersion exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_isSyncing_VALUE:
{
if (service != Message.Servs.s_net_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
try {
Optional<Long> localBestBlockNumber = this.ac.getLocalBestBlockNumber();
Optional<Long> networkBestBlockNumber = this.ac.getNetworkBestBlockNumber();
// Check that we actually have real values in our hands.
if (!localBestBlockNumber.isPresent()) {
LOG.error("Unable to determine the local node's best block number!");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
}
if (!networkBestBlockNumber.isPresent()) {
LOG.error("Unable to determine the network's best block number!");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
}
SyncInfo syncInfo = this.getSyncInfo(localBestBlockNumber.get(), networkBestBlockNumber.get());
Message.rsp_isSyncing rsp = Message.rsp_isSyncing.newBuilder().setSyncing(!syncInfo.done).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.syncing exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_syncInfo_VALUE:
{
if (service != Message.Servs.s_net_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
Optional<Long> localBestBlockNumber = this.ac.getLocalBestBlockNumber();
Optional<Long> networkBestBlockNumber = this.ac.getNetworkBestBlockNumber();
// Check that we actually have real values in our hands.
if (!localBestBlockNumber.isPresent()) {
LOG.error("Unable to determine the local node's best block number!");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
}
if (!networkBestBlockNumber.isPresent()) {
LOG.error("Unable to determine the network's best block number!");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_VALUE);
}
SyncInfo syncInfo = this.getSyncInfo(localBestBlockNumber.get(), networkBestBlockNumber.get());
try {
Message.rsp_syncInfo rsp = Message.rsp_syncInfo.newBuilder().setChainBestBlock(syncInfo.chainBestBlkNumber).setNetworkBestBlock(syncInfo.networkBestBlkNumber).setSyncing(!syncInfo.done).setMaxImportBlocks(24).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.syncInfo exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_accountCreate_VALUE:
{
if (service != Message.Servs.s_account_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_accountCreate req;
try {
req = Message.req_accountCreate.parseFrom(data);
List<ByteString> addressList = new ArrayList<>();
List<ByteString> pKeyList = new ArrayList<>();
for (int i = 0; i < req.getPasswordList().size() && i < ACCOUNT_CREATE_LIMIT; i++) {
String addr = Keystore.create(req.getPassword(i));
byte[] pKey;
if (req.getPrivateKey()) {
pKey = Keystore.getKey(addr, req.getPassword(i)).getPrivKeyBytes();
if (pKey == null) {
pKey = new byte[] { (byte) 0x0 };
}
pKeyList.add(ByteString.copyFrom(pKey));
}
addressList.add(ByteString.copyFrom(AddressUtils.wrapAddress(addr).toByteArray()));
}
Message.rsp_accountCreate rsp = Message.rsp_accountCreate.newBuilder().addAllAddress(addressList).addAllPrivateKey(pKeyList).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.accountCreate exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_accountLock_VALUE:
{
if (service != Message.Servs.s_wallet_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
if (data == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
boolean result;
try {
Message.req_accountlock req = Message.req_accountlock.parseFrom(data);
result = this.lockAccount(new AionAddress(req.getAccount().toByteArray()), req.getPassword());
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.lockAccount exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, (byte) (result ? 0x01 : 0x00));
}
case Message.Funcs.f_userPrivilege_VALUE:
{
if (service != Message.Servs.s_privilege_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_unsupport_api_VALUE);
}
case Message.Funcs.f_mining_VALUE:
{
if (service != Message.Servs.s_mine_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
Message.rsp_mining rsp = Message.rsp_mining.newBuilder().setMining(this.isMining()).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_estimateNrg_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_estimateNrg req;
long result;
try {
req = Message.req_estimateNrg.parseFrom(data);
ArgTxCall params = new ArgTxCall(new AionAddress(req.getFrom().toByteArray()), new AionAddress(req.getTo().toByteArray()), req.getData().toByteArray(), BigInteger.ZERO, new BigInteger(req.getValue().toByteArray()), req.getNrg(), req.getNrgPrice(), null);
result = this.estimateNrg(params);
} catch (InvalidProtocolBufferException e) {
LOG.error("ApiAion0.process.estimateNrg exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
}
Message.rsp_estimateNrg rsp = Message.rsp_estimateNrg.newBuilder().setNrg(result).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_exportAccounts_VALUE:
case Message.Funcs.f_backupAccounts_VALUE:
{
if (service != Message.Servs.s_account_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_exportAccounts req;
try {
req = Message.req_exportAccounts.parseFrom(data);
} catch (Exception e) {
LOG.error("ApiAion0.process.exportAccounts exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
Map<AionAddress, String> addrMap = new HashMap<>();
for (int i = 0; i < req.getKeyFileList().size() && i < ACCOUNT_CREATE_LIMIT; i++) {
addrMap.put(new AionAddress(req.getKeyFile(i).getAddress().toByteArray()), req.getKeyFile(i).getPassword());
}
Map<AionAddress, ByteArrayWrapper> res = ((short) request[2] == Message.Funcs.f_exportAccounts_VALUE) ? Keystore.exportAccount(addrMap) : Keystore.backupAccount(addrMap);
List<ByteString> invalidKey = addrMap.keySet().parallelStream().filter(addr -> res.keySet().parallelStream().noneMatch(ad -> ad.equals(addr))).map(match -> ByteString.copyFrom(match.toByteArray())).collect(Collectors.toList());
List<ByteString> keyBins = res.values().parallelStream().map(key -> ByteString.copyFrom(key.toBytes())).collect(Collectors.toList());
Message.rsp_exportAccounts rsp = Message.rsp_exportAccounts.newBuilder().addAllKeyFile(keyBins).addAllFailedKey(invalidKey).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_importAccounts_VALUE:
{
if (service != Message.Servs.s_account_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_importAccounts req;
try {
req = Message.req_importAccounts.parseFrom(data);
} catch (Exception e) {
LOG.error("ApiAion0.process.importAccount exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
Map<String, String> importKey = req.getPrivateKeyList().parallelStream().collect(Collectors.toMap(Message.t_PrivateKey::getPrivateKey, Message.t_PrivateKey::getPassword));
if (importKey == null) {
LOG.error("ApiAion0.process.importAccount exception: [null importKey]");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
Set<String> res = Keystore.importAccount(importKey);
if (res == null) {
throw new NullPointerException();
}
Message.rsp_importAccounts rsp = Message.rsp_importAccounts.newBuilder().addAllInvalidKey(res).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
case Message.Funcs.f_signedTransaction_VALUE:
case Message.Funcs.f_rawTransaction_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE, msgHash);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_rawTransaction req;
ApiTxResponse result;
try {
req = Message.req_rawTransaction.parseFrom(data);
byte[] encodedTx = req.getEncodedTx().toByteArray();
if (encodedTx == null) {
LOG.error("ApiAion0.process.rawTransaction exception: [null encodedTx]");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
result = this.sendTransaction(encodedTx);
} catch (Exception e) {
LOG.error("ApiAion0.process.rawTransaction exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE, msgHash);
}
return processSendTxRsp(result, msgHash, socketId);
}
case Message.Funcs.f_eventRegister_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_eventRegister req;
try {
req = Message.req_eventRegister.parseFrom(data);
List<String> evtList = new ArrayList<>(req.getEventsList());
if (evtList.isEmpty()) {
LOG.error("ApiNucoNcp.process.eventRegister : [{}]", "empty event list");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
Message.t_FilterCt fltr = req.getFilter();
List<byte[]> accList = new ArrayList<>();
fltr.getAddressesList().forEach(a -> accList.add(a.toByteArray()));
long lv = ByteUtil.byteArrayToLong(socketId);
FltrCt preFc = (FltrCt) installedFilters.get(lv);
if (Optional.ofNullable(preFc).isPresent()) {
preFc.getTopics().forEach(t -> {
if (!fltr.getTopicsList().contains(t)) {
evtList.add(t);
}
});
}
FltrCt fc = new FltrCt(fltr.getContractAddr().toByteArray(), fltr.getTo(), fltr.getFrom(), evtList, accList, fltr.getExpireTime());
installedFilters.put(lv, fc);
Message.rsp_eventRegister rsp = Message.rsp_eventRegister.newBuilder().setResult(true).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.eventRegister exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_eventDeregister_VALUE:
{
if (service != Message.Servs.s_tx_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_eventDeregister req;
try {
req = Message.req_eventDeregister.parseFrom(data);
List<String> evtList = new ArrayList<>(req.getEventsList());
byte[] contractAddr;
if (req.getContractAddr() == null) {
contractAddr = null;
} else {
contractAddr = req.getContractAddr().toByteArray();
}
if (evtList.isEmpty()) {
LOG.error("ApiAion0.process.eventRegister : [{}]", "empty event list");
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
long lv = ByteUtil.byteArrayToLong(socketId);
FltrCt preFc = (FltrCt) installedFilters.get(lv);
boolean changed = false;
if (Optional.ofNullable(preFc).isPresent() && Arrays.equals(preFc.getContractAddr(), contractAddr)) {
evtList.forEach(ev -> preFc.getTopics().remove(ev));
installedFilters.put(lv, preFc);
changed = true;
}
Message.rsp_eventRegister rsp = Message.rsp_eventRegister.newBuilder().setResult(changed).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.eventDeregister exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockDetailsByNumber_VALUE:
{
if (service != Message.Servs.s_admin_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockDetailsByNumber req;
try {
req = Message.req_getBlockDetailsByNumber.parseFrom(data);
long latestBlkNum = this.getBestBlock().getNumber();
List<Long> blkNum = req.getBlkNumbersList().parallelStream().filter(n -> n <= latestBlkNum).collect(Collectors.toSet()).parallelStream().sorted().collect(Collectors.toList());
if (blkNum.size() > 1000) {
blkNum = blkNum.subList(0, 1000);
}
List<Block> blks = getBlocksForBlkNumList(blkNum);
if (blks == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
} else {
List<Message.t_BlockDetail> bds = getRsp_getBlockDetails(blks);
Message.rsp_getBlockDetailsByNumber rsp = Message.rsp_getBlockDetailsByNumber.newBuilder().addAllBlkDetails(bds).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockSqlByRange_VALUE:
{
if (service != Message.Servs.s_admin_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockSqlByRange req;
try {
if (LOG.isDebugEnabled()) {
LOG.debug("BlockSqlByRange: start");
}
req = Message.req_getBlockSqlByRange.parseFrom(data);
long latestBlkNum = this.getBestBlock().getNumber();
Long _blkStart = req.getBlkNumberStart();
Long _blkEnd = req.getBlkNumberEnd();
// no null check here
long blkStart;
long blkEnd;
if (_blkStart < 0) {
blkStart = 0;
} else {
blkStart = _blkStart;
}
if (_blkEnd > latestBlkNum) {
blkEnd = latestBlkNum;
} else {
blkEnd = _blkEnd;
}
if (blkEnd < blkStart) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
// truncate the thing
if (blkEnd - blkStart > 1000) {
blkStart = blkEnd - 1000 + 1;
if (blkStart < 0) {
blkStart = 0;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("BlockSqlByRange: range " + blkStart + "-" + blkEnd);
}
Long lastBlockTimestamp = null;
long listLength = blkEnd - blkStart + 1;
List<Message.t_BlockSql> bds = new ArrayList<>();
for (int i = 0; i < listLength; i++) {
long blkNum = blkStart + i;
Block b = getBlock(blkNum);
long blocktime;
if (blkNum != 0 && lastBlockTimestamp == null) {
lastBlockTimestamp = getBlock(blkNum - 1).getTimestamp();
}
if (blkNum == 0) {
blocktime = 0;
} else {
blocktime = b.getTimestamp() - lastBlockTimestamp;
}
lastBlockTimestamp = b.getTimestamp();
String blockSql = generateBlockSqlStatement(b, b.getTotalDifficulty(), blocktime);
List<String> transactionSql = new ArrayList<>();
AionBlockSummary bs = null;
if (explorerBlockCache != null) {
// remove from cache since after consumed, we're probably not gonna
// revisit it
bs = explorerBlockCache.remove(b.getHashWrapper());
}
if (bs != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("BlockSqlByRange: cache HIT for #: " + b.getNumber());
}
Map<ByteArrayWrapper, AionTxReceipt> receipts = new HashMap<>();
for (AionTxReceipt r : bs.getReceipts()) {
receipts.put(ByteArrayWrapper.wrap(r.getTransaction().getTransactionHash()), r);
}
List<AionTransaction> txns = b.getTransactionsList();
for (int j = 0; j < txns.size(); j++) {
AionTransaction tx = txns.get(j);
AionTxReceipt r = receipts.get(ByteArrayWrapper.wrap(tx.getTransactionHash()));
if (r == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("BlockSqlByRange: transaction not in Block Summary: " + b.getNumber() + "." + j);
}
AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
r = ti.getReceipt();
}
if (r == null) {
LOG.error("BlockSqlByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
} else {
transactionSql.add(generateTransactionSqlStatement(b, tx, r.getLogInfoList(), j, r.getEnergyUsed()));
}
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("BlockSqlByRange: cache MISS for #: " + b.getNumber());
}
List<AionTransaction> txs = b.getTransactionsList();
transactionSql = txs.parallelStream().filter(Objects::nonNull).map((AionTransaction tx) -> {
AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
if (ti == null) {
LOG.error("BlockSqlByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
return null;
} else {
return generateTransactionSqlStatement(b, tx, ti.getReceipt().getLogInfoList(), ti.getIndex(), ti.getReceipt().getEnergyUsed());
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}
Message.t_BlockSql sqlObj = Message.t_BlockSql.newBuilder().setBlockNumber(b.getNumber()).setBlockHash(ByteUtil.toHexString(b.getHash())).setParentHash(ByteUtil.toHexString(b.getParentHash())).setBlock(blockSql).addAllTx(transactionSql).build();
bds.add(sqlObj);
}
Message.rsp_getBlockSqlByRange rsp = Message.rsp_getBlockSqlByRange.newBuilder().addAllBlkSql(bds).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockDetailsByRange_VALUE:
{
if (service != Message.Servs.s_admin_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockDetailsByRange req;
try {
if (LOG.isDebugEnabled()) {
LOG.debug("getBlockDetailsByRange: start");
}
req = Message.req_getBlockDetailsByRange.parseFrom(data);
long latestBlkNum = this.getBestBlock().getNumber();
Long _blkStart = req.getBlkNumberStart();
Long _blkEnd = req.getBlkNumberEnd();
// no null check here
long blkStart;
long blkEnd;
if (_blkStart < 0) {
blkStart = 0;
} else {
blkStart = _blkStart;
}
// blocks requested in the future. return empty result
if (blkStart > latestBlkNum) {
Message.rsp_getBlockDetailsByRange rsp = Message.rsp_getBlockDetailsByRange.newBuilder().addAllBlkDetails(new ArrayList<>()).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
if (_blkEnd > latestBlkNum) {
blkEnd = latestBlkNum;
} else {
blkEnd = _blkEnd;
}
if (blkEnd < blkStart) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
// truncate at the beginning of range
if (blkEnd - blkStart > 1000) {
blkStart = blkEnd - 1000 + 1;
if (blkStart < 0) {
blkStart = 0;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("getBlockDetailsByRange: range " + blkStart + "-" + blkEnd);
}
Long lastBlockTimestamp = null;
long listLength = blkEnd - blkStart + 1;
List<Message.t_BlockDetail> bds = new ArrayList<>();
for (int i = 0; i < listLength; i++) {
long blkNum = blkStart + i;
Block b = getBlockWithInfo(blkNum);
if (b == null) {
throw new NullPointerException("Can retrieve the block#" + blkNum + "in the database!");
}
long blocktime = 0;
if (b.getNumber() > 0 && lastBlockTimestamp == null) {
lastBlockTimestamp = getBlockByHash(b.getParentHash()).getTimestamp();
}
if (lastBlockTimestamp != null) {
blocktime = b.getTimestamp() - lastBlockTimestamp;
}
lastBlockTimestamp = b.getTimestamp();
Message.t_BlockDetail.Builder blockDetails = getBlockDetailsObj(b, blocktime);
List<Message.t_TxDetail> txDetails = new ArrayList<>();
AionBlockSummary bs = null;
if (explorerBlockCache != null) {
// remove from cache since after consumed, we're probably not gonna
// revisit it
bs = explorerBlockCache.remove(b.getHashWrapper());
}
if (bs != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("getBlockDetailsByRange: cache HIT for #: " + b.getNumber());
}
Map<ByteArrayWrapper, AionTxReceipt> receipts = new HashMap<>();
for (AionTxReceipt r : bs.getReceipts()) {
receipts.put(ByteArrayWrapper.wrap(r.getTransaction().getTransactionHash()), r);
}
List<AionTransaction> txns = b.getTransactionsList();
for (int j = 0; j < txns.size(); j++) {
AionTransaction tx = txns.get(j);
AionTxReceipt r = receipts.get(ByteArrayWrapper.wrap(tx.getTransactionHash()));
if (r == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("getBlockDetailsByRange: transaction not in Block Summary: " + b.getNumber() + "." + j);
}
AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
r = ti.getReceipt();
}
if (r == null) {
LOG.error("getBlockDetailsByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
} else {
txDetails.add(getTxDetailsObj(tx, r.getLogInfoList(), j, r.getEnergyUsed(), r.getError()));
}
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("getBlockDetailsByRange: cache MISS for #: " + b.getNumber());
}
List<AionTransaction> txs = b.getTransactionsList();
txDetails = txs.parallelStream().filter(Objects::nonNull).map((AionTransaction tx) -> {
AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), b.getHash());
if (ti == null) {
LOG.error("getBlockDetailsByRange: missing DB transaction: " + ByteUtil.toHexString(tx.getTransactionHash()));
return null;
} else {
return getTxDetailsObj(tx, ti.getReceipt().getLogInfoList(), ti.getIndex(), ti.getReceipt().getEnergyUsed(), ti.getReceipt().getError());
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}
bds.add(blockDetails.addAllTx(txDetails).build());
}
Message.rsp_getBlockDetailsByRange rsp = Message.rsp_getBlockDetailsByRange.newBuilder().addAllBlkDetails(bds).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlockDetailsByLatest_VALUE:
{
if (service != Message.Servs.s_admin_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlockDetailsByLatest req;
try {
req = Message.req_getBlockDetailsByLatest.parseFrom(data);
// clip the requested count up to 1000
Long count = req.getCount();
if (count > 1000) {
count = 1000L;
}
// clip start block to 0 at the bottom
Long endBlock = this.getBestBlock().getNumber();
Long startBlock = (endBlock - count + 1) >= 0 ? (endBlock - count + 1) : 0;
List<Long> blkNum = LongStream.rangeClosed(startBlock, endBlock).boxed().collect(Collectors.toList());
List<Block> blks = getBlocksForBlkNumList(blkNum);
if (blks == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
} else {
List<Message.t_BlockDetail> bds = getRsp_getBlockDetails(blks);
Message.rsp_getBlockDetailsByLatest rsp = Message.rsp_getBlockDetailsByLatest.newBuilder().addAllBlkDetails(bds).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockDetailsByLatest exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getBlocksByLatest_VALUE:
{
if (service != Message.Servs.s_admin_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getBlocksByLatest req;
try {
req = Message.req_getBlocksByLatest.parseFrom(data);
// clip the requested count up to 1000
Long count = req.getCount();
if (count > 1000) {
count = 1000L;
}
// clip start block to 0 at the bottom
Long endBlock = this.getBestBlock().getNumber();
Long startBlock = (endBlock - count + 1) >= 0 ? (endBlock - count + 1) : 0;
List<Long> blkNum = LongStream.rangeClosed(startBlock, endBlock).boxed().collect(Collectors.toList());
List<Block> blks = getBlocksForBlkNumList(blkNum);
if (blks == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
} else {
List<Message.t_Block> bs = getRsp_getBlocks(blks);
Message.rsp_getBlocksByLatest rsp = Message.rsp_getBlocksByLatest.newBuilder().addAllBlks(bs).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
}
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlocksByLatest exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
case Message.Funcs.f_getAccountDetailsByAddressList_VALUE:
{
if (service != Message.Servs.s_admin_VALUE) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_service_call_VALUE);
}
byte[] data = parseMsgReq(request, msgHash);
Message.req_getAccountDetailsByAddressList req;
try {
req = Message.req_getAccountDetailsByAddressList.parseFrom(data);
List<ByteString> num = req.getAddressesList();
if (num.size() > 1000) {
num = num.subList(0, 1000);
}
List<Message.t_AccountDetail> accounts = num.parallelStream().map(a -> {
BigInteger b = this.getBalance(new AionAddress(a.toByteArray()));
Message.t_AccountDetail.Builder builder = Message.t_AccountDetail.newBuilder();
if (b != null) {
builder.setBalance(ByteString.copyFrom(b.toByteArray()));
}
builder.setAddress(a);
return builder.build();
}).collect(Collectors.toList());
if (accounts == null) {
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_arguments_VALUE);
}
Message.rsp_getAccountDetailsByAddressList rsp = Message.rsp_getAccountDetailsByAddressList.newBuilder().addAllAccounts(accounts).build();
byte[] retHeader = ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_success_VALUE);
return ApiUtil.combineRetMsg(retHeader, rsp.toByteArray());
} catch (Exception e) {
LOG.error("ApiAion0.process.getBlockDetailsByNumber exception: [{}]", e);
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_exception_VALUE);
}
}
// case Message.Funcs.f_getWork_VALUE:
default:
return ApiUtil.toReturnHeader(getApiVersion(), Retcode.r_fail_function_call_VALUE);
}
}
use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.
the class ApiAion0 method getRsp_getBlockDetails.
private List<Message.t_BlockDetail> getRsp_getBlockDetails(List<Block> blks) {
return blks.parallelStream().filter(Objects::nonNull).map(blk -> {
Message.t_BlockDetail.Builder builder;
if (blk.getHeader().getSealType() == Seal.PROOF_OF_WORK) {
MiningBlock b = (MiningBlock) blk;
builder = Message.t_BlockDetail.newBuilder().setBlockNumber(b.getNumber()).setDifficulty(ByteString.copyFrom(b.getDifficulty())).setExtraData(ByteString.copyFrom(b.getExtraData())).setHash(ByteString.copyFrom(b.getHash())).setLogsBloom(ByteString.copyFrom(b.getLogBloom())).setMinerAddress(ByteString.copyFrom(b.getCoinbase().toByteArray())).setNonce(ByteString.copyFrom(b.getNonce())).setNrgConsumed(b.getNrgConsumed()).setNrgLimit(b.getNrgLimit()).setParentHash(ByteString.copyFrom(b.getParentHash())).setTimestamp(b.getTimestamp()).setTxTrieRoot(ByteString.copyFrom(b.getTxTrieRoot())).setReceiptTrieRoot(ByteString.copyFrom(b.getReceiptsRoot())).setStateRoot(ByteString.copyFrom(b.getStateRoot())).setSize(b.size()).setSolution(ByteString.copyFrom(b.getHeader().getSolution())).setTotalDifficulty(ByteString.copyFrom(blk.getTotalDifficulty().toByteArray()));
} else if (blk.getHeader().getSealType() == Seal.PROOF_OF_STAKE) {
StakingBlock b = (StakingBlock) blk;
builder = Message.t_BlockDetail.newBuilder().setBlockNumber(b.getNumber()).setDifficulty(ByteString.copyFrom(b.getDifficulty())).setExtraData(ByteString.copyFrom(b.getExtraData())).setHash(ByteString.copyFrom(b.getHash())).setLogsBloom(ByteString.copyFrom(b.getLogBloom())).setMinerAddress(ByteString.copyFrom(b.getCoinbase().toByteArray())).setNonce(ByteString.copyFrom(new byte[0])).setNrgConsumed(b.getNrgConsumed()).setNrgLimit(b.getNrgLimit()).setParentHash(ByteString.copyFrom(b.getParentHash())).setTimestamp(b.getTimestamp()).setTxTrieRoot(ByteString.copyFrom(b.getTxTrieRoot())).setReceiptTrieRoot(ByteString.copyFrom(b.getReceiptsRoot())).setStateRoot(ByteString.copyFrom(b.getStateRoot())).setSize(b.size()).setSolution(ByteString.copyFrom(new byte[0])).setTotalDifficulty(ByteString.copyFrom(blk.getTotalDifficulty().toByteArray()));
} else {
throw new IllegalStateException("Invalid block type!");
}
List<AionTransaction> txs = blk.getTransactionsList();
List<Message.t_TxDetail> tds = txs.parallelStream().filter(Objects::nonNull).map((AionTransaction tx) -> {
AionTxInfo ti = ((AionBlockchainImpl) this.ac.getAionHub().getBlockchain()).getTransactionInfoLite(tx.getTransactionHash(), blk.getHeader().getHash());
List<Message.t_LgEle> tles = ti.getReceipt().getLogInfoList().parallelStream().map(log -> {
List<String> topics = new ArrayList<>();
for (int i = 0; i < log.copyOfTopics().size(); i++) {
topics.add(StringUtils.toJsonHex(log.copyOfTopics().get(i)));
}
return Message.t_LgEle.newBuilder().setData(ByteString.copyFrom(log.copyOfData())).setAddress(ByteString.copyFrom(log.copyOfAddress())).addAllTopics(topics).build();
}).filter(Objects::nonNull).collect(Collectors.toList());
Message.t_TxDetail.Builder tdBuilder = Message.t_TxDetail.newBuilder().setData(ByteString.copyFrom(tx.getData())).setTo(ByteString.copyFrom(tx.getDestinationAddress() == null ? EMPTY_BYTE_ARRAY : tx.getDestinationAddress().toByteArray())).setFrom(ByteString.copyFrom(tx.getSenderAddress().toByteArray())).setNonce(ByteString.copyFrom(tx.getNonce())).setValue(ByteString.copyFrom(tx.getValue())).setNrgConsumed(ti.getReceipt().getEnergyUsed()).setNrgPrice(tx.getEnergyPrice()).setTxHash(ByteString.copyFrom(tx.getTransactionHash())).setTxIndex(ti.getIndex()).setType(ByteString.copyFrom(new byte[] { tx.getType() })).addAllLogs(tles);
return tdBuilder.build();
}).filter(Objects::nonNull).collect(Collectors.toList());
return builder.addAllTx(tds).build();
}).filter(Objects::nonNull).collect(Collectors.toList());
}
use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.
the class ApiWeb3Aion method ops_getTransactionReceiptByTransactionAndBlockHash.
/**
* This function runs as fast as is possible with the on-disk data model Use this to retrieve
* the Transaction Receipt if you know the block hash already
*/
public RpcMsg ops_getTransactionReceiptByTransactionAndBlockHash(Object _params) {
String _transactionHash;
String _blockHash;
if (_params instanceof JSONArray) {
_transactionHash = ((JSONArray) _params).get(0) + "";
_blockHash = ((JSONArray) _params).get(1) + "";
} else if (_params instanceof JSONObject) {
_transactionHash = ((JSONObject) _params).get("transactionHash") + "";
_blockHash = ((JSONObject) _params).get("blockHash") + "";
} else {
return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
}
byte[] transactionHash = StringUtils.StringHexToByteArray(_transactionHash);
byte[] blockHash = StringUtils.StringHexToByteArray(_blockHash);
// cast will cause issues after the PoW refactor goes in
AionBlockchainImpl chain = (AionBlockchainImpl) this.ac.getAionHub().getBlockchain();
AionTxInfo info = chain.getTransactionInfoLite(transactionHash, blockHash);
if (info == null) {
return new RpcMsg(JSONObject.NULL);
}
Block block = blockCache.get(ByteArrayWrapper.wrap(blockHash));
AionTransaction t = block.getTransactionsList().get(info.getIndex());
if (Arrays.compare(t.getTransactionHash(), transactionHash) != 0) {
LOG.error("INCONSISTENT STATE: transaction info's transaction index is wrong.");
return new RpcMsg(null, RpcError.INTERNAL_ERROR, "Database Error");
}
info.setTransaction(t);
return new RpcMsg((new TxRecpt(block, info, 0L, true)).toJson());
}
use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.
the class ApiWeb3Aion method ops_getTransactionReceiptListByBlockHash.
public RpcMsg ops_getTransactionReceiptListByBlockHash(Object _params) {
String _blockHash;
if (_params instanceof JSONArray) {
_blockHash = ((JSONArray) _params).get(0) + "";
} else if (_params instanceof JSONObject) {
_blockHash = ((JSONObject) _params).get("blockHash") + "";
} else {
return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
}
byte[] blockHash = StringUtils.StringHexToByteArray(_blockHash);
if (blockHash.length != 32) {
return new RpcMsg(null, RpcError.INVALID_PARAMS, "Invalid parameters");
}
// ok to getUnchecked() since the load() implementation does not throw checked exceptions
Block b;
try {
b = blockCache.get(ByteArrayWrapper.wrap(blockHash));
} catch (Exception e) {
// Catch errors if send an incorrect tx hash
return new RpcMsg(null, RpcError.INVALID_REQUEST, "Invalid Request " + e + " " + e.getMessage() != null ? e.getMessage() : "");
}
// cast will cause issues after the PoW refactor goes in
AionBlockchainImpl chain = (AionBlockchainImpl) this.ac.getAionHub().getBlockchain();
Function<AionTransaction, JSONObject> extractTxReceipt = t -> {
AionTxInfo info = chain.getTransactionInfoLite(t.getTransactionHash(), b.getHash());
info.setTransaction(t);
return ((new TxRecpt(b, info, 0L, true)).toJson());
};
List<JSONObject> receipts;
// use the fork-join pool to parallelize receipt retrieval if necessary
int PARALLELIZE_RECEIPT_COUNT = 20;
if (b.getTransactionsList().size() > PARALLELIZE_RECEIPT_COUNT) {
receipts = b.getTransactionsList().parallelStream().map(extractTxReceipt).collect(toList());
} else {
receipts = b.getTransactionsList().stream().map(extractTxReceipt).collect(toList());
}
return new RpcMsg(new JSONArray(receipts));
}
use of org.aion.zero.impl.blockchain.AionBlockchainImpl in project aion by aionnetwork.
the class Cli method call.
private ReturnType call(final String[] args, CfgAion cfg, boolean initializeAvm) {
final CommandLine.ParseResult parseResult;
try {
// the pre-process method handles arguments that are separated by space
// parsing populates the options object
parseResult = parser.parseArgs(Arguments.preProcess(args));
} catch (Exception e) {
System.out.println("Unable to parse the input arguments due to: ");
if (e.getMessage() != null) {
System.out.println(e.getMessage());
} else {
e.printStackTrace();
}
System.out.println();
printHelp();
return ERROR;
}
// make sure that there is no conflicting arguments; otherwise send warning
checkArguments(options, parseResult);
try {
if (options.isHelp()) {
printHelp();
return EXIT;
}
if (options.isVersion() || options.isVersionTag()) {
if (options.isVersion()) {
System.out.println("\nVersion");
System.out.println("--------------------------------------------");
}
System.out.println(Version.KERNEL_VERSION);
return EXIT;
}
if (options.getNetwork() != null || (options.getConfig() != null && !options.getConfig().isEmpty())) {
String strNet = options.getNetwork();
// the network given in config overwrites the -n option
if (options.getConfig() != null && !options.getConfig().isEmpty()) {
strNet = options.getConfig();
}
setNetwork(strNet, cfg);
// no return -> allow for other parameters combined with -n
}
if (options.getDirectory() != null) {
if (!setDirectory(options.getDirectory(), cfg)) {
return ERROR;
}
// no return -> allow for other parameters combined with -d
}
// reading from correct config file
File configFile = cfg.getExecConfigFile();
if (!configFile.exists()) {
configFile = cfg.getInitialConfigFile();
} else {
cfg.setReadConfigFile(configFile);
}
// reading from correct fork file
File forkFile = cfg.getForkFile();
if (forkFile != null && forkFile.exists()) {
cfg.setForkProperties(cfg.getNetwork(), forkFile);
}
// true means the UUID must be set
boolean overwrite = cfg.fromXML(configFile);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ initialize the avm ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (initializeAvm) {
try {
// Grab the project root directory.
String projectRootDirectory = System.getProperty("user.dir") + File.separator;
// Create the multi-version schedule. Note that avm version 1 is always enabled, from block zero
// because it handles balance transfers. The kernel is responsible for ensuring it is not called
// with anything else.
Properties forkProperties = CfgAion.inst().getFork().getProperties();
String fork2 = forkProperties.getProperty("fork1.0");
AvmVersionSchedule schedule;
if (fork2 != null) {
schedule = AvmVersionSchedule.newScheduleForBothVersions(0, Long.valueOf(fork2), 100);
} else {
schedule = AvmVersionSchedule.newScheduleForOnlySingleVersionSupport(0, 100);
}
AvmConfigurations.initializeConfigurationsAsReadOnly(schedule, projectRootDirectory);
} catch (Exception e) {
System.out.println("A fatal error occurred attempting to configure the AVM: " + e.getMessage());
System.exit(SystemExitCodes.INITIALIZATION_ERROR);
}
}
// determine the port configuration, can be combined with the -n, -d, -c, -i arguments
if (parseResult.subcommand() != null && parseResult.subcommand().commandSpec().userObject().getClass() == EditCli.class && editCli.runCommand(cfg)) {
overwrite = true;
}
if (editCli.help) {
return ReturnType.EXIT;
}
if (options.getPort() != null) {
int currentPort = cfg.getNet().getP2p().getPort();
int portNumber = currentPort;
boolean validPort = true;
try {
portNumber = Integer.parseInt(options.getPort());
} catch (NumberFormatException e) {
validPort = false;
System.out.println("Port must be a positive integer value");
}
if (portNumber < 0 || portNumber > 0xFFFF) {
validPort = false;
System.out.println("Port out of range: " + portNumber);
}
if (validPort && portNumber != currentPort) {
// update port in config
cfg.getNet().getP2p().setPort(portNumber);
overwrite = true;
System.out.println("Port set to: " + portNumber);
} else {
System.out.println("Using the current port configuration: " + currentPort);
}
// no return, allow for other parameters combined with -p
}
if (options.getConfig() != null) {
// if the directory was set we generate a new file
if (options.getDirectory() != null) {
configFile = cfg.getExecConfigFile();
// ensure path exists
File dir = cfg.getExecConfigDirectory();
if (!dir.exists()) {
if (!dir.mkdirs()) {
System.out.println("ERROR: Unable to create directory: " + getRelativePath(dir.getAbsolutePath()));
return ERROR;
}
}
try {
configFile.createNewFile();
} catch (IOException e) {
System.out.println("ERROR: Unable to create file: " + getRelativePath(configFile.getAbsolutePath()));
return ERROR;
}
}
// save to disk
cfg.toXML(null, configFile);
System.out.println("\nNew config generated at: " + getRelativePath(configFile.getAbsolutePath()));
return ReturnType.EXIT;
}
if (options.isInfo()) {
System.out.println("Reading config file from: " + getRelativePath(configFile.getAbsolutePath()));
if (overwrite) {
// updating the file in case the user id was not set; overwrite port
cfg.toXML(null, configFile);
}
printInfo(cfg);
return ReturnType.EXIT;
}
// make directories for kernel execution
makeDirs(configFile, forkFile, cfg);
if (overwrite) {
// updating the file in case the user id was not set; overwrite port
cfg.toXML(null, cfg.getExecConfigFile());
}
// set correct keystore directory
Keystore.setKeystorePath(cfg.getKeystoreDir().getAbsolutePath());
CommandSpec commandSpec = findCommandSpec(parseResult, AccountCli.class);
if (commandSpec != null) {
return ((AccountCli) commandSpec.userObject()).runCommand(passwordReader);
}
if (options.getSsl() != null) {
String[] parameters = options.getSsl();
if (parameters.length == 0 || parameters.length == 2) {
createKeystoreDirIfMissing();
Console console = System.console();
checkConsoleExists(console);
List<String> scriptArgs = new ArrayList<>();
scriptArgs.add("/bin/bash");
scriptArgs.add("script/generateSslCert.sh");
scriptArgs.add(getCertName(console));
scriptArgs.add(getCertPass(console));
// add the hostname and ip optionally passed in as cli args
scriptArgs.addAll(Arrays.asList(parameters));
new ProcessBuilder(scriptArgs).inheritIO().start().waitFor();
return EXIT;
} else {
System.out.println("Incorrect usage of -s create command.\n" + "Command must enter both hostname AND ip or else neither one.");
return ERROR;
}
}
if (options.isRebuildBlockInfo()) {
System.out.println("Starting database clean-up.");
CfgAion.inst().dbFromXML();
Map<LogEnum, LogLevel> cfgLog = new HashMap<>();
cfgLog.put(LogEnum.GEN, LogLevel.INFO);
AionLoggerFactory.initAll(cfgLog);
// get the current blockchain
AionRepositoryImpl repository = AionRepositoryImpl.inst();
repository.pruneAndCorrectBlockStore(AionLoggerFactory.getLogger(LogEnum.GEN.name()));
repository.close();
System.out.println("Finished database clean-up.");
return EXIT;
}
if (options.getRevertToBlock() != null) {
String block = options.getRevertToBlock();
if (revertTo(block)) {
System.out.println("Blockchain successfully reverted to block number " + block + ".");
return EXIT;
} else {
System.out.println("Unable to revert to block number " + block + ".");
return ERROR;
}
}
if (options.getPruneStateOption() != null) {
String pruning_type = options.getPruneStateOption();
try {
// ensure mining is disabled
CfgAion localCfg = CfgAion.inst();
localCfg.fromXML();
localCfg.getConsensus().setMining(false);
// setting pruning to the version requested
CfgDb.PruneOption option = CfgDb.PruneOption.fromValue(pruning_type);
localCfg.getDb().setPrune(option.toString());
AionLoggerFactory.initAll(Map.of(LogEnum.GEN, LogLevel.INFO));
final Logger log = AionLoggerFactory.getLogger(LogEnum.GEN.name());
log.info("Reorganizing the state storage to " + option + " mode ...");
AionBlockchainImpl chain = new AionBlockchainImpl(localCfg, null, false);
chain.pruneOrRecoverState(pruning_type.equals("spread"), localCfg.getGenesis(), log);
chain.close();
return EXIT;
} catch (Exception e) {
System.out.println("Reorganizing the state storage FAILED due to:");
e.printStackTrace();
return ERROR;
}
}
CommandLine.Model.CommandSpec spec = findCommandSpec(parseResult, DevCLI.class);
if (spec != null) {
ReturnType returnType = ((DevCLI) spec.userObject()).runCommand();
if (returnType != RUN) {
return returnType;
}
}
if (options.isDbCompact()) {
// read database configuration
CfgAion.inst().dbFromXML();
AionLoggerFactory.initAll(Map.of(LogEnum.DB, LogLevel.INFO));
// get the current blockchain
AionRepositoryImpl repository = AionRepositoryImpl.inst();
// compact database after the changes were applied
repository.compact();
repository.close();
return EXIT;
}
if (options.isRedoImport() != null) {
long height = 0L;
String parameter = options.isRedoImport();
// ensure mining is disabled
CfgAion localCfg = CfgAion.inst();
localCfg.dbFromXML();
localCfg.getConsensus().setMining(false);
AionLoggerFactory.initAll(Map.of(LogEnum.GEN, LogLevel.INFO));
final Logger log = AionLoggerFactory.getLogger(LogEnum.GEN.name());
if (height < 0) {
log.error("Negative values are not valid as starting height. Nothing to do.");
return ERROR;
}
log.info("Importing stored blocks INITIATED...");
AionBlockchainImpl chain = new AionBlockchainImpl(localCfg, null, false);
if (parameter.isEmpty()) {
chain.redoMainChainImport(height, localCfg.getGenesis(), log);
chain.close();
return EXIT;
} else {
try {
height = Long.parseLong(parameter);
} catch (NumberFormatException e) {
log.error("The given argument «" + parameter + "» cannot be converted to a number.");
chain.close();
return ERROR;
}
chain.redoMainChainImport(height, localCfg.getGenesis(), log);
chain.close();
return EXIT;
}
}
// if no return happened earlier, run the kernel
return RUN;
} catch (Exception e) {
// TODO: should be moved to individual procedures
System.out.println();
e.printStackTrace();
return ERROR;
}
}
Aggregations