use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class PocConsensusResource method getWithdrawFee.
@GET
@Path("/withdraw/fee")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "get the fee of cancel deposit! 获取撤销委托的手续费", notes = "返回撤销委托交易手续费")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = String.class) })
public RpcClientResult getWithdrawFee(@ApiParam(name = "address", value = "委托账户地址", required = true) @QueryParam("address") String address, @ApiParam(name = "depositTxHash", value = "委托交易摘要", required = true) @QueryParam("depositTxHash") String depositTxHash) throws NulsException, IOException {
AssertUtil.canNotEmpty(depositTxHash);
if (!NulsDigestData.validHash(depositTxHash)) {
return Result.getFailed(KernelErrorCode.PARAMETER_ERROR).toRpcClientResult();
}
AssertUtil.canNotEmpty(address);
if (!AddressTool.validAddress(address)) {
return Result.getFailed(AccountErrorCode.ADDRESS_ERROR).toRpcClientResult();
}
Account account = accountService.getAccount(address).getData();
if (null == account) {
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST).toRpcClientResult();
}
if (!account.isOk()) {
return Result.getFailed(AccountErrorCode.IMPORTING_ACCOUNT).toRpcClientResult();
}
CancelDepositTransaction tx = new CancelDepositTransaction();
CancelDeposit cancelDeposit = new CancelDeposit();
NulsDigestData hash = NulsDigestData.fromDigestHex(depositTxHash);
DepositTransaction depositTransaction = (DepositTransaction) ledgerService.getTx(hash);
if (null == depositTransaction) {
return Result.getFailed(TransactionErrorCode.TX_NOT_EXIST).toRpcClientResult();
}
cancelDeposit.setAddress(account.getAddress().getAddressBytes());
cancelDeposit.setJoinTxHash(hash);
tx.setTxData(cancelDeposit);
CoinData coinData = new CoinData();
List<Coin> toList = new ArrayList<>();
toList.add(new Coin(cancelDeposit.getAddress(), depositTransaction.getTxData().getDeposit(), 0));
coinData.setTo(toList);
List<Coin> fromList = new ArrayList<>();
for (int index = 0; index < depositTransaction.getCoinData().getTo().size(); index++) {
Coin coin = depositTransaction.getCoinData().getTo().get(index);
if (coin.getLockTime() == -1L && coin.getNa().equals(depositTransaction.getTxData().getDeposit())) {
coin.setOwner(ArraysTool.concatenate(hash.serialize(), new VarInt(index).encode()));
fromList.add(coin);
break;
}
}
if (fromList.isEmpty()) {
return Result.getFailed(KernelErrorCode.DATA_ERROR).toRpcClientResult();
}
coinData.setFrom(fromList);
tx.setCoinData(coinData);
Na fee = TransactionFeeCalculator.getMaxFee(108 + tx.size());
coinData.getTo().get(0).setNa(coinData.getTo().get(0).getNa().subtract(fee));
Na resultFee = TransactionFeeCalculator.getMaxFee(108 + tx.size());
Map<String, Long> map = new HashMap<>();
map.put("fee", fee.getValue());
map.put("maxAmount", getMaxAmount(resultFee, account.getAddress().getBase58(), tx));
return Result.getSuccess().setData(map).toRpcClientResult();
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class PocConsensusResource method withdraw.
@POST
@Path("/withdraw")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "退出共识 [3.6.11]", notes = "返回退出成功的交易hash")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = String.class) })
public RpcClientResult withdraw(@ApiParam(name = "form", value = "退出共识表单数据", required = true) WithdrawForm form) throws NulsException, IOException {
AssertUtil.canNotEmpty(form);
AssertUtil.canNotEmpty(form.getTxHash());
if (!NulsDigestData.validHash(form.getTxHash())) {
return Result.getFailed(KernelErrorCode.PARAMETER_ERROR).toRpcClientResult();
}
AssertUtil.canNotEmpty(form.getAddress());
if (!AddressTool.validAddress(form.getAddress())) {
return Result.getFailed(AccountErrorCode.ADDRESS_ERROR).toRpcClientResult();
}
Account account = accountService.getAccount(form.getAddress()).getData();
if (null == account) {
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST).toRpcClientResult();
}
if (account.isEncrypted() && account.isLocked()) {
AssertUtil.canNotEmpty(form.getPassword(), "password is wrong");
if (!account.validatePassword(form.getPassword())) {
return Result.getFailed(AccountErrorCode.PASSWORD_IS_WRONG).toRpcClientResult();
}
}
CancelDepositTransaction tx = new CancelDepositTransaction();
CancelDeposit cancelDeposit = new CancelDeposit();
NulsDigestData hash = NulsDigestData.fromDigestHex(form.getTxHash());
DepositTransaction depositTransaction = null;
try {
depositTransaction = (DepositTransaction) ledgerService.getTx(hash);
} catch (Exception e) {
return Result.getFailed(KernelErrorCode.PARAMETER_ERROR).toRpcClientResult();
}
if (null == depositTransaction) {
return Result.getFailed(TransactionErrorCode.TX_NOT_EXIST).toRpcClientResult();
}
cancelDeposit.setAddress(AddressTool.getAddress(form.getAddress()));
cancelDeposit.setJoinTxHash(hash);
tx.setTxData(cancelDeposit);
CoinData coinData = new CoinData();
List<Coin> toList = new ArrayList<>();
toList.add(new Coin(cancelDeposit.getAddress(), depositTransaction.getTxData().getDeposit(), 0));
coinData.setTo(toList);
List<Coin> fromList = new ArrayList<>();
for (int index = 0; index < depositTransaction.getCoinData().getTo().size(); index++) {
Coin coin = depositTransaction.getCoinData().getTo().get(index);
if (coin.getLockTime() == -1L && coin.getNa().equals(depositTransaction.getTxData().getDeposit())) {
coin.setOwner(ArraysTool.concatenate(hash.serialize(), new VarInt(index).encode()));
fromList.add(coin);
break;
}
}
if (fromList.isEmpty()) {
return Result.getFailed(KernelErrorCode.DATA_ERROR).toRpcClientResult();
}
coinData.setFrom(fromList);
tx.setCoinData(coinData);
Na fee = TransactionFeeCalculator.getMaxFee(108 + tx.size());
coinData.getTo().get(0).setNa(coinData.getTo().get(0).getNa().subtract(fee));
RpcClientResult result1 = this.txProcessing(tx, null, account, form.getPassword());
if (!result1.isSuccess()) {
return result1;
}
Map<String, String> valueMap = new HashMap<>();
valueMap.put("value", tx.getHash().getDigestHex());
return Result.getSuccess().setData(valueMap).toRpcClientResult();
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class PocConsensusResource method createWithdrawMutil.
@POST
@Path("/multiAccount/mutilWithdraw")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "多签账户退出共识", notes = "返回退出成功的交易hash")
@ApiResponses(value = { @ApiResponse(code = 200, message = "success", response = String.class) })
public RpcClientResult createWithdrawMutil(@ApiParam(name = "form", value = "多签退出共识表单数据", required = true) CreateMultiWithdrawForm form) throws Exception {
AssertUtil.canNotEmpty(form);
AssertUtil.canNotEmpty(form.getTxHash());
AssertUtil.canNotEmpty(form.getAddress());
AssertUtil.canNotEmpty(form.getSignAddress());
if (!NulsDigestData.validHash(form.getTxHash())) {
return Result.getFailed(KernelErrorCode.PARAMETER_ERROR).toRpcClientResult();
}
if (!AddressTool.validAddress(form.getAddress()) || !AddressTool.validAddress(form.getSignAddress())) {
return Result.getFailed(AccountErrorCode.ADDRESS_ERROR).toRpcClientResult();
}
Account account = accountService.getAccount(form.getSignAddress()).getData();
if (null == account) {
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST).toRpcClientResult();
}
if (account.isEncrypted() && account.isLocked()) {
AssertUtil.canNotEmpty(form.getPassword(), "password is wrong");
if (!account.validatePassword(form.getPassword())) {
return Result.getFailed(AccountErrorCode.PASSWORD_IS_WRONG).toRpcClientResult();
}
}
Result<MultiSigAccount> sigAccountResult = accountService.getMultiSigAccount(form.getAddress());
MultiSigAccount multiSigAccount = sigAccountResult.getData();
// 验证签名账户是否属于多签账户,如果不是多签账户下的地址则提示错误
if (!AddressTool.validSignAddress(multiSigAccount.getPubKeyList(), account.getPubKey())) {
return Result.getFailed(AccountErrorCode.SIGN_ADDRESS_NOT_MATCH).toRpcClientResult();
}
Script redeemScript = accountLedgerService.getRedeemScript(multiSigAccount);
if (redeemScript == null) {
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST).toRpcClientResult();
}
CancelDepositTransaction tx = new CancelDepositTransaction();
TransactionSignature transactionSignature = new TransactionSignature();
List<Script> scripts = new ArrayList<>();
CancelDeposit cancelDeposit = new CancelDeposit();
NulsDigestData hash = NulsDigestData.fromDigestHex(form.getTxHash());
DepositTransaction depositTransaction = null;
try {
depositTransaction = (DepositTransaction) ledgerService.getTx(hash);
} catch (Exception e) {
return Result.getFailed(KernelErrorCode.PARAMETER_ERROR).toRpcClientResult();
}
if (null == depositTransaction) {
return Result.getFailed(TransactionErrorCode.TX_NOT_EXIST).toRpcClientResult();
}
// Create unlock script
cancelDeposit.setAddress(AddressTool.getAddress(form.getAddress()));
cancelDeposit.setJoinTxHash(hash);
tx.setTxData(cancelDeposit);
CoinData coinData = new CoinData();
List<Coin> toList = new ArrayList<>();
if (cancelDeposit.getAddress()[2] == NulsContext.P2SH_ADDRESS_TYPE) {
Script scriptPubkey = SignatureUtil.createOutputScript(cancelDeposit.getAddress());
toList.add(new Coin(scriptPubkey.getProgram(), depositTransaction.getTxData().getDeposit(), PocConsensusConstant.CONSENSUS_LOCK_TIME));
} else {
toList.add(new Coin(cancelDeposit.getAddress(), depositTransaction.getTxData().getDeposit(), 0));
}
coinData.setTo(toList);
List<Coin> fromList = new ArrayList<>();
for (int index = 0; index < depositTransaction.getCoinData().getTo().size(); index++) {
Coin coin = depositTransaction.getCoinData().getTo().get(index);
if (coin.getLockTime() == -1L && coin.getNa().equals(depositTransaction.getTxData().getDeposit())) {
coin.setOwner(ArraysTool.concatenate(hash.serialize(), new VarInt(index).encode()));
fromList.add(coin);
break;
}
}
if (fromList.isEmpty()) {
return Result.getFailed(KernelErrorCode.DATA_ERROR).toRpcClientResult();
}
coinData.setFrom(fromList);
tx.setCoinData(coinData);
Na fee = TransactionFeeCalculator.getMaxFee(108 + tx.size());
coinData.getTo().get(0).setNa(coinData.getTo().get(0).getNa().subtract(fee));
tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
// 将赎回脚本先存储在签名脚本中
scripts.add(redeemScript);
transactionSignature.setScripts(scripts);
Result resultData = accountLedgerService.txMultiProcess(tx, transactionSignature, account, form.getPassword());
if (resultData.isSuccess()) {
Map<String, String> valueMap = new HashMap<>();
valueMap.put("txData", (String) resultData.getData());
return Result.getSuccess().setData(valueMap).toRpcClientResult();
}
return resultData.toRpcClientResult();
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class LocalUtxoServiceImpl method deleteUtxoOfTransaction.
@Override
public Result deleteUtxoOfTransaction(Transaction tx) {
if (tx == null) {
return Result.getFailed(KernelErrorCode.NULL_PARAMETER);
}
CoinData coinData = tx.getCoinData();
if (coinData != null) {
// delete utxo - to
List<Coin> tos = coinData.getTo();
List<byte[]> toList = new ArrayList<>();
byte[] outKey;
for (int i = 0, length = tos.size(); i < length; i++) {
try {
// if(!AccountLegerUtils.isLocalAccount(tos.get(i).getOwner()))
if (null == AccountLegerUtils.isLocalAccount(tos.get(i).getAddress())) {
continue;
}
outKey = ArraysTool.concatenate(tx.getHash().serialize(), new VarInt(i).encode());
toList.add(outKey);
} catch (IOException e) {
throw new NulsRuntimeException(e);
}
}
// save - from
List<Coin> froms = coinData.getFrom();
List<Entry<byte[], byte[]>> fromList = new ArrayList<>();
byte[] fromSource;
Coin fromOfFromCoin;
byte[] utxoFromSource;
byte[] fromIndex;
Transaction sourceTx;
byte[] address;
for (Coin from : froms) {
fromSource = from.getOwner();
fromOfFromCoin = from.getFrom();
if (fromOfFromCoin == null) {
utxoFromSource = new byte[tx.getHash().size()];
fromIndex = new byte[fromSource.length - utxoFromSource.length];
System.arraycopy(fromSource, 0, utxoFromSource, 0, tx.getHash().size());
System.arraycopy(fromSource, tx.getHash().size(), fromIndex, 0, fromIndex.length);
try {
sourceTx = ledgerService.getTx(NulsDigestData.fromDigestHex(Hex.encode(utxoFromSource)));
} catch (Exception e) {
continue;
}
if (sourceTx == null) {
return Result.getFailed(TransactionErrorCode.TX_NOT_EXIST);
}
fromOfFromCoin = sourceTx.getCoinData().getTo().get((int) new VarInt(fromIndex, 0).value);
from.setFrom(fromOfFromCoin);
}
if (fromOfFromCoin == null) {
Log.warn("from coin not found!");
continue;
}
address = fromOfFromCoin.getAddress();
if (null == AccountLegerUtils.isLocalAccount(address)) {
continue;
}
try {
fromList.add(new Entry<>(fromSource, fromOfFromCoin.serialize()));
} catch (IOException e) {
throw new NulsRuntimeException(e);
}
}
Result result = localUtxoStorageService.batchSaveAndDeleteUTXO(fromList, toList);
if (result.isFailed() || result.getData() == null || (int) result.getData() != fromList.size() + toList.size()) {
return Result.getFailed();
}
}
return Result.getSuccess();
}
use of io.nuls.kernel.utils.VarInt in project nuls by nuls-io.
the class CallContractTxProcessor method onCommit.
@Override
public Result onCommit(CallContractTransaction tx, Object secondaryData) {
try {
ContractResult contractResult = tx.getContractResult();
// 保存调用合约交易的UTXO
Result utxoResult = contractUtxoService.saveUtxoForContractAddress(tx);
if (utxoResult.isFailed()) {
Log.error("save confirmed contract utxo error, reason is {}.", utxoResult.getMsg());
return utxoResult;
}
long blockHeight = tx.getBlockHeight();
/**
* 保存子交易到全网账本、合约账本、本地账本
*/
Collection<ContractTransferTransaction> contractTransferTxs = tx.getContractTransferTxs();
if (contractTransferTxs != null && contractTransferTxs.size() > 0) {
for (ContractTransferTransaction transferTx : contractTransferTxs) {
try {
transferTx.setBlockHeight(blockHeight);
Result result = ledgerService.saveTx(transferTx);
if (result.isFailed()) {
Log.error("save contract transfer tx to ledger error. msg: {}", result.getMsg());
return result;
}
result = contractService.saveContractTransferTx(transferTx);
if (result.isFailed()) {
Log.error("save contract transfer tx to contract ledger error. msg: {}", result.getMsg());
return result;
}
result = accountLedgerService.saveConfirmedTransaction(transferTx);
if (result.isFailed()) {
Log.error("save contract transfer tx to account ledger error. msg: {}", result.getMsg());
return result;
}
} catch (Exception e) {
e.printStackTrace();
Log.error("save contract transfer tx error. msg: {}", e.getMessage());
return Result.getFailed();
}
}
}
// 保存代币交易
CallContractData callContractData = tx.getTxData();
byte[] contractAddress = callContractData.getContractAddress();
Result<ContractAddressInfoPo> contractAddressInfoPoResult = contractAddressStorageService.getContractAddressInfo(contractAddress);
if (contractAddressInfoPoResult.isFailed()) {
return contractAddressInfoPoResult;
}
ContractAddressInfoPo contractAddressInfoPo = contractAddressInfoPoResult.getData();
if (contractAddressInfoPo == null) {
return Result.getFailed(ContractErrorCode.CONTRACT_ADDRESS_NOT_EXIST);
}
contractResult.setNrc20(contractAddressInfoPo.isNrc20());
BlockHeader blockHeader = tx.getBlockHeader();
byte[] newestStateRoot = blockHeader.getStateRoot();
// 获取合约当前状态
ProgramStatus status = vmHelper.getContractStatus(newestStateRoot, contractAddress);
boolean isTerminatedContract = ContractUtil.isTerminatedContract(status.ordinal());
// 处理合约执行失败 - 没有transferEvent的情况, 直接从数据库中获取, 若是本地创建的交易,获取到修改为失败交易
if (isTerminatedContract || !contractResult.isSuccess()) {
if (contractAddressInfoPo != null && contractAddressInfoPo.isNrc20() && ContractUtil.isTransferMethod(callContractData.getMethodName())) {
byte[] txHashBytes = tx.getHash().serialize();
byte[] infoKey = ArraysTool.concatenate(callContractData.getSender(), txHashBytes, new VarInt(0).encode());
Result<ContractTokenTransferInfoPo> infoResult = contractTokenTransferStorageService.getTokenTransferInfo(infoKey);
ContractTokenTransferInfoPo po = infoResult.getData();
if (po != null) {
po.setStatus((byte) 2);
contractTokenTransferStorageService.saveTokenTransferInfo(infoKey, po);
// 刷新token余额
if (isTerminatedContract) {
// 终止的合约,回滚token余额
this.rollbackContractToken(po);
contractResult.setError(true);
contractResult.setErrorMessage("this contract has been terminated");
} else {
if (po.getFrom() != null) {
vmHelper.refreshTokenBalance(newestStateRoot, contractAddressInfoPo, AddressTool.getStringAddressByBytes(po.getFrom()), po.getContractAddress());
}
if (po.getTo() != null) {
vmHelper.refreshTokenBalance(newestStateRoot, contractAddressInfoPo, AddressTool.getStringAddressByBytes(po.getTo()), po.getContractAddress());
}
}
}
}
}
if (!isTerminatedContract) {
// 处理合约事件
vmHelper.dealEvents(newestStateRoot, tx, contractResult, contractAddressInfoPo);
}
// 保存合约执行结果
contractService.saveContractExecuteResult(tx.getHash(), contractResult);
} catch (Exception e) {
Log.error("save call contract tx error.", e);
return Result.getFailed();
}
return Result.getSuccess();
}
Aggregations