区块链钱包之创建比特离线交易(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交易)的主要内容,如果未能解决你的问题,请参考以下文章