Search in sources :

Example 16 with NulsException

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

the class SyncVersionRunner method syncNewestVersionInfo.

private void syncNewestVersionInfo() throws NulsException, UnsupportedEncodingException {
    String jsonStr = null;
    try {
        jsonStr = new String(HttpDownloadUtils.download(this.versionJsonUrl), NulsConfig.DEFAULT_ENCODING);
    } catch (IOException e) {
        throw new NulsException(KernelErrorCode.DOWNLOAD_VERSION_FAILD);
    }
    Map<String, Object> map = null;
    try {
        map = JSONUtils.json2map(jsonStr);
    } catch (Exception e) {
        throw new NulsException(KernelErrorCode.PARSE_JSON_FAILD);
    }
    String version = (String) map.get("version");
    String versionFileHash = (String) map.get("versionFileHash");
    String signature = (String) map.get("signature");
    boolean result = VersionConstant.EC_KEY.verify(Sha256Hash.hash((version + "&" + versionFileHash).getBytes("UTF-8")), Hex.decode(signature));
    if (!result) {
        return;
    }
    NEWEST_VERSION = version;
    VERSION_FILE_HASH = versionFileHash;
    INFORMATION = (String) map.get("information");
}
Also used : NulsException(io.nuls.kernel.exception.NulsException) IOException(java.io.IOException) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Example 17 with NulsException

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

the class ForkChainProcess method doProcess.

public boolean doProcess() throws IOException, NulsException {
    if (ConsensusStatusContext.getConsensusStatus().ordinal() < ConsensusStatus.RUNNING.ordinal()) {
        NulsContext.WALLET_STATUS = NulsConstant.SYNCHING;
        return false;
    }
    Lockers.CHAIN_LOCK.lock();
    try {
        printChainStatusLog();
        ChainContainer masterChain = chainManager.getMasterChain();
        if (null == masterChain) {
            return false;
        }
        // Monitor the status of the orphan chain, if it is available, join the verification chain
        // 监控孤立链的状态,如果有可连接的,则加入验证链里面
        monitorOrphanChains();
        BlockHeader masterBestHeader = masterChain.getBestBlock().getHeader();
        // 寻找可切换的链
        ChainContainer wantToChangeChain = findWantToChangeChain(masterBestHeader);
        if (wantToChangeChain != null) {
            NulsContext.WALLET_STATUS = NulsConstant.ROLLBACK;
            // 验证新的链,结合当前最新的链,获取到分叉节点时的状态
            ChainContainer resultChain = chainManager.getMasterChain().getBeforeTheForkChain(wantToChangeChain);
            List<Object[]> verifyResultList = new ArrayList<>();
            for (Block forkBlock : wantToChangeChain.getChain().getAllBlockList()) {
                Result success = resultChain.verifyAndAddBlock(forkBlock, true, false);
                if (success.isFailed()) {
                    resultChain = null;
                    break;
                } else {
                    verifyResultList.add((Object[]) success.getData());
                }
            }
            if (resultChain == null) {
                ChainLog.debug("verify the fork chain fail {} remove it", wantToChangeChain.getChain().getId());
                chainManager.getChains().remove(wantToChangeChain);
            } else {
                // Verify pass, try to switch chain
                // 验证通过,尝试切换链
                boolean success = changeChain(resultChain, wantToChangeChain, verifyResultList);
                if (success) {
                    chainManager.getChains().remove(wantToChangeChain);
                    /**
                     ********************************************************************************************************
                     */
                    try {
                        Log.info("");
                        Log.info("****************************************************");
                        Log.info("完成 切换连成功,获取当前bestblock, height:{},- {}", chainManager.getBestBlock().getHeader().getHeight(), chainManager.getBestBlock().getHeader().getHash());
                        Log.info("****************************************************");
                        Log.info("");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                /**
                 ********************************************************************************************************
                 */
                } else {
                    Log.info("切换链失败了---------------------------------");
                }
                ChainLog.debug("verify the fork chain {} success, change master chain result : {} , new master chain is {} : {} - {}", wantToChangeChain.getChain().getId(), success, chainManager.getBestBlock().getHeader().getHeight(), chainManager.getBestBlock().getHeader().getHash());
            }
        }
        clearExpiredChain();
    } finally {
        NulsContext.WALLET_STATUS = NulsConstant.RUNNING;
        Lockers.CHAIN_LOCK.unlock();
    }
    return true;
}
Also used : ChainContainer(io.nuls.consensus.poc.container.ChainContainer) IOException(java.io.IOException) NulsException(io.nuls.kernel.exception.NulsException) ContractResult(io.nuls.contract.dto.ContractResult) ValidateResult(io.nuls.kernel.validate.ValidateResult)

Example 18 with NulsException

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

the class UtxoLedgerServiceImpl method rollbackUnlockTxCoinData.

@Override
public Result rollbackUnlockTxCoinData(Transaction tx) throws NulsException {
    if (tx == null || tx.getCoinData() == null) {
        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.NULL_PARAMETER);
    }
    try {
        CoinData coinData = tx.getCoinData();
        List<Coin> tos = coinData.getTo();
        boolean isExistLockUtxo = false;
        Coin needUnLockUtxo = null;
        int needUnLockUtxoIndex = 0;
        for (Coin to : tos) {
            if (to.getLockTime() == -1) {
                isExistLockUtxo = true;
                needUnLockUtxo = to;
                break;
            }
            needUnLockUtxoIndex++;
        }
        if (!isExistLockUtxo) {
            return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.UTXO_STATUS_CHANGE);
        }
        byte[] txHashBytes = tx.getHash().serialize();
        Result result = utxoLedgerUtxoStorageService.saveUtxo(Arrays.concatenate(txHashBytes, new VarInt(needUnLockUtxoIndex).encode()), needUnLockUtxo);
        if (result.isFailed()) {
            throw new NulsException(result.getErrorCode());
        }
        return result;
    } catch (IOException e) {
        Log.error(e);
        throw new NulsException(KernelErrorCode.IO_ERROR);
    }
}
Also used : VarInt(io.nuls.kernel.utils.VarInt) NulsException(io.nuls.kernel.exception.NulsException) IOException(java.io.IOException) ValidateResult(io.nuls.kernel.validate.ValidateResult)

Example 19 with NulsException

use of io.nuls.kernel.exception.NulsException 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 20 with NulsException

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

the class UtxoLedgerServiceImpl method unlockTxCoinData.

@Override
public Result unlockTxCoinData(Transaction tx, long newockTime) throws NulsException {
    if (tx == null || tx.getCoinData() == null) {
        return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.NULL_PARAMETER);
    }
    try {
        CoinData coinData = tx.getCoinData();
        List<Coin> tos = coinData.getTo();
        boolean isExistLockUtxo = false;
        Coin needUnLockUtxo = null;
        int needUnLockUtxoIndex = 0;
        for (Coin to : tos) {
            if (to.getLockTime() == -1) {
                isExistLockUtxo = true;
                needUnLockUtxo = to;
                break;
            }
            needUnLockUtxoIndex++;
        }
        if (!isExistLockUtxo) {
            return ValidateResult.getFailedResult(CLASS_NAME, LedgerErrorCode.UTXO_STATUS_CHANGE);
        }
        byte[] txHashBytes = txHashBytes = tx.getHash().serialize();
        Coin needUnLockUtxoNew = new Coin(needUnLockUtxo.getOwner(), needUnLockUtxo.getNa(), newockTime);
        needUnLockUtxoNew.setFrom(needUnLockUtxo.getFrom());
        Result result = utxoLedgerUtxoStorageService.saveUtxo(Arrays.concatenate(txHashBytes, new VarInt(needUnLockUtxoIndex).encode()), needUnLockUtxoNew);
        if (result.isFailed()) {
            Result rollbackResult = rollbackUnlockTxCoinData(tx);
            if (rollbackResult.isFailed()) {
                throw new NulsException(rollbackResult.getErrorCode());
            }
        }
        return result;
    } catch (IOException e) {
        Result rollbackResult = rollbackUnlockTxCoinData(tx);
        if (rollbackResult.isFailed()) {
            throw new NulsException(rollbackResult.getErrorCode());
        }
        Log.error(e);
        return Result.getFailed(KernelErrorCode.IO_ERROR);
    }
}
Also used : VarInt(io.nuls.kernel.utils.VarInt) NulsException(io.nuls.kernel.exception.NulsException) IOException(java.io.IOException) ValidateResult(io.nuls.kernel.validate.ValidateResult)

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