Search in sources :

Example 1 with ContractData

use of io.nuls.contract.entity.txdata.ContractData in project nuls by nuls-io.

the class ContractResource method getContractTx.

@GET
@Path("/tx/{hash}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "获取智能合约交易详情")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = ContractTransactionDto.class) })
public RpcClientResult getContractTx(@ApiParam(name = "hash", value = "交易hash", required = true) @PathParam("hash") String hash) {
    if (StringUtils.isBlank(hash)) {
        return Result.getFailed(LedgerErrorCode.NULL_PARAMETER).toRpcClientResult();
    }
    if (!NulsDigestData.validHash(hash)) {
        return Result.getFailed(LedgerErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    Result result;
    try {
        NulsDigestData txHashObj = NulsDigestData.fromDigestHex(hash);
        Transaction tx = ledgerService.getTx(txHashObj);
        if (tx == null) {
            result = Result.getFailed(TransactionErrorCode.TX_NOT_EXIST);
        } else {
            if (!ContractUtil.isContractTransaction(tx) && tx.getType() != NulsConstant.TX_TYPE_COINBASE) {
                return Result.getFailed(ContractErrorCode.NON_CONTRACTUAL_TRANSACTION).toRpcClientResult();
            }
            tx.setStatus(TxStatusEnum.CONFIRMED);
            ContractTransactionDto txDto = null;
            CoinData coinData = tx.getCoinData();
            byte[] txHashBytes = tx.getHash().serialize();
            if (coinData != null) {
                // 组装from数据
                List<Coin> froms = coinData.getFrom();
                if (froms != null && froms.size() > 0) {
                    byte[] fromHash, owner;
                    int fromIndex;
                    NulsDigestData fromHashObj;
                    Transaction fromTx;
                    Coin fromUtxo;
                    for (Coin from : froms) {
                        owner = from.getOwner();
                        // owner拆分出txHash和index
                        fromHash = LedgerUtil.getTxHashBytes(owner);
                        fromIndex = LedgerUtil.getIndex(owner);
                        // 查询from UTXO
                        fromHashObj = new NulsDigestData();
                        fromHashObj.parse(fromHash, 0);
                        fromTx = ledgerService.getTx(fromHashObj);
                        fromUtxo = fromTx.getCoinData().getTo().get(fromIndex);
                        from.setFrom(fromUtxo);
                    }
                }
                txDto = new ContractTransactionDto(tx);
                List<OutputDto> outputDtoList = new ArrayList<>();
                // 组装to数据
                List<Coin> tos = coinData.getTo();
                if (tos != null && tos.size() > 0) {
                    String txHash = hash;
                    OutputDto outputDto;
                    Coin to, temp;
                    long bestHeight = NulsContext.getInstance().getBestHeight();
                    long currentTime = TimeService.currentTimeMillis();
                    long lockTime;
                    for (int i = 0, length = tos.size(); i < length; i++) {
                        to = tos.get(i);
                        outputDto = new OutputDto(to);
                        outputDto.setTxHash(txHash);
                        outputDto.setIndex(i);
                        temp = ledgerService.getUtxo(org.spongycastle.util.Arrays.concatenate(txHashBytes, new VarInt(i).encode()));
                        if (temp == null) {
                            // 已花费
                            outputDto.setStatus(3);
                        } else {
                            lockTime = temp.getLockTime();
                            if (lockTime < 0) {
                                // 共识锁定
                                outputDto.setStatus(2);
                            } else if (lockTime == 0) {
                                // 正常未花费
                                outputDto.setStatus(0);
                            } else if (lockTime > NulsConstant.BlOCKHEIGHT_TIME_DIVIDE) {
                                // 判定是否时间高度锁定
                                if (lockTime > currentTime) {
                                    // 时间高度锁定
                                    outputDto.setStatus(1);
                                } else {
                                    // 正常未花费
                                    outputDto.setStatus(0);
                                }
                            } else {
                                // 判定是否区块高度锁定
                                if (lockTime > bestHeight) {
                                    // 区块高度锁定
                                    outputDto.setStatus(1);
                                } else {
                                    // 正常未花费
                                    outputDto.setStatus(0);
                                }
                            }
                        }
                        outputDtoList.add(outputDto);
                    }
                }
                txDto.setOutputs(outputDtoList);
                // 计算交易实际发生的金额
                calTransactionValue(txDto);
            }
            // 获取合约执行结果
            if (tx.getType() != ContractConstant.TX_TYPE_CONTRACT_TRANSFER) {
                ContractResult contractExecuteResult = contractService.getContractExecuteResult(txHashObj);
                if (contractExecuteResult != null) {
                    Result<ContractAddressInfoPo> contractAddressInfoResult = contractAddressStorageService.getContractAddressInfo(contractExecuteResult.getContractAddress());
                    ContractAddressInfoPo po = contractAddressInfoResult.getData();
                    if (po != null && po.isNrc20()) {
                        contractExecuteResult.setNrc20(true);
                        if (contractExecuteResult.isSuccess()) {
                            txDto.setContractResult(new ContractResultDto(contractExecuteResult, tx, po));
                        } else {
                            ContractData contractData = (ContractData) tx.getTxData();
                            byte[] sender = contractData.getSender();
                            byte[] infoKey = ArraysTool.concatenate(sender, txHashBytes, new VarInt(0).encode());
                            Result<ContractTokenTransferInfoPo> tokenTransferResult = contractTokenTransferStorageService.getTokenTransferInfo(infoKey);
                            ContractTokenTransferInfoPo transferInfoPo = tokenTransferResult.getData();
                            txDto.setContractResult(new ContractResultDto(contractExecuteResult, tx, po, transferInfoPo));
                        }
                    } else {
                        txDto.setContractResult(new ContractResultDto(contractExecuteResult, tx));
                    }
                    ContractResultDto contractResultDto = txDto.getContractResult();
                    List<ContractTokenTransferDto> tokenTransfers = contractResultDto.getTokenTransfers();
                    List<ContractTokenTransferDto> realTokenTransfers = this.filterRealTokenTransfers(tokenTransfers);
                    contractResultDto.setTokenTransfers(realTokenTransfers);
                }
            }
            result = Result.getSuccess();
            result.setData(txDto);
        }
    } catch (NulsRuntimeException e) {
        Log.error(e);
        result = Result.getFailed(e.getErrorCode());
    } catch (Exception e) {
        Log.error(e);
        result = Result.getFailed(LedgerErrorCode.SYS_UNKOWN_EXCEPTION);
    }
    return result.toRpcClientResult();
}
Also used : NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) ContractResult(io.nuls.contract.dto.ContractResult) ContractAddressInfoPo(io.nuls.contract.storage.po.ContractAddressInfoPo) CreateContractData(io.nuls.contract.entity.txdata.CreateContractData) ContractData(io.nuls.contract.entity.txdata.ContractData) ContractTokenTransferInfoPo(io.nuls.contract.dto.ContractTokenTransferInfoPo) ContractResult(io.nuls.contract.dto.ContractResult) VarInt(io.nuls.kernel.utils.VarInt) NulsException(io.nuls.kernel.exception.NulsException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) CreateContractTransaction(io.nuls.contract.entity.tx.CreateContractTransaction)

Example 2 with ContractData

use of io.nuls.contract.entity.txdata.ContractData in project nuls by nuls-io.

the class ContractResource method getContractTxResult.

@GET
@Path("/result/{hash}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "获取智能合约执行结果")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = ContractResultDto.class) })
public RpcClientResult getContractTxResult(@ApiParam(name = "hash", value = "交易hash", required = true) @PathParam("hash") String hash) {
    if (StringUtils.isBlank(hash)) {
        return Result.getFailed(LedgerErrorCode.NULL_PARAMETER).toRpcClientResult();
    }
    if (!NulsDigestData.validHash(hash)) {
        return Result.getFailed(LedgerErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    try {
        ContractResultDto contractResultDto = null;
        ContractResult contractExecuteResult;
        boolean flag = true;
        String msg = EMPTY;
        // long confirmCount = 0L;
        do {
            NulsDigestData txHash = NulsDigestData.fromDigestHex(hash);
            Transaction tx = ledgerService.getTx(txHash);
            if (tx == null) {
                flag = false;
                msg = TransactionErrorCode.TX_NOT_EXIST.getMsg();
                break;
            } else {
                if (!ContractUtil.isContractTransaction(tx)) {
                    flag = false;
                    msg = ContractErrorCode.NON_CONTRACTUAL_TRANSACTION.getMsg();
                    break;
                }
            }
            contractExecuteResult = contractService.getContractExecuteResult(txHash);
            if (contractExecuteResult != null) {
                // long bestBlockHeight = NulsContext.getInstance().getBestHeight();
                // confirmCount = bestBlockHeight - tx.getBlockHeight() + 1;
                Result<ContractAddressInfoPo> contractAddressInfoResult = contractAddressStorageService.getContractAddressInfo(contractExecuteResult.getContractAddress());
                ContractAddressInfoPo po = contractAddressInfoResult.getData();
                if (po != null && po.isNrc20()) {
                    contractExecuteResult.setNrc20(true);
                    if (contractExecuteResult.isSuccess()) {
                        contractResultDto = new ContractResultDto(contractExecuteResult, tx, po);
                    } else {
                        ContractData contractData = (ContractData) tx.getTxData();
                        byte[] sender = contractData.getSender();
                        byte[] infoKey = ArraysTool.concatenate(sender, tx.getHash().serialize(), new VarInt(0).encode());
                        Result<ContractTokenTransferInfoPo> tokenTransferResult = contractTokenTransferStorageService.getTokenTransferInfo(infoKey);
                        ContractTokenTransferInfoPo transferInfoPo = tokenTransferResult.getData();
                        contractResultDto = new ContractResultDto(contractExecuteResult, tx, po, transferInfoPo);
                    }
                } else {
                    contractResultDto = new ContractResultDto(contractExecuteResult, tx);
                }
                break;
            } else {
                flag = false;
                msg = TransactionErrorCode.DATA_NOT_FOUND.getMsg();
                break;
            }
        } while (false);
        Map<String, Object> resultMap = MapUtil.createLinkedHashMap(2);
        resultMap.put("flag", flag);
        if (!flag && StringUtils.isNotBlank(msg)) {
            resultMap.put("msg", msg);
        }
        if (flag && contractResultDto != null) {
            List<ContractTokenTransferDto> tokenTransfers = contractResultDto.getTokenTransfers();
            List<ContractTokenTransferDto> realTokenTransfers = this.filterRealTokenTransfers(tokenTransfers);
            contractResultDto.setTokenTransfers(realTokenTransfers);
            resultMap.put("data", contractResultDto);
        }
        return Result.getSuccess().setData(resultMap).toRpcClientResult();
    } catch (Exception e) {
        Log.error(e);
        return Result.getFailed().setMsg(e.getMessage()).toRpcClientResult();
    }
}
Also used : ContractResult(io.nuls.contract.dto.ContractResult) VarInt(io.nuls.kernel.utils.VarInt) NulsException(io.nuls.kernel.exception.NulsException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) ContractAddressInfoPo(io.nuls.contract.storage.po.ContractAddressInfoPo) CreateContractData(io.nuls.contract.entity.txdata.CreateContractData) ContractData(io.nuls.contract.entity.txdata.ContractData) CreateContractTransaction(io.nuls.contract.entity.tx.CreateContractTransaction) ContractTokenTransferInfoPo(io.nuls.contract.dto.ContractTokenTransferInfoPo)

Example 3 with ContractData

use of io.nuls.contract.entity.txdata.ContractData in project nuls by nuls-io.

the class ConsensusTool method returnContractSenderNa.

private static List<Coin> returnContractSenderNa(List<Transaction> txList, long unlockHeight) {
    // 去重, 可能存在同一个sender发出的几笔合约交易,需要把退还的GasNa累加到一起
    Map<ByteArrayWrapper, Na> returnMap = new HashMap<>();
    List<Coin> returnList = new ArrayList<>();
    if (txList != null && txList.size() > 0) {
        int txType;
        for (Transaction tx : txList) {
            txType = tx.getType();
            if (txType == ContractConstant.TX_TYPE_CREATE_CONTRACT || txType == ContractConstant.TX_TYPE_CALL_CONTRACT || txType == ContractConstant.TX_TYPE_DELETE_CONTRACT) {
                ContractTransaction contractTx = (ContractTransaction) tx;
                ContractResult contractResult = contractTx.getContractResult();
                if (contractResult == null) {
                    contractResult = contractService.getContractExecuteResult(tx.getHash());
                    if (contractResult == null) {
                        Log.error("get contract tx contractResult error: " + tx.getHash().getDigestHex());
                        continue;
                    }
                }
                contractTx.setContractResult(contractResult);
                // 终止合约不消耗Gas,跳过
                if (txType == ContractConstant.TX_TYPE_DELETE_CONTRACT) {
                    continue;
                }
                // 减差额作为退还Gas
                ContractData contractData = (ContractData) tx.getTxData();
                long realGasUsed = contractResult.getGasUsed();
                long txGasUsed = contractData.getGasLimit();
                long returnGas = 0;
                Na returnNa = Na.ZERO;
                if (txGasUsed > realGasUsed) {
                    returnGas = txGasUsed - realGasUsed;
                    returnNa = Na.valueOf(LongUtils.mul(returnGas, contractData.getPrice()));
                    // 用于计算本次矿工共识奖励 -> 需扣除退还给sender的Gas部分, Call,Create,DeleteContractTransaction 覆写getFee方法来处理
                    contractTx.setReturnNa(returnNa);
                    ByteArrayWrapper sender = new ByteArrayWrapper(contractData.getSender());
                    Na senderNa = returnMap.get(sender);
                    if (senderNa == null) {
                        senderNa = Na.ZERO.add(returnNa);
                    } else {
                        senderNa = senderNa.add(returnNa);
                    }
                    returnMap.put(sender, senderNa);
                }
            }
        }
        Set<Map.Entry<ByteArrayWrapper, Na>> entries = returnMap.entrySet();
        Coin returnCoin;
        for (Map.Entry<ByteArrayWrapper, Na> entry : entries) {
            returnCoin = new Coin(entry.getKey().getBytes(), entry.getValue(), unlockHeight);
            returnList.add(returnCoin);
        }
    }
    return returnList;
}
Also used : ContractResult(io.nuls.contract.dto.ContractResult) ContractTransaction(io.nuls.contract.entity.tx.ContractTransaction) ContractData(io.nuls.contract.entity.txdata.ContractData) ByteArrayWrapper(io.nuls.kernel.utils.ByteArrayWrapper) DepositTransaction(io.nuls.consensus.poc.protocol.tx.DepositTransaction) YellowPunishTransaction(io.nuls.consensus.poc.protocol.tx.YellowPunishTransaction) CreateAgentTransaction(io.nuls.consensus.poc.protocol.tx.CreateAgentTransaction) ContractTransaction(io.nuls.contract.entity.tx.ContractTransaction) CoinBaseTransaction(io.nuls.protocol.model.tx.CoinBaseTransaction)

Aggregations

ContractResult (io.nuls.contract.dto.ContractResult)3 ContractData (io.nuls.contract.entity.txdata.ContractData)3 ContractTokenTransferInfoPo (io.nuls.contract.dto.ContractTokenTransferInfoPo)2 CreateContractTransaction (io.nuls.contract.entity.tx.CreateContractTransaction)2 CreateContractData (io.nuls.contract.entity.txdata.CreateContractData)2 ContractAddressInfoPo (io.nuls.contract.storage.po.ContractAddressInfoPo)2 NulsException (io.nuls.kernel.exception.NulsException)2 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)2 VarInt (io.nuls.kernel.utils.VarInt)2 IOException (java.io.IOException)2 CreateAgentTransaction (io.nuls.consensus.poc.protocol.tx.CreateAgentTransaction)1 DepositTransaction (io.nuls.consensus.poc.protocol.tx.DepositTransaction)1 YellowPunishTransaction (io.nuls.consensus.poc.protocol.tx.YellowPunishTransaction)1 ContractTransaction (io.nuls.contract.entity.tx.ContractTransaction)1 ByteArrayWrapper (io.nuls.kernel.utils.ByteArrayWrapper)1 CoinBaseTransaction (io.nuls.protocol.model.tx.CoinBaseTransaction)1