您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)如何使用Golang將誓言存在比特幣的區(qū)塊鏈上,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
大家先看一個(gè)區(qū)域鏈瀏覽器的交易鏈接:
https://www.blocktrail.com/tBCC/tx/a63edbbfa17e45b0890520ca30fce6d8eacd41635d1c447418fcfedffa14d914 打開(kāi)這個(gè)鏈接, 滑到最后, 會(huì)看如圖所示的文字
這是怎么做到的? 這是一個(gè)比特幣的交易, 怎么能附上中文呢? 本文就一步步教 你怎么在比特幣交易上添加文字. 因?yàn)楸忍貛诺慕灰拙哂胁豢纱鄹男? 且永久存在區(qū)域鏈上, 那么其附帶的文字就有這個(gè)屬性, 這就好像是一個(gè)誓言! 誓言記存, 多有意義!!
比特幣交易是需要手續(xù)費(fèi)的, 而當(dāng)前的手續(xù)費(fèi)并不便宜, 動(dòng)則至少上百元, 這太貴了. 所以我推薦大家先去比特幣測(cè)試網(wǎng)絡(luò)先弄一些幣來(lái)測(cè)試. 怎么在獲取比特幣測(cè)試網(wǎng)絡(luò)的免費(fèi)比特幣, 大家可以Google下, 有一些網(wǎng)站會(huì)免費(fèi)送. 比如大家可以去 https://testnet.coinfaucet.eu/en/ 這個(gè)站點(diǎn)去獲取, 當(dāng)前獲取的前提是你有一個(gè)測(cè)試網(wǎng)絡(luò)的比特幣地址, 不然不知道給誰(shuí)發(fā)幣啊. 下面教你怎么用Golang 生成比特幣測(cè)試地址:
https://github.com/btcsuite/btcd 是bitcoin的golang版實(shí)現(xiàn), 先按照它的文檔安裝, 這里假設(shè)你已經(jīng)成功安裝在本地了.
下面這段代碼包含生成測(cè)試和正式地址, 你可以運(yùn)行得到測(cè)試地址.
package main import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcd/chaincfg" "fmt" ) func GenerateBTC() (string, string, error) { privKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return "", "", err } privKeyWif, err := btcutil.NewWIF(privKey, &chaincfg.MainNetParams, false) if err != nil { return "", "", err } pubKeySerial := privKey.PubKey().SerializeUncompressed() pubKeyAddress, err := btcutil.NewAddressPubKey(pubKeySerial, &chaincfg.MainNetParams) if err != nil { return "", "", err } return privKeyWif.String(), pubKeyAddress.EncodeAddress(), nil } func GenerateBTCTest() (string, string, error) { privKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return "", "", err } privKeyWif, err := btcutil.NewWIF(privKey, &chaincfg.TestNet3Params, false) if err != nil { return "", "", err } pubKeySerial := privKey.PubKey().SerializeUncompressed() pubKeyAddress, err := btcutil.NewAddressPubKey(pubKeySerial, &chaincfg.TestNet3Params) if err != nil { return "", "", err } return privKeyWif.String(), pubKeyAddress.EncodeAddress(), nil } func main() { wifKey, address, _ := GenerateBTCTest() // 測(cè)試地址 // wifKey, address, _ := GenerateBTC() // 正式地址 fmt.Println(address, wifKey) }
假設(shè)你得到了一個(gè)測(cè)試地址:
地址: mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd
私鑰: cV4HmdzGF3gG7NdEtVV7sjq22yoBmZBe5MEGKUqvQTXXXXX(注意,該密鑰不是正確的,請(qǐng)不要使用)
然后, 你去https://testnet.coinfaucet.eu/en/ 領(lǐng)免費(fèi)的測(cè)試比特幣, 可以通過(guò)接口查看該地址的未花費(fèi)交易信息:
https://api.blockcypher.com/v1/btc/test3/addrs/mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd/full
總共發(fā)了兩筆, 第一筆 0.65 第二筆 1.3 總共這個(gè)地址的余額是 1.95
{ "address": "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd", "total_received": 195000000, "total_sent": 0, "balance": 195000000, "unconfirmed_balance": 0, "final_balance": 195000000, "n_tx": 2, "unconfirmed_n_tx": 0, "final_n_tx": 2, "txs": [ // 第二筆 { "block_hash": "00000000000004149feebc41cfeb5a66df052f989aec60faec711caee4f93b3c", "block_height": 1255326, "block_index": 53, "hash": "2c56134c99b24e17f5c3852d910e2e090848652c4e7b08ee8aa7450b2e14d7c4", "addresses": [ "2N48GnaEkd8eZgQ5MLTb6EGBvqfuQ94sVTv", "2NAwfhDByKfV5ZPr4cnLVg9hMHcx31CZbEp", "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd" ], "total": 197064067190, "fees": 100000, "size": 140, "preference": "high", "relayed_by": "94.130.106.254:18333", "confirmed": "2017-12-19T02:32:36Z", "received": "2017-12-19T02:17:26.601Z", "ver": 1, "double_spend": false, "vin_sz": 1, "vout_sz": 2, "confirmations": 5672, "confidence": 1, "inputs": [ { "prev_hash": "7265ffdf8310fc2ecd6277759f39de9c801149ca602c6b2236667d2af2d5dd29", "output_index": 1, "script": "1600149eb46621cceac0e393b5cd5ffb481fafa48a16fc", "output_value": 197064167190, "sequence": 4294967295, "addresses": [ "2NAwfhDByKfV5ZPr4cnLVg9hMHcx31CZbEp" ], "script_type": "pay-to-script-hash", "age": 1255313, "witness": [ "3044022034bb850d1efab224a14b7cd7565a9fce58fb89794f50471419115f1b893f626d022027a849a46f3a902944e3f01a66eb0fc489bfe8e5a7815b8644128b7e6f89ace101", "030916ad60b499268f909e20867b49d22e55b3864aafc896120c6daec1011ceecb" ] } ], "outputs": [ { "value": 130000000, "script": "76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac", "addresses": [ "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd" ], "script_type": "pay-to-pubkey-hash" }, { "value": 196934067190, "script": "a9147758cec0a445f9908186f5cfeeb52bc0077c7e1487", "spent_by": "5c3c00896db0ba1a7526c6e8c3495c29264df99d4a494afbd909af4f0d4df605", "addresses": [ "2N48GnaEkd8eZgQ5MLTb6EGBvqfuQ94sVTv" ], "script_type": "pay-to-script-hash" } ] }, // 第一筆 { "block_hash": "00000000000004149feebc41cfeb5a66df052f989aec60faec711caee4f93b3c", "block_height": 1255326, "block_index": 40, "hash": "48eea09764713f3dadcfed29490ab5e288299e01e571e1f7a1396a75ce38e067", "addresses": [ "2N4Mrw2XRMEfAuf51JiZsaQCSxr9UowxSbJ", "2N5CNRLZXXZt2JFxPLX9z6HF9gdgLqG3ycH", "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd" ], "total": 196092936523, "fees": 100000, "size": 140, "preference": "high", "relayed_by": "88.196.208.18:18333", "confirmed": "2017-12-19T02:32:36Z", "received": "2017-12-19T02:17:33.267Z", "ver": 1, "double_spend": false, "vin_sz": 1, "vout_sz": 2, "confirmations": 5672, "confidence": 1, "inputs": [ { "prev_hash": "2880f6c768afa728fa9374af0617d535a960243f2820de53992279a59b84d8a3", "output_index": 1, "script": "1600147ce118c5a9faa2fdf5bc1c7feb41ddac7084a481", "output_value": 196093036523, "sequence": 4294967295, "addresses": [ "2N5CNRLZXXZt2JFxPLX9z6HF9gdgLqG3ycH" ], "script_type": "pay-to-script-hash", "age": 1255313, "witness": [ "30440220741aa14828e97e0fd9668b9070e2ab886f3646456c33b143c291f6c47e1ec985022005f624843908a745dbc5d703361065a5fbca9aa0b1fb4aca105cd09d8e6fd09e01", "02fe3a6a5cfb075b84d5a0e6daa2220dc49c8a36b61f49f86111dd08141166b7fc" ] } ], // 以下幾個(gè)值比較重要 "outputs": [ { "value": 65000000, "script": "76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac", "addresses": [ "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd" ], "script_type": "pay-to-pubkey-hash" }, { "value": 196027936523, "script": "a91479eab7f3bf5054cc47da2761f0b61d6cb622622a87", "spent_by": "dc32b80ba7f863572c8dd97508d8c7a04af35d10671c9ca3c60f0d28c552c8d1", "addresses": [ "2N4Mrw2XRMEfAuf51JiZsaQCSxr9UowxSbJ" ], "script_type": "pay-to-script-hash" } ] } ] }
記住第一筆的這幾個(gè)值:
tx_hash 48eea09764713f3dadcfed29490ab5e288299e01e571e1f7a1396a75ce38e067
tx_output_n 0
script: 76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac
value 65000000
我們接下來(lái)會(huì)用到這個(gè)未花費(fèi)交易
下面構(gòu)造一個(gè)交易, 這個(gè)交易給自己發(fā)一筆錢(qián), 交易費(fèi)是0.001
address := "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd" var balance int64 = 65000000 // 余額 var fee int64 = 0.001 * 1e8 // 交易費(fèi) var leftToMe = balance - fee // 余額-交易費(fèi)就是剩下再給我的 // 1. 構(gòu)造輸出 outputs := []*wire.TxOut{} // 1.1 輸出1, 給自己轉(zhuǎn)剩下的錢(qián) addr, _ := btcutil.DecodeAddress(address, &chaincfg.SimNetParams) pkScript, _ := txscript.PayToAddrScript(addr) outputs = append(outputs, wire.NewTxOut(leftToMe, pkScript)) // 1.2 輸出2, 添加文字 comment := "這是一個(gè)留言, 哈哈" pkScript, _ = txscript.NullDataScript([]byte(comment)) outputs = append(outputs, wire.NewTxOut(int64(0), pkScript))
// 2. 構(gòu)造輸入 prevTxHash := "48eea09764713f3dadcfed29490ab5e288299e01e571e1f7a1396a75ce38e067" prevPkScriptHex := "76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac" prevTxOutputN := uint32(0) hash, _ := chainhash.NewHashFromStr(prevTxHash) // tx hash outPoint := wire.NewOutPoint(hash, prevTxOutputN) // 第幾個(gè)輸出 txIn := wire.NewTxIn(outPoint, nil, nil) inputs := []*wire.TxIn{txIn} prevPkScript, _ := hex.DecodeString(prevPkScriptHex) prevPkScripts := make([][]byte, 1) prevPkScripts[0] = prevPkScript tx := &wire.MsgTx{ Version: wire.TxVersion, TxIn: inputs, TxOut: outputs, LockTime: 0, }
// 3. 簽名 privKey := "cV4HmdzGF3gG7NdEtVV7sjq22yoBmZBe5MEGKUqvQTXXXXX" // 私鑰 sign(tx, privKey, prevPkScripts) // 簽名方法 func sign(tx *wire.MsgTx, privKeyStr string, prevPkScripts [][]byte) { inputs := tx.TxIn wif, err := btcutil.DecodeWIF(privKeyStr) fmt.Println("wif err", err) privKey := wif.PrivKey for i := range inputs { pkScript := prevPkScripts[i] var script []byte script, err = txscript.SignatureScript(tx, i, pkScript, txscript.SigHashAll, privKey, false) inputs[i].SignatureScript = script } }
// 4. 輸出Hex buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) if err := tx.Serialize(buf); err != nil { } txHex := hex.EncodeToString(buf.Bytes()) fmt.Println("hex", txHex)
將輸出的hex廣播到網(wǎng)絡(luò)上, https://tbtc.blockdozer.com/insight/tx/send
下面給出完整源碼:
package tx import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/chaincfg/chainhash" "encoding/hex" "fmt" "bytes" ) func main() { address := "mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd" var balance int64 = 65000000 // 余額 var fee int64 = 0.001 * 1e8 // 交易費(fèi) var leftToMe = balance - fee // 余額-交易費(fèi)就是剩下再給我的 // 1. 構(gòu)造輸出 outputs := []*wire.TxOut{} // 1.1 輸出1, 給自己轉(zhuǎn)剩下的錢(qián) addr, _ := btcutil.DecodeAddress(address, &chaincfg.SimNetParams) pkScript, _ := txscript.PayToAddrScript(addr) outputs = append(outputs, wire.NewTxOut(leftToMe, pkScript)) // 1.2 輸出2, 添加文字 comment := "這是一個(gè)留言, 哈哈" pkScript, _ = txscript.NullDataScript([]byte(comment)) outputs = append(outputs, wire.NewTxOut(int64(0), pkScript)) // 2. 構(gòu)造輸入 prevTxHash := "48eea09764713f3dadcfed29490ab5e288299e01e571e1f7a1396a75ce38e067" prevPkScriptHex := "76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac" prevTxOutputN := uint32(0) hash, _ := chainhash.NewHashFromStr(prevTxHash) // tx hash outPoint := wire.NewOutPoint(hash, prevTxOutputN) // 第幾個(gè)輸出 txIn := wire.NewTxIn(outPoint, nil, nil) inputs := []*wire.TxIn{txIn} prevPkScript, _ := hex.DecodeString(prevPkScriptHex) prevPkScripts := make([][]byte, 1) prevPkScripts[0] = prevPkScript tx := &wire.MsgTx{ Version: wire.TxVersion, TxIn: inputs, TxOut: outputs, LockTime: 0, } // 3. 簽名 privKey := "cV4HmdzGF3gG7NdEtVV7sjq22yoBmZBe5MEGKUqvQTXXXXX" // 私鑰 sign(tx, privKey, prevPkScripts) // 4. 輸出Hex buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) if err := tx.Serialize(buf); err != nil { } txHex := hex.EncodeToString(buf.Bytes()) fmt.Println("hex", txHex) } // 簽名 func sign(tx *wire.MsgTx, privKeyStr string, prevPkScripts [][]byte) { inputs := tx.TxIn wif, err := btcutil.DecodeWIF(privKeyStr) fmt.Println("wif err", err) privKey := wif.PrivKey for i := range inputs { pkScript := prevPkScripts[i] var script []byte script, err = txscript.SignatureScript(tx, i, pkScript, txscript.SigHashAll, privKey, false) inputs[i].SignatureScript = script } }
關(guān)于“如何使用Golang將誓言存在比特幣的區(qū)塊鏈上”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。