Search in sources :

Example 1 with TransactionSignature

use of io.nuls.kernel.script.TransactionSignature in project nuls by nuls-io.

the class AccountLedgerResource method signMultipleTx.

@POST
@Path("/signMultipleTx")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "签名多地址转账交易", notes = "result.data: resultJson 返回签名后的txHex")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success") })
public RpcClientResult signMultipleTx(@ApiParam(name = "form", value = "签名多地址转账交易", required = true) MulitpleTxForm form) {
    String txHex = form.getTxHex();
    List<String> priKeys = form.getPriKeys();
    String password = form.getPassword();
    if (StringUtils.isBlank(txHex) || priKeys.isEmpty()) {
        return Result.getFailed(AccountErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    List<String> signKeys = new ArrayList<>(priKeys.size());
    for (int i = 0; i < priKeys.size(); i++) {
        String encryptPrivKey = priKeys.get(i);
        if (StringUtils.isBlank(password)) {
            signKeys.add(encryptPrivKey);
            continue;
        }
        byte[] privateKeyBytes = null;
        try {
            privateKeyBytes = AESEncrypt.decrypt(Hex.decode(encryptPrivKey), password);
        } catch (Exception e) {
            return Result.getFailed(AccountErrorCode.DECRYPT_ACCOUNT_ERROR).toRpcClientResult();
        }
        signKeys.add(Hex.encode(privateKeyBytes));
    }
    // conversion private key string to ECKey
    List<ECKey> keys = signKeys.stream().map(p -> ECKey.fromPrivate(new BigInteger(Hex.decode(p)))).collect(Collectors.toList());
    try {
        byte[] data = Hex.decode(txHex);
        Transaction tx = TransactionManager.getInstance(new NulsByteBuffer(data));
        List<P2PHKSignature> p2PHKSignatures = SignatureUtil.createSignaturesByEckey(tx, keys);
        TransactionSignature transactionSignature = new TransactionSignature();
        transactionSignature.setP2PHKSignatures(p2PHKSignatures);
        tx.setTransactionSignature(transactionSignature.serialize());
        txHex = Hex.encode(tx.serialize());
        Map<String, String> map = new HashMap<>();
        map.put("value", txHex);
        return Result.getSuccess().setData(map).toRpcClientResult();
    } catch (Exception e) {
        Log.error(e);
        return Result.getFailed(AccountErrorCode.DATA_PARSE_ERROR).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) ECKey(io.nuls.core.tools.crypto.ECKey) TransactionSignature(io.nuls.kernel.script.TransactionSignature) 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) P2PHKSignature(io.nuls.kernel.script.P2PHKSignature) BigInteger(java.math.BigInteger)

Example 2 with TransactionSignature

use of io.nuls.kernel.script.TransactionSignature in project nuls by nuls-io.

the class UtxoLedgerServiceImpl method verifyCoinData.

/**
 * 此txList是待打包的块中的交易,所以toList是下一步的UTXO,应该校验它
 * coinData的交易和txList同处一个块中,txList中的to可能是coinData的from,
 * 也就是可能存在,在同一个块中,下一笔输入就是上一笔的输出,所以需要校验它
 * bestHeight is used when switch chain.
 *
 * @return ValidateResult
 */
@Override
public ValidateResult verifyCoinData(Transaction transaction, Map<String, Coin> temporaryToMap, Set<String> temporaryFromSet, Long bestHeight) {
    if (transaction == null || transaction.getCoinData() == null) {
        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.NULL_PARAMETER);
    }
    try {
        /*
            校验开始
             */
        CoinData coinData = transaction.getCoinData();
        List<Coin> froms = coinData.getFrom();
        int fromSize = froms.size();
        TransactionSignature transactionSignature = new TransactionSignature();
        // 交易签名反序列化
        if (transaction.needVerifySignature() && fromSize > 0) {
            try {
                transactionSignature.parse(transaction.getTransactionSignature(), 0);
            } catch (NulsException e) {
                return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.LEDGER_P2PKH_SCRIPT_ERROR);
            }
        }
        // 保存Set用于验证自身双花
        if (temporaryFromSet == null) {
            temporaryFromSet = new HashSet<>();
        }
        Na fromTotal = Na.ZERO;
        byte[] fromBytes;
        // 保存在数据库中或者txList中的utxo数据
        Coin fromOfFromCoin = null;
        byte[] fromAddressBytes = null;
        /**
         * 存放真实地址(如果为脚本验证的情况fromAddressBytes存的是脚本信息)
         */
        byte[] realAddressBytes = null;
        for (int i = 0; i < froms.size(); i++) {
            Coin from = froms.get(i);
            fromBytes = from.getOwner();
            // 验证是否可花费, 校验的coinData的fromUTXO,检查数据库中是否存在此UTXO
            fromOfFromCoin = utxoLedgerUtxoStorageService.getUtxo(fromBytes);
            // 检查txList中是否存在此UTXO
            if (temporaryToMap != null && fromOfFromCoin == null) {
                fromOfFromCoin = temporaryToMap.get(asString(fromBytes));
            }
            if (null == fromOfFromCoin) {
                // 如果既不存在于txList的to中(如果txList不为空),又不存在于数据库中,那么这是一笔问题数据,进一步检查是否存在这笔交易,交易有就是双花,没有就是孤儿交易,则返回失败
                if (null != utxoLedgerTransactionStorageService.getTxBytes(LedgerUtil.getTxHashBytes(fromBytes))) {
                    return ValidateResult.getFailedResult(CLASS_NAME, TransactionErrorCode.TRANSACTION_REPEATED);
                } else {
                    return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.ORPHAN_TX);
                }
            } else {
                fromAddressBytes = fromOfFromCoin.getOwner();
                realAddressBytes = fromOfFromCoin.getAddress();
                // pierre add 非合约转账(从合约转出)交易,验证fromAdress是否是合约地址,如果是,则返回失败,非合约转账(从合约转出)交易不能转出合约地址资产
                if (transaction.getType() != ContractConstant.TX_TYPE_CONTRACT_TRANSFER) {
                    boolean isContractAddress = contractService.isContractAddress(realAddressBytes);
                    if (isContractAddress) {
                        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.DATA_ERROR);
                    }
                }
                // 验证地址中的公钥hash160和交易中的公钥hash160是否相等,不相等则说明这笔utxo不属于交易发出者
                boolean signtureValidFlag = false;
                if (transaction.needVerifySignature()) {
                    if (transactionSignature != null) {
                        if (fromAddressBytes != null && transactionSignature.getScripts() != null && transactionSignature.getScripts().size() > 0) {
                            if (fromAddressBytes.length != Address.ADDRESS_LENGTH) {
                                Script scriptPubkey = new Script(fromAddressBytes);
                                for (Script scriptSig : transactionSignature.getScripts()) {
                                    signtureValidFlag = scriptSig.correctlyNulsSpends(transaction, 0, scriptPubkey);
                                    if (signtureValidFlag) {
                                        break;
                                    }
                                }
                            } else {
                                for (Script scriptSig : transactionSignature.getScripts()) {
                                    Script redeemScript = new Script(scriptSig.getChunks().get(scriptSig.getChunks().size() - 1).data);
                                    Address address = new Address(NulsContext.getInstance().getDefaultChainId(), NulsContext.P2SH_ADDRESS_TYPE, SerializeUtils.sha256hash160(redeemScript.getProgram()));
                                    Script publicScript = SignatureUtil.createOutputScript(address.getAddressBytes());
                                    signtureValidFlag = scriptSig.correctlyNulsSpends(transaction, 0, publicScript);
                                    if (signtureValidFlag) {
                                        break;
                                    }
                                }
                            }
                        } else {
                            if (transactionSignature.getP2PHKSignatures() != null && transactionSignature.getP2PHKSignatures().size() != 0) {
                                for (P2PHKSignature signature : transactionSignature.getP2PHKSignatures()) {
                                    signtureValidFlag = AddressTool.checkPublicKeyHash(realAddressBytes, signature.getSignerHash160());
                                    if (signtureValidFlag) {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (!signtureValidFlag) {
                        Log.warn("public key hash160 check error.");
                        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.INVALID_INPUT);
                    }
                }
                if (java.util.Arrays.equals(realAddressBytes, NulsConstant.BLACK_HOLE_ADDRESS) || java.util.Arrays.equals(realAddressBytes, NulsConstant.BLACK_HOLE_ADDRESS_TEST_NET)) {
                    return ValidateResult.getFailedResult(CLASS_NAME, KernelErrorCode.ADDRESS_IS_BLOCK_HOLE);
                }
                if (NulsContext.getInstance().getDefaultChainId() != SerializeUtils.bytes2Short(realAddressBytes)) {
                    return ValidateResult.getFailedResult(CLASS_NAME, KernelErrorCode.ADDRESS_IS_NOT_BELONGS_TO_CHAIN);
                }
            }
            // 验证非解锁类型的交易及解锁类型的交易
            if (!transaction.isUnlockTx()) {
                // 验证非解锁类型的交易,验证是否可用,检查是否还在锁定时间内
                if (bestHeight == null) {
                    if (!fromOfFromCoin.usable()) {
                        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.UTXO_UNUSABLE);
                    }
                } else {
                    if (!fromOfFromCoin.usable(bestHeight)) {
                        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.UTXO_UNUSABLE);
                    }
                }
            } else {
                // 验证解锁类型的交易
                if (fromOfFromCoin.getLockTime() != -1) {
                    return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.UTXO_STATUS_CHANGE);
                }
            }
            // 验证与待确认交易列表中是否有双花,既是待校验交易的fromUtxo是否和txList中的fromUtxo重复,有重复则是双花
            if (temporaryFromSet != null && !temporaryFromSet.add(asString(fromBytes))) {
                if (i > 0) {
                    for (int x = 0; x < i; x++) {
                        Coin theFrom = froms.get(i);
                        temporaryFromSet.remove(asString(theFrom.getOwner()));
                    }
                }
                return ValidateResult.getFailedResult(CLASS_NAME, TransactionErrorCode.TRANSACTION_REPEATED);
            }
            // 验证from的锁定时间和金额
            if (!(fromOfFromCoin.getNa().equals(from.getNa()) && fromOfFromCoin.getLockTime() == from.getLockTime())) {
                return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.DATA_ERROR);
            }
            fromTotal = fromTotal.add(fromOfFromCoin.getNa());
            from.setFrom(fromOfFromCoin);
        }
        List<Coin> tos = coinData.getTo();
        Na toTotal = Na.ZERO;
        byte[] txBytes = transaction.getHash().serialize();
        for (int i = 0; i < tos.size(); i++) {
            Coin to = tos.get(i);
            // 如果不是调用合约的类型,并且合约地址作为nuls接收者,则返回错误,非合约交易不能转入nuls(CoinBase交易不过此验证)
            if (ContractConstant.TX_TYPE_CALL_CONTRACT != transaction.getType() && AddressTool.validContractAddress(to.getOwner())) {
                Log.error("Ledger verify error: {}.", ContractErrorCode.NON_CONTRACTUAL_TRANSACTION_NO_TRANSFER.getEnMsg());
                return ValidateResult.getFailedResult(CLASS_NAME, ContractErrorCode.NON_CONTRACTUAL_TRANSACTION_NO_TRANSFER);
            }
            toTotal = toTotal.add(to.getNa());
            if (temporaryToMap != null) {
                temporaryToMap.put(asString(ArraysTool.concatenate(txBytes, new VarInt(i).encode())), to);
            }
        }
        // 验证输出不能大于输入
        if (fromTotal.compareTo(toTotal) < 0) {
            return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.INVALID_AMOUNT);
        }
    } catch (Exception e) {
        Log.error(e);
        return ValidateResult.getFailedResult(CLASS_NAME, KernelErrorCode.SYS_UNKOWN_EXCEPTION);
    }
    return ValidateResult.getSuccessResult();
}
Also used : Script(io.nuls.kernel.script.Script) VarInt(io.nuls.kernel.utils.VarInt) TransactionSignature(io.nuls.kernel.script.TransactionSignature) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) NulsException(io.nuls.kernel.exception.NulsException) P2PHKSignature(io.nuls.kernel.script.P2PHKSignature)

Example 3 with TransactionSignature

use of io.nuls.kernel.script.TransactionSignature in project nuls by nuls-io.

the class TransactionResource method getTxByHash.

@GET
@Path("/hash/{hash}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "根据hash查询交易")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = TransactionDto.class) })
public RpcClientResult getTxByHash(@ApiParam(name = "hash", value = "交易hash", required = true) @PathParam("hash") String hash) {
    if (StringUtils.isBlank(hash)) {
        return Result.getFailed(LedgerErrorCode.NULL_PARAMETER).toRpcClientResult();
    }
    if (!NulsDigestData.validHash(hash)) {
        return Result.getFailed(LedgerErrorCode.PARAMETER_ERROR).toRpcClientResult();
    }
    Result result = null;
    try {
        Transaction tx = ledgerService.getTx(NulsDigestData.fromDigestHex(hash));
        if (tx == null) {
            result = Result.getFailed(TransactionErrorCode.TX_NOT_EXIST);
        } else {
            tx.setStatus(TxStatusEnum.CONFIRMED);
            TransactionDto txDto = null;
            CoinData coinData = tx.getCoinData();
            String fromAddress = null;
            if (tx.getTransactionSignature() != null) {
                TransactionSignature signature = new TransactionSignature();
                signature.parse(new NulsByteBuffer(tx.getTransactionSignature()));
                if (signature.getP2PHKSignatures() != null && signature.getP2PHKSignatures().size() == 1) {
                    byte[] addressBytes = AddressTool.getAddress(signature.getP2PHKSignatures().get(0).getPublicKey());
                    fromAddress = AddressTool.getStringAddressByBytes(addressBytes);
                }
            }
            if (coinData != null) {
                // 组装from数据
                List<Coin> froms = coinData.getFrom();
                if (froms != null && froms.size() > 0) {
                    byte[] fromHash, owner;
                    int fromIndex;
                    NulsDigestData fromHashObj;
                    Transaction fromTx;
                    Coin fromUtxo;
                    for (Coin from : froms) {
                        if (fromAddress != null) {
                            from.setFromAddress(fromAddress);
                        } else {
                            owner = from.getOwner();
                            // owner拆分出txHash和index
                            fromHash = LedgerUtil.getTxHashBytes(owner);
                            fromIndex = LedgerUtil.getIndex(owner);
                            // 查询from UTXO
                            fromHashObj = new NulsDigestData();
                            fromHashObj.parse(fromHash, 0);
                            fromTx = ledgerService.getTx(fromHashObj);
                            fromUtxo = fromTx.getCoinData().getTo().get(fromIndex);
                            from.setFrom(fromUtxo);
                        }
                    }
                }
                txDto = new TransactionDto(tx);
                List<OutputDto> outputDtoList = new ArrayList<>();
                // 组装to数据
                List<Coin> tos = coinData.getTo();
                if (tos != null && tos.size() > 0) {
                    byte[] txHashBytes = tx.getHash().serialize();
                    String txHash = hash;
                    OutputDto outputDto = null;
                    Coin to, temp;
                    long bestHeight = NulsContext.getInstance().getBestHeight();
                    long currentTime = TimeService.currentTimeMillis();
                    long lockTime;
                    for (int i = 0, length = tos.size(); i < length; i++) {
                        to = tos.get(i);
                        outputDto = new OutputDto(to);
                        outputDto.setTxHash(txHash);
                        outputDto.setIndex(i);
                        temp = utxoLedgerUtxoStorageService.getUtxo(Arrays.concatenate(txHashBytes, new VarInt(i).encode()));
                        if (temp == null) {
                            // 已花费
                            outputDto.setStatus(3);
                        } else {
                            lockTime = temp.getLockTime();
                            if (lockTime < 0) {
                                // 共识锁定
                                outputDto.setStatus(2);
                            } else if (lockTime == 0) {
                                // 正常未花费
                                outputDto.setStatus(0);
                            } else if (lockTime > NulsConstant.BlOCKHEIGHT_TIME_DIVIDE) {
                                // 判定是否时间高度锁定
                                if (lockTime > currentTime) {
                                    // 时间高度锁定
                                    outputDto.setStatus(1);
                                } else {
                                    // 正常未花费
                                    outputDto.setStatus(0);
                                }
                            } else {
                                // 判定是否区块高度锁定
                                if (lockTime > bestHeight) {
                                    // 区块高度锁定
                                    outputDto.setStatus(1);
                                } else {
                                    // 正常未花费
                                    outputDto.setStatus(0);
                                }
                            }
                        }
                        outputDtoList.add(outputDto);
                    }
                }
                txDto.setOutputs(outputDtoList);
                // 计算交易实际发生的金额
                calTransactionValue(txDto);
            }
            result = Result.getSuccess();
            result.setData(txDto);
        }
    } catch (NulsRuntimeException e) {
        Log.error(e);
        result = Result.getFailed(e.getErrorCode());
    } catch (Exception e) {
        Log.error(e);
        result = Result.getFailed(LedgerErrorCode.SYS_UNKOWN_EXCEPTION);
    }
    return result.toRpcClientResult();
}
Also used : OutputDto(io.nuls.ledger.rpc.model.OutputDto) TransactionDto(io.nuls.ledger.rpc.model.TransactionDto) VarInt(io.nuls.kernel.utils.VarInt) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) TransactionSignature(io.nuls.kernel.script.TransactionSignature) NulsRuntimeException(io.nuls.kernel.exception.NulsRuntimeException) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) NulsByteBuffer(io.nuls.kernel.utils.NulsByteBuffer)

Example 4 with TransactionSignature

use of io.nuls.kernel.script.TransactionSignature in project nuls by nuls-io.

the class CreateAgentTxValidator method validate.

@Override
public ValidateResult validate(CreateAgentTransaction tx) {
    Agent agent = tx.getTxData();
    if (null == agent) {
        return ValidateResult.getFailedResult(getClass().getName(), PocConsensusErrorCode.AGENT_NOT_EXIST);
    }
    if (!AddressTool.validNormalAddress(agent.getPackingAddress())) {
        return ValidateResult.getFailedResult(getClass().getName(), AccountErrorCode.ADDRESS_ERROR);
    }
    if (Arrays.equals(agent.getAgentAddress(), agent.getPackingAddress())) {
        return ValidateResult.getFailedResult(getClass().getName(), PocConsensusErrorCode.AGENTADDR_AND_PACKING_SAME);
    }
    if (Arrays.equals(agent.getRewardAddress(), agent.getPackingAddress())) {
        return ValidateResult.getFailedResult(getClass().getName(), PocConsensusErrorCode.REWARDADDR_PACKING_SAME);
    }
    if (tx.getTime() <= 0) {
        return ValidateResult.getFailedResult(getClass().getName(), KernelErrorCode.DATA_ERROR);
    }
    double commissionRate = agent.getCommissionRate();
    if (commissionRate < PocConsensusProtocolConstant.MIN_COMMISSION_RATE || commissionRate > PocConsensusProtocolConstant.MAX_COMMISSION_RATE) {
        return ValidateResult.getFailedResult(this.getClass().getSimpleName(), PocConsensusErrorCode.COMMISSION_RATE_OUT_OF_RANGE);
    }
    if (PocConsensusProtocolConstant.AGENT_DEPOSIT_LOWER_LIMIT.isGreaterThan(agent.getDeposit())) {
        return ValidateResult.getFailedResult(this.getClass().getName(), PocConsensusErrorCode.DEPOSIT_NOT_ENOUGH);
    }
    if (PocConsensusProtocolConstant.AGENT_DEPOSIT_UPPER_LIMIT.isLessThan(agent.getDeposit())) {
        return ValidateResult.getFailedResult(this.getClass().getName(), PocConsensusErrorCode.DEPOSIT_TOO_MUCH);
    }
    if (!isDepositOk(agent.getDeposit(), tx.getCoinData())) {
        return ValidateResult.getFailedResult(this.getClass().getName(), SeverityLevelEnum.FLAGRANT_FOUL, PocConsensusErrorCode.DEPOSIT_ERROR);
    }
    TransactionSignature sig = new TransactionSignature();
    try {
        sig.parse(tx.getTransactionSignature(), 0);
    } catch (NulsException e) {
        Log.error(e);
        return ValidateResult.getFailedResult(this.getClass().getName(), e.getErrorCode());
    }
    try {
        if (!SignatureUtil.containsAddress(tx, agent.getAgentAddress())) {
            ValidateResult result = ValidateResult.getFailedResult(this.getClass().getName(), KernelErrorCode.SIGNATURE_ERROR);
            result.setLevel(SeverityLevelEnum.FLAGRANT_FOUL);
            return result;
        }
    } catch (NulsException e) {
        ValidateResult result = ValidateResult.getFailedResult(this.getClass().getName(), KernelErrorCode.SIGNATURE_ERROR);
        result.setLevel(SeverityLevelEnum.FLAGRANT_FOUL);
        return result;
    }
    CoinData coinData = tx.getCoinData();
    Set<String> addressSet = new HashSet<>();
    int lockCount = 0;
    for (Coin coin : coinData.getTo()) {
        if (coin.getLockTime() == PocConsensusConstant.CONSENSUS_LOCK_TIME) {
            lockCount++;
        }
        // addressSet.add(AddressTool.getStringAddressByBytes(coin.()));
        addressSet.add(AddressTool.getStringAddressByBytes(coin.getAddress()));
    }
    if (lockCount > 1) {
        return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
    }
    if (addressSet.size() > 1) {
        return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
    }
    return ValidateResult.getSuccessResult();
}
Also used : Agent(io.nuls.consensus.poc.protocol.entity.Agent) Coin(io.nuls.kernel.model.Coin) NulsException(io.nuls.kernel.exception.NulsException) CoinData(io.nuls.kernel.model.CoinData) ValidateResult(io.nuls.kernel.validate.ValidateResult) TransactionSignature(io.nuls.kernel.script.TransactionSignature) HashSet(java.util.HashSet)

Example 5 with TransactionSignature

use of io.nuls.kernel.script.TransactionSignature in project nuls by nuls-io.

the class StopAgentTxValidator method validate.

@Override
public ValidateResult validate(StopAgentTransaction data) throws NulsException {
    AgentPo agentPo = agentStorageService.get(data.getTxData().getCreateTxHash());
    if (null == agentPo || agentPo.getDelHeight() > 0) {
        return ValidateResult.getFailedResult(this.getClass().getName(), PocConsensusErrorCode.AGENT_NOT_EXIST);
    }
    TransactionSignature sig = new TransactionSignature();
    try {
        sig.parse(data.getTransactionSignature(), 0);
    } catch (NulsException e) {
        Log.error(e);
        return ValidateResult.getFailedResult(this.getClass().getName(), e.getErrorCode());
    }
    if (!SignatureUtil.containsAddress(data, agentPo.getAgentAddress())) {
        ValidateResult result = ValidateResult.getFailedResult(this.getClass().getName(), KernelErrorCode.SIGNATURE_ERROR);
        result.setLevel(SeverityLevelEnum.FLAGRANT_FOUL);
        return result;
    }
    if (data.getCoinData().getTo() == null || data.getCoinData().getTo().isEmpty()) {
        return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
    }
    List<DepositPo> allDepositList = depositStorageService.getList();
    Map<NulsDigestData, DepositPo> depositMap = new HashMap<>();
    Na totalNa = agentPo.getDeposit();
    DepositPo ownDeposit = new DepositPo();
    ownDeposit.setDeposit(agentPo.getDeposit());
    ownDeposit.setAddress(agentPo.getAgentAddress());
    depositMap.put(data.getTxData().getCreateTxHash(), ownDeposit);
    for (DepositPo deposit : allDepositList) {
        if (deposit.getDelHeight() > -1L && (data.getBlockHeight() == -1L || deposit.getDelHeight() < data.getBlockHeight())) {
            continue;
        }
        if (!deposit.getAgentHash().equals(agentPo.getHash())) {
            continue;
        }
        depositMap.put(deposit.getTxHash(), deposit);
        totalNa = totalNa.add(deposit.getDeposit());
    }
    Na fromTotal = Na.ZERO;
    Map<String, Na> verifyToMap = new HashMap<>();
    for (Coin coin : data.getCoinData().getFrom()) {
        if (coin.getLockTime() != -1L) {
            return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
        }
        NulsDigestData txHash = new NulsDigestData();
        txHash.parse(coin.getOwner(), 0);
        DepositPo deposit = depositMap.remove(txHash);
        if (deposit == null) {
            return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
        }
        if (deposit.getAgentHash() == null && !coin.getNa().equals(agentPo.getDeposit())) {
            return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
        } else if (!deposit.getDeposit().equals(coin.getNa())) {
            return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
        }
        fromTotal = fromTotal.add(coin.getNa());
        if (deposit.getAgentHash() == null) {
            continue;
        }
        String address = AddressTool.getStringAddressByBytes(deposit.getAddress());
        Na na = verifyToMap.get(address);
        if (null == na) {
            na = deposit.getDeposit();
        } else {
            na = na.add(deposit.getDeposit());
        }
        verifyToMap.put(address, na);
    }
    if (!depositMap.isEmpty()) {
        return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
    }
    if (!totalNa.equals(fromTotal)) {
        return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
    }
    Na ownToCoin = ownDeposit.getDeposit().subtract(data.getFee());
    long ownLockTime = 0L;
    for (Coin coin : data.getCoinData().getTo()) {
        // String address = AddressTool.getStringAddressByBytes(coin.());
        String address = AddressTool.getStringAddressByBytes(coin.getAddress());
        Na na = verifyToMap.get(address);
        if (null != na && na.equals(coin.getNa())) {
            verifyToMap.remove(address);
            continue;
        }
        if (ownToCoin != null && Arrays.equals(coin.getAddress(), ownDeposit.getAddress()) && coin.getNa().equals(ownToCoin)) {
            ownToCoin = null;
            ownLockTime = coin.getLockTime();
            continue;
        } else {
            return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
        }
    }
    if (ownLockTime < (data.getTime() + PocConsensusConstant.STOP_AGENT_LOCK_TIME)) {
        return ValidateResult.getFailedResult(this.getClass().getName(), PocConsensusErrorCode.LOCK_TIME_NOT_REACHED);
    } else if (data.getBlockHeight() <= 0 && ownLockTime < (TimeService.currentTimeMillis() + PocConsensusConstant.STOP_AGENT_LOCK_TIME - 300000L)) {
        return ValidateResult.getFailedResult(this.getClass().getName(), PocConsensusErrorCode.LOCK_TIME_NOT_REACHED);
    }
    if (!verifyToMap.isEmpty()) {
        return ValidateResult.getFailedResult(this.getClass().getName(), TransactionErrorCode.TX_DATA_VALIDATION_ERROR);
    }
    return ValidateResult.getSuccessResult();
}
Also used : ValidateResult(io.nuls.kernel.validate.ValidateResult) TransactionSignature(io.nuls.kernel.script.TransactionSignature) Coin(io.nuls.kernel.model.Coin) DepositPo(io.nuls.consensus.poc.storage.po.DepositPo) Na(io.nuls.kernel.model.Na) NulsException(io.nuls.kernel.exception.NulsException) NulsDigestData(io.nuls.kernel.model.NulsDigestData) AgentPo(io.nuls.consensus.poc.storage.po.AgentPo)

Aggregations

NulsException (io.nuls.kernel.exception.NulsException)10 TransactionSignature (io.nuls.kernel.script.TransactionSignature)10 ValidateResult (io.nuls.kernel.validate.ValidateResult)7 Coin (io.nuls.kernel.model.Coin)4 IOException (java.io.IOException)4 DepositPo (io.nuls.consensus.poc.storage.po.DepositPo)3 NulsRuntimeException (io.nuls.kernel.exception.NulsRuntimeException)3 CoinData (io.nuls.kernel.model.CoinData)3 CoinDataResult (io.nuls.account.ledger.model.CoinDataResult)2 AgentPo (io.nuls.consensus.poc.storage.po.AgentPo)2 CryptoException (io.nuls.core.tools.crypto.Exception.CryptoException)2 Na (io.nuls.kernel.model.Na)2 P2PHKSignature (io.nuls.kernel.script.P2PHKSignature)2 Script (io.nuls.kernel.script.Script)2 VarInt (io.nuls.kernel.utils.VarInt)2 AccountErrorCode (io.nuls.account.constant.AccountErrorCode)1 LocalUtxoService (io.nuls.account.ledger.base.service.LocalUtxoService)1 AccountLegerUtils (io.nuls.account.ledger.base.util.AccountLegerUtils)1 CoinComparator (io.nuls.account.ledger.base.util.CoinComparator)1 AccountLedgerErrorCode (io.nuls.account.ledger.constant.AccountLedgerErrorCode)1