from:https://blog.csdn.net/u010662978/article/details/79195284
大家先看一個區(qū)域鏈瀏覽器的交易鏈接:
https://www.blocktrail.com/tBCC/tx/a63edbbfa17e45b0890520ca30fce6d8eacd41635d1c447418fcfedffa14d914打開這個鏈接, 滑到最后, 會看如圖所示的文字
這是怎么做到的? 這是一個比特幣的交易, 怎么能附上中文呢? 本文就一步步教 你怎么在比特幣交易上添加文字. 因為比特幣的交易具有不可篡改性, 且永久存在區(qū)域鏈上, 那么其附帶的文字就有這個屬性, 這就好像是一個誓言! 誓言記存, 多有意義!!
比特幣交易是需要手續(xù)費的, 而當(dāng)前的手續(xù)費并不便宜, 動則至少上百元, 這太貴了. 所以我推薦大家先去比特幣測試網(wǎng)絡(luò)先弄一些幣來測試. 怎么在獲取比特幣測試網(wǎng)絡(luò)的免費比特幣, 大家可以Google下, 有一些網(wǎng)站會免費送. 比如大家可以去https://testnet.coinfaucet.eu/en/這個站點去獲取, 當(dāng)前獲取的前提是你有一個測試網(wǎng)絡(luò)的比特幣地址, 不然不知道給誰發(fā)幣啊. 下面教你怎么用Golang 生成比特幣測試地址:
https://github.com/btcsuite/btcd是bitcoin的golang版實現(xiàn), 先按照它的文檔安裝, 這里假設(shè)你已經(jīng)成功安裝在本地了.
下面這段代碼包含生成測試和正式地址, 你可以運行得到測試地址.
[plain]?view plain?copy
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()?//?測試地址??
???//?wifKey,?address,?_?:=?GenerateBTC()?//?正式地址??
???fmt.Println(address,?wifKey)??
}??
假設(shè)你得到了一個測試地址:?
地址: mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd
私鑰: cV4HmdzGF3gG7NdEtVV7sjq22yoBmZBe5MEGKUqvQTXXXXX(注意,該密鑰不是正確的,請不要使用)
然后, 你去https://testnet.coinfaucet.eu/en/領(lǐng)免費的測試比特幣, 可以通過接口查看該地址的未花費交易信息:
https://api.blockcypher.com/v1/btc/test3/addrs/mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd/full
總共發(fā)了兩筆, 第一筆 0.65 第二筆 1.3 總共這個地址的余額是 1.95
[javascript]?view plain?copy
{??
"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"??
??????????]??
????????}??
??????],??
//?以下幾個值比較重要??
"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"??
????????}??
??????]??
????}??
??]??
}??
記住第一筆的這幾個值:
tx_hash 48eea09764713f3dadcfed29490ab5e288299e01e571e1f7a1396a75ce38e067
tx_output_n 0
script: 76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac
value 65000000
我們接下來會用到這個未花費交易
下面構(gòu)造一個交易, 這個交易給自己發(fā)一筆錢, 交易費是0.001
[plain]?view plain?copy
address?:=?"mt4p3rZpJE5fXEqvGzNBk9HxYXcWKpPJSd"??
var?balance?int64?=?65000000?//?余額??
var?fee?int64?=?0.001?*?1e8?//?交易費??
var?leftToMe?=?balance?-?fee?//?余額-交易費就是剩下再給我的??
//?1.?構(gòu)造輸出??
outputs?:=?[]*wire.TxOut{}??
//?1.1?輸出1,?給自己轉(zhuǎn)剩下的錢??
addr,?_?:=?btcutil.DecodeAddress(address,?&chaincfg.SimNetParams)??
pkScript,?_?:=?txscript.PayToAddrScript(addr)??
outputs?=?append(outputs,?wire.NewTxOut(leftToMe,?pkScript))??
//?1.2?輸出2,?添加文字??
comment?:=?"這是一個留言,?哈哈"??
pkScript,?_?=?txscript.NullDataScript([]byte(comment))??
outputs?=?append(outputs,?wire.NewTxOut(int64(0),?pkScript))??
[plain]?view plain?copy
//?2.?構(gòu)造輸入??
prevTxHash?:=?"48eea09764713f3dadcfed29490ab5e288299e01e571e1f7a1396a75ce38e067"??
prevPkScriptHex?:=?"76a91489a7f0117eaf47d8b4af740c66116e35ffe1bea988ac"??
prevTxOutputN?:=?uint32(0)??
hash,?_?:=?chainhash.NewHashFromStr(prevTxHash)?//?tx?hash??
outPoint?:=?wire.NewOutPoint(hash,?prevTxOutputN)?//?第幾個輸出??
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,??
}??
[plain]?view plain?copy
//?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??
???}??
}??
第五步: 輸出交易原始信息, 廣播到網(wǎng)絡(luò)上
[plain]?view plain?copy
//?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
下面給出完整源碼:
[plain]?view plain?copy
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?//?交易費??
????var?leftToMe?=?balance?-?fee?//?余額-交易費就是剩下再給我的??
????//?1.?構(gòu)造輸出??
????outputs?:=?[]*wire.TxOut{}??
????//?1.1?輸出1,?給自己轉(zhuǎn)剩下的錢??
????addr,?_?:=?btcutil.DecodeAddress(address,?&chaincfg.SimNetParams)??
????pkScript,?_?:=?txscript.PayToAddrScript(addr)??
????outputs?=?append(outputs,?wire.NewTxOut(leftToMe,?pkScript))??
????//?1.2?輸出2,?添加文字??
????comment?:=?"這是一個留言,?哈哈"??
????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)?//?第幾個輸出??
????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??
????}??
}??
通過以上的方法, 比特幣刻字我已在?www.ibitlin.com?上實現(xiàn), 歡迎使用!!