区块链钱包之创建比特离线交易(BTC交易)

Posted 陳英傑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链钱包之创建比特离线交易(BTC交易)相关的知识,希望对你有一定的参考价值。

(一)区块链钱包之生成助记词
(二)区块链钱包之创建钱包地址
(三)区块链钱包之加密算法简介
(四)区块链钱包之创建交易
(五)区块链钱包之创建以太坊交易(ETH交易)

首先需要导入Gradle依赖

api group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.15.10'

这里介绍在客户端如何离线创建签名交易,创建的交易结果为字符串,需要广播出去才算发起交易。


/*
 * currencyType: btc btctest
 * 转入地址
 * 支付地址
 * 转账金额和矿工费 最好都用BigDecimal
 * 拥有的UTXO
 */
public String createBtcTransaction(String currencyType, List<String> keywords, String destinationAddress, String payAddress, BigDecimal amount, BigDecimal txFee, List<UnSpentUtxo> unSpentUtxos) {
	String hex = "";
      try {
        if (!ArrayUtils.isEmpty(unSpentUtxos)) {
          NetworkParameters params = null;
          if (TextUtils.equals(currencyType, "btc")) {
            params = MainNetParams.get();
          }
          if (TextUtils.equals(currencyType, "btctest")) {
            params = TestNet3Params.get();
          }
          Transaction transaction = new Transaction(params);

          BigDecimal totalValue = BigDecimal.ZERO;

		  // 计算你的UTXO总额
          for (UnSpentUtxo unSpentUtxo : unSpentUtxos) {
            totalValue = totalValue.add(BigDecimal.valueOf(NumUtils.parseToDouble(unSpentUtxo.value)));
          }
          // 找零给自己
          BigDecimal giveChange = totalValue.subtract(amount).subtract(txFee);
          if (giveChange.compareTo(BigDecimal.ZERO) > 0) {
            Address selfAddress = Address.fromString(params, payAddress);
            transaction.addOutput(Coin.parseCoin(giveChange.toPlainString()), selfAddress);
          }
          // 转给目标地址的
          Address toAddress = Address.fromString(params, destinationAddress);
          transaction.addOutput(Coin.parseCoin(amount.toPlainString()), toAddress);
          // 注意:到此output设置完了,剩下的就是矿工费了;output必须在input之前设置。

	 	  // 把所有UTXO签名放入input中
          List<UTXO> utxos = new ArrayList<>();
          for (UnSpentUtxo unSpentUtxo : unSpentUtxos) {
            UTXO utxo = new UTXO(
              Sha256Hash.wrap(unSpentUtxo.txId),
              unSpentUtxo.outputNo,
              Coin.parseCoin(unSpentUtxo.value),
              0,
              false,
              new Script(Hex.decode(unSpentUtxo.scriptHex)),
              unSpentUtxo.address
            );
            utxos.add(utxo);
          }
          for (UTXO utxo : utxos) {
            TransactionOutPoint outPoint = new TransactionOutPoint(params, utxo.getIndex(), utxo.getHash());
            transaction.addSignedInput(outPoint, utxo.getScript(), ecKey, Transaction.SigHash.ALL, true);
          }

		  /*
		   * Context对象可不是我们android中的Contenxt,而是bitcoinj中的。
		   * 虽然这里看起来context对象好像没有被使用,但是getConfidence方法中用到了
		   * 所以不new出来会报错。
		   */
          Context context = new Context(params);
          transaction.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
          transaction.setPurpose(Transaction.Purpose.USER_PAYMENT);

          hex = new String(Hex.encode(transaction.bitcoinSerialize()));
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
   return hex;
}

public ECKey getKey(String type, List<String> keywords) {
	ECKey eckey = null;
	if(keywords != null && keywords.size() > 0) {
		// path 和创建钱包地址的时候一样,最好做一个保存。
		eckey = generateKeyByPath(keywords, path);
	}
	return eckey;
}

public DeterministicKey generateKeyByPath(List<String> keywords, String path) {
    DeterministicKeyChain chain = generateRootKey(keywords);
    return generateKeyByPath(chain, path);
}
public DeterministicKeyChain generateRootKey(List<String> keyWords) {
    DeterministicSeed seed = new DeterministicSeed(keyWords, null, "", 0);
    return DeterministicKeyChain.builder().seed(seed).build();
}

UTXO: 可以理解为一张纸币,只不过它的面值是大于0的任意数值(包括小数,最小为0.00000001),比特币的最小单位聪,1BTC = 100000000聪。
可以通过url来查看你地址下的utxo:

https://chain.so/api/v2/get_tx_unspent/钱包类型/钱包地址
比如BTCTEST的地址为:mfi34ywr84fserutgsreg85,查询url为:
https://chain.so/api/v2/get_tx_unspent/BTCTEST/mfi34ywr84fserutgsreg85

如果你没有BTCTEST的UTXO没关系,到测试网站领取:
https://coinfaucet.eu/en/btc-testnet/

UTXO格式大概是:

{
        "txid": "UTXO的hash,相当于编号",
        "output_no": 1,// 在区块中的编号
        "script_asm": "OP_DUP OP_HASH160 b6fcc6a9f87d8ec8e49688d30486bc5dab9a9c8b OP_EQUALVERIFY OP_CHECKSIG",
        "script_hex": "76a914b6fcc6a9f87d8ec8e49688d30486bc5dab9a9c8b88ac",
        "value": "0.01007293",// 面值
        "confirmations": 183,// 确认数,转账之后确认数为0,当增加到一定值交易才真正完成。
        "time": 1621417019
      }

最后生成的hex字符串,我们可以在这里decode出来看一下,应该是一个json,包含你创建的交易信息
https://live.blockcypher.com/btc/decodetx/

然后可以在这里给你的交易广播出去:
https://live.blockcypher.com/btc/pushtx/

希望我的分享能帮助到大家
在这里插入图片描述

以上是关于区块链钱包之创建比特离线交易(BTC交易)的主要内容,如果未能解决你的问题,请参考以下文章

区块链钱包之创建比特离线交易(BTC交易)

区块链钱包之创建以太坊离线交易(ETH交易)

区块链钱包之创建以太坊离线交易(ETH交易)

区块链钱包之创建以太坊离线交易(ETH交易)

区块链钱包之创建钱包地址

区块链钱包之创建钱包地址