use of io.nuls.account.ledger.model.TransactionDataResult in project nuls by nuls-io.
the class AccountLedgerServiceImpl method sendToAddress.
@Override
public Result sendToAddress(byte[] from, byte[] to, Na values, String password, byte[] remark, Na price) {
try {
Result<Account> accountResult = accountService.getAccount(from);
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);
}
}
// 检查to是否为合约地址,如果是合约地址,则返回错误
if (contractService.isContractAddress(to)) {
return Result.getFailed(ContractErrorCode.NON_CONTRACTUAL_TRANSACTION_NO_TRANSFER);
}
if (price == null) {
price = TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES;
}
TransactionDataResult txResult = createTransferTx(from, values, price, to, remark);
if (!txResult.isEnough()) {
return Result.getFailed(AccountLedgerErrorCode.INSUFFICIENT_BALANCE);
}
Transaction tx = txResult.getTransaction();
tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
// 生成签名
List<ECKey> signEckeys = new ArrayList<>();
List<ECKey> scriptEckeys = new ArrayList<>();
ECKey eckey = account.getEcKey(password);
// 如果最后一位为1则表示该交易包含普通签名
if ((txResult.getSignType() & 0x01) == 0x01) {
signEckeys.add(eckey);
}
// 如果倒数第二位位为1则表示该交易包含脚本签名
if ((txResult.getSignType() & 0x02) == 0x02) {
scriptEckeys.add(eckey);
}
SignatureUtil.createTransactionSignture(tx, scriptEckeys, signEckeys);
// 保存未确认交易到本地账户
Result saveResult = verifyAndSaveUnconfirmedTransaction(tx);
if (saveResult.isFailed()) {
if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
// 重新算一次交易(不超出最大交易数据大小下)的最大金额
Result rs = getMaxAmountOfOnce(from, 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;
}
// transactionService.newTx(tx);
Result sendResult = transactionService.broadcastTx(tx);
if (sendResult.isFailed()) {
this.deleteTransaction(tx);
return sendResult;
}
return Result.getSuccess().setData(tx.getHash().getDigestHex());
} catch (IOException e) {
Log.error(e);
return Result.getFailed(KernelErrorCode.IO_ERROR);
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
}
}
use of io.nuls.account.ledger.model.TransactionDataResult in project nuls by nuls-io.
the class AccountLedgerServiceImpl method createTransferTx.
public TransactionDataResult createTransferTx(byte[] address, Na amount, Na price, byte[] to, byte[] remark) {
TransactionDataResult result = new TransactionDataResult();
result.setEnough(false);
TransferTransaction tx = new TransferTransaction();
tx.setRemark(remark);
tx.setTime(TimeService.currentTimeMillis());
CoinData coinData = new CoinData();
lock.lock();
try {
int size = tx.size();
int signType = 0;
List<Coin> coinList = balanceManager.getCoinListByAddress(address);
coinList = coinList.stream().filter(coin1 -> coin1.usable() && !Na.ZERO.equals(coin1.getNa())).sorted(CoinComparator.getInstance()).collect(Collectors.toList());
if (coinList.isEmpty()) {
return result;
}
List<Coin> coins = new ArrayList<>();
Na values = Na.ZERO;
// 累加到足够支付转出额与手续费
for (int i = 0; i < coinList.size(); i++) {
Coin coin = coinList.get(i);
coins.add(coin);
size += coin.size();
if (i == 127) {
size += 1;
}
/**
* 判断是否是脚本验证UTXO
*/
signType = result.getSignType();
if (signType != 3) {
if ((signType & 0x01) == 0 && coin.getTempOwner().length == 23) {
result.setSignType((byte) (signType | 0x01));
size += P2PHKSignature.SERIALIZE_LENGTH;
} else if ((signType & 0x02) == 0 && coin.getTempOwner().length != 23) {
result.setSignType((byte) (signType | 0x02));
size += P2PHKSignature.SERIALIZE_LENGTH;
}
}
values = values.add(coin.getNa());
if (values.isGreaterOrEquals(amount)) {
result.setEnough(true);
break;
}
}
if (!result.isEnough()) {
return result;
}
// 如果为多签地址则以脚本方式存储
Coin toCoin;
if (to[2] == NulsContext.P2SH_ADDRESS_TYPE) {
Script scriptPubkey = SignatureUtil.createOutputScript(to);
toCoin = new Coin(scriptPubkey.getProgram(), values);
} else {
toCoin = new Coin(to, values);
}
coinData.getTo().add(toCoin);
// 如果金额足够,判断是否找零,以及计算手续费
if (values.isGreaterThan(amount)) {
Na change = values.subtract(amount);
Coin changeCoin = new Coin();
if (address[2] == NulsContext.P2SH_ADDRESS_TYPE) {
changeCoin.setOwner(SignatureUtil.createOutputScript(address).getProgram());
} else {
changeCoin.setOwner(address);
}
changeCoin.setNa(change);
coinData.getTo().add(changeCoin);
}
size += coinData.size();
Na fee = TransactionFeeCalculator.getFee(size, price);
toCoin.setNa(amount.subtract(fee));
coinData.setFrom(coins);
tx.setCoinData(coinData);
result.setTransaction(tx);
return result;
} finally {
lock.unlock();
}
}
Aggregations