usdt omni离线签名
/**
* usdt 离线签名
* @param privateKey
* @param changeAddress
* @param changeAmount
* @param toAddress
* @param outputs
* @param amount
* @return
*/
public String sign(String privateKey, String changeAddress,Long changeAmount, String toAddress, List<Utxo> outputs,Long amount) {
MainNetParams network = MainNetParams.get();
Transaction tran = new Transaction(MainNetParams.get());
//这是比特币的限制最小转账金额,所以很多usdt转账会收到一笔0.00000546的btc
tran.addOutput(Coin.valueOf(546L), Address.fromBase58(network, toAddress));
//构建usdt的输出脚本 注意这里的金额是要乘10的8次方
String usdtHex = "6a146f6d6e69" + String.format("%016x", 31) + String.format("%016x", amount);
//与比特币比较只是多了这一个输出
tran.addOutput(Coin.valueOf(0L), new Script(Utils.HEX.decode(usdtHex)));
//如果有找零就添加找零
if (changeAmount.compareTo(0L) > 0) {
tran.addOutput(Coin.valueOf(changeAmount), Address.fromBase58(network, changeAddress));
}
//先添加未签名的输入,也就是utxo
for (Utxo output : outputs) {
tran.addInput(Sha256Hash.wrap(output.getTxHash()), output.getVout(), new Script(HexUtil.decodeHex(output.getScriptPubKey()))).setSequenceNumber(TransactionInput.NO_SEQUENCE - 2);
}
//下面就是签名
for (int i = 0; i < outputs.size(); i++) {
Utxo output = outputs.get(i);
ECKey ecKey = DumpedPrivateKey.fromBase58(network, privateKey).getKey();
TransactionInput transactionInput = tran.getInput(i);
Script scriptPubKey = ScriptBuilder.createOutputScript(Address.fromBase58(network, output.getAddress()));
Sha256Hash hash = tran.hashForSignature(i, scriptPubKey, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature ecSig = ecKey.sign(hash);
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
transactionInput.setScriptSig(ScriptBuilder.createInputScript(txSig, ecKey));
}
//这是签名之后的原始交易,直接去广播就行了
String signedHex = HexUtil.encodeHexStr(tran.bitcoinSerialize());
//这是交易的hash
String txHash = HexUtil.encodeHexStr(Utils.reverseBytes(Sha256Hash.hash(Sha256Hash.hash(tran.bitcoinSerialize()))));
return signedHex;
}
也可以
public void send(String address, BigInteger value, List<String> mnemonicWords, String passPhrase, String data) {
//如果需要指定交易费账户 可用获取指定账户的utxo来支付交易费 但是最小金额min必须有发送方支付
int num = checkNetStatus() ? 0 : CoinType.BTC.ordinal();
ECKey bip44Address = createBip44Address(mnemonicWords, "", num);//实现方法在上一篇
String from = bip44Address.toAddress(params).toBase58();
UsdtRpc instance = UsdtRpc.getInstance();
List<BtcUnspent> utxo = null;
try {
utxo = instance.getListUnspent(CoinConstant.MIN_COMFIRMATION, CoinConstant.MAX_COMFIRMATION, Arrays.asList(from));
} catch (Throwable throwable) {
return new WalletManagerReturnDto(throwable.getMessage(),false,20020);
}
if (utxo == null) {
return ;
}
// BigDecimal reduce = utxo.stream().map(bchListUnspent -> bchListUnspent.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
BigInteger balance = BigInteger.ZERO;
try {
OmniBalance omniBalance = instance.getOmniBalance(from, propertyid);
balance = new BigDecimal(omniBalance.getBalance()).multiply(BigDecimal.valueOf(CoinConstant.BTC_UNIT)).toBigInteger();
} catch (Throwable throwable) {
return new WalletManagerReturnDto(throwable.getMessage(),false,20020);
}
if (value.compareTo(balance) > 0) {
return new WalletManagerReturnDto("余额不足",false,20020);
}
utxo.sort(Comparator.comparing(BtcUnspent::getConfirmations).reversed());
Transaction transaction = new Transaction(params);
BigInteger select = BigInteger.ZERO;
List<BtcUnspent> spend = new ArrayList<>();
for (BtcUnspent btcUnspent : utxo) {
if (select.compareTo(min.add(mbfee)) >= 0) {
break;
} else {
select = select.add(btcUnspent.getAmount().multiply(BigDecimal.valueOf(CoinConstant.BTC_UNIT)).toBigInteger());
spend.add(btcUnspent);
}
}
if (select.compareTo(min.add(mbfee)) < 0) {
return ;
}
String usdtHex = "6a146f6d6e69" + String.format("%016x", propertyid) + String.format("%016x", value.longValue());
BigInteger change = select.subtract(min).subtract(mbfee);
transaction.addOutput(Coin.valueOf(min.longValue()), Address.fromBase58(params, address));
transaction.addOutput(Coin.valueOf(0L), new Script(HEX.decode(usdtHex)));
if (change.compareTo(BigInteger.ZERO) > 0) {
transaction.addOutput(Coin.valueOf(change.longValue()), bip44Address.toAddress(params));
}
spend.stream().forEach(btcUnspent -> {
TransactionOutPoint transactionOutPoint = new TransactionOutPoint(params, btcUnspent.getVout(), Sha256Hash.wrap(btcUnspent.getTxid()));
Script utxo_script = (new Script(HEX.decode(btcUnspent.getScriptPubKey())));
//如果输入是不同私钥 anyoneCanPay true (最后一个参数)
transaction.addSignedInput(transactionOutPoint, utxo_script, bip44Address, Transaction.SigHash.ALL, true);
});
// ECKey ecKey = DumpedPrivateKey.fromBase58(params, pk).getKey();
byte[] spendBytes = transaction.bitcoinSerialize();
String signDataStr = HEX.encode(spendBytes);
String txhash = instance.sendrawtransaction(signDataStr);
System.out.println(txhash);
if (txhash.isEmpty()){
}
依赖和比特币是一样的
参考https://blog.csdn.net/qq_38052781/article/details/85234947
网友评论