区块链钱包开发之Omni USDT Java版本离线签名

前言

大家好,我是凉凉,今天是第一次写博客,如有不足之处,请多多包涵。

从事区块链钱包方向已经快一年了,一直处于研究方向,没时间分享经验,趁着这次机会就分享一下大家比较头疼的基于Omni协议上USDT有坑的地方,以及如何离线签名。

正文

1.转usdt的关键

我们先要知道BTC和USDT之间的关系,omni协议的usdt转账就是基于btc链的,见下图

区块链钱包开发之Omni USDT Java版本离线签名_第1张图片

 如图就是一笔usdt转账,和btc转账的区别就是多了一个null_data的输出脚本

我们只要把这一部分构建好了就可以转usdt了

 

2.usdt的输出脚本的组成

6a146f6d6e69是固定的前缀,测试网络和正式网络都是一样的。

000000000000001f是31的16进制,补零补足16位

0000000000989680是金额*10^8再转16进制,补零补足16位

 

3.代码如何写

如果做过btc的离线签名,那么这一部分应该可以直接复用,加一个ouput就行了,需要引bitcoinj这个依赖,直接去仓库搜就行了

/**
 * 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 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;
}

如果有什么不明白的直接下面留言,或者加我qq:520283995

 

 

 

 

 

你可能感兴趣的:(区块链,钱包)