use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class ContractTxServiceImpl method saveUnConfirmedTokenTransfer.
private Result<byte[]> saveUnConfirmedTokenTransfer(CallContractTransaction tx, String sender, String contractAddress, String methodName, String[][] args) {
try {
byte[] senderBytes = AddressTool.getAddress(sender);
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
Result<ContractAddressInfoPo> contractAddressInfoResult = contractAddressStorageService.getContractAddressInfo(contractAddressBytes);
ContractAddressInfoPo po = contractAddressInfoResult.getData();
if (po != null && po.isNrc20() && ContractUtil.isTransferMethod(methodName)) {
byte[] txHashBytes = tx.getHash().serialize();
byte[] infoKey = ArraysTool.concatenate(senderBytes, txHashBytes, new VarInt(0).encode());
ContractTokenTransferInfoPo tokenTransferInfoPo = new ContractTokenTransferInfoPo();
if (ContractConstant.NRC20_METHOD_TRANSFER.equals(methodName)) {
String to = args[0][0];
String tokenValue = args[1][0];
BigInteger token = new BigInteger(tokenValue);
Result result = contractBalanceManager.subtractContractToken(sender, contractAddress, token);
if (result.isFailed()) {
return result;
}
contractBalanceManager.addContractToken(to, contractAddress, token);
tokenTransferInfoPo.setFrom(senderBytes);
tokenTransferInfoPo.setTo(AddressTool.getAddress(to));
tokenTransferInfoPo.setValue(token);
} else {
String from = args[0][0];
// 转出的不是自己的代币(代币授权逻辑),则不保存token待确认交易,因为有调用合约的待确认交易
if (!sender.equals(from)) {
return Result.getSuccess();
}
String to = args[1][0];
String tokenValue = args[2][0];
BigInteger token = new BigInteger(tokenValue);
Result result = contractBalanceManager.subtractContractToken(from, contractAddress, token);
if (result.isFailed()) {
return result;
}
contractBalanceManager.addContractToken(to, contractAddress, token);
tokenTransferInfoPo.setFrom(AddressTool.getAddress(from));
tokenTransferInfoPo.setTo(AddressTool.getAddress(to));
tokenTransferInfoPo.setValue(token);
}
tokenTransferInfoPo.setName(po.getNrc20TokenName());
tokenTransferInfoPo.setSymbol(po.getNrc20TokenSymbol());
tokenTransferInfoPo.setDecimals(po.getDecimals());
tokenTransferInfoPo.setTime(tx.getTime());
tokenTransferInfoPo.setContractAddress(contractAddress);
tokenTransferInfoPo.setBlockHeight(tx.getBlockHeight());
tokenTransferInfoPo.setTxHash(txHashBytes);
tokenTransferInfoPo.setStatus((byte) 0);
Result result = contractTokenTransferStorageService.saveTokenTransferInfo(infoKey, tokenTransferInfoPo);
if (result.isFailed()) {
return result;
}
return Result.getSuccess().setData(infoKey);
}
return Result.getSuccess();
} catch (Exception e) {
Log.error(e);
Result result = Result.getFailed(ContractErrorCode.CONTRACT_TX_CREATE_ERROR);
result.setMsg(e.getMessage());
return result;
}
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class ContractTxServiceImpl method contractDeleteTx.
/**
* 创建删除智能合约的交易
*
* @param sender 交易创建者
* @param contractAddress 合约地址
* @param password 账户密码
* @param remark 备注
* @return
*/
@Override
public Result contractDeleteTx(String sender, String contractAddress, String password, String remark) {
try {
AssertUtil.canNotEmpty(sender, "the sender address can not be empty");
AssertUtil.canNotEmpty(contractAddress, "the contractAddress can not be empty");
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
Result<ContractAddressInfoPo> contractAddressInfoPoResult = contractAddressStorageService.getContractAddressInfo(contractAddressBytes);
if (contractAddressInfoPoResult.isFailed()) {
return contractAddressInfoPoResult;
}
ContractAddressInfoPo contractAddressInfoPo = contractAddressInfoPoResult.getData();
if (contractAddressInfoPo == null) {
return Result.getFailed(ContractErrorCode.CONTRACT_ADDRESS_NOT_EXIST);
}
BlockHeader blockHeader = NulsContext.getInstance().getBestBlock().getHeader();
// 当前区块状态根
byte[] stateRoot = ContractUtil.getStateRoot(blockHeader);
// 获取合约当前状态
ProgramStatus status = vmHelper.getContractStatus(stateRoot, contractAddressBytes);
boolean isTerminatedContract = ContractUtil.isTerminatedContract(status.ordinal());
if (isTerminatedContract) {
return Result.getFailed(ContractErrorCode.CONTRACT_DELETED);
}
byte[] senderBytes = AddressTool.getAddress(sender);
if (!ArraysTool.arrayEquals(senderBytes, contractAddressInfoPo.getSender())) {
return Result.getFailed(ContractErrorCode.CONTRACT_DELETE_CREATER);
}
Result<ContractBalance> result = contractBalanceManager.getBalance(contractAddressBytes);
ContractBalance balance = (ContractBalance) result.getData();
if (balance == null) {
return result;
}
Na totalBalance = balance.getBalance();
if (totalBalance.compareTo(Na.ZERO) != 0) {
return Result.getFailed(ContractErrorCode.CONTRACT_DELETE_BALANCE);
}
Result<Account> accountResult = accountService.getAccount(sender);
if (accountResult.isFailed()) {
return accountResult;
}
Account account = accountResult.getData();
// 验证账户密码
if (account.isEncrypted() && account.isLocked()) {
AssertUtil.canNotEmpty(password, "the password can not be empty");
if (!account.validatePassword(password)) {
return Result.getFailed(AccountErrorCode.PASSWORD_IS_WRONG);
}
}
if (!account.isOk()) {
return Result.getFailed(AccountErrorCode.IMPORTING_ACCOUNT);
}
DeleteContractTransaction tx = new DeleteContractTransaction();
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(NulsConfig.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
Log.error(e);
throw new RuntimeException(e);
}
}
tx.setTime(TimeService.currentTimeMillis());
// 组装txData
DeleteContractData deleteContractData = new DeleteContractData();
deleteContractData.setContractAddress(contractAddressBytes);
deleteContractData.setSender(senderBytes);
tx.setTxData(deleteContractData);
// 计算CoinData
/*
* 没有Gas消耗,在终止智能合约里
*/
CoinData coinData = new CoinData();
// 总花费 终止智能合约的交易手续费按普通交易计算手续费
CoinDataResult coinDataResult = accountLedgerService.getCoinData(senderBytes, Na.ZERO, tx.size() + coinData.size(), TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
// 找零的UTXO
if (coinDataResult.getChange() != null) {
coinData.getTo().add(coinDataResult.getChange());
}
tx.setCoinData(coinData);
tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
// 生成签名
List<ECKey> signEckeys = new ArrayList<>();
List<ECKey> scriptEckeys = new ArrayList<>();
ECKey eckey = account.getEcKey(password);
// 如果最后一位为1则表示该交易包含普通签名
if ((coinDataResult.getSignType() & 0x01) == 0x01) {
signEckeys.add(eckey);
}
// 如果倒数第二位位为1则表示该交易包含脚本签名
if ((coinDataResult.getSignType() & 0x02) == 0x02) {
scriptEckeys.add(eckey);
}
SignatureUtil.createTransactionSignture(tx, scriptEckeys, signEckeys);
// 保存删除合约的交易到本地账本
Result saveResult = accountLedgerService.verifyAndSaveUnconfirmedTransaction(tx);
if (saveResult.isFailed()) {
if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
// 重新算一次交易(不超出最大交易数据大小下)的最大金额
Result rs = accountLedgerService.getMaxAmountOfOnce(senderBytes, tx, TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
if (rs.isSuccess()) {
Na maxAmount = (Na) rs.getData();
rs = Result.getFailed(KernelErrorCode.DATA_SIZE_ERROR_EXTEND);
rs.setMsg(rs.getMsg() + maxAmount.toDouble());
}
return rs;
}
return saveResult;
}
// 广播交易
Result sendResult = transactionService.broadcastTx(tx);
if (sendResult.isFailed()) {
// 失败则回滚
accountLedgerService.deleteTransaction(tx);
return sendResult;
}
return Result.getSuccess().setData(tx.getHash().getDigestHex());
} catch (IOException e) {
Log.error(e);
Result result = Result.getFailed(ContractErrorCode.CONTRACT_TX_CREATE_ERROR);
result.setMsg(e.getMessage());
return result;
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
} catch (Exception e) {
Log.error(e);
Result result = Result.getFailed(ContractErrorCode.CONTRACT_TX_CREATE_ERROR);
result.setMsg(e.getMessage());
return result;
}
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class CreateContractTxProcessor method onCommit.
@Override
public Result onCommit(CreateContractTransaction tx, Object secondaryData) {
ContractResult contractResult = tx.getContractResult();
contractService.saveContractExecuteResult(tx.getHash(), contractResult);
CreateContractData txData = tx.getTxData();
byte[] contractAddress = txData.getContractAddress();
byte[] sender = txData.getSender();
String senderStr = AddressTool.getStringAddressByBytes(sender);
String contractAddressStr = AddressTool.getStringAddressByBytes(contractAddress);
// 移除未确认的创建合约交易
contractTxService.removeLocalUnconfirmedCreateContractTransaction(senderStr, contractAddressStr, contractResult);
// 执行失败的合约直接返回
if (!contractResult.isSuccess()) {
return Result.getSuccess();
}
NulsDigestData hash = tx.getHash();
long blockHeight = tx.getBlockHeight();
long bestBlockHeight = NulsContext.getInstance().getBestHeight();
ContractAddressInfoPo info = new ContractAddressInfoPo();
info.setContractAddress(contractAddress);
info.setSender(sender);
try {
info.setCreateTxHash(hash.serialize());
} catch (IOException e) {
throw new NulsRuntimeException(e);
}
info.setCreateTime(tx.getTime());
info.setBlockHeight(blockHeight);
// byte[] stateRoot = contractResult.getStateRoot();
boolean isNrc20Contract = contractResult.isNrc20();
boolean acceptDirectTransfer = contractResult.isAcceptDirectTransfer();
info.setAcceptDirectTransfer(acceptDirectTransfer);
info.setNrc20(isNrc20Contract);
// 获取 token tracker
if (isNrc20Contract) {
BlockHeader blockHeader = tx.getBlockHeader();
byte[] newestStateRoot = blockHeader.getStateRoot();
// NRC20 token 标准方法获取名称数据
ProgramResult programResult = vmHelper.invokeViewMethod(newestStateRoot, bestBlockHeight, contractAddress, NRC20_METHOD_NAME, null, null);
if (programResult.isSuccess()) {
String tokenName = programResult.getResult();
info.setNrc20TokenName(tokenName);
}
programResult = vmHelper.invokeViewMethod(newestStateRoot, bestBlockHeight, contractAddress, NRC20_METHOD_SYMBOL, null, null);
if (programResult.isSuccess()) {
String symbol = programResult.getResult();
info.setNrc20TokenSymbol(symbol);
}
programResult = vmHelper.invokeViewMethod(newestStateRoot, bestBlockHeight, contractAddress, NRC20_METHOD_DECIMALS, null, null);
if (programResult.isSuccess()) {
String decimals = programResult.getResult();
if (StringUtils.isNotBlank(decimals)) {
try {
info.setDecimals(new BigInteger(decimals).longValue());
} catch (Exception e) {
Log.error("Get nrc20 decimals error.", e);
// skip it
}
}
}
programResult = vmHelper.invokeViewMethod(newestStateRoot, bestBlockHeight, contractAddress, NRC20_METHOD_TOTAL_SUPPLY, null, null);
if (programResult.isSuccess()) {
String totalSupply = programResult.getResult();
if (StringUtils.isNotBlank(totalSupply)) {
try {
info.setTotalSupply(new BigInteger(totalSupply));
} catch (Exception e) {
Log.error("Get nrc20 totalSupply error.", e);
// skip it
}
}
}
// 刷新创建者的token余额
vmHelper.refreshTokenBalance(newestStateRoot, info, senderStr, contractAddressStr);
// 处理合约事件
vmHelper.dealEvents(newestStateRoot, tx, contractResult, info);
}
Result result = contractAddressStorageService.saveContractAddress(contractAddress, info);
return result;
}
use of io.nuls.contract.storage.po.ContractAddressInfoPo in project nuls by nuls-io.
the class ContractBalanceManager method initAllTokensForAllAccounts.
public void initAllTokensForAllAccounts() {
Result<Collection<Account>> result = accountService.getAccountList();
if (result.isFailed()) {
return;
}
Result<List<ContractAddressInfoPo>> allContractInfoListResult = contractAddressStorageService.getAllNrc20ContractInfoList();
if (allContractInfoListResult.isFailed()) {
return;
}
List<ContractAddressInfoPo> contractAddressInfoPoList = allContractInfoListResult.getData();
Collection<Account> list = result.getData();
for (Account account : list) {
Address address = account.getAddress();
String addressStr = address.getBase58();
for (ContractAddressInfoPo po : contractAddressInfoPoList) {
initialContractToken(addressStr, AddressTool.getStringAddressByBytes(po.getContractAddress()));
}
}
}
Aggregations