Search in sources :

Example 26 with ECKey

use of io.nuls.core.tools.crypto.ECKey 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 27 with ECKey

use of io.nuls.core.tools.crypto.ECKey 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)

Example 28 with ECKey

use of io.nuls.core.tools.crypto.ECKey in project nuls by nuls-io.

the class AccountLedgerServiceImpl method transfer.

@Override
public Result transfer(byte[] from, byte[] to, Na values, String password, byte[] remark, Na price) {
    try {
        if (NulsContext.WALLET_STATUS == NulsConstant.SYNCHING) {
            return Result.getFailed(KernelErrorCode.WALLET_STATUS_SYNCHING);
        } else if (NulsContext.WALLET_STATUS == NulsConstant.ROLLBACK) {
            return Result.getFailed(KernelErrorCode.WALLET_STATUS_ROLLBACK);
        }
        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);
            }
        }
        if (!account.isOk()) {
            return Result.getFailed(AccountErrorCode.IMPORTING_ACCOUNT);
        }
        // 检查to是否为合约地址,如果是合约地址,则返回错误
        if (contractService.isContractAddress(to)) {
            return Result.getFailed(ContractErrorCode.NON_CONTRACTUAL_TRANSACTION_NO_TRANSFER);
        }
        TransferTransaction tx = new TransferTransaction();
        tx.setRemark(remark);
        tx.setTime(TimeService.currentTimeMillis());
        CoinData coinData = new CoinData();
        // 如果为多签地址则以脚本方式存储
        Coin toCoin;
        if (to[2] == NulsContext.P2SH_ADDRESS_TYPE) {
            Script scriptPubkey = SignatureUtil.createOutputScript(to);
            toCoin = new Coin(scriptPubkey.getProgram(), values);
        } else {
            toCoin = new Coin(to, values);
        }
        coinData.getTo().add(toCoin);
        if (price == null) {
            price = TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES;
        }
        CoinDataResult coinDataResult = getCoinData(from, values, tx.size() + coinData.size(), 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()));
        // 生成签名
        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, 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;
        }
        // transactionService.newTx(tx);
        Result sendResult = transactionService.broadcastTx(tx);
        if (sendResult.isFailed()) {
            this.deleteTransaction(tx);
            return sendResult;
        }
        return Result.getSuccess().setData(tx.getHash().getDigestHex());
    } 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) 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)

Example 29 with ECKey

use of io.nuls.core.tools.crypto.ECKey in project nuls by nuls-io.

the class AccountLedgerResource method signTransaction.

@POST
@Path("/transaction/sign")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "交易签名", notes = "result.data: resultJson 返回交易对象")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success") })
public RpcClientResult signTransaction(@ApiParam(name = "form", value = "交易信息", required = true) TransactionHexForm form) {
    if (StringUtils.isBlank(form.getPriKey())) {
        return Result.getFailed(AccountErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    if (StringUtils.isBlank(form.getTxHex())) {
        return Result.getFailed(AccountErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    if (!AddressTool.validAddress(form.getAddress())) {
        return Result.getFailed(AccountErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    String priKey = form.getPriKey();
    if (StringUtils.isNotBlank(form.getPassword())) {
        if (StringUtils.validPassword(form.getPassword())) {
            // decrypt
            byte[] privateKeyBytes = null;
            try {
                privateKeyBytes = AESEncrypt.decrypt(Hex.decode(priKey), form.getPassword());
            } catch (CryptoException e) {
                return Result.getFailed(AccountLedgerErrorCode.PARAMETER_ERROR).toRpcClientResult();
            }
            priKey = Hex.encode(privateKeyBytes);
        } else {
            return Result.getFailed(AccountLedgerErrorCode.PARAMETER_ERROR).toRpcClientResult();
        }
    }
    if (!ECKey.isValidPrivteHex(priKey)) {
        return Result.getFailed(AccountErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    // is private key matches address
    ECKey key = ECKey.fromPrivate(new BigInteger(1, Hex.decode(priKey)));
    try {
        String newAddress = AccountTool.newAddress(key).getBase58();
        if (!newAddress.equals(form.getAddress())) {
            return Result.getFailed(AccountErrorCode.ADDRESS_ERROR).toRpcClientResult();
        }
    } catch (NulsException e) {
        return Result.getFailed(AccountErrorCode.ADDRESS_ERROR).toRpcClientResult();
    }
    try {
        byte[] data = Hex.decode(form.getTxHex());
        Transaction tx = TransactionManager.getInstance(new NulsByteBuffer(data));
        tx = accountLedgerService.signTransaction(tx, key);
        // Result validateResult = tx.verify();
        // if (validateResult.isFailed()) {
        // return Result.getFailed(validateResult.getErrorCode()).toRpcClientResult();
        // }
        // for (Coin coin : tx.getCoinData().getFrom()) {
        // Coin utxo = ledgerService.getUtxo(coin.());
        // if (utxo == null) {
        // return Result.getFailed(LedgerErrorCode.UTXO_NOT_FOUND).toRpcClientResult();
        // }
        // 
        // if (!form.getAddress().equals(AddressTool.getStringAddressByBytes(utxo.()))) {
        // return Result.getFailed(LedgerErrorCode.INVALID_INPUT).toRpcClientResult();
        // }
        // 
        // }
        Map<String, String> map = new HashMap<>();
        map.put("value", Hex.encode(tx.serialize()));
        return Result.getSuccess().setData(map).toRpcClientResult();
    } catch (Exception e) {
        Log.error(e);
        return Result.getFailed(LedgerErrorCode.DATA_PARSE_ERROR).toRpcClientResult();
    }
}
Also used : TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction) NulsException(io.nuls.kernel.exception.NulsException) BigInteger(java.math.BigInteger) ECKey(io.nuls.core.tools.crypto.ECKey) CryptoException(io.nuls.core.tools.crypto.Exception.CryptoException) 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)

Example 30 with ECKey

use of io.nuls.core.tools.crypto.ECKey in project nuls by nuls-io.

the class Script method createMultiSigOutputScript.

/**
 * Creates a program that requires at least N of the given keys to sign, using OP_CHECKMULTISIG.
 * 将OutputScript/scriptPublicKry  转为字节数组 用于传输
 */
public static byte[] createMultiSigOutputScript(int threshold, List<ECKey> pubkeys) {
    checkArgument(threshold > 0);
    checkArgument(threshold <= pubkeys.size());
    // That's the max we can represent with a single opcode.
    checkArgument(pubkeys.size() <= 16);
    if (pubkeys.size() > 3) {
        log.warn("Creating a multi-signature output that is non-standard: {} pubkeys, should be <= 3", pubkeys.size());
    }
    try {
        ByteArrayOutputStream bits = new ByteArrayOutputStream();
        bits.write(encodeToOpN(threshold));
        for (ECKey key : pubkeys) {
            writeBytes(bits, key.getPubKey());
        }
        bits.write(encodeToOpN(pubkeys.size()));
        bits.write(OP_CHECKMULTISIG);
        return bits.toByteArray();
    } catch (IOException e) {
        // Cannot happen.
        throw new RuntimeException(e);
    }
}
Also used : ECKey(io.nuls.core.tools.crypto.ECKey) ByteArrayOutputStream(java.io.ByteArrayOutputStream) UnsafeByteArrayOutputStream(io.nuls.core.tools.crypto.UnsafeByteArrayOutputStream) IOException(java.io.IOException)

Aggregations

ECKey (io.nuls.core.tools.crypto.ECKey)43 NulsException (io.nuls.kernel.exception.NulsException)26 IOException (java.io.IOException)20 CoinDataResult (io.nuls.account.ledger.model.CoinDataResult)15 BigInteger (java.math.BigInteger)14 Account (io.nuls.account.model.Account)12 ArrayList (java.util.ArrayList)11 TransferTransaction (io.nuls.protocol.model.tx.TransferTransaction)10 MultiSigAccount (io.nuls.account.model.MultiSigAccount)8 ValidateResult (io.nuls.kernel.validate.ValidateResult)8 UnsupportedEncodingException (java.io.UnsupportedEncodingException)8 TransactionDataResult (io.nuls.account.ledger.model.TransactionDataResult)6 CryptoException (io.nuls.core.tools.crypto.Exception.CryptoException)6 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)4 MultipleAddressTransferModel (io.nuls.account.ledger.model.MultipleAddressTransferModel)3 Alias (io.nuls.account.model.Alias)3 AliasTransaction (io.nuls.account.tx.AliasTransaction)3 Agent (io.nuls.consensus.poc.protocol.entity.Agent)3 ContractResult (io.nuls.contract.dto.ContractResult)3 Script (io.nuls.kernel.script.Script)3