Search in sources :

Example 16 with ContractResult

use of io.nuls.contract.dto.ContractResult in project nuls by nuls-io.

the class ContractServiceImpl method deleteContract.

/**
 * @param executor
 * @param number        当前块编号
 * @param prevStateRoot 上一区块状态根
 * @param delete        删除智能合约的参数
 * @return
 */
private Result<ContractResult> deleteContract(ProgramExecutor executor, long number, byte[] prevStateRoot, DeleteContractData delete) {
    if (number < 0) {
        return Result.getFailed(ContractErrorCode.PARAMETER_ERROR);
    }
    if (executor == null && prevStateRoot == null) {
        return Result.getFailed(ContractErrorCode.NULL_PARAMETER);
    }
    try {
        byte[] contractAddress = delete.getContractAddress();
        byte[] sender = delete.getSender();
        ProgramExecutor track;
        if (executor == null) {
            track = programExecutor.begin(prevStateRoot);
        } else {
            track = executor.startTracking();
        }
        ProgramResult programResult = track.stop(contractAddress, sender);
        // 批量提交方式,交易track放置到外部处理合约执行结果的方法里去提交
        if (executor == null) {
            track.commit();
        }
        // current state root
        byte[] stateRoot = executor == null ? track.getRoot() : null;
        ContractResult contractResult = new ContractResult();
        contractResult.setNonce(programResult.getNonce());
        contractResult.setGasUsed(programResult.getGasUsed());
        contractResult.setStateRoot(stateRoot);
        contractResult.setBalance(programResult.getBalance());
        contractResult.setContractAddress(contractAddress);
        contractResult.setSender(sender);
        contractResult.setRemark(ContractConstant.DELETE);
        // 批量提交方式,交易track放置到外部处理合约执行结果的方法里去提交
        contractResult.setTxTrack(track);
        if (!programResult.isSuccess()) {
            Result<ContractResult> result = Result.getFailed(ContractErrorCode.CONTRACT_EXECUTE_ERROR);
            contractResult.setError(programResult.isError());
            contractResult.setRevert(programResult.isRevert());
            contractResult.setErrorMessage(programResult.getErrorMessage());
            contractResult.setStackTrace(programResult.getStackTrace());
            result.setMsg(programResult.getErrorMessage());
            result.setData(contractResult);
            return result;
        }
        // 返回状态根
        contractResult.setError(false);
        contractResult.setRevert(false);
        Result<ContractResult> result = Result.getSuccess();
        result.setData(contractResult);
        return result;
    } catch (Exception e) {
        Log.error(e);
        Result result = Result.getFailed(ContractErrorCode.CONTRACT_EXECUTE_ERROR);
        result.setMsg(e.getMessage());
        return result;
    }
}
Also used : ContractResult(io.nuls.contract.dto.ContractResult) NulsException(io.nuls.kernel.exception.NulsException) IOException(java.io.IOException) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult)

Example 17 with ContractResult

use of io.nuls.contract.dto.ContractResult in project nuls by nuls-io.

the class ContractServiceImpl method handleContractTransferTxs.

private byte[] handleContractTransferTxs(CallContractTransaction tx, ContractResult contractResult, byte[] stateRoot, byte[] preStateRoot, List<ContractTransfer> transfers, long time, Map<String, Coin> toMaps, Map<String, Coin> contractUsedCoinMap, Long blockHeight) {
    boolean isCorrectContractTransfer = true;
    // 用于保存本次交易产生的合约转账(从合约转出)交易
    Map<String, ContractTransferTransaction> successContractTransferTxs = new LinkedHashMap<>();
    // 创建合约转账(从合约转出)交易
    if (transfers != null && transfers.size() > 0) {
        Result<ContractTransferTransaction> contractTransferResult;
        do {
            // 验证合约转账(从合约转出)交易的最小转移金额
            Result result = this.verifyTransfer(transfers);
            if (result.isFailed()) {
                isCorrectContractTransfer = false;
                contractResult.setError(true);
                String errorMsg = contractResult.getErrorMessage();
                errorMsg = errorMsg == null ? result.getErrorCode().getEnMsg() : (errorMsg + "," + result.getErrorCode().getEnMsg());
                contractResult.setErrorMessage(errorMsg);
                break;
            }
            // 合约转账(从合约转出)使用的交易时间为区块时间
            ContractTransferTransaction contractTransferTx;
            for (ContractTransfer transfer : transfers) {
                // 保存外部合约交易hash
                transfer.setOrginHash(tx.getHash());
                contractTransferResult = this.createContractTransferTx(transfer, time, toMaps, contractUsedCoinMap, blockHeight);
                if (contractTransferResult.isFailed()) {
                    this.rollbackContractTransferTxs(successContractTransferTxs, toMaps, contractUsedCoinMap);
                    isCorrectContractTransfer = false;
                    contractResult.setError(true);
                    String errorMsg = contractResult.getErrorMessage();
                    errorMsg = errorMsg == null ? contractTransferResult.getMsg() : (errorMsg + "," + contractTransferResult.getMsg());
                    contractResult.setErrorMessage(errorMsg);
                    break;
                }
                contractTransferTx = contractTransferResult.getData();
                // 保存内部转账交易hash
                transfer.setHash(contractTransferTx.getHash());
                successContractTransferTxs.put(contractTransferTx.getHash().getDigestHex(), contractTransferTx);
            }
        } while (false);
        // 如果合约转账(从合约转出)出现错误,整笔合约交易视作合约执行失败
        if (!isCorrectContractTransfer) {
            if (Log.isDebugEnabled()) {
                Log.debug("contract transfer execution failed, reason: {}", contractResult.getErrorMessage());
            }
            // 执行合约产生的状态根回滚到上一个世界状态
            stateRoot = preStateRoot;
            contractResult.setStateRoot(stateRoot);
            // 余额还原到上一次的余额
            contractResult.setBalance(contractResult.getPreBalance());
            // 清空成功转账列表
            successContractTransferTxs.clear();
            // 回滚临时余额
            this.rollbackContractTempBalance(tx, contractResult);
            // 清空内部转账列表
            transfers.clear();
            // 合约转账(从合约转出)交易失败,且调用者存在资金转入合约地址,创建一笔合约转账(从合约转出),退回这笔资金
            if (contractResult.getValue() > 0) {
                Na sendBack = Na.valueOf(contractResult.getValue());
                List<ContractTransfer> transferList = this.createReturnFundsContractTransfer(tx, sendBack);
                for (ContractTransfer transfer : transferList) {
                    transfer.setOrginHash(tx.getHash());
                    contractTransferResult = this.createContractTransferTx(transfer, time, toMaps, contractUsedCoinMap, blockHeight);
                    if (contractTransferResult.isFailed()) {
                        successContractTransferTxs.clear();
                        contractResult.setErrorMessage(contractResult.getErrorMessage() + ", " + contractTransferResult.getMsg());
                        break;
                    } else {
                        ContractTransferTransaction _contractTransferTx = contractTransferResult.getData();
                        // 保存内部转账交易hash和外部合约交易hash
                        transfer.setHash(_contractTransferTx.getHash());
                        transfers.add(transfer);
                        successContractTransferTxs.put(_contractTransferTx.getHash().getDigestHex(), _contractTransferTx);
                    }
                }
            }
        } else {
            // 归集转入合约地址的UTXOs
            this.contractExchange(tx, contractResult, time, toMaps, contractUsedCoinMap, blockHeight, transfers, successContractTransferTxs);
        }
        // 保存内部转账子交易到父交易对象中
        tx.setContractTransferTxs(successContractTransferTxs.values());
    } else {
        // `transfers.size() == 0` 智能合约在打包节点上只执行一次(打包区块和验证区块), 打包节点在打包时已处理过, 不重复处理
        if (null != transfers && transfers.size() == 0) {
            this.contractExchange(tx, contractResult, time, toMaps, contractUsedCoinMap, blockHeight, transfers, successContractTransferTxs);
            tx.setContractTransferTxs(successContractTransferTxs.values());
        }
    }
    // 合约执行成功并且合约转账(从合约转出)执行成功,提交这笔交易
    if (contractResult.isSuccess() && isCorrectContractTransfer) {
        Object txTrackObj = contractResult.getTxTrack();
        if (txTrackObj != null && txTrackObj instanceof ProgramExecutor) {
            ProgramExecutor txTrack = (ProgramExecutor) txTrackObj;
            if (Log.isDebugEnabled()) {
                Log.debug("===tx track commit.");
            }
            txTrack.commit();
        }
    }
    return stateRoot;
}
Also used : ContractTransfer(io.nuls.contract.dto.ContractTransfer) LedgerUtil.asString(io.nuls.ledger.util.LedgerUtil.asString) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult)

Example 18 with ContractResult

use of io.nuls.contract.dto.ContractResult in project nuls by nuls-io.

the class ContractServiceImpl method batchPackageTx.

@Override
public Result<ContractResult> batchPackageTx(Transaction tx, long bestHeight, Block block, byte[] stateRoot, Map<String, Coin> toMaps, Map<String, Coin> contractUsedCoinMap) {
    if (stateRoot == null) {
        return Result.getFailed();
    }
    BlockHeader blockHeader = block.getHeader();
    long blockTime = blockHeader.getTime();
    ProgramExecutor executor = localProgramExecutor.get();
    if (executor == null) {
        return Result.getFailed();
    }
    ContractTransaction contractTx = (ContractTransaction) tx;
    contractTx.setBlockHeader(blockHeader);
    // 验证区块时发现智能合约交易就调用智能合约
    Result<ContractResult> invokeContractResult = this.invokeContract(executor, tx, bestHeight, null, false);
    ContractResult contractResult = invokeContractResult.getData();
    if (contractResult != null) {
        this.handleContractResult(tx, contractResult, stateRoot, blockTime, toMaps, contractUsedCoinMap);
    }
    return Result.getSuccess().setData(contractResult);
}
Also used : ContractResult(io.nuls.contract.dto.ContractResult)

Aggregations

ContractResult (io.nuls.contract.dto.ContractResult)18 ValidateResult (io.nuls.kernel.validate.ValidateResult)11 IOException (java.io.IOException)10 NulsException (io.nuls.kernel.exception.NulsException)7 CoinDataResult (io.nuls.account.ledger.model.CoinDataResult)5 ContractAddressInfoPo (io.nuls.contract.storage.po.ContractAddressInfoPo)5 ContractTokenTransferInfoPo (io.nuls.contract.dto.ContractTokenTransferInfoPo)4 VarInt (io.nuls.kernel.utils.VarInt)4 ContractTransferTransaction (io.nuls.contract.entity.tx.ContractTransferTransaction)3 ContractData (io.nuls.contract.entity.txdata.ContractData)3 CreateContractData (io.nuls.contract.entity.txdata.CreateContractData)3 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)3 Result (io.nuls.kernel.model.Result)3 MeetingMember (io.nuls.consensus.poc.model.MeetingMember)2 MeetingRound (io.nuls.consensus.poc.model.MeetingRound)2 RedPunishTransaction (io.nuls.consensus.poc.protocol.tx.RedPunishTransaction)2 YellowPunishTransaction (io.nuls.consensus.poc.protocol.tx.YellowPunishTransaction)2 ContractTransfer (io.nuls.contract.dto.ContractTransfer)2 CallContractTransaction (io.nuls.contract.entity.tx.CallContractTransaction)2 CreateContractTransaction (io.nuls.contract.entity.tx.CreateContractTransaction)2