摘要:原文鏈接如何設(shè)計(jì)一個(gè)比特幣錢(qián)包服務(wù)概述總所周知,比特幣全節(jié)點(diǎn)的實(shí)現(xiàn)目前有兩個(gè)版本,一個(gè)是中本聰寫(xiě)的原版,一個(gè)是語(yǔ)言寫(xiě)的。查詢最新區(qū)塊高度,錢(qián)包轉(zhuǎn)賬后通過(guò)區(qū)塊高度來(lái)計(jì)算交易是否已經(jīng)確認(rèn),比特幣是個(gè)區(qū)塊確認(rèn)。
原文鏈接 https://github.com/liyue201/b...
如何設(shè)計(jì)一個(gè)比特幣錢(qián)包服務(wù) 概述總所周知,比特幣全節(jié)點(diǎn)的實(shí)現(xiàn)目前有兩個(gè)版本,一個(gè)是中本聰c++寫(xiě)的原版bitcoin core,一個(gè)是go語(yǔ)言寫(xiě)的btcd。這兩個(gè)版本從功能上并沒(méi)有多大差異,都實(shí)現(xiàn)了比特幣協(xié)議。從理論上講,比特幣網(wǎng)絡(luò)中的每個(gè)全節(jié)點(diǎn)只要遵循相同的比特幣協(xié)議,至于用什么語(yǔ)言實(shí)現(xiàn),用什么方式存儲(chǔ)都是無(wú)所謂的。bitcoin core和btcd都沒(méi)有實(shí)現(xiàn)通用的錢(qián)包服務(wù),這里說(shuō)的錢(qián)包服務(wù)指的是一個(gè)可以給錢(qián)包app提供所數(shù)據(jù)的服務(wù),私鑰保存在錢(qián)包app中,用戶交易在錢(qián)包app中簽名,再將簽名數(shù)據(jù)發(fā)給錢(qián)包服務(wù),再由錢(qián)包服務(wù)轉(zhuǎn)發(fā)到全節(jié)點(diǎn)上鏈,如圖:
所幸的是全節(jié)點(diǎn)提供了一些JSON RPC接口,通過(guò)這些接口可以讀取區(qū)塊數(shù)據(jù)和發(fā)起轉(zhuǎn)賬交易。但是能讀到的數(shù)據(jù)還是太原始了,就連獲取某個(gè)地址的余額都做不到。因?yàn)楸忍貛攀褂玫氖荱TXO賬號(hào)體系,并沒(méi)有一個(gè)統(tǒng)一的地方存儲(chǔ)地址余額,只有UTXO。而UTXO是分散在每個(gè)區(qū)塊中的,要想知道某個(gè)地址的UTXO,需要從第一個(gè)區(qū)塊開(kāi)始遍歷。有些人說(shuō)這樣設(shè)計(jì)可以更好的并發(fā)執(zhí)行,這個(gè)鄙人真的不敢茍同。說(shuō)可以更好的溯源倒是真的,因?yàn)槊恳还P交易都可以追溯到上一筆交易。
錢(qián)包服務(wù)功能好了,廢話不多說(shuō),我們看一下一個(gè)錢(qián)包服務(wù)應(yīng)該具備什么樣的功能。
(1)查詢?nèi)我庖粋€(gè)地址的余額,錢(qián)包需要知道自己地址的余額。
(2)查詢?nèi)我庖粋€(gè)地址的UTXO,錢(qián)包轉(zhuǎn)賬時(shí)需要UTXO來(lái)簽名打包。
(3)發(fā)起轉(zhuǎn)賬交易。錢(qián)包需要調(diào)服務(wù)發(fā)起轉(zhuǎn)賬交易。
(4)查詢?nèi)我庖粋€(gè)地址的歷史交易記錄。
(5)查詢最新區(qū)塊高度,錢(qián)包轉(zhuǎn)賬后通過(guò)區(qū)塊高度來(lái)計(jì)算交易是否已經(jīng)確認(rèn),比特幣是6個(gè)區(qū)塊確認(rèn)。
第(1)(2)點(diǎn)實(shí)際上是一個(gè)問(wèn)題,知道UTXO自然就知道余額了。第(3)(5)可以直接調(diào)全節(jié)點(diǎn)接口。所以錢(qián)包服務(wù)的難點(diǎn)只剩下(2)(4)這兩個(gè)功能。錢(qián)包服務(wù)要做的就是從全節(jié)點(diǎn)從第一個(gè)區(qū)塊開(kāi)始遍歷讀取所有的交易記錄,并推導(dǎo)出每個(gè)地址當(dāng)前區(qū)塊高度的UTXO,再將這個(gè)信息保存到數(shù)據(jù)庫(kù)中方便錢(qián)包使用。
全節(jié)點(diǎn)選擇bitcoin core 雖然是原版的比特幣全節(jié)點(diǎn),但是他只提供了http接口,沒(méi)有websocket接口,不能實(shí)時(shí)推送未上鏈的交易。一個(gè)體驗(yàn)好的錢(qián)包不僅要獲取已經(jīng)上鏈的交易記錄,也要知道未上鏈的交易。btcd不僅提供了http接口,還有websocket,所以btcd應(yīng)該是更好的選擇。
數(shù)據(jù)庫(kù)選型到目前為止(2018-12-26)比特幣的交易量是3.6億,因?yàn)橐还P交易涉及到多個(gè)輸入和多個(gè)輸出地址(如果你研究過(guò)區(qū)塊鏈瀏覽器上的數(shù)據(jù),會(huì)發(fā)現(xiàn)一筆交易幾千個(gè)輸入和幾千個(gè)輸出都是很正常的,這樣可以省礦工費(fèi),可能是交易所轉(zhuǎn)賬),解析出來(lái)后大約是16.6億條(這個(gè)我自己跑的數(shù)據(jù))。若是用傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)肯定扛不住的,所以一般人都會(huì)往nosql或者列式數(shù)據(jù)庫(kù)方向考慮,比如用mongo或cassandra等。雖然能夠解決問(wèn)題,但是面對(duì)這么大的數(shù)據(jù),這類(lèi)型的數(shù)據(jù)庫(kù)都需要部署分片集群。對(duì)于一個(gè)小創(chuàng)業(yè)公司來(lái)說(shuō),如果用戶不是很多,從運(yùn)維成本上來(lái)看,是不是都點(diǎn)殺雞用牛刀大感覺(jué)呢。有沒(méi)有經(jīng)濟(jì)實(shí)惠的方案?當(dāng)然有,比如leveldb和rocksdb這類(lèi)kv嵌入式數(shù)據(jù)庫(kù),只需要單個(gè)機(jī)器就可以滿足要求。在幾億數(shù)據(jù)量情況下,leveldb在普通硬盤(pán)上讀寫(xiě)速度可以達(dá)到幾萬(wàn)每秒,使用ssd硬盤(pán)更快,而且內(nèi)存占用極少。當(dāng)然使用leveldb或rocksdb,也有其缺點(diǎn),就是單機(jī)數(shù)據(jù)安全的問(wèn)題,如果硬盤(pán)壞了怎么辦。恰好我們這個(gè)業(yè)務(wù)對(duì)數(shù)據(jù)的安全性要求并不高,因?yàn)樗袛?shù)據(jù)都是從全節(jié)點(diǎn)來(lái)的,要是硬盤(pán)壞了,大不了重新跑一遍數(shù)據(jù)。rocksdb是facebook的開(kāi)源產(chǎn)品,據(jù)說(shuō)是對(duì)leveldb做了優(yōu)化,性能更強(qiáng)。rocksdb是c++寫(xiě)的,而leveldb除了c++版本之外,還有g(shù)o語(yǔ)言版本,比特幣全節(jié)點(diǎn)btcd和以太坊全節(jié)點(diǎn)geth都是用的go版本的leveldb。最終我選擇了leveldb,因?yàn)槲业姆?wù)是用go寫(xiě)的,雖然go也可以通過(guò)cgo調(diào)用C++,但是代碼寫(xiě)起來(lái)沒(méi)有純go那么舒服。
數(shù)據(jù)結(jié)構(gòu)leveldb是kv數(shù)據(jù)庫(kù),沒(méi)有表的概念,所以數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)非常關(guān)鍵。比如地址的歷史交易記錄,在關(guān)系型數(shù)據(jù)庫(kù)中可以建一個(gè)以地址為索引的歷史交易記錄表。而kv數(shù)據(jù)庫(kù)則沒(méi)有索引的概念。好在level的key是有序的,可以根據(jù)key的順序讀取內(nèi)容。根據(jù)這個(gè)特性,我們可以這樣設(shè)計(jì)索引,每個(gè)地址的交易是一組key,這組key在數(shù)據(jù)庫(kù)的所有key中是緊挨著的。這樣只要知道某個(gè)地址的第一個(gè)索引key就可以按順序讀到這個(gè)地址的其他交易。因?yàn)橐粋€(gè)交易涉及到多個(gè)輸入地址和輸出地址所以需要索引跟數(shù)據(jù)分開(kāi),對(duì)于utxo只關(guān)聯(lián)到一個(gè)地址,就不需要多帶帶設(shè)計(jì)索引了,索引跟數(shù)據(jù)可以放在一起。
數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)好了,該怎么存。這個(gè)就是序列化的問(wèn)題了,可以是json,或者go自帶的gob,也可以自己寫(xiě)。最后從編碼難度,執(zhí)行效率和壓縮率等方面綜合考慮采用了protobuf。這是我的proto文件
syntax = "proto3"; package models; //key: utxo-{addr}-{Transaction.id}-{Transaction.vout} message Utxo { string txId = 1; uint32 vout = 2; int64 amount = 3; string scriptPubKey = 4; } //context //key: context message Context { int64 blockHeight = 1; // 當(dāng)前處理的區(qū)塊高度 string blockHash = 2; // 當(dāng)前處理的區(qū)塊hash int32 blockTotalTx = 3; // 當(dāng)前區(qū)塊的交易數(shù) int32 BlockProcessedTx = 4; // 當(dāng)前區(qū)塊已經(jīng)處理的交易數(shù) int64 totalTx = 5; // 總共的交易數(shù) int64 totalTxNode = 6; // } message TxInput { string txId = 1; //上一筆交易id uint32 vout = 2; //上一筆交易輸出的idx string addr = 3; //通過(guò)查詢獲得 int64 amount = 4; //通過(guò)查詢獲得 } message TxOutput { string addr = 1; int64 amount = 2; uint32 vout = 3; string scriptPubKey = 4; } //key: tx-{Transaction.txId} message Transaction { int64 id = 1; //自增di string txId = 2; int64 blockTime = 3; string blockHash = 4; int64 blockHeight = 5; repeated TxInput inputs = 6; repeated TxOutput outputs = 7; } //key: txnode-{addr}-{TxNode.id} message TxNode{ int64 id = 1; //自增di string txId = 2; uint32 type = 3; //1-intput 2-output 3-intput|output }總結(jié)
這個(gè)項(xiàng)目的難點(diǎn)不在編碼而是技術(shù)選型,當(dāng)然還有調(diào)試。代碼寫(xiě)完后經(jīng)過(guò)漫長(zhǎng)的同步,大概半個(gè)月才同步完成。 只有同步完成才能進(jìn)行完整的功能測(cè)試,若果有數(shù)據(jù)的bug還得從頭開(kāi)始同步。需要注意的是這里只是設(shè)計(jì)了已經(jīng)確認(rèn)的區(qū)塊,對(duì)于未確認(rèn)的區(qū)塊和內(nèi)存池的交易要多帶帶考慮。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/24521.html
摘要:比特幣區(qū)塊鏈無(wú)疑是當(dāng)今業(yè)界的最熱門(mén)的。目前,每個(gè)成功的礦工獲得可能每年更換一次或通過(guò)比特幣社區(qū)決策作為成功向區(qū)塊鏈添加一塊交易的獎(jiǎng)勵(lì)。填寫(xiě)其他詳細(xì)信息,例如比特幣金額和可選說(shuō)明。 比特幣區(qū)塊鏈無(wú)疑是當(dāng)今業(yè)界的最熱門(mén)的。通過(guò)這篇博客,我將盡力向大家介紹加密貨幣比特幣的概念,以及它如何創(chuàng)造我們稱之為區(qū)塊鏈的革命性技術(shù)。 這個(gè)問(wèn)題經(jīng)常引起混淆。這篇文章可以快速解釋和清理這方面的混亂! 什么是...
摘要:創(chuàng)建比特幣錢(qián)包需要一組優(yōu)秀的程序員。如何使用流行的庫(kù)構(gòu)建自己的比特幣錢(qián)包應(yīng)用程序創(chuàng)建比特幣錢(qián)包應(yīng)用程序的一種方法是依賴現(xiàn)有工具。具有以下功能它允許開(kāi)發(fā)人員使用密碼加密創(chuàng)建比特幣錢(qián)包應(yīng)用程序。 盡管目前加密貨幣市場(chǎng)相當(dāng)黯淡,但比特幣和其他山寨幣繼續(xù)受歡迎。每天都有新的交易者加入市場(chǎng),希望能夠在下一個(gè)價(jià)格高漲時(shí)獲利。 隨著市場(chǎng)的突飛猛進(jìn),開(kāi)發(fā)商也在獲益。新交易者的首要任務(wù)是設(shè)置比特幣錢(qián)包。...
摘要:創(chuàng)建比特幣錢(qián)包需要一組優(yōu)秀的程序員。如何使用流行的庫(kù)構(gòu)建自己的比特幣錢(qián)包應(yīng)用程序創(chuàng)建比特幣錢(qián)包應(yīng)用程序的一種方法是依賴現(xiàn)有工具。具有以下功能它允許開(kāi)發(fā)人員使用密碼加密創(chuàng)建比特幣錢(qián)包應(yīng)用程序。 盡管目前加密貨幣市場(chǎng)相當(dāng)黯淡,但比特幣和其他山寨幣繼續(xù)受歡迎。每天都有新的交易者加入市場(chǎng),希望能夠在下一個(gè)價(jià)格高漲時(shí)獲利。 隨著市場(chǎng)的突飛猛進(jìn),開(kāi)發(fā)商也在獲益。新交易者的首要任務(wù)是設(shè)置比特幣錢(qián)包。...
摘要:要點(diǎn)提醒確保比特幣錢(qián)包安全的全部在于確保錢(qián)包私鑰安全,好消息是,這個(gè)你可以采取措施。 本文是有關(guān)比特幣相關(guān)的系列文章,發(fā)布于GIT-HUB,地址如下:https://github.com/junahan/JU... 比特幣錢(qián)包安全概要 有關(guān)比特幣錢(qián)包安全,可以簡(jiǎn)單的分為兩類(lèi),一類(lèi)是做為用戶的你不可控制的安全問(wèn)題,一類(lèi)是做為用戶的你可以控制的安全問(wèn)題。之所以這樣看似廢話的區(qū)分,提醒你...
摘要:側(cè)鏈側(cè)鏈協(xié)議允許資產(chǎn)在比特幣區(qū)塊鏈和其他區(qū)塊鏈之間互轉(zhuǎn)。實(shí)現(xiàn)了比特幣區(qū)塊鏈的擴(kuò)展證明在比特幣系統(tǒng)中驗(yàn)證交易時(shí),涉及交易合法性檢查雙重花費(fèi)檢查腳本檢查等。 比特幣項(xiàng)目簡(jiǎn)介 比特幣是基于區(qū)塊鏈技術(shù)的一種數(shù)字貨幣實(shí)現(xiàn),比特幣網(wǎng)絡(luò)是歷史上首個(gè)經(jīng)過(guò)大規(guī)模、長(zhǎng)時(shí)間檢查的數(shù)字貨幣系統(tǒng) 比特幣網(wǎng)絡(luò)在功能上具有如下特點(diǎn): 去中心化: 意味著沒(méi)有任何獨(dú)立個(gè)體可以對(duì)網(wǎng)絡(luò)中的交易進(jìn)行破壞,任何交易請(qǐng)求都需要...
閱讀 1972·2021-09-27 13:35
閱讀 3499·2019-08-30 14:16
閱讀 2556·2019-08-30 10:52
閱讀 917·2019-08-29 16:35
閱讀 1465·2019-08-29 15:22
閱讀 3748·2019-08-23 18:21
閱讀 3203·2019-08-23 18:00
閱讀 3199·2019-08-23 16:50