Search in sources :

Example 61 with NulsException

use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.

the class AccountLedgerServiceImpl method transferP2SH.

/**
 * A transfers NULS to B   多签交易
 *
 * @param fromAddr address of A
 * @param signAddr address of B
 * @param values   NULS amount
 * @param password password of A
 * @param remark   remarks of transaction
 * @param price    Unit price of fee
 * @param pubkeys  公钥列表
 * @param m        至少需要签名验证通过
 * @return Result
 */
@Override
public Result transferP2SH(byte[] fromAddr, byte[] signAddr, List<MultipleAddressTransferModel> outputs, Na values, String password, String remark, Na price, List<String> pubkeys, int m, String txdata) {
    try {
        Result<Account> accountResult = accountService.getAccount(signAddr);
        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);
        }
        TransferTransaction tx = new TransferTransaction();
        TransactionSignature transactionSignature = new TransactionSignature();
        List<P2PHKSignature> p2PHKSignatures = new ArrayList<>();
        List<Script> scripts = new ArrayList<>();
        // 如果txdata为空则表示当前请求为多签发起者调用,需要创建交易
        if (txdata == null || txdata.trim().length() == 0) {
            if (StringUtils.isNotBlank(remark)) {
                try {
                    tx.setRemark(remark.getBytes(NulsConfig.DEFAULT_ENCODING));
                } catch (UnsupportedEncodingException e) {
                    Log.error(e);
                }
            }
            Script redeemScript = ScriptBuilder.createNulsRedeemScript(m, pubkeys);
            tx.setTime(TimeService.currentTimeMillis());
            CoinData coinData = new CoinData();
            for (MultipleAddressTransferModel to : outputs) {
                // 如果为多签地址
                Coin toCoin = null;
                if (to.getAddress()[2] == NulsContext.P2SH_ADDRESS_TYPE) {
                    Script scriptPubkey = SignatureUtil.createOutputScript(to.getAddress());
                    toCoin = new Coin(scriptPubkey.getProgram(), Na.valueOf(to.getAmount()));
                } else {
                    toCoin = new Coin(to.getAddress(), Na.valueOf(to.getAmount()));
                }
                coinData.getTo().add(toCoin);
            }
            if (price == null) {
                price = TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES;
            }
            // 交易签名的长度为m*单个签名长度+赎回脚本长度
            int scriptSignLenth = redeemScript.getProgram().length + m * 72;
            CoinDataResult coinDataResult = getMutilCoinData(fromAddr, values, tx.size() + coinData.size() + scriptSignLenth, price);
            if (!coinDataResult.isEnough()) {
                return Result.getFailed(AccountLedgerErrorCode.INSUFFICIENT_BALANCE);
            }
            coinData.setFrom(coinDataResult.getCoinList());
            if (coinDataResult.getChange() != null) {
                coinData.getTo().add(coinDataResult.getChange());
            }
            tx.setCoinData(coinData);
            tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
            // 将赎回脚本先存储在签名脚本中
            scripts.add(redeemScript);
            transactionSignature.setScripts(scripts);
        } else // 如果txdata不为空表示多签交易已经创建好了,将交易反序列化出来
        {
            byte[] txByte = Hex.decode(txdata);
            tx.parse(new NulsByteBuffer(txByte));
            transactionSignature.parse(new NulsByteBuffer(tx.getTransactionSignature()));
            p2PHKSignatures = transactionSignature.getP2PHKSignatures();
            scripts = transactionSignature.getScripts();
        }
        // 使用签名账户对交易进行签名
        P2PHKSignature p2PHKSignature = new P2PHKSignature();
        ECKey eckey = account.getEcKey(password);
        p2PHKSignature.setPublicKey(eckey.getPubKey());
        // 用当前交易的hash和账户的私钥账户
        p2PHKSignature.setSignData(accountService.signDigest(tx.getHash().getDigestBytes(), eckey));
        p2PHKSignatures.add(p2PHKSignature);
        // 当已签名数等于M则自动广播该交易
        if (p2PHKSignatures.size() == SignatureUtil.getM(scripts.get(0))) {
            // 将交易中的签名数据P2PHKSignatures按规则排序
            Collections.sort(p2PHKSignatures, P2PHKSignature.PUBKEY_COMPARATOR);
            // 将排序后的P2PHKSignatures的签名数据取出和赎回脚本结合生成解锁脚本
            List<byte[]> signatures = new ArrayList<>();
            for (P2PHKSignature p2PHKSignatureTemp : p2PHKSignatures) {
                signatures.add(p2PHKSignatureTemp.getSignData().getSignBytes());
            }
            transactionSignature.setP2PHKSignatures(null);
            Script scriptSign = ScriptBuilder.createNulsP2SHMultiSigInputScript(signatures, scripts.get(0));
            transactionSignature.getScripts().clear();
            transactionSignature.getScripts().add(scriptSign);
            tx.setTransactionSignature(transactionSignature.serialize());
            // 保存未确认交易到本地账户
            Result saveResult = verifyAndSaveUnconfirmedTransaction(tx);
            if (saveResult.isFailed()) {
                if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
                    // 重新算一次交易(不超出最大交易数据大小下)的最大金额
                    Result rs = getMaxAmountOfOnce(fromAddr, tx, price);
                    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()) {
                this.deleteTransaction(tx);
                return sendResult;
            }
            return Result.getSuccess().setData(tx.getHash().getDigestHex());
        } else // 如果签名数还没达到,则返回交易
        {
            transactionSignature.setP2PHKSignatures(p2PHKSignatures);
            tx.setTransactionSignature(transactionSignature.serialize());
            return Result.getSuccess().setData(Hex.encode(tx.serialize()));
        }
    } catch (IOException e) {
        Log.error(e);
        return Result.getFailed(KernelErrorCode.IO_ERROR);
    } catch (NulsException e) {
        Log.error(e);
        return Result.getFailed(e.getErrorCode());
    }
}
Also used : Account(io.nuls.account.model.Account) MultiSigAccount(io.nuls.account.model.MultiSigAccount) MultipleAddressTransferModel(io.nuls.account.ledger.model.MultipleAddressTransferModel) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ECKey(io.nuls.core.tools.crypto.ECKey) IOException(java.io.IOException) TransactionDataResult(io.nuls.account.ledger.model.TransactionDataResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) NulsException(io.nuls.kernel.exception.NulsException) TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) NulsByteBuffer(io.nuls.kernel.utils.NulsByteBuffer)

Example 62 with NulsException

use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.

the class AccountLedgerServiceImpl method createP2shTransfer.

/**
 * A transfers NULS to B   多签交易
 *
 * @param fromAddr 输入地址
 * @param signAddr 签名地址
 * @param outputs  输出地址
 * @param password password of A
 * @param remark   remarks of transaction
 * @return Result
 */
@Override
public Result createP2shTransfer(String fromAddr, String signAddr, List<MultipleAddressTransferModel> outputs, String password, String remark) {
    try {
        Result<Account> accountResult = accountService.getAccount(signAddr);
        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);
            }
        }
        TransferTransaction tx = new TransferTransaction();
        TransactionSignature transactionSignature = new TransactionSignature();
        List<Script> scripts = new ArrayList<>();
        Result<MultiSigAccount> result = accountService.getMultiSigAccount(fromAddr);
        MultiSigAccount multiSigAccount = result.getData();
        // 验证签名账户是否属于多签账户,如果不是多签账户下的地址则提示错误
        if (!AddressTool.validSignAddress(multiSigAccount.getPubKeyList(), account.getPubKey())) {
            return Result.getFailed(AccountErrorCode.SIGN_ADDRESS_NOT_MATCH);
        }
        Script redeemScript = getRedeemScript(multiSigAccount);
        if (redeemScript == null) {
            return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST);
        }
        tx.setTime(TimeService.currentTimeMillis());
        if (StringUtils.isNotBlank(remark)) {
            try {
                tx.setRemark(remark.getBytes(NulsConfig.DEFAULT_ENCODING));
            } catch (UnsupportedEncodingException e) {
                Log.error(e);
            }
        }
        CoinData coinData = new CoinData();
        Na values = Na.ZERO;
        for (MultipleAddressTransferModel to : outputs) {
            // 如果为多签地址
            Coin toCoin = null;
            values = values.add(Na.valueOf(to.getAmount()));
            if (to.getAddress()[2] == NulsContext.P2SH_ADDRESS_TYPE) {
                Script scriptPubkey = SignatureUtil.createOutputScript(to.getAddress());
                toCoin = new Coin(scriptPubkey.getProgram(), Na.valueOf(to.getAmount()));
            } else {
                toCoin = new Coin(to.getAddress(), Na.valueOf(to.getAmount()));
            }
            coinData.getTo().add(toCoin);
        }
        // 交易签名的长度为m*单个签名长度+赎回脚本长度
        int scriptSignLenth = redeemScript.getProgram().length + ((int) multiSigAccount.getM()) * 72;
        CoinDataResult coinDataResult = getMutilCoinData(AddressTool.getAddress(fromAddr), values, tx.size() + coinData.size() + scriptSignLenth, TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
        if (!coinDataResult.isEnough()) {
            return Result.getFailed(AccountLedgerErrorCode.INSUFFICIENT_BALANCE);
        }
        coinData.setFrom(coinDataResult.getCoinList());
        if (coinDataResult.getChange() != null) {
            coinData.getTo().add(coinDataResult.getChange());
        }
        tx.setCoinData(coinData);
        tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
        // 将赎回脚本先存储在签名脚本中
        scripts.add(redeemScript);
        transactionSignature.setScripts(scripts);
        return txMultiProcess(tx, transactionSignature, account, password);
    } catch (IOException e) {
        Log.error(e);
        return Result.getFailed(KernelErrorCode.IO_ERROR);
    } catch (NulsException e) {
        Log.error(e);
        return Result.getFailed(e.getErrorCode());
    } catch (Exception e) {
        Log.error(e);
        return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST);
    }
}
Also used : MultiSigAccount(io.nuls.account.model.MultiSigAccount) Account(io.nuls.account.model.Account) MultiSigAccount(io.nuls.account.model.MultiSigAccount) MultipleAddressTransferModel(io.nuls.account.ledger.model.MultipleAddressTransferModel) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult)

Example 63 with NulsException

use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.

the class AccountLedgerResource method getTxInfoList.

@GET
@Path("/tx/list/{address}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "账户地址查询交易列表", notes = "result.data: balanceJson 返回账户相关的交易列表")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = Page.class) })
public RpcClientResult getTxInfoList(@ApiParam(name = "address", value = "账户地址", required = true) @PathParam("address") String address, @ApiParam(name = "assetType", value = "资产类型") @QueryParam("assetType") String assetType, @ApiParam(name = "type", value = "类型") @QueryParam("type") Integer type, @ApiParam(name = "pageNumber", value = "页码") @QueryParam("pageNumber") Integer pageNumber, @ApiParam(name = "pageSize", value = "每页条数") @QueryParam("pageSize") Integer pageSize) {
    if (null == pageNumber || pageNumber == 0) {
        pageNumber = 1;
    }
    if (null == pageSize || pageSize == 0) {
        pageSize = 10;
    }
    if (pageNumber < 0 || pageSize < 0 || pageSize > 100) {
        return Result.getFailed(KernelErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    if (type == null || type <= 0) {
        type = -1;
    }
    byte[] addressBytes = null;
    Result dtoResult = Result.getSuccess();
    try {
        addressBytes = AddressTool.getAddress(address.trim());
    } catch (Exception e) {
        return Result.getFailed(AccountLedgerErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    List<TransactionInfo> result = new ArrayList<TransactionInfo>();
    boolean isEmptyAssetType = StringUtils.isBlank(assetType);
    boolean isNeedQueryToken = StringUtils.isBlank(assetType) || AddressTool.validAddress(assetType);
    boolean isNeedQueryNuls = StringUtils.isBlank(assetType) || "NULS".equals(assetType);
    Set<String> hashCheckSet = MapUtil.createHashSet(8);
    // 合约token代币转账交易记录
    if (isNeedQueryToken) {
        Result<List<ContractTokenTransferInfoPo>> listResult = contractService.getTokenTransferInfoList(address);
        List<ContractTokenTransferInfoPo> list = listResult.getData();
        if (list != null && list.size() > 0) {
            List<ContractTokenTransferInfoPo> tokenInfoList = null;
            if (!isEmptyAssetType) {
                String contractAddress = assetType;
                if (AddressTool.validAddress(contractAddress)) {
                    tokenInfoList = list.stream().filter(po -> contractAddress.equals(po.getContractAddress())).collect(Collectors.toList());
                }
            } else {
                tokenInfoList = list;
            }
            TransactionInfo info = null;
            if (null != tokenInfoList) {
                for (ContractTokenTransferInfoPo po : tokenInfoList) {
                    info = new TransactionInfo();
                    // 临时type,用于区分资产类型 - 基础币和代币
                    info.setTxType(1000);
                    NulsDigestData hashData = new NulsDigestData();
                    try {
                        hashData.parse(po.getTxHash(), 0);
                    } catch (NulsException e) {
                        Log.error(e);
                    // skip it
                    }
                    info.setTxHash(hashData);
                    info.setContractAddress(AddressTool.getAddress(po.getContractAddress()));
                    info.setTime(po.getTime());
                    info.setBlockHeight(po.getBlockHeight());
                    info.setStatus(po.getStatus());
                    info.setInfo(po.getInfo(addressBytes));
                    info.setSymbol(po.getSymbol());
                    result.add(info);
                    hashCheckSet.add(hashData.getDigestHex());
                }
            }
        }
    }
    // 基础币交易记录
    if (isNeedQueryNuls) {
        Result<List<TransactionInfo>> rawResult = accountLedgerService.getTxInfoList(addressBytes);
        if (rawResult.isFailed()) {
            dtoResult.setSuccess(false);
            dtoResult.setErrorCode(rawResult.getErrorCode());
            return dtoResult.toRpcClientResult();
        }
        List<TransactionInfo> infoList = rawResult.getData();
        if (infoList != null && infoList.size() > 0) {
            // 过滤掉既是调用合约的交易类型,又是代币转账类型的交易
            List<TransactionInfo> baseList = infoList.stream().filter(info -> hashCheckSet.add(info.getTxHash().getDigestHex())).collect(Collectors.toList());
            if (type == -1) {
                result.addAll(baseList);
            } else {
                for (TransactionInfo txInfo : baseList) {
                    if (txInfo.getTxType() == type) {
                        result.add(txInfo);
                    }
                }
            }
        }
    }
    result.sort(new Comparator<TransactionInfo>() {

        @Override
        public int compare(TransactionInfo o1, TransactionInfo o2) {
            return o1.compareTo(o2.getTime());
        }
    });
    Page<TransactionInfoDto> page = new Page<>(pageNumber, pageSize, result.size());
    int start = pageNumber * pageSize - pageSize;
    if (start >= page.getTotal()) {
        dtoResult.setData(page);
        return dtoResult.toRpcClientResult();
    }
    int end = start + pageSize;
    if (end > page.getTotal()) {
        end = (int) page.getTotal();
    }
    List<TransactionInfoDto> infoDtoList = new ArrayList<>();
    for (int i = start; i < end; i++) {
        TransactionInfo info = result.get(i);
        Transaction tx = ledgerService.getTx(info.getTxHash());
        if (tx == null) {
            tx = accountLedgerService.getUnconfirmedTransaction(info.getTxHash()).getData();
        }
        if (tx == null) {
            continue;
        }
        info.setBlockHeight(tx.getBlockHeight());
        // 非合约Token转账
        if (info.getTxType() != 1000) {
            info.setInfo(tx.getInfo(addressBytes));
        }
        infoDtoList.add(new TransactionInfoDto(info));
    }
    page.setList(infoDtoList);
    dtoResult.setSuccess(true);
    dtoResult.setData(page);
    return dtoResult.toRpcClientResult();
}
Also used : io.nuls.accout.ledger.rpc.form(io.nuls.accout.ledger.rpc.form) Output(io.protostuff.Output) ECKey(io.nuls.core.tools.crypto.ECKey) StringUtils(io.nuls.core.tools.str.StringUtils) CryptoException(io.nuls.core.tools.crypto.Exception.CryptoException) MediaType(javax.ws.rs.core.MediaType) UtxoDtoComparator(io.nuls.accout.ledger.rpc.util.UtxoDtoComparator) AccountTool(io.nuls.account.util.AccountTool) NulsContext(io.nuls.kernel.context.NulsContext) Page(io.nuls.core.tools.page.Page) io.swagger.annotations(io.swagger.annotations) BigInteger(java.math.BigInteger) SignatureUtil(io.nuls.kernel.script.SignatureUtil) TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction) AccountLedgerErrorCode(io.nuls.account.ledger.constant.AccountLedgerErrorCode) TransactionSignature(io.nuls.kernel.script.TransactionSignature) CoinDataTool(io.nuls.account.ledger.util.CoinDataTool) TxStatusEnum(io.nuls.kernel.constant.TxStatusEnum) Collectors(java.util.stream.Collectors) ProtocolConstant(io.nuls.protocol.constant.ProtocolConstant) Arrays(org.spongycastle.util.Arrays) AccountService(io.nuls.account.service.AccountService) MultipleAddressTransferModel(io.nuls.account.ledger.model.MultipleAddressTransferModel) NulsException(io.nuls.kernel.exception.NulsException) javax.ws.rs(javax.ws.rs) AESEncrypt(io.nuls.core.tools.crypto.AESEncrypt) Autowired(io.nuls.kernel.lite.annotation.Autowired) ContractTokenTransferInfoPo(io.nuls.contract.dto.ContractTokenTransferInfoPo) TxMaxSizeValidator(io.nuls.protocol.model.validator.TxMaxSizeValidator) UnsupportedEncodingException(java.io.UnsupportedEncodingException) LedgerService(io.nuls.ledger.service.LedgerService) java.util(java.util) TimeService(io.nuls.kernel.func.TimeService) Script(io.nuls.kernel.script.Script) AccountLedgerService(io.nuls.account.ledger.service.AccountLedgerService) io.nuls.kernel.utils(io.nuls.kernel.utils) P2PHKSignature(io.nuls.kernel.script.P2PHKSignature) LedgerRpcUtil(io.nuls.accout.ledger.rpc.util.LedgerRpcUtil) Component(io.nuls.kernel.lite.annotation.Component) io.nuls.kernel.model(io.nuls.kernel.model) ValidateResult(io.nuls.kernel.validate.ValidateResult) AccountLegerUtils(io.nuls.account.ledger.base.util.AccountLegerUtils) AccountErrorCode(io.nuls.account.constant.AccountErrorCode) NulsConstant(io.nuls.kernel.constant.NulsConstant) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) MapUtil(io.nuls.core.tools.map.MapUtil) KernelErrorCode(io.nuls.kernel.constant.KernelErrorCode) TransactionErrorCode(io.nuls.kernel.constant.TransactionErrorCode) io.nuls.accout.ledger.rpc.dto(io.nuls.accout.ledger.rpc.dto) CoinComparator(io.nuls.account.ledger.base.util.CoinComparator) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) TransactionInfo(io.nuls.account.ledger.model.TransactionInfo) NulsConfig(io.nuls.kernel.cfg.NulsConfig) IOException(java.io.IOException) Log(io.nuls.core.tools.log.Log) ConvertCoinTool(io.nuls.accout.ledger.rpc.util.ConvertCoinTool) ContractService(io.nuls.contract.service.ContractService) Hex(io.nuls.core.tools.crypto.Hex) LedgerErrorCode(io.nuls.ledger.constant.LedgerErrorCode) LocalUtxoService(io.nuls.account.ledger.base.service.LocalUtxoService) Balance(io.nuls.account.model.Balance) Page(io.nuls.core.tools.page.Page) ValidateResult(io.nuls.kernel.validate.ValidateResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) NulsException(io.nuls.kernel.exception.NulsException) TransactionInfo(io.nuls.account.ledger.model.TransactionInfo) ContractTokenTransferInfoPo(io.nuls.contract.dto.ContractTokenTransferInfoPo) CryptoException(io.nuls.core.tools.crypto.Exception.CryptoException) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction)

Example 64 with NulsException

use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.

the class AccountLedgerServiceImpl method getChangeWholeTxInfoList.

private TransferTransaction getChangeWholeTxInfoList(byte[] address, Account account, String password, Na price) {
    // 这里要重新获取可用余额
    List<Coin> coinList = balanceManager.getCoinListByAddress(address);
    TransferTransaction tx = new TransferTransaction();
    changeWholeLock.lock();
    try {
        tx.setTime(TimeService.currentTimeMillis());
        // 默认coindata中to暂定38字节(一条tocoin)
        int size = tx.size() + 38;
        // 计算目标size,coindata中from的总大小
        int targetSize = TxMaxSizeValidator.MAX_TX_SIZE - size;
        if (coinList.isEmpty()) {
            return null;
        }
        // 从大到小
        Collections.sort(coinList, CoinComparatorDesc.getInstance());
        Na max = Na.ZERO;
        List<Coin> coins = new ArrayList<>();
        byte signType = 0;
        for (int i = 0; i < coinList.size(); i++) {
            Coin coin = coinList.get(i);
            if (!coin.usable()) {
                continue;
            }
            if (coin.getNa().equals(Na.ZERO)) {
                continue;
            }
            size += coin.size();
            if (i == 127) {
                size += 1;
            }
            if (size > targetSize) {
                break;
            }
            coins.add(coin);
            /**
             * 判断是否是脚本验证UTXO
             */
            if (signType != 3) {
                if ((signType & 0x01) == 0 && coin.getTempOwner().length == 23) {
                    signType = (byte) (signType | 0x01);
                    size += P2PHKSignature.SERIALIZE_LENGTH;
                } else if ((signType & 0x02) == 0 && coin.getTempOwner().length != 23) {
                    signType = (byte) (signType | 0x02);
                    size += P2PHKSignature.SERIALIZE_LENGTH;
                }
            }
            max = max.add(coin.getNa());
        }
        Na fee = TransactionFeeCalculator.getFee(size, price);
        max = max.subtract(fee);
        CoinData coinData = new CoinData();
        Coin toCoin = new Coin(address, max);
        coinData.getTo().add(toCoin);
        coinData.setFrom(coins);
        tx.setCoinData(coinData);
        // 一定要交易组装完才能setHash
        tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
        // 生成签名
        List<ECKey> signEckeys = new ArrayList<>();
        List<ECKey> scriptEckeys = new ArrayList<>();
        ECKey eckey = account.getEcKey(password);
        // 如果最后一位为1则表示该交易包含普通签名
        if ((signType & 0x01) == 0x01) {
            signEckeys.add(eckey);
        }
        // 如果倒数第二位位为1则表示该交易包含脚本签名
        if ((signType & 0x02) == 0x02) {
            scriptEckeys.add(eckey);
        }
        SignatureUtil.createTransactionSignture(tx, scriptEckeys, signEckeys);
        return tx;
    } catch (RuntimeException | IOException | NulsException e) {
        Log.error(e);
        return null;
    } finally {
        changeWholeLock.unlock();
    }
}
Also used : ECKey(io.nuls.core.tools.crypto.ECKey) IOException(java.io.IOException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) NulsException(io.nuls.kernel.exception.NulsException) TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction)

Example 65 with NulsException

use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.

the class AccountLedgerServiceImpl method dapp.

@Override
public Result dapp(byte[] from, String password, byte[] data, byte[] remark) {
    Result<Account> accountResult = accountService.getAccount(from);
    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);
        }
    }
    DataTransaction tx = new DataTransaction();
    tx.setRemark(remark);
    tx.setTime(TimeService.currentTimeMillis());
    LogicData logicData = new LogicData(data);
    tx.setTxData(logicData);
    CoinData coinData = new CoinData();
    try {
        CoinDataResult coinDataResult = getCoinData(from, Na.ZERO, tx.size() + coinData.size(), TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
        if (!coinDataResult.isEnough()) {
            return Result.getFailed(AccountLedgerErrorCode.INSUFFICIENT_BALANCE);
        }
        coinData.setFrom(coinDataResult.getCoinList());
        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 = verifyAndSaveUnconfirmedTransaction(tx);
        if (saveResult.isFailed()) {
            if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
                // 重新算一次交易(不超出最大交易数据大小下)的最大金额
                Result rs = getMaxAmountOfOnce(from, 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()) {
            this.deleteTransaction(tx);
            return sendResult;
        }
        return Result.getSuccess().setData(tx.getHash().getDigestHex());
    } catch (NulsException e) {
        Log.error(e);
        return Result.getFailed(e.getErrorCode());
    } catch (IOException e) {
        Log.error(e);
        return Result.getFailed(KernelErrorCode.IO_ERROR);
    }
}
Also used : Account(io.nuls.account.model.Account) MultiSigAccount(io.nuls.account.model.MultiSigAccount) ECKey(io.nuls.core.tools.crypto.ECKey) IOException(java.io.IOException) TransactionDataResult(io.nuls.account.ledger.model.TransactionDataResult) ValidateResult(io.nuls.kernel.validate.ValidateResult) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) NulsException(io.nuls.kernel.exception.NulsException) CoinDataResult(io.nuls.account.ledger.model.CoinDataResult) LogicData(io.nuls.protocol.model.tx.LogicData) DataTransaction(io.nuls.protocol.model.tx.DataTransaction)

Aggregations

NulsException (io.nuls.kernel.exception.NulsException)109 IOException (java.io.IOException)35 Account (io.nuls.account.model.Account)25 ValidateResult (io.nuls.kernel.validate.ValidateResult)23 ECKey (io.nuls.core.tools.crypto.ECKey)20 CoinDataResult (io.nuls.account.ledger.model.CoinDataResult)18 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)16 UnsupportedEncodingException (java.io.UnsupportedEncodingException)14 TransferTransaction (io.nuls.protocol.model.tx.TransferTransaction)13 Coin (io.nuls.kernel.model.Coin)12 MultiSigAccount (io.nuls.account.model.MultiSigAccount)11 ContractResult (io.nuls.contract.dto.ContractResult)9 NulsByteBuffer (io.nuls.kernel.utils.NulsByteBuffer)9 ArrayList (java.util.ArrayList)9 TransactionSignature (io.nuls.kernel.script.TransactionSignature)8 BigInteger (java.math.BigInteger)8 TransactionDataResult (io.nuls.account.ledger.model.TransactionDataResult)7 AccountPo (io.nuls.account.storage.po.AccountPo)7 AliasPo (io.nuls.account.storage.po.AliasPo)7 CryptoException (io.nuls.core.tools.crypto.Exception.CryptoException)7