Search in sources :

Example 21 with ContractAddressInfoPo

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;
    }
}
Also used : ContractAddressInfoPo(io.nuls.contract.storage.po.ContractAddressInfoPo) VarInt(io.nuls.kernel.utils.VarInt) BigInteger(java.math.BigInteger) ContractTokenTransferInfoPo(io.nuls.contract.dto.ContractTokenTransferInfoPo) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) ContractResult(io.nuls.contract.dto.ContractResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult)

Example 22 with ContractAddressInfoPo

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;
    }
}
Also used : Account(io.nuls.account.model.Account) ContractBalance(io.nuls.contract.ledger.module.ContractBalance) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ECKey(io.nuls.core.tools.crypto.ECKey) IOException(java.io.IOException) DeleteContractTransaction(io.nuls.contract.entity.tx.DeleteContractTransaction) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) ContractResult(io.nuls.contract.dto.ContractResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) ContractAddressInfoPo(io.nuls.contract.storage.po.ContractAddressInfoPo) NulsException(io.nuls.kernel.exception.NulsException) DeleteContractData(io.nuls.contract.entity.txdata.DeleteContractData) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult)

Example 23 with ContractAddressInfoPo

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;
}
Also used : ContractResult(io.nuls.contract.dto.ContractResult) ProgramResult(io.nuls.contract.vm.program.ProgramResult) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) ProgramResult(io.nuls.contract.vm.program.ProgramResult) Result(io.nuls.kernel.model.Result) ContractAddressInfoPo(io.nuls.contract.storage.po.ContractAddressInfoPo) CreateContractData(io.nuls.contract.entity.txdata.CreateContractData) NulsDigestData(io.nuls.kernel.model.NulsDigestData) BigInteger(java.math.BigInteger) BlockHeader(io.nuls.kernel.model.BlockHeader)

Example 24 with ContractAddressInfoPo

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()));
        }
    }
}
Also used : ContractAddressInfoPo(io.nuls.contract.storage.po.ContractAddressInfoPo) Account(io.nuls.account.model.Account) Address(io.nuls.kernel.model.Address) LedgerUtil.asString(io.nuls.ledger.util.LedgerUtil.asString)

Aggregations

ContractAddressInfoPo (io.nuls.contract.storage.po.ContractAddressInfoPo)24 IOException (java.io.IOException)15 NulsException (io.nuls.kernel.exception.NulsException)14 ContractResult (io.nuls.contract.dto.ContractResult)9 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)9 ContractTokenTransferInfoPo (io.nuls.contract.dto.ContractTokenTransferInfoPo)6 VarInt (io.nuls.kernel.utils.VarInt)6 Account (io.nuls.account.model.Account)5 CreateContractTransaction (io.nuls.contract.entity.tx.CreateContractTransaction)4 CreateContractData (io.nuls.contract.entity.txdata.CreateContractData)4 BigInteger (java.math.BigInteger)4 ArrayList (java.util.ArrayList)4 ContractBalance (io.nuls.contract.ledger.module.ContractBalance)3 ContractCollectionInfoPo (io.nuls.contract.storage.po.ContractCollectionInfoPo)3 Result (io.nuls.kernel.model.Result)3 ValidateResult (io.nuls.kernel.validate.ValidateResult)3 LinkedList (java.util.LinkedList)3 List (java.util.List)3 CoinDataResult (io.nuls.account.ledger.model.CoinDataResult)2 ContractTransferTransaction (io.nuls.contract.entity.tx.ContractTransferTransaction)2