現(xiàn)在,因?yàn)?a href="http://www.1cnz.cn/tags/比特幣/" target="_blank">比特幣談?wù)?a href="http://www.1cnz.cn/v/tag/5687/" target="_blank">區(qū)塊鏈的人越來越多了,甚至將區(qū)塊鏈作為龐氏騙局的說法都開始出現(xiàn)了。區(qū)塊鏈算法本身是一種分布式存儲模型,專門用于解決記賬問題的算法。與其看這么多區(qū)塊鏈的文章,不如讀一下比特幣的代碼更可靠。
就像是我們寫代碼的來做一個炒菜的設(shè)備,你的關(guān)注重心應(yīng)該在哪里?我覺得不應(yīng)該是你用了什么語言,采用了什么框架,系統(tǒng)穩(wěn)定性參數(shù)是多少,成本有多低,而應(yīng)該是炒的菜好不好吃。正像是沒人關(guān)注技術(shù)細(xì)節(jié)一樣,人們關(guān)注的都是它能做什么。無論你的代碼寫得多好,系統(tǒng)架構(gòu)是怎樣的,硬件或者模型設(shè)計(jì)多優(yōu)化,用了多么高科技的技術(shù),但只要菜做的不好吃就是一個廢品。
現(xiàn)在大體上只要提到區(qū)塊鏈就是“噶韭菜”、“加密貨幣”、“圈錢”,但是區(qū)塊鏈實(shí)際上只是一個為了解決中心記賬問題的模型。
現(xiàn)在讓我們回歸區(qū)塊鏈的記賬系統(tǒng)的本質(zhì),接下來按照區(qū)塊鏈?zhǔn)且粋€記賬模型來講。
傳統(tǒng)會計(jì)記賬的模型都是中心模型,以阿里舉例,阿里中心有一個財(cái)務(wù)總部門,省級有財(cái)務(wù)部門,市級也有財(cái)務(wù)部門。阿里每天都有大量的交易產(chǎn)生,財(cái)務(wù)部門也會有無數(shù)的賬單。市級財(cái)務(wù)部門的會計(jì)統(tǒng)計(jì)賬單,發(fā)給省級;省級統(tǒng)計(jì)完市級發(fā)上來的賬單,發(fā)給阿里的財(cái)務(wù)總部。
我們現(xiàn)在的財(cái)務(wù)記賬模型看起來都是這樣的,但是像阿里這樣的大公司,每分每秒產(chǎn)生的交易額都是夸張的,在這種情況下數(shù)據(jù)量小的時候,各級財(cái)務(wù)部門自己就統(tǒng)計(jì)了,但是越匯總,做的帳就越是大的恐怖。如果這里面有人作假帳或者有人修改歷史賬單或者有人漏寫了某筆帳,在無數(shù)的海量賬單里,基本上就是一筆爛賬了。不管管理體系做得多好,想要查出來被修改的錯誤賬單,基本都是不可能的。
區(qū)塊鏈就是為了解決這個財(cái)務(wù)壞賬問題而使用的算法模型。
階 段 一
這里先例舉一個盡可能簡單的區(qū)塊鏈最基本的存儲模型的代碼。
// 塊
type Block struct {
// 時間戳
Timestamp int64
// 賬單數(shù)據(jù)
Data []byte
// 前一個塊的hash值
PrevBlockHash []byte
// 哈希值
Hash []byte
}
Golang的代碼不用看的太明白,看注釋就行。比特幣代碼里這個Block可以理解為在財(cái)務(wù)賬單上記了一筆帳,而賬單上需要寫明記賬的時間、賬單上的交易數(shù)據(jù)。
PrevBlockHash暫且理解為一個數(shù)字,后面再作解釋。
這個Hash可以理解為當(dāng)前記賬時間和交易數(shù)據(jù),還有PrevBlockHash這個數(shù)字,用一個奇怪的數(shù)學(xué)公式算出來一個校驗(yàn)值,這個校驗(yàn)值是用來保護(hù)該賬單不被修改的。
如果有人想來查賬有沒有被修改,需要看一下記賬的時間和交易的原始數(shù)據(jù),然后查一下PrevBlockHash這個數(shù)字是多少。把這三個數(shù)據(jù)都算一遍,看算出來的數(shù)字是不是Hash里面的數(shù)字,就知道賬單有沒有被修改了。
這樣的數(shù)據(jù)塊可以理解成一張一張的賬單,一條一條的交易數(shù)據(jù)。后面使用賬單塊來稱呼,每一個賬單塊都寫上一個編號。
編號1的賬單的PrevBlockHash就是一個數(shù)字,直接寫成數(shù)字0,這個編號1的賬單塊俗稱創(chuàng)世塊。
編號2的賬單的PrevBlockHash寫的是編號為1的賬單的Hash校驗(yàn)值,以此類推。
假設(shè)這個賬單現(xiàn)在有100個賬單塊。如果有人想搞事情,作假帳,修改了編號為1的賬單的數(shù)據(jù)。
編號1的賬單的Hash數(shù)字是記賬時間、賬單交易內(nèi)容和PrevBlockHash計(jì)算出來的數(shù)字,賬單1的PrevBlockHash內(nèi)容是0。修改賬單記賬時間或者修改賬單的交易內(nèi)容,都會導(dǎo)致Hash數(shù)字算出來會有變化。這個人要作假帳,他一定需要把Hash這個數(shù)字給改成重新算出來的數(shù)字。
但是我們的賬單要求編號2的賬單的PrevBlockHash這個數(shù)字要寫賬單1的Hash校驗(yàn)值。
同理因?yàn)橘~單2里的PrevBlockHash這個數(shù)字變化了,Hash這個數(shù)字也就變化了。
以此類推,我們現(xiàn)在的賬單塊是100個,為了修改賬單1里的任何一點(diǎn)數(shù)據(jù),都會導(dǎo)致需要將從1到100的所有賬單都跟著修改,否則因?yàn)樾r?yàn)值錯誤,該賬本會被作為錯誤賬本被廢棄掉。
這樣一來,之前記的帳就基本不可能被修改了。這也就是區(qū)塊鏈作為分布式存儲和記賬系統(tǒng)的優(yōu)勢所在,賬單一旦錄入基本不可能被修改。記賬系統(tǒng)也是存儲模型,存儲賬單的模型。
階 段 二
上面只是講了最基本的區(qū)塊鏈存儲模型。真實(shí)使用的時候,Data這里并不是真的賬單,而是一個默克爾樹的根節(jié)點(diǎn)的校驗(yàn)值。后面加上默克爾樹,再重新理解一下區(qū)塊鏈。
// 塊
type Block struct {
// 塊頭
Head BlockHead
// 賬單數(shù)據(jù)
Data Merkle
}
// 塊頭
type BlockHead struct {
// 時間戳
Timestamp int64
// 賬單數(shù)據(jù)
MerkleRoot []byte
// 前一個塊的hash值
PrevBlockHash []byte
// 哈希值
Hash []byte
}
// 賬單
type Merkle struct {
// 每一筆交易記錄
Data []byte
}
上面這個Merkle參數(shù),默克爾樹可以理解為就是一個賬單。還是剛才的階段一,每一個Data不是一條交易記錄,可以理解為一個塊記錄就是一個賬單。
當(dāng)交易記錄太多的時候,記賬的交易數(shù)據(jù)量太大了,將整個賬單參與Hash值的計(jì)算,運(yùn)算量太大,太麻煩了,所以用Merkle樹的方式記賬。
關(guān)于默克爾樹就不講太多了,有興趣的可以去查一下,跟區(qū)塊鏈其實(shí)很像,其中每一個樹節(jié)點(diǎn)都是這個樹節(jié)點(diǎn)的子節(jié)點(diǎn)的Hash校驗(yàn)值計(jì)算出來的。
簡單一點(diǎn)理解,可以認(rèn)為通過Merkle樹的方式做了一個賬單,這個賬單有一個根節(jié)點(diǎn),這里記做MerkleRoot,是樹結(jié)構(gòu)的一個節(jié)點(diǎn),不明白的還可以理解為一個校驗(yàn)數(shù)字。整個賬單里只要有任何一個字節(jié)對不上,都會導(dǎo)致MerkleRoot這個數(shù)字產(chǎn)生變化,所以一旦這個賬單做好了之后,將Merkle賬單的MerkleRoot這個數(shù)字寫入到區(qū)塊頭里面,那么整個賬單的任何一個字都不能修改,一旦有任何修改,都會導(dǎo)致整個樹結(jié)構(gòu)上面的每一筆交易記錄的Hash值需要重算。
最終導(dǎo)致MerkleRoot這個數(shù)字會發(fā)生變化,一旦有變化,就會導(dǎo)致塊頭的Hash值發(fā)生變化。導(dǎo)致這個賬單錄入之后的所有賬單的PrevBlockHash值發(fā)生改變,這個塊之后的所有的帳要全部作廢重做。區(qū)塊鏈就是通過這樣一個管理模式來管理賬單。
區(qū)塊鏈總結(jié)
其實(shí)到此為止區(qū)塊鏈已經(jīng)講完了。區(qū)塊鏈其實(shí)就是一個簡單的記賬模型,目的是為了避免有人為意圖的對賬單做修改。區(qū)塊鏈的每一個塊都是在隨著交易記錄的增加不停地添加進(jìn)來的。因?yàn)槿魏我粋€塊的數(shù)據(jù)都被一個完善的數(shù)學(xué)系統(tǒng)鎖定了,任何一個字都是不可修改的,只要有修改,都需要重算從這個賬單塊開始的后面所有的賬單塊,否則賬單就是一個錯誤賬單,不會被系統(tǒng)采納了。
現(xiàn)在的區(qū)塊鏈其實(shí)有三種使用模型:去中心化型、聯(lián)盟中心型、多中心型。按照投票確定誰的賬單是最長的,按照誰的賬單作為總賬。
通過這種方式,避免了中心化記賬,財(cái)務(wù)總中心的人惡意修改數(shù)據(jù),還沒人管得了的問題。如果是多個中心互相牽制,每人手里都有一筆完整的帳,其一驗(yàn)證賬單每個節(jié)點(diǎn)是否計(jì)算正確,來確保賬單不被修改,其次驗(yàn)證每個塊的內(nèi)容,誰的賬單記賬數(shù)量最多(俗稱區(qū)塊鏈最長),按照誰的賬單作為總賬,其它所有節(jié)點(diǎn)接到通知之后,更新自己的賬單。
去中心型是任何人都可以加入到財(cái)務(wù)中心里來,每個人都能拿到總賬,都能驗(yàn)證總賬,也都能幫忙記賬。只要你算的是對的,而且算的最快,都可以被采納。
聯(lián)盟中心型是多公司互相牽制的模型,多個公司用這種模型管理總賬,任何一家公司都不能輕易修改這本動態(tài)的一直在記錄的賬單。
多中心型類似中國銀行這種,還是中央管理,但是并非一個節(jié)點(diǎn)記賬,而是多個點(diǎn)同時記賬,避免任何一本帳被財(cái)務(wù)總中心的人修改。
這里區(qū)塊鏈已經(jīng)需要面對兩個嚴(yán)重的問題。區(qū)塊鏈的每個賬單塊能記的賬單數(shù)量是有上限的,現(xiàn)在一個賬單塊大小是2 MB,不能超過這個大小,一旦要修改這個塊大小,就需要區(qū)塊鏈系統(tǒng)的所有節(jié)點(diǎn)算法跟著變化,代價(jià)會變得很高。
這里隨便說一個數(shù)字,一個塊假設(shè)能保存2千筆交易記錄,像是阿里今年雙十一,3分01秒,成交額100億元。除一下就是五百萬,也就是說3分鐘內(nèi)要寫入500萬賬單塊。因?yàn)橥诘V等某些原因(后面講解),比特幣平均每十分鐘寫入一個賬單塊。
每小時6個塊,一天是24小時,也就是說阿里巴巴去年雙十一這一天,三分鐘產(chǎn)生的賬單,需要大約34 722天,大概95年來記賬。這個記賬速度根本就是來開玩笑的。
這個記賬速度是可以通過算法調(diào)整的,但是這么大的交易量,增加記賬速度會使塊容易沖突,因?yàn)樾枰贁?shù)服從多數(shù)投票選用哪個最長的賬單,全網(wǎng)通知并投票選舉這件事情也是需要時間的,雖然計(jì)算機(jī)很快,但是也是需要時間的。增加塊大小還是加快記賬速度都有很高的通信代價(jià),也是一件賬單數(shù)量過大情況下很不現(xiàn)實(shí)的事情。
階 段 三
看到這里大家應(yīng)該明白什么是區(qū)塊鏈了,比特幣是用區(qū)塊鏈技術(shù)來管理它的賬單的,比特幣使用區(qū)塊鏈技術(shù)如何交易也非常清楚了。但是比特幣挖礦又是怎么一回事兒呢?
在這里,加密貨幣的加密交易過程部分就不詳細(xì)講了,有興趣的可以自己去查一下。我這里假設(shè)明文交易的模型,每一筆交易的交易記錄都不加密,直接寫在賬單上。
這個記賬系統(tǒng)的管理工作都用算法實(shí)現(xiàn)了,需要的只有實(shí)際記下每一筆帳的“會計(jì)”,而在區(qū)塊鏈系統(tǒng)里的“會計(jì)”,也就是我們俗稱的“礦工”。
所謂礦工挖礦是什么意思,是指這個多中心模型里,沒有財(cái)務(wù)管理,每一個人都是“會計(jì)”,每一個“會計(jì)”手里都拿著整個系統(tǒng)完整的賬本,然后開始做賬,在整個區(qū)塊鏈里記下下一個賬單塊這樣的工作,成功將賬單寫進(jìn)去,而且計(jì)算正確的那個人,將自己的賬單發(fā)給所有人,然后將我們每個人做的帳放到一起,計(jì)算正確的賬本而且又是最長的,一定是第一個將該賬單成功寫進(jìn)去的那個“會計(jì)”。
然后按照算法當(dāng)場計(jì)算,他成功記了一筆賬,應(yīng)該給他多少錢,然后當(dāng)場發(fā)放獎勵,這就是挖礦。但是這個挖礦是有問題的,誰的算力強(qiáng),算得快就總是誰拿錢,別人就沒有工作的熱情了,而且大家記賬的速度都差不多的,很容易撞車,同時提交賬單。
所以我們重新調(diào)整一下這個塊的結(jié)構(gòu)。
// 塊
type Block struct {
// 塊頭
Head BlockHead
// 賬單數(shù)據(jù)
Data Merkle
}
// 塊頭
type BlockHead struct {
// 時間戳
Timestamp int64
// 難度值
Bits []byte
// 目標(biāo)數(shù)
Nonce []byte
// 賬單數(shù)據(jù)
MerkleRoot []byte
// 前一個塊的hash值
PrevBlockHash []byte
// 哈希值
Hash []byte
}
// 賬單
type Merkle struct {
// 每一筆交易記錄
Data []byte
}
這里在塊頭結(jié)構(gòu)里添加了兩個參數(shù):Bits難度值和Nonce目標(biāo)數(shù)。
先說一下加這兩個參數(shù)的原因。剛才遇到的問題是,一屋子“會計(jì)”,每個人都在做賬,誰最快做出來帳,統(tǒng)計(jì)投票之后所有人更新賬單,按照最快做賬那個人的賬本更新。
但是算這個賬單,雖然加了一些很麻煩的算法,還是很簡單的,大家算得都很快,一起提交,而且都算得是對的,這事兒很容易產(chǎn)生紛爭。如果有一個人算得非常快,賬本總是他在記,他是不是會搞點(diǎn)小手段呢?所以,還是應(yīng)該每人記一點(diǎn)帳,這個帳更可靠。
這個就是中本聰提出的“工作證明機(jī)制”,我們所有人都先別開始記賬。我們都開始算一個非常難的數(shù)學(xué)題,而且是個超級麻煩,完全沒有用,基本靠撞大運(yùn)的數(shù)學(xué)題。誰算出來了,誰再按照流程算你的帳,計(jì)算機(jī)按照流程記賬基本就是瞬間寫入,但是算這個很麻煩的數(shù)學(xué)題,就需要時間了,而且是個基于撞大運(yùn)的數(shù)學(xué)題,沒人確保自己能算出來。通過這種方式來拖延記賬時間。
如果真的拿區(qū)塊鏈作為記賬系統(tǒng)來用,根本不需要一個刻意去拖慢記賬速度的東西,但是比特幣就是這么寫的。也是我認(rèn)為這個“工作證明機(jī)制”是一個資源空轉(zhuǎn),純屬浪費(fèi)的東西。然后我詳細(xì)講一下這個數(shù)學(xué)體是什么。
剛才講區(qū)塊頭的Hash校驗(yàn)值計(jì)算是用記賬時間、賬單數(shù)據(jù)和前一個塊的Hash值算出來的,我們把Bits難度值和Nonce這兩個數(shù)也參與到Hash運(yùn)算里來。
先說Bits難度值,這個數(shù)是依賴于之前記過的帳算出來的,可以認(rèn)為在當(dāng)前要記的這個帳里,它是一個確定的寫死的一個數(shù)字,具體怎么來的,可以自己查一下資料。
Bits = difficulty_1_target / current_target
所以我要開始計(jì)算這個塊的Hash值的時候,這個Bits可以認(rèn)為不影響計(jì)算結(jié)果。
然后是Nonce目標(biāo)數(shù),記賬人隨便寫這個數(shù)字。但是因?yàn)镹once參與運(yùn)算,所以寫不同的Nonce數(shù)值,算出來的結(jié)果都是不同的。
然后接下來的工作全靠蒙,不停地嘗試各種各樣的Nonce這個數(shù)字,讓計(jì)算出來的Hash數(shù)值小于Bits這個寫死的數(shù)字。
如果你成功蒙到了這個數(shù)字,就趕緊把算好的賬單,以及帶著賬單里的這個Nonce數(shù)字廣播發(fā)給屋里所有的人,大家都驗(yàn)證了一下賬單沒問題。全靠猜寫的Nonce這個數(shù)字算出來的Hash數(shù)字確實(shí)小于Bits這個數(shù)字。屋里所有的“會計(jì)”全部更新自己的賬單,把你成功記賬這件事情寫到賬單里,然后系統(tǒng)計(jì)算應(yīng)該給你多少工資,當(dāng)場結(jié)算。
因?yàn)樗愠鰜淼腍ash小于Bits這個數(shù)字,如果Bits這個數(shù)字太大還是會導(dǎo)致很多人很快能算出來。因?yàn)橛涃~的時候賬單上寫著記賬的當(dāng)前時間,而且這個數(shù)字還是不允許修改的,所以能算出來平均你們一堆人多長時間可以算出來一個賬單塊,并提交寫入總賬本的。如果速度太快,不到10分鐘就算出來了,稍微把Bits這個數(shù)字按照算法稍微調(diào)小一點(diǎn),基于前面的賬本記錄時間計(jì)算。
因?yàn)槊總€人手里都有賬本,這個數(shù)字要寫多少,自己就直接算出來了,不需要誰來控制這個記賬難度系數(shù),繼續(xù)維持區(qū)塊鏈記賬系統(tǒng),無中心無管理的狀態(tài)。
同時通過這種難度波動的方式控制大家的記賬速度,也就是上面提到的比特幣平均每10分鐘記賬一次,寫入一個賬單塊,避免多人同時記賬導(dǎo)致數(shù)據(jù)沖突。
繼續(xù)吐槽一下,這個“工作證明機(jī)制”單純的是用來拖慢記賬速度的,此模式確實(shí)有點(diǎn)蠢,但是的確很有效,確實(shí)解決了在互相不信任的無中心模型下,怎么讓互相完全不信任的人之間管理賬本的問題。
補(bǔ) 充
其實(shí)還有很多細(xì)節(jié)沒講,比如比特幣的發(fā)放這個模型。通過記賬成功的方式直接按照算法發(fā)放獎勵,這只是一種中本聰隨手寫的獎勵方式。為了讓大家把這個記賬游戲繼續(xù)玩下去。
比特幣系統(tǒng)里能憑空獲得比特幣的只有“會計(jì)”挖礦,記賬成功時按照算法自動獲得,還有系統(tǒng)獎勵衰減來回避通貨膨脹問題等。
但是現(xiàn)在更多的模型是“會計(jì)”無獎勵的,由系統(tǒng)從最一開始直接發(fā)行貨幣,由中心系統(tǒng)發(fā)放貨幣,其實(shí)也是有監(jiān)管的,監(jiān)管中心可能導(dǎo)致貨幣控制等問題。
這個記賬系統(tǒng)沒什么可記的賬本,就變成了中本聰寫的一個記賬游戲系統(tǒng)“比特幣”系統(tǒng)。在記賬的過程中去產(chǎn)生只對“會計(jì)”發(fā)放的貨幣,再由參與者之間互相交易的模型。但說白了,比特幣就是個游戲系統(tǒng),沒人用的時候就是一堆廢棄的數(shù)據(jù)。尤其當(dāng)“會計(jì)”從系統(tǒng)里消失的時候,這個記賬系統(tǒng)就崩壞了,沒有記賬的“會計(jì)”,就無法成交了,所有的成交單都會成為廢品。
再加上比特幣的每次記賬成功發(fā)放數(shù)量,平均每四年會除以二,你四年前成功記賬獲得一萬,現(xiàn)在成功記賬獲得五千。數(shù)字是我隨便寫的,因?yàn)楠剟畎l(fā)放是浮點(diǎn)數(shù)記錄的,不是數(shù)學(xué)上那種可以無限細(xì)分的數(shù)字,所以其實(shí)從某一刻開始比特幣記賬就拿不到收益了。
要么有辦法用其它手段讓“會計(jì)”掙到錢或者采用交易提成等手段,否則“會計(jì)”一定會從這個不賺錢的游戲里退出來,也就是比特幣系統(tǒng)一定有崩壞的那一天。
雖然比特幣的游戲模型是一個注定會崩壞的模型,但它只是一個記賬游戲而已。區(qū)塊鏈技術(shù)也絕對不是什么龐氏騙局,只是一個記賬系統(tǒng)罷了。
-
區(qū)塊鏈
+關(guān)注
關(guān)注
111文章
15562瀏覽量
105941 -
比特幣
+關(guān)注
關(guān)注
57文章
7005瀏覽量
140525
原文標(biāo)題:研究完比特幣代碼,發(fā)現(xiàn)了一個驚人秘密!
文章出處:【微信號:mcuworld,微信公眾號:嵌入式資訊精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論