Search in sources :

Example 11 with NulsByteBuffer

use of io.nuls.kernel.utils.NulsByteBuffer 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 12 with NulsByteBuffer

use of io.nuls.kernel.utils.NulsByteBuffer in project nuls by nuls-io.

the class AccountLedgerServiceImpl method signMultiTransaction.

/**
 * A transfers NULS to B   多签交易
 *
 * @param signAddr 签名地址
 * @param password password of A
 * @param txdata   需要签名的数据
 * @return Result
 */
@Override
public Result signMultiTransaction(String signAddr, String password, 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);
            }
        }
        byte[] txByte = Hex.decode(txdata);
        Transaction tx = TransactionManager.getInstance(new NulsByteBuffer(txByte));
        TransactionSignature transactionSignature = new TransactionSignature();
        transactionSignature.parse(new NulsByteBuffer(tx.getTransactionSignature()));
        // 验证签名地址账户是否属于多签账户
        List<byte[]> pubkeys = SignatureUtil.getPublicKeyList(transactionSignature.getScripts().get(0));
        if (pubkeys == null || pubkeys.size() == 0 || !AddressTool.validSignAddress(pubkeys, account.getPubKey())) {
            return Result.getFailed(AccountErrorCode.SIGN_ADDRESS_NOT_MATCH);
        }
        return txMultiProcess(tx, transactionSignature, account, password);
    } 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 : Account(io.nuls.account.model.Account) MultiSigAccount(io.nuls.account.model.MultiSigAccount) TransferTransaction(io.nuls.protocol.model.tx.TransferTransaction) DataTransaction(io.nuls.protocol.model.tx.DataTransaction) NulsException(io.nuls.kernel.exception.NulsException) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) NulsByteBuffer(io.nuls.kernel.utils.NulsByteBuffer)

Example 13 with NulsByteBuffer

use of io.nuls.kernel.utils.NulsByteBuffer in project nuls by nuls-io.

the class CreateP2shTransactionForm method validAddress.

public static boolean validAddress(String address) {
    if (StringUtils.isBlank(address)) {
        return false;
    }
    byte[] bytes;
    try {
        bytes = Base58.decode(address);
        if (bytes.length != Address.ADDRESS_LENGTH + 1) {
            return false;
        }
    } catch (NulsException e) {
        return false;
    } catch (Exception e) {
        return false;
    }
    NulsByteBuffer byteBuffer = new NulsByteBuffer(bytes);
    short chainId;
    byte type;
    try {
        chainId = byteBuffer.readShort();
        type = byteBuffer.readByte();
    } catch (NulsException e) {
        Log.error(e);
        return false;
    }
    if (NulsContext.getInstance().getDefaultChainId() != chainId) {
        return false;
    }
    if (NulsContext.MAIN_NET_VERSION <= 1 || NulsContext.CONTRACT_ADDRESS_TYPE == type) {
        return false;
    }
    if (NulsContext.DEFAULT_ADDRESS_TYPE != type && NulsContext.P2SH_ADDRESS_TYPE != type) {
        return false;
    }
    try {
        AddressTool.checkXOR(bytes);
    } catch (Exception e) {
        return false;
    }
    return true;
}
Also used : NulsException(io.nuls.kernel.exception.NulsException) NulsException(io.nuls.kernel.exception.NulsException) NulsByteBuffer(io.nuls.kernel.utils.NulsByteBuffer)

Example 14 with NulsByteBuffer

use of io.nuls.kernel.utils.NulsByteBuffer in project nuls by nuls-io.

the class BaseNulsData method parse.

@Override
public final void parse(byte[] bytes, int cursor) throws NulsException {
    if (bytes == null || bytes.length == 0 || ((bytes.length == 4) && Arrays.equals(NulsConstant.PLACE_HOLDER, bytes))) {
        return;
    }
    NulsByteBuffer byteBuffer = new NulsByteBuffer(bytes);
    byteBuffer.setCursor(cursor);
    this.parse(byteBuffer);
}
Also used : NulsByteBuffer(io.nuls.kernel.utils.NulsByteBuffer)

Example 15 with NulsByteBuffer

use of io.nuls.kernel.utils.NulsByteBuffer in project nuls by nuls-io.

the class ChainContainer method verifyRedPunish.

private boolean verifyRedPunish(RedPunishTransaction data) {
    RedPunishData punishData = data.getTxData();
    if (ConsensusConfig.getSeedNodeStringList().contains(AddressTool.getStringAddressByBytes(punishData.getAddress()))) {
        Log.warn("The seed node can not be punished!");
        return false;
    }
    HeaderSignValidator validator = NulsContext.getServiceBean(HeaderSignValidator.class);
    LedgerService ledgerService = NulsContext.getServiceBean(LedgerService.class);
    if (punishData.getReasonCode() == PunishReasonEnum.DOUBLE_SPEND.getCode()) {
        if (NulsContext.MAIN_NET_VERSION <= 1) {
            Log.warn("The red punish tx need higher version!");
            return false;
        }
        SmallBlock smallBlock = new SmallBlock();
        try {
            smallBlock.parse(punishData.getEvidence(), 0);
        } catch (NulsException e) {
            Log.error(e);
            return false;
        }
        BlockHeader header = smallBlock.getHeader();
        if (header.getTime() != data.getTime()) {
            return false;
        }
        ValidateResult result = validator.validate(header);
        if (result.isFailed()) {
            Log.warn(result.getMsg());
            return false;
        }
        List<NulsDigestData> txHashList = smallBlock.getTxHashList();
        if (!header.getMerkleHash().equals(NulsDigestData.calcMerkleDigestData(txHashList))) {
            Log.warn(TransactionErrorCode.TX_DATA_VALIDATION_ERROR.getMsg());
            return false;
        }
        List<Transaction> txList = smallBlock.getSubTxList();
        if (null == txList || txList.size() < 2) {
            Log.warn(TransactionErrorCode.TX_DATA_VALIDATION_ERROR.getMsg());
            return false;
        }
        result = ledgerService.verifyDoubleSpend(txList);
        if (result.isSuccess()) {
            Log.warn(PocConsensusErrorCode.TRANSACTIONS_NEVER_DOUBLE_SPEND.getMsg());
            return false;
        }
    } else if (punishData.getReasonCode() == PunishReasonEnum.BIFURCATION.getCode()) {
        if (NulsContext.MAIN_NET_VERSION <= 1) {
            Log.warn("The red punish tx need higher version!");
            return false;
        }
        NulsByteBuffer byteBuffer = new NulsByteBuffer(punishData.getEvidence());
        // 轮次
        long[] roundIndex = new long[NulsContext.REDPUNISH_BIFURCATION];
        for (int i = 0; i < NulsContext.REDPUNISH_BIFURCATION && !byteBuffer.isFinished(); i++) {
            BlockHeader header1 = null;
            BlockHeader header2 = null;
            try {
                header1 = byteBuffer.readNulsData(new BlockHeader());
                header2 = byteBuffer.readNulsData(new BlockHeader());
            } catch (NulsException e) {
                Log.error(e);
            }
            if (null == header1 || null == header2) {
                Log.warn(KernelErrorCode.DATA_NOT_FOUND.getMsg());
                return false;
            }
            if (header1.getHeight() != header2.getHeight()) {
                Log.warn(TransactionErrorCode.TX_DATA_VALIDATION_ERROR.getMsg());
                return false;
            }
            if (i == NulsContext.REDPUNISH_BIFURCATION - 1 && (header1.getTime() + header2.getTime()) / 2 != data.getTime()) {
                return false;
            }
            ValidateResult result = validator.validate(header1);
            if (result.isFailed()) {
                Log.warn(TransactionErrorCode.TX_DATA_VALIDATION_ERROR.getMsg());
                return false;
            }
            result = validator.validate(header2);
            if (result.isFailed()) {
                Log.warn(TransactionErrorCode.TX_DATA_VALIDATION_ERROR.getMsg());
                return false;
            }
            if (!Arrays.equals(header1.getBlockSignature().getPublicKey(), header2.getBlockSignature().getPublicKey())) {
                Log.warn(TransactionErrorCode.SIGNATURE_ERROR.getMsg());
                return false;
            }
            BlockExtendsData blockExtendsData = new BlockExtendsData(header1.getExtend());
            roundIndex[i] = blockExtendsData.getRoundIndex();
        }
        // 验证轮次是否连续
        boolean rs = true;
        for (int i = 0; i < roundIndex.length; i++) {
            if (i < roundIndex.length - 2 && roundIndex[i + 1] - roundIndex[i] != 1) {
                rs = false;
                break;
            }
        }
        if (!rs) {
            Log.warn(PocConsensusErrorCode.RED_CARD_VERIFICATION_FAILED.getMsg());
            return false;
        }
    } else if (punishData.getReasonCode() != PunishReasonEnum.TOO_MUCH_YELLOW_PUNISH.getCode()) {
        Log.warn(PocConsensusErrorCode.RED_CARD_VERIFICATION_FAILED.getMsg());
        return false;
    }
    try {
        return verifyCoinData(data);
    } catch (IOException e) {
        Log.error(e);
        return false;
    }
}
Also used : SmallBlock(io.nuls.protocol.model.SmallBlock) ValidateResult(io.nuls.kernel.validate.ValidateResult) IOException(java.io.IOException) LedgerService(io.nuls.ledger.service.LedgerService) HeaderSignValidator(io.nuls.protocol.model.validator.HeaderSignValidator) CoinBaseTransaction(io.nuls.protocol.model.tx.CoinBaseTransaction) RedPunishData(io.nuls.consensus.poc.protocol.entity.RedPunishData) NulsException(io.nuls.kernel.exception.NulsException) NulsByteBuffer(io.nuls.kernel.utils.NulsByteBuffer)

Aggregations

NulsByteBuffer (io.nuls.kernel.utils.NulsByteBuffer)17 NulsException (io.nuls.kernel.exception.NulsException)14 IOException (java.io.IOException)9 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)5 Account (io.nuls.account.model.Account)4 MultiSigAccount (io.nuls.account.model.MultiSigAccount)4 Transaction (io.nuls.kernel.model.Transaction)3 ValidateResult (io.nuls.kernel.validate.ValidateResult)3 CoinDataResult (io.nuls.account.ledger.model.CoinDataResult)2 AliasPo (io.nuls.account.storage.po.AliasPo)2 AliasTransaction (io.nuls.account.tx.AliasTransaction)2 ECKey (io.nuls.core.tools.crypto.ECKey)2 VarInt (io.nuls.kernel.utils.VarInt)2 TransferTransaction (io.nuls.protocol.model.tx.TransferTransaction)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 ArrayList (java.util.ArrayList)2 MultipleAddressTransferModel (io.nuls.account.ledger.model.MultipleAddressTransferModel)1 TransactionDataResult (io.nuls.account.ledger.model.TransactionDataResult)1 UnconfirmedTxPo (io.nuls.account.ledger.storage.po.UnconfirmedTxPo)1 Alias (io.nuls.account.model.Alias)1