use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class VMHelper method dealEvents.
public void dealEvents(byte[] newestStateRoot, Transaction tx, ContractResult contractResult, ContractAddressInfoPo po) {
if (po == null) {
return;
}
try {
List<String> events = contractResult.getEvents();
int size = events.size();
// 目前只处理Transfer事件, 为了刷新账户的token余额
String event;
ContractAddressInfoPo contractAddressInfo;
if (events != null && size > 0) {
for (int i = 0; i < size; i++) {
event = events.get(i);
// 按照NRC20标准,TransferEvent事件中第一个参数是转出地址-from,第二个参数是转入地址-to, 第三个参数是金额
ContractTokenTransferInfoPo tokenTransferInfoPo = ContractUtil.convertJsonToTokenTransferInfoPo(event);
if (tokenTransferInfoPo == null) {
continue;
}
String contractAddress = tokenTransferInfoPo.getContractAddress();
if (StringUtils.isBlank(contractAddress)) {
continue;
}
if (!AddressTool.validAddress(contractAddress)) {
continue;
}
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
if (ArraysTool.arrayEquals(po.getContractAddress(), contractAddressBytes)) {
contractAddressInfo = po;
} else {
Result<ContractAddressInfoPo> contractAddressInfoResult = contractAddressStorageService.getContractAddressInfo(contractAddressBytes);
contractAddressInfo = contractAddressInfoResult.getData();
}
if (contractAddressInfo == null) {
continue;
}
// 事件不是NRC20合约的事件
if (!contractAddressInfo.isNrc20()) {
continue;
}
byte[] txHashBytes;
byte[] from = tokenTransferInfoPo.getFrom();
byte[] to = tokenTransferInfoPo.getTo();
tokenTransferInfoPo.setName(contractAddressInfo.getNrc20TokenName());
tokenTransferInfoPo.setSymbol(contractAddressInfo.getNrc20TokenSymbol());
tokenTransferInfoPo.setDecimals(contractAddressInfo.getDecimals());
tokenTransferInfoPo.setTime(tx.getTime());
tokenTransferInfoPo.setBlockHeight(tx.getBlockHeight());
txHashBytes = tx.getHash().serialize();
tokenTransferInfoPo.setTxHash(txHashBytes);
tokenTransferInfoPo.setStatus((byte) (contractResult.isSuccess() ? 1 : 2));
if (from != null) {
this.refreshTokenBalance(newestStateRoot, contractAddressInfo, AddressTool.getStringAddressByBytes(from), contractAddress);
this.saveTokenTransferInfo(from, txHashBytes, new VarInt(i).encode(), tokenTransferInfoPo);
}
if (to != null) {
this.refreshTokenBalance(newestStateRoot, contractAddressInfo, AddressTool.getStringAddressByBytes(to), contractAddress);
this.saveTokenTransferInfo(to, txHashBytes, new VarInt(i).encode(), tokenTransferInfoPo);
}
}
}
} catch (Exception e) {
Log.warn("contract event parse error.", e);
}
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class CallContractTxProcessor method onRollback.
@Override
public Result onRollback(CallContractTransaction tx, Object secondaryData) {
try {
// 回滚代币转账交易
byte[] txHashBytes = null;
try {
txHashBytes = tx.getHash().serialize();
} catch (IOException e) {
Log.error(e);
}
ContractResult contractResult = tx.getContractResult();
if (contractResult == null) {
contractResult = contractService.getContractExecuteResult(tx.getHash());
}
CallContractData txData = tx.getTxData();
byte[] senderContractAddressBytes = txData.getContractAddress();
Result<ContractAddressInfoPo> senderContractAddressInfoResult = contractAddressStorageService.getContractAddressInfo(senderContractAddressBytes);
ContractAddressInfoPo po = senderContractAddressInfoResult.getData();
if (po != null) {
if (contractResult != null) {
// 处理合约执行失败 - 没有transferEvent的情况, 直接从数据库中删除
if (!contractResult.isSuccess()) {
if (ContractUtil.isTransferMethod(txData.getMethodName())) {
contractTokenTransferStorageService.deleteTokenTransferInfo(ArraysTool.concatenate(txData.getSender(), txHashBytes, new VarInt(0).encode()));
}
}
List<String> events = contractResult.getEvents();
int size = events.size();
// 目前只处理Transfer事件
String event;
ContractAddressInfoPo contractAddressInfo;
if (events != null && size > 0) {
for (int i = 0; i < size; i++) {
event = events.get(i);
// 按照NRC20标准,TransferEvent事件中第一个参数是转出地址-from,第二个参数是转入地址-to, 第三个参数是金额
ContractTokenTransferInfoPo tokenTransferInfoPo = ContractUtil.convertJsonToTokenTransferInfoPo(event);
if (tokenTransferInfoPo == null) {
continue;
}
String contractAddress = tokenTransferInfoPo.getContractAddress();
if (StringUtils.isBlank(contractAddress)) {
continue;
}
if (!AddressTool.validAddress(contractAddress)) {
continue;
}
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
if (ArraysTool.arrayEquals(senderContractAddressBytes, contractAddressBytes)) {
contractAddressInfo = po;
} else {
Result<ContractAddressInfoPo> contractAddressInfoResult = contractAddressStorageService.getContractAddressInfo(contractAddressBytes);
contractAddressInfo = contractAddressInfoResult.getData();
}
if (contractAddressInfo == null) {
continue;
}
// 事件不是NRC20合约的事件
if (!contractAddressInfo.isNrc20()) {
continue;
}
// 回滚token余额
this.rollbackContractToken(tokenTransferInfoPo);
contractTokenTransferStorageService.deleteTokenTransferInfo(ArraysTool.concatenate(tokenTransferInfoPo.getFrom(), txHashBytes, new VarInt(i).encode()));
contractTokenTransferStorageService.deleteTokenTransferInfo(ArraysTool.concatenate(tokenTransferInfoPo.getTo(), txHashBytes, new VarInt(i).encode()));
}
}
}
}
// 删除子交易从全网账本
// 删除子交易从合约账本
// 删除子交易从本地账本
List<ContractTransferTransaction> contractTransferTxList = this.extractContractTransferTxs(contractResult);
if (contractTransferTxList != null && !contractTransferTxList.isEmpty()) {
// 用于回滚本地账本
List<Transaction> txList = new ArrayList<>();
for (ContractTransferTransaction transferTx : contractTransferTxList) {
try {
txList.add(transferTx);
Result result = ledgerService.rollbackTx(transferTx);
if (result.isFailed()) {
Log.error("rollback contract transfer tx from ledger error. msg: {}", result.getMsg());
return result;
}
result = contractService.rollbackContractTransferTx(transferTx);
if (result.isFailed()) {
Log.error("rollback contract transfer tx from contract ledger error. msg: {}", result.getMsg());
return Result.getFailed();
}
} catch (Exception e) {
Log.error("rollback contract transfer tx error. msg: {}", e.getMessage());
return Result.getFailed();
}
}
Result result = accountLedgerService.rollbackTransactions(txList);
if (result.isFailed()) {
Log.error("rollback contract transfer tx from account ledger error. msg: {}", result.getMsg());
return Result.getFailed();
}
}
// 删除合约调用交易的UTXO
contractUtxoService.deleteUtxoOfTransaction(tx);
// 删除合约执行结果
contractService.deleteContractExecuteResult(tx.getHash());
} catch (Exception e) {
Log.error("rollback call contract tx error.", e);
return Result.getFailed();
}
return Result.getSuccess();
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class ContractAddressStorageServiceImpl method getAllContractInfoList.
@Override
public Result<List<ContractAddressInfoPo>> getAllContractInfoList() {
List<Entry<byte[], ContractAddressInfoPo>> list = dbService.entryList(ContractStorageConstant.DB_NAME_CONTRACT_ADDRESS, ContractAddressInfoPo.class);
if (list == null || list.size() == 0) {
return Result.getFailed(KernelErrorCode.DATA_NOT_FOUND);
}
List<ContractAddressInfoPo> resultList = new ArrayList<>();
ContractAddressInfoPo po;
for (Entry<byte[], ContractAddressInfoPo> entry : list) {
po = entry.getValue();
po.setContractAddress(entry.getKey());
resultList.add(po);
}
Result<List<ContractAddressInfoPo>> result = Result.getSuccess();
result.setData(resultList);
return result;
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class ContractAddressStorageServiceImpl method getAllNrc20ContractInfoList.
@Override
public Result<List<ContractAddressInfoPo>> getAllNrc20ContractInfoList() {
Result<List<ContractAddressInfoPo>> allContractInfoListResult = getAllContractInfoList();
if (allContractInfoListResult.isFailed()) {
return allContractInfoListResult;
}
List<ContractAddressInfoPo> resultList = new ArrayList<>();
List<ContractAddressInfoPo> contractAddressInfoPoList = allContractInfoListResult.getData();
for (ContractAddressInfoPo po : contractAddressInfoPoList) {
if (po.isNrc20()) {
resultList.add(po);
}
}
return Result.getSuccess().setData(resultList);
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo 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();
}
}
Aggregations