Get started with the Bitcoin Testnet 比特幣開發
在初學使用比特幣時,建議先使用Testnet開發,這樣在不冒險失去或花費比特幣風險的情況下嘗試了。這是我所做工作的教程式提要,內容包括:
- 選擇一個JS比特幣庫。
- 創建比特幣私鑰/公鑰對。
- 免費在Testnet上獲取比特幣。
- 通過第三方API從Testnet區塊鏈讀取數據。
5.構建有效的事務,包括OP_RETURN事務。
6.將這些事務推送到第三方API,以傳輸到Testnet網絡。
Setup
在示例中,我將使用帶有現代JavaScript的Node,因此您需要安裝Node的最新版本。我正在使用
node v10.16.0
npm v6.9.0
建立一個資料
mkdir bitcointestnet
npm init
選擇一個JS比特幣庫
我之所以選擇bitcoinjs-lib是因為以下原因:
- 它仍處於活動狀態(在撰寫本文時,是2天前的最新提交)。
- 它有大量的貢獻者和發行者。
- 主要貢獻者dcousens也為Bitcoin Core貢獻了很多。
- 就功能而言,它非常全面,除了地址外還包括支付腳本。
- 有許多範例與有人解決回答問題 (最重要的點)
bitcore-lib看起來是另一個非常相似的選項,但是1.範例不全面 2.它是Bitpay維護的
安裝最新版本的最簡單方法是使用yarn或npm:
yarn add bitcoinjs-lib
# or
npm install bitcoinjs-lib
我寫這篇時用 v 5.1.7 版本
創建比特幣私鑰/公鑰對
為了對比特幣做任何事情,您需要一個私鑰/公鑰對。他人可以使用公鑰向您發送比特幣,而您可以通過驗證創建交易的人是您使用私鑰將比特幣發送給其他人。
我們可以這樣做:
const bitcoin = require('bitcoinjs-lib')
const { testnet } = bitcoin.networks
const myKeyPair = bitcoin.ECPair.makeRandom({ network: testnet })
是“橢圓曲線”,“ ECPair”中的“ EC”代表“橢圓曲線”,也就是比特幣安全的基礎數學。
myKeyPair具有使用這些密鑰進行簽名交易的方法,我們利用myKeyPair產生私鑰、公鑰與地址。請嘗試以下操作:
const myWIF = myKeyPair.toWIF() // eg 'cUQv17kNEpY3j6x1x9tSS1QDUHH94gYzEYLcUpVSSRqb1subMW6x'const myPublicKey = myKeyPair.publicKey.toString('hex'); //eg '02f12b93c7347c33c1fa83f076a269d060c8bffe0d5a69d254fcab39bd8a32529c'const myAddress = bitcoin.payments.p2pkh({ pubkey: myKeyPair.publicKey, network: testnet });// eg 'mrTebkFmXCdvejQXFwA78xgBeJCH6uKrEm'
myWIF是您的電子錢包導入格式(WIF)的私鑰,其中還包含有關它是主網絡還是Testnet的信息,以及以base58編碼形式用於防止輸入錯誤的校驗和。 (base58由數字以及大寫和小寫字母組成,O,0,l和I除外,它們很容易彼此混淆。)您可以使用myWIF將錢包導入許多GUI錢包提供程序,例如Blockchain.info。其他任何人也可以,所以如果您以後使用真正的比特幣進行此操作,請保持myWIF的秘密。
myAddress的編碼類似,只是您可以將它提供給想要向您發送比特幣的人,這裡要注意的是測試鏈與正式鏈的地址是不同的。
testnet address : mrTebkFmXCdvejQXFwA78xgBeJCH6uKrEm
main address : 1EeHuYstLN7E6WvKVSvwRBRMUXTDEgPafp
獲得免費的Testnet bitcoin硬幣
現在您有了地址,是時候獲取一些免費的Testnet比特幣了。如果人們開始用真實貨幣進行交易,則重置網絡的威脅會故意使Testnet上的比特幣無價值,並且有很多地方免費發放硬幣,因此您可以測試自己的比特幣應用程序而不會冒實際風險。
我發現最好的水龍頭是https://testnet.manu.backend.hamburg/faucet,它將在一次付款中為您提供比特幣-足夠玩。現在您有了地址,只需在此處的表格中輸入以獲得硬幣即可。幾分鐘後,您應該會看到您的交易得到了一些確認,這實際上意味著網絡現在識別出您擁有那些比特幣。

恭喜,您現在是一些毫無價值的加密貨幣的驕傲擁有者!順便說一句,將您的Testnet硬幣用完後,將它們退還給水龍頭被認為是禮貌的,以便其他人可以使用它們。
從Testnet區塊鏈讀取數據
就像主要的比特幣區塊鏈一樣,Testnet區塊鍊是完全公開的。因此,您可以選擇自己喜歡的區塊瀏覽器,甚至運行自己的節點並自己進行探索。在這裡,我們將使用smartbit,因為它們具有可靠的API,非常好的文檔站點,並且您不需要API密鑰。
文檔站點在這裡。展開“地址”部分,單擊“參數”,然後在“地址ID”字段中輸入您的地址。單擊“獲取”,您應該看到有關您的地址的各種信息,尤其是有關剛從水龍頭髮送的比特幣的信息。 (如果沒有任何顯示,則可能需要等待幾分鐘才能檢測到該事務。)
現在,在Node中進行操作。我將axios用於一些友好的Promises。
yarn add axios
# or
npm install axios
我安裝v 0.19.2版本
這是使用其API的同一smartbit查詢:
const axios = require('axios');
const myAddress = 'mjJ5gQ89ZryZ5wrJQp3ELTu5V7KNX8s3uu';
const urlForMyAddress = `https://testnet-api.smartbit.com.au/v1/blockchain/address/${myAddress}`
axios
.get(urlForMyAddress)
.then(response => console.log(response.data))

或者,如果我們僅對地址的未完成交易感興趣:
const myAddress = 'mjJ5gQ89ZryZ5wrJQp3ELTu5V7KNX8s3uu';
const urlForMyAddress = `https://testnet-api.smartbit.com.au/v1/blockchain/address/${myAddress}`
const urlForMyUnspentTransactions = `${urlForMyAddress}/unspent`
axios
.get(urlForMyUnspentTransactions)
.then(response => console.log(response.data))

建立有效的交易
好,讓我們花一些比特幣。這是我們需要做的:
- 確定我們要發送比特幣的地址。
- 確定發送多少錢到那個地址。
- 為將交易包括在區塊中的礦工計算適當的費用。
- 查找一筆交易,該交易的輸出未使用到我們的地址,以用作我們交易的輸入。
- 簽署交易輸入。
- 將輸出添加到我們的交易中,以便接收者獲得我們想要給他們的比特幣。
- 將輸出添加回我們自己的地址以進行更改。
如果您還沒有地方可以發送比特幣,請創建第二個密鑰對以將硬幣發送到,並指定一個金額以satoshis進行發送:
const receiver = bitcoin.ECPair.makeRandom({ network: testnet })
const amountToSend = 5000000 // 0.05 BTC
該費用很重要,因為如果您將其設置得太低,那麼您的交易對礦工就不會有吸引力,並且可能需要很長時間才能出現在區塊鏈中,甚至可能永遠不會被接受。在沒有這麼多流量的Testnet上,這不是問題,但對比特幣主網絡來說卻是一個大問題。
const getRecommendedFee = () => {
const url = 'https://bitcoinfees.earn.com/api/v1/fees/recommended'
const medianTransactionSize = 226 // bytes
return axios
.get(url)
.then(response => response.data.fastestFee * medianTransactionSize)
}

現在,我們擁有開始構建交易所需的一切。
const buildTransaction = (keyPair, receiverAddress, amount) =>
Promise.all([
getUnspentTransactionsForAddress(keyPair.getAddress()),
getRecommendedFee(),
])
.then(([unspentTransactions, recommendedFee]) => {
const unspent = unspentTransactions[0]
const totalCost = amount + recommendedFee
const change = unspent.value_int - totalCost
const tx = new bitcoin.TransactionBuilder(testnet)
tx.addInput(unspent.txid, unspent.n)
tx.sign(0, keyPair)
tx.addOutput(receiverAddress, amount)
tx.addOutput(keyPair.getAddress(), change)
return tx.build()
})
我們得到一個地址未使用的交易清單。我們選擇第一個交易(例如水龍頭中的交易)。我們還通過API獲得建議的交易費用。
然後,我們開始建立交易。我們使用其交易ID和unspent.n將未用完的輸出添加為輸入,這將指定我們正在使用的該交易中的哪個輸出(請記住,事務可以有多個輸出)。然後,我們使用密鑰對對輸入進行簽名(0指定我們正在對哪個輸入進行簽名,即第一個)。
然後,我們添加將所需金額發送到接收方地址的輸出,然後將更改返回到我們自己的地址。我們通過從未用金額中減去我們要發送的金額和我們要支付的費用,計算出有多少更改。
重要信息:我們需要將更改發送回我們的地址,因為輸出中未指定的任何金額都將被用作採礦費。忘記這一步可能會非常昂貴!
最後,我們建立交易並將其返回。
建立OP_RETURN交易
從一個錢包向另一個錢包匯款只是區塊鏈實現的功能之一。另一種是將數據存儲在不可變的數據庫中。這可以通過OP_RETURN來實現,該OP_RETURN產生不可用的輸出以及最多80個字節的消息。
我們需要一個稍微不同的功能:
const buildOpReturnTransaction = (keyPair, message) =>
Promise.all([
getUnspentTransactionsForAddress(keyPair.getAddress()),
getRecommendedFee(),
])
.then(([unspentTransactions, recommendedFee]) => {
const unspent = unspentTransactions[0]
const change = unspent.value_int - recommendedFee
const dataToStore = Buffer.from(message)
const opReturnScript = bitcoin.script.nullData.output.encode(dataToStore)
const tx = new bitcoin.TransactionBuilder(testnet)
tx.addInput(unspent.txid, unspent.n)
tx.sign(0, keyPair)
tx.addOutput(opReturnScript, 0)
tx.addOutput(keyPair.getAddress(), change)
return tx.build()
})
就像在我們收到未使用的交易和建議的費用之前一樣。我們將消息轉換為緩衝區(以防緩衝區還沒有緩衝區),並創建一個OP_RETURN腳本,將其用作輸出之一,發送0個satoshis。我們會將所有未使用的金額(減去費用)寄回我們自己的地址。和之前一樣,我們構建事務並將其返回。
重要提示:如果您將任何硬幣發送到OP_RETURN腳本,它們將永遠消失。收費有誤,一個好的礦工可能(但可能不會!)決定將硬幣退還給您。使用OP_RETURN犯錯誤,即使他們願意,也沒有人可以找回他們。
將交易發佈到比特幣網路
好的,我們可以建立交易。但是現在,我們是唯一了解它們的人。我們必須以某種方式使它們進入網絡,以便礦工可以將它們包含在一個塊中。
const pushTransaction = transaction => {
const url = 'https://testnet-api.smartbit.com.au/v1/blockchain/pushtx'
const params = { hex: transaction.toHex() }
return axios.post(url, params)
}
簡單!您也可以將請求發佈到/ decodetx而不是/ pushtx,以便在廣播之前仔細檢查交易外觀是否符合您的期望。
這是使用我們的函數創建OP_RETURN交易的示例:
const importantMessage = 'For good luck, I like my rhymes atrocious\nSupercalafragilisticexpialidocious'
buildTransaction(myKeyPair, importantMessage)
.then(pushTransaction)
.then(response => console.log(response.data))
在瀏覽器的Testnet區塊鏈資源管理器中進行檢查-僅搜索您的地址,您應該在公共區塊鏈上看到OP_RETURN輸出和消息(一旦交易包含在區塊中)。
您還可以稍後使用smartbit的/ address / $ {myAddress} / op_returns端點將這些消息從區塊鏈中移出。
結論
似乎很難開始使用比特幣進行開發,因為(a)許多比特幣代碼都是用C ++等低級語言編寫的;(b)運行一個完整的節點需要大量的設置和系統資源,並且( c)比特幣很有價值,因此錯誤可能會非常昂貴。希望這篇文章表明您可以真正輕鬆地開始使用JavaScript,第三方API和Testnet。