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;
}
}
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;
}
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);
}
Aggregations