use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.
the class RpcServerFilter method toResponse.
@Override
public Response toResponse(Exception e) {
// System.out.println("---------------" + request.getRequestURI());
Log.error("RequestURI is " + request.getRequestURI(), e);
RpcClientResult result;
if (e instanceof NulsException) {
NulsException exception = (NulsException) e;
result = new RpcClientResult(false, exception.getErrorCode());
} else if (e instanceof NulsRuntimeException) {
NulsRuntimeException exception = (NulsRuntimeException) e;
result = new RpcClientResult(false, new ErrorData(exception.getCode(), exception.getMessage()));
} else {
result = Result.getFailed().setMsg(e.getMessage()).toRpcClientResult();
}
return Response.ok(result, MediaType.APPLICATION_JSON).build();
}
use of io.nuls.kernel.exception.NulsException 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;
}
}
use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.
the class ContractTxServiceImpl method validateContractCreateTx.
/**
* 验证创建生成智能合约的交易
*
* @param gasLimit 最大gas消耗
* @param price 执行合约单价
* @param contractCode 合约代码
* @param args 参数列表
* @return
*/
@Override
public Result validateContractCreateTx(Long gasLimit, Long price, byte[] contractCode, String[][] args) {
try {
AssertUtil.canNotEmpty(contractCode, "the contractCode can not be empty");
Na value = Na.ZERO;
if (!ContractUtil.checkPrice(price.longValue())) {
return Result.getFailed(ContractErrorCode.CONTRACT_MINIMUM_PRICE);
}
Account senderAccount = AccountTool.createAccount();
// 生成一个地址作为智能合约地址
Address contractAddress = AccountTool.createContractAddress();
byte[] contractAddressBytes = contractAddress.getAddressBytes();
byte[] senderBytes = senderAccount.getAddress().getAddressBytes();
BlockHeader blockHeader = NulsContext.getInstance().getBestBlock().getHeader();
// 当前区块高度
long blockHeight = blockHeader.getHeight();
// 当前区块状态根
byte[] prevStateRoot = ContractUtil.getStateRoot(blockHeader);
AssertUtil.canNotEmpty(prevStateRoot, "All features of the smart contract are locked.");
// 执行VM验证合法性
ProgramCreate programCreate = new ProgramCreate();
programCreate.setContractAddress(contractAddressBytes);
programCreate.setSender(senderBytes);
programCreate.setValue(BigInteger.valueOf(value.getValue()));
programCreate.setPrice(price.longValue());
programCreate.setGasLimit(gasLimit.longValue());
programCreate.setNumber(blockHeight);
programCreate.setContractCode(contractCode);
if (args != null) {
programCreate.setArgs(args);
}
ProgramExecutor track = programExecutor.begin(prevStateRoot);
// 验证合约时跳过Gas验证
long realGasLimit = programCreate.getGasLimit();
programCreate.setGasLimit(MAX_GASLIMIT);
ProgramResult programResult = track.create(programCreate);
// 执行结果失败时,交易直接返回错误,不上链,不消耗Gas,
if (!programResult.isSuccess()) {
Log.error(programResult.getStackTrace());
Result result = Result.getFailed(ContractErrorCode.DATA_ERROR);
result.setMsg(ContractUtil.simplifyErrorMsg(programResult.getErrorMessage()));
result = checkVmResultAndReturn(programResult.getErrorMessage(), result);
return result;
} else {
// 其他合法性都通过后,再验证Gas
track = programExecutor.begin(prevStateRoot);
programCreate.setGasLimit(realGasLimit);
programResult = track.create(programCreate);
if (!programResult.isSuccess()) {
Log.error(programResult.getStackTrace());
Result result = Result.getFailed(ContractErrorCode.DATA_ERROR);
result.setMsg(ContractUtil.simplifyErrorMsg(programResult.getErrorMessage()));
return result;
}
}
return Result.getSuccess();
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
}
}
use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.
the class ContractTxServiceImpl method contractDeleteTx.
/**
* 创建删除智能合约的交易
*
* @param sender 交易创建者
* @param contractAddress 合约地址
* @param password 账户密码
* @param remark 备注
* @return
*/
@Override
public Result contractDeleteTx(String sender, String contractAddress, String password, String remark) {
try {
AssertUtil.canNotEmpty(sender, "the sender address can not be empty");
AssertUtil.canNotEmpty(contractAddress, "the contractAddress can not be empty");
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
Result<ContractAddressInfoPo> contractAddressInfoPoResult = contractAddressStorageService.getContractAddressInfo(contractAddressBytes);
if (contractAddressInfoPoResult.isFailed()) {
return contractAddressInfoPoResult;
}
ContractAddressInfoPo contractAddressInfoPo = contractAddressInfoPoResult.getData();
if (contractAddressInfoPo == null) {
return Result.getFailed(ContractErrorCode.CONTRACT_ADDRESS_NOT_EXIST);
}
BlockHeader blockHeader = NulsContext.getInstance().getBestBlock().getHeader();
// 当前区块状态根
byte[] stateRoot = ContractUtil.getStateRoot(blockHeader);
// 获取合约当前状态
ProgramStatus status = vmHelper.getContractStatus(stateRoot, contractAddressBytes);
boolean isTerminatedContract = ContractUtil.isTerminatedContract(status.ordinal());
if (isTerminatedContract) {
return Result.getFailed(ContractErrorCode.CONTRACT_DELETED);
}
byte[] senderBytes = AddressTool.getAddress(sender);
if (!ArraysTool.arrayEquals(senderBytes, contractAddressInfoPo.getSender())) {
return Result.getFailed(ContractErrorCode.CONTRACT_DELETE_CREATER);
}
Result<ContractBalance> result = contractBalanceManager.getBalance(contractAddressBytes);
ContractBalance balance = (ContractBalance) result.getData();
if (balance == null) {
return result;
}
Na totalBalance = balance.getBalance();
if (totalBalance.compareTo(Na.ZERO) != 0) {
return Result.getFailed(ContractErrorCode.CONTRACT_DELETE_BALANCE);
}
Result<Account> accountResult = accountService.getAccount(sender);
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);
}
DeleteContractTransaction tx = new DeleteContractTransaction();
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(NulsConfig.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
Log.error(e);
throw new RuntimeException(e);
}
}
tx.setTime(TimeService.currentTimeMillis());
// 组装txData
DeleteContractData deleteContractData = new DeleteContractData();
deleteContractData.setContractAddress(contractAddressBytes);
deleteContractData.setSender(senderBytes);
tx.setTxData(deleteContractData);
// 计算CoinData
/*
* 没有Gas消耗,在终止智能合约里
*/
CoinData coinData = new CoinData();
// 总花费 终止智能合约的交易手续费按普通交易计算手续费
CoinDataResult coinDataResult = accountLedgerService.getCoinData(senderBytes, Na.ZERO, tx.size() + coinData.size(), TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
// 找零的UTXO
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 = accountLedgerService.verifyAndSaveUnconfirmedTransaction(tx);
if (saveResult.isFailed()) {
if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
// 重新算一次交易(不超出最大交易数据大小下)的最大金额
Result rs = accountLedgerService.getMaxAmountOfOnce(senderBytes, 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()) {
// 失败则回滚
accountLedgerService.deleteTransaction(tx);
return sendResult;
}
return Result.getSuccess().setData(tx.getHash().getDigestHex());
} catch (IOException e) {
Log.error(e);
Result result = Result.getFailed(ContractErrorCode.CONTRACT_TX_CREATE_ERROR);
result.setMsg(e.getMessage());
return result;
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
} catch (Exception e) {
Log.error(e);
Result result = Result.getFailed(ContractErrorCode.CONTRACT_TX_CREATE_ERROR);
result.setMsg(e.getMessage());
return result;
}
}
use of io.nuls.kernel.exception.NulsException in project nuls by nuls-io.
the class ContractTxServiceImpl method contractPreCreateTx.
/**
* 预创建生成智能合约的交易
* 用于测试合约是否能正确创建
*
* @param sender 交易创建者
* @param gasLimit 最大gas消耗
* @param price 执行合约单价
* @param contractCode 合约代码
* @param args 参数列表
* @param password 账户密码
* @param remark 备注
* @return
*/
@Override
public Result contractPreCreateTx(String sender, Long gasLimit, Long price, byte[] contractCode, String[][] args, String password, String remark) {
try {
AssertUtil.canNotEmpty(sender, "the sender address can not be empty");
AssertUtil.canNotEmpty(contractCode, "the contractCode can not be empty");
Na value = Na.ZERO;
Result<Account> accountResult = accountService.getAccount(sender);
if (accountResult.isFailed()) {
return accountResult;
}
// 生成一个地址作为智能合约地址
Address contractAddress = AccountTool.createContractAddress();
byte[] contractAddressBytes = contractAddress.getAddressBytes();
byte[] senderBytes = AddressTool.getAddress(sender);
CreateContractTransaction tx = new CreateContractTransaction();
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(NulsConfig.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
Log.error(e);
throw new RuntimeException(e);
}
}
tx.setTime(TimeService.currentTimeMillis());
// 计算CoinData
/*
* 智能合约计算手续费以消耗的Gas*Price为根据,然而创建交易时并不执行智能合约,
* 所以此时交易的CoinData是不固定的,比实际要多,
* 打包时执行智能合约,真实的手续费已算出,然而tx的手续费已扣除,
* 多扣除的费用会以CoinBase交易还给Sender
*/
CoinData coinData = new CoinData();
// 向智能合约账户转账
if (!Na.ZERO.equals(value)) {
Coin toCoin = new Coin(contractAddressBytes, value);
coinData.getTo().add(toCoin);
}
BlockHeader blockHeader = NulsContext.getInstance().getBestBlock().getHeader();
// 当前区块高度
long blockHeight = blockHeader.getHeight();
// 当前区块状态根
byte[] prevStateRoot = ContractUtil.getStateRoot(blockHeader);
AssertUtil.canNotEmpty(prevStateRoot, "All features of the smart contract are locked.");
// 执行VM验证合法性
ProgramCreate programCreate = new ProgramCreate();
programCreate.setContractAddress(contractAddressBytes);
programCreate.setSender(senderBytes);
programCreate.setValue(BigInteger.valueOf(value.getValue()));
programCreate.setPrice(price.longValue());
programCreate.setGasLimit(gasLimit.longValue());
programCreate.setNumber(blockHeight);
programCreate.setContractCode(contractCode);
if (args != null) {
programCreate.setArgs(args);
}
ProgramExecutor track = programExecutor.begin(prevStateRoot);
// 验证合约时跳过Gas验证
long realGasLimit = programCreate.getGasLimit();
programCreate.setGasLimit(MAX_GASLIMIT);
ProgramResult programResult = track.create(programCreate);
// 执行结果失败时,交易直接返回错误,不上链,不消耗Gas,
if (!programResult.isSuccess()) {
Log.error(programResult.getStackTrace());
Result result = Result.getFailed(ContractErrorCode.DATA_ERROR);
result.setMsg(ContractUtil.simplifyErrorMsg(programResult.getErrorMessage()));
result = checkVmResultAndReturn(programResult.getErrorMessage(), result);
return result;
} else {
// 其他合法性都通过后,再验证Gas
track = programExecutor.begin(prevStateRoot);
programCreate.setGasLimit(realGasLimit);
programResult = track.create(programCreate);
if (!programResult.isSuccess()) {
Log.error(programResult.getStackTrace());
Result result = Result.getFailed(ContractErrorCode.DATA_ERROR);
result.setMsg(ContractUtil.simplifyErrorMsg(programResult.getErrorMessage()));
return result;
}
}
long gasUsed = gasLimit.longValue();
Na imputedNa = Na.valueOf(LongUtils.mul(gasUsed, price));
// 总花费
Na totalNa = imputedNa.add(value);
// 组装txData
CreateContractData createContractData = new CreateContractData();
createContractData.setSender(senderBytes);
createContractData.setContractAddress(contractAddressBytes);
createContractData.setValue(value.getValue());
createContractData.setGasLimit(gasLimit);
createContractData.setPrice(price);
createContractData.setCodeLen(contractCode.length);
createContractData.setCode(contractCode);
if (args != null) {
createContractData.setArgsCount((byte) args.length);
if (args.length > 0) {
createContractData.setArgs(args);
}
}
tx.setTxData(createContractData);
CoinDataResult coinDataResult = accountLedgerService.getCoinData(senderBytes, totalNa, tx.size(), TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
return Result.getSuccess();
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
} catch (Exception e) {
Log.error(e);
Result result = Result.getFailed(ContractErrorCode.CONTRACT_TX_CREATE_ERROR);
result.setMsg(e.getMessage());
return result;
}
}
Aggregations