BitcoinJS-lib比特币开发简明教程【JavaScript】

在这个教程中,我们将学习如何使用Bitconjs-lib开发库来 开发一个简单的JavaScript版本的比特币应用。我们要实现的 特性包括:离线创建比特币私钥和地址、进行账户充值、离线构造 转账裸交易并广播到比特币网络中等。

Node.js区块链开发相关教程推荐:

1、安装BitcoinJS-lib

BitcoinJS-lib是一个npm包,可以用于node.js或浏览器javascript环境中。 可以使用npm或yarn安装BitcoinJS-lib开发包:

1
npm install bitcoinjs-lib

2、引入BitcoinJS-lib

首先引入bitcoinjs-lib开发库:

1
const Btc = require('bitcoinjs-lib')

比特币的主链和测试链有不同的网络参数,出于简化和安全性考虑, 我们使用测试链来开发这个教程中的应用,因此引入测试链网络参数:

1
const TestNet = Btc.networks.testnet

3、用BitcoinJS创建比特币地址

每个比特币地址都对应一对密钥(私钥和公钥),因此我们首先 用BitcoinJS创建密钥对并从密钥对推导出地址:

1
2
3
4
let keyPair = Btc.ECPair.makeRandom({ network: TestNet })
let address = keyPair.getAddress()
let wifKey = keyPair.toWIF()
console.log(`Address: ${address} \n WifKey: ${wifKey}`)

在上边的代码中,我们首先使用BitcoinJS的ECPair类的静态方法makeRandom() 生成一个随机密钥对,然后使用密钥对的getAddress()方法推导出 对应的比特币地址,并使用toWif()获取WIF格式的私钥,最后显示 出得到的地址和WIF格式的私钥。

代码运行结果如下(你的结果应该与此不同):

1
2
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
WifKey: cTEAh2DsC7KE4mzY5YFTYommzr7czbdiBfLPsXZrF6o3zSQLLw9Q

4、用BitcoinJS导入WIF私钥

如果你有其他钱包到处的WIF格式的私钥,也可以导入BitcoinJS并 推导出对应的地址,例如:

1
2
3
let wifKey = 'cTEAh2DsC7KE4mzY5YFTYommzr7czbdiBfLPsXZrF6o3zSQLLw9Q'
let keyPair = new Btc.ECPair.fromWIF(privKey, TestNet)
console.log("Address:", keyPair.getAddress())

结果类似如下:

1
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1

5、使用密码辅助记忆私钥

要记住私钥有点麻烦,我们可以用密码来辅助推导私钥,这样就可以 进一步推导出公钥和地址。下面的代码使用BitcoinJS和nodejs大数计算 库bigi实现:

1
2
3
4
5
6
7
8
9
10
11
const BigInteger = require('bigi')
let passphrase = 'J@vaScr1pt'
let keyPair = generateAddressFromSHA256Hash(passphrase);
console.log('Address: ', keyPair.getAddress())

function generateAddressFromSHA256Hash(passphrase) {
let hash = Btc.crypto.sha256(passphrase);
let d = BigInteger.fromBuffer(hash);
let keyPair = new Btc.ECPair(d, null, { network: TestNet });
return keyPair;
}

结果如下:

1
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1

现在使用generateAddressFromSHA256Hash()函数,我们就可以 在任何时候用J@VaSc1pt这个密码来会付出地址mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1 以及其对应的密钥对了。

6、使用测试链Faucet为账户充值

在继续之前,我们需要为创建的比特币地址充点比特币。在网上有 一些比特币测试链的Faucet,可以用来为任意指定的比特币地址充入 一些比特币以便进行开发和测试。我使用的是这个, 当然你可以搜索出更多的这种Faucet。

让Faucet给我们的测试地址充值结果如下:

cool,现在我们有了1.3个比特币可以继续测试了!

7、查询比特币地址详情

有两种办法查询一个比特币地址的余额、UTXO等信息:使用自己的节点,或者使用 第三方API。出于简化考虑,在本教程中我们使用第三方API来查询指定 比特币地址的余额与UTXO:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
onst request = require('request');
let addr = 'mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1'
let apiUrl = 'https://testnet.blockexplorer.com/api/addr/'

// log unspent transactions
request.get(apiUrl + addr + '/utxo', (err, req, body) => {
console.log('utxo => ', JSON.parse(body))
}
);
// log balance
request.get(apiUrl + addr + '/balance', (err, req, body) => {
console.log('balance => ', JSON.parse(body))
}
);

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
utxo => [{
address: 'mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1',
txid: '2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b',
vout: 0,
scriptPubKey: '76a9146d622b371423d2e450c19d98059867d71e6aa87c88ac',
amount: 1.3,
satoshis: 130000000,
height: 1180957,
confirmations: 14
}]

balance => 130000000 // 1.3 BTC = 130000000 satoshis

8、用BitcoinJS构造比特币转账裸交易

构造比特币裸交易要复杂一点,我们需要自己组织交易的输入和输出。

首先用BitcoinJS的交易构造器TransactionBuider创建一个交易对象:

1
let tx = new Btc.TransactionBuilder(TestNet)

然后我们声明转出账号和转入账号:

1
2
let keyPair1 = generateAddressFromSHA256Hash('J@vaScr1pt')
let keyPair2 = generateAddressFromSHA256Hash('B*tc0in')

然后声明转账金额、手续费等参数,并计算找零金额:

1
2
3
4
let amountWeHave = 130000000 // 1.3 BTC
let amountToKeep = 100000000 // 1 BTC
let transactionFee = 1000 // .00001 BTC
let amountToSend = amountWeHave - amountToKeep - transactionFee

好了,现在可以为交易添加输入了。还记得前面我们查询出来的交易输出吗? 这个交易输出我们将用作新交易的输入:

1
2
3
4
5
[{
txid: '2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b',
vout: 0,
satoshis: 130000000,
}]

使用BitcoinJS交易对象的addInput()方法添加交易输入:

1
tx.addInput('2d742aa8409...', 0)

接下来添加交易输出,我们需要声明交易输出目标地址和金额:

1
tx.addOutput(keyPair2.getAddress(), amountToSend)

由于交易输入金额大于上述交易输出金额,因此我们还需要添加 找零输出:

1
tx.addOutput(keyPair1.getAddress(), amountToKeep)

现在我们进行签名,由于用的是keyPair1的比特币,因此需要 使用keyPair1的私钥进行签名:

1
tx.sign(0, keyPair1)

接下来把签名交易序列化为16进制码流,以便广播到比特币网络中:

1
let tx_hex = tx.build().toHex()

完整的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
let tx = new Btc.TransactionBuilder(TestNet)
let keyPair1 = generateAddressFromSHA256Hash('J@vaScr1pt')
let keyPair2 = generateAddressFromSHA256Hash('B*tc0in')
let amountWeHave = 130000000 // 1.3 BTC
let amountToKeep = 100000000 // 1 BTC
let transactionFee = 1000 // .00001 BTC
let amountToSend = amountWeHave - amountToKeep - transactionFee
tx.addInput('2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b', 0)
tx.addOutput(keyPair2.getAddress(), amountToSend)
tx.addOutput(keyPair1.getAddress(), amountToKeep)
tx.sign(0, keyPair1)
let tx_hex = tx.build().toHex()console.log('our beautiful transaction: ', tx_hex)

输出结果如下:

1
2
3
4
5
6
7
01000000019b4cf9ed6a4cc0c93523cafbfa78b447de6eac9af5b2fc8acde49e40
a82a742d000000006b483045022100b8e1bc891bbd910960cf00b52b87493ddf80
8c0b6816b05724b62c507c2ea552022071d775d9b89e0bbc1c2d1b907b700dbda5
8d880508ba7f6e11a3acc659d3ebe20121034ec9060d1935b235794e22f5335b4e
5c55e764ba9bddab2cf7f199dac7309ce1ffffffff0298bfc901000000001976a9
1423e6e135110f5fcacbd77323382bb70e4f76105f88ac00e1f505000000001976
a9146d622b371423d2e450c19d98059867d71e6aa87c88ac00000000

9、解码裸交易

在广播裸交易之前,检查一下裸交易的内容是一种有效的调试方法。 我们可以使用BlockCypher提供的解码工具 来查看裸交易的内容,结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{
"addresses": [
"mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1",
"minnXa8Qarg5WbxPQg3vjLZdpbZGHavCzC"
],
"block_height": -1,
"block_index": -1,
"confirmations": 0,
"double_spend": false,
"fees": 1000,
"hash": "64697ab2a3c76b8c5930ca128316238bba5b172b2f8f61a0046b6630b1f80f08",
"inputs": [
{
"addresses": [
"mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1"
],
"age": 1180957,
"output_index": 0,
"output_value": 130000000,
"prev_hash": "2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b",
"script": "483045022100b8e1bc891bbd910960cf00b52b87493ddf808c0b6816b05724b62c507c2ea552022071d775d9b89e0bbc1c2d1b907b700dbda58d880508ba7f6e11a3acc659d3ebe20121034ec9060d1935b235794e22f5335b4e5c55e764ba9bddab2cf7f199dac7309ce1",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
}
],
"outputs": [
{
"addresses": [
"minnXa8Qarg5WbxPQg3vjLZdpbZGHavCzC"
],
"script": "76a91423e6e135110f5fcacbd77323382bb70e4f76105f88ac",
"script_type": "pay-to-pubkey-hash",
"value": 29999000
},
{
"addresses": [
"mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1"
],
"script": "76a9146d622b371423d2e450c19d98059867d71e6aa87c88ac",
"script_type": "pay-to-pubkey-hash",
"value": 100000000
}
],
"preference": "low",
"received": "2017-09-04T05:24:14.417939071Z",
"relayed_by": "54.158.194.253",
"size": 226,
"total": 129999000,
"ver": 1,
"vin_sz": 1,
"vout_sz": 2
}

10、广播比特币裸交易

一旦生成比特币裸交易,可以在网上找到很多提供广播比特币裸交易的服务。 如果你希望在代码中进行广播,也可以使用这个API

广播完成后,你可以在区块浏览器中查看交易确认情况:

DONE.


原文链接:Crafting a Blockchain Transaction with JavaScript

汇智网翻译整理,转载请标明出处