usdt omni离线签名

2019-11-16  本文已影响0人  YANG_ad29

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

https://blog.csdn.net/tjl373725/article/details/90643113

上一篇 下一篇

猜你喜欢

热点阅读