use of io.nuls.account.model.Account in project nuls by nuls-io.
the class AccountLedgerServiceImpl method createP2shTransfer.
/**
* A transfers NULS to B 多签交易
*
* @param fromAddr 输入地址
* @param signAddr 签名地址
* @param outputs 输出地址
* @param password password of A
* @param remark remarks of transaction
* @return Result
*/
@Override
public Result createP2shTransfer(String fromAddr, String signAddr, List<MultipleAddressTransferModel> outputs, String password, String remark) {
try {
Result<Account> accountResult = accountService.getAccount(signAddr);
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);
}
}
TransferTransaction tx = new TransferTransaction();
TransactionSignature transactionSignature = new TransactionSignature();
List<Script> scripts = new ArrayList<>();
Result<MultiSigAccount> result = accountService.getMultiSigAccount(fromAddr);
MultiSigAccount multiSigAccount = result.getData();
// 验证签名账户是否属于多签账户,如果不是多签账户下的地址则提示错误
if (!AddressTool.validSignAddress(multiSigAccount.getPubKeyList(), account.getPubKey())) {
return Result.getFailed(AccountErrorCode.SIGN_ADDRESS_NOT_MATCH);
}
Script redeemScript = getRedeemScript(multiSigAccount);
if (redeemScript == null) {
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST);
}
tx.setTime(TimeService.currentTimeMillis());
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(NulsConfig.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
Log.error(e);
}
}
CoinData coinData = new CoinData();
Na values = Na.ZERO;
for (MultipleAddressTransferModel to : outputs) {
// 如果为多签地址
Coin toCoin = null;
values = values.add(Na.valueOf(to.getAmount()));
if (to.getAddress()[2] == NulsContext.P2SH_ADDRESS_TYPE) {
Script scriptPubkey = SignatureUtil.createOutputScript(to.getAddress());
toCoin = new Coin(scriptPubkey.getProgram(), Na.valueOf(to.getAmount()));
} else {
toCoin = new Coin(to.getAddress(), Na.valueOf(to.getAmount()));
}
coinData.getTo().add(toCoin);
}
// 交易签名的长度为m*单个签名长度+赎回脚本长度
int scriptSignLenth = redeemScript.getProgram().length + ((int) multiSigAccount.getM()) * 72;
CoinDataResult coinDataResult = getMutilCoinData(AddressTool.getAddress(fromAddr), values, tx.size() + coinData.size() + scriptSignLenth, TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
if (!coinDataResult.isEnough()) {
return Result.getFailed(AccountLedgerErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
if (coinDataResult.getChange() != null) {
coinData.getTo().add(coinDataResult.getChange());
}
tx.setCoinData(coinData);
tx.setHash(NulsDigestData.calcDigestData(tx.serializeForHash()));
// 将赎回脚本先存储在签名脚本中
scripts.add(redeemScript);
transactionSignature.setScripts(scripts);
return txMultiProcess(tx, transactionSignature, account, password);
} catch (IOException e) {
Log.error(e);
return Result.getFailed(KernelErrorCode.IO_ERROR);
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
} catch (Exception e) {
Log.error(e);
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST);
}
}
use of io.nuls.account.model.Account in project nuls by nuls-io.
the class AccountLegerUtils method getLocalAddresses.
public static List<byte[]> getLocalAddresses() {
List<byte[]> result = new ArrayList<>();
Collection<Account> localAccountList = accountService.getAccountList().getData();
if (localAccountList == null || localAccountList.size() == 0) {
return result;
}
List<byte[]> destAddresses = new ArrayList<>();
for (Account account : localAccountList) {
destAddresses.add(account.getAddress().getAddressBytes());
}
return destAddresses;
}
use of io.nuls.account.model.Account in project nuls by nuls-io.
the class AccountLedgerServiceImpl method dapp.
@Override
public Result dapp(byte[] from, String password, byte[] data, byte[] remark) {
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);
}
}
DataTransaction tx = new DataTransaction();
tx.setRemark(remark);
tx.setTime(TimeService.currentTimeMillis());
LogicData logicData = new LogicData(data);
tx.setTxData(logicData);
CoinData coinData = new CoinData();
try {
CoinDataResult coinDataResult = getCoinData(from, Na.ZERO, tx.size() + coinData.size(), TransactionFeeCalculator.MIN_PRICE_PRE_1024_BYTES);
if (!coinDataResult.isEnough()) {
return Result.getFailed(AccountLedgerErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
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 = verifyAndSaveUnconfirmedTransaction(tx);
if (saveResult.isFailed()) {
if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
// 重新算一次交易(不超出最大交易数据大小下)的最大金额
Result rs = getMaxAmountOfOnce(from, 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()) {
this.deleteTransaction(tx);
return sendResult;
}
return Result.getSuccess().setData(tx.getHash().getDigestHex());
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
} catch (IOException e) {
Log.error(e);
return Result.getFailed(KernelErrorCode.IO_ERROR);
}
}
use of io.nuls.account.model.Account in project nuls by nuls-io.
the class AccountLedgerServiceImpl method signMultiTransaction.
/**
* A transfers NULS to B 多签交易
*
* @param signAddr 签名地址
* @param password password of A
* @param txdata 需要签名的数据
* @return Result
*/
@Override
public Result signMultiTransaction(String signAddr, String password, String txdata) {
try {
Result<Account> accountResult = accountService.getAccount(signAddr);
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);
}
}
byte[] txByte = Hex.decode(txdata);
Transaction tx = TransactionManager.getInstance(new NulsByteBuffer(txByte));
TransactionSignature transactionSignature = new TransactionSignature();
transactionSignature.parse(new NulsByteBuffer(tx.getTransactionSignature()));
// 验证签名地址账户是否属于多签账户
List<byte[]> pubkeys = SignatureUtil.getPublicKeyList(transactionSignature.getScripts().get(0));
if (pubkeys == null || pubkeys.size() == 0 || !AddressTool.validSignAddress(pubkeys, account.getPubKey())) {
return Result.getFailed(AccountErrorCode.SIGN_ADDRESS_NOT_MATCH);
}
return txMultiProcess(tx, transactionSignature, account, password);
} catch (NulsException e) {
Log.error(e);
return Result.getFailed(e.getErrorCode());
} catch (Exception e) {
Log.error(e);
return Result.getFailed(AccountErrorCode.ACCOUNT_NOT_EXIST);
}
}
use of io.nuls.account.model.Account in project nuls by nuls-io.
the class AccountLedgerServiceImpl method changeWhole.
@Override
public Result changeWhole(byte[] address, String password, Na price) {
try {
Result<Account> accountResult = accountService.getAccount(address);
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(address)) {
return Result.getFailed(ContractErrorCode.NON_CONTRACTUAL_TRANSACTION_NO_TRANSFER);
}
TransferTransaction tx = null;
boolean flag = true;
while (flag) {
tx = getChangeWholeTxInfoList(address, account, password, price);
// 保存未确认交易到本地账户
if (null != tx) {
Result saveResult = verifyAndSaveUnconfirmedTransaction(tx);
if (saveResult.isFailed()) {
if (KernelErrorCode.DATA_SIZE_ERROR.getCode().equals(saveResult.getErrorCode().getCode())) {
// 重新算一次交易(不超出最大交易数据大小下)的最大金额
Result rs = getMaxAmountOfOnce(address, 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;
}
Result sendResult = transactionService.broadcastTx(tx);
if (sendResult.isFailed()) {
this.deleteTransaction(tx);
return sendResult;
}
// 可用总额
Result available = getAvailableTotalUTXO(address);
Map<String, Object> map = (Map<String, Object>) available.getData();
int size = (int) map.get("size");
if (size < AccountConstant.MIM_COUNT) {
// 小于20就停止
flag = false;
}
} else {
flag = false;
}
}
return Result.getSuccess().setData(tx.getHash().getDigestHex());
} catch (Exception e) {
Log.error(e);
Log.error("零钱换整错误");
return Result.getFailed();
}
}
Aggregations