自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

區(qū)塊鏈難理解?200行代碼教你寫(xiě)一個(gè)自己的區(qū)塊鏈!

區(qū)塊鏈 新聞
“區(qū)塊鏈”三個(gè)字,無(wú)疑是近一年來(lái)最火的投資概念。隨著比特幣等區(qū)塊鏈資產(chǎn)價(jià)格的大幅飆升,普通投資者對(duì)區(qū)塊鏈,以及數(shù)字貨幣投資的興趣越來(lái)越大,突然間,似乎全世界都在談?wù)搮^(qū)塊鏈、比特幣。

“區(qū)塊鏈”三個(gè)字,無(wú)疑是近一年來(lái)最火的投資概念。隨著比特幣等區(qū)塊鏈資產(chǎn)價(jià)格的大幅飆升,普通投資者對(duì)區(qū)塊鏈,以及數(shù)字貨幣投資的興趣越來(lái)越大,突然間,似乎全世界都在談?wù)搮^(qū)塊鏈、比特幣。

[[219571]]

區(qū)塊鏈就像一次對(duì)全人類(lèi)經(jīng)濟(jì)層面的入侵,這種入侵,比互聯(lián)網(wǎng)的入侵,可能還要徹底,人們開(kāi)始轉(zhuǎn)移的,并不是簡(jiǎn)單的信息以及消費(fèi)習(xí)慣,而是對(duì)資產(chǎn)的重新認(rèn)識(shí)和選擇。

區(qū)塊鏈難理解?這里有一篇初學(xué)者指南

我并不明白為什么人們會(huì)覺(jué)得要理解區(qū)塊鏈會(huì)有點(diǎn)難,而我也想知道為什么自己并沒(méi)有。

那是在 2013 年,我第一次聽(tīng)說(shuō)有比特幣這個(gè)東西(是的,知道的太晚啦)。我窮得連一個(gè)都買(mǎi)不起,看到這兒你也許已經(jīng)對(duì)此文無(wú)愛(ài)了。

后來(lái),我想要去了解一下它所依賴的底層技術(shù),也就是區(qū)塊鏈。 不過(guò)因?yàn)樘α?,所以遲遲沒(méi)有開(kāi)始(那就并不存在什么開(kāi)始不開(kāi)始了)。

[[219572]]

“區(qū)塊鏈”到底是什么?

區(qū)塊鏈其實(shí)是兩個(gè)東西:一個(gè)是區(qū)塊,一個(gè)是鏈。說(shuō)玄虛一點(diǎn),就是一鏈子的區(qū)塊。

因?yàn)樗谴嬖谟谟?jì)算機(jī)中的東西,所以我們可以厘定它的一個(gè)物理形態(tài)是啥樣子的,就是數(shù)字信息被分成一個(gè)一個(gè)區(qū)塊然后把這些區(qū)塊鏈接起來(lái)。

舉個(gè)例子,下圖中的方塊,每一個(gè)都表示一個(gè)國(guó)家,而且每一個(gè)都包含了對(duì)應(yīng)國(guó)家的城市名稱(chēng)。

等等,其實(shí)還有更多東西來(lái)著。這里的每一個(gè)方塊都是一個(gè)叫做哈希的東西。一個(gè)哈希就是一串字符 (比如 “1hi515AHA5H” )。

哈希是根據(jù)方塊里面所包含的信息來(lái)得到的。U.S.A 的方塊擁有 New York, Los Angeles,還有 Chicago 這幾個(gè)城市,所以它的哈希就是像 “NYLAC” 的東西了 (技術(shù)上其實(shí)遠(yuǎn)非如此,但你理會(huì)精要就行了)。

每一個(gè)接續(xù)的方塊都會(huì)包含前一個(gè)方塊的哈希,所以這個(gè)就是(強(qiáng)制性的)將它們綁到一起的紐帶。

如果有人擅自篡改了第一個(gè)方塊,加入了城市 Boston,那么新的哈希就會(huì)是 “NYLACB”。

然而后面接續(xù)的 India 這個(gè)方塊已經(jīng)存著的哈希還是 “NYLAC”,這種不匹配就會(huì)把鏈條打斷。所以哈希的目的就是確保沒(méi)有人可以篡改區(qū)塊。

那如果有人修改了一個(gè)方塊的內(nèi)容,然后把后面的接續(xù)方塊的哈希也一并更新會(huì)如何呢? 

這也是有可能的,不過(guò)有一件事情我還沒(méi)有告訴你。區(qū)塊鏈的數(shù)據(jù)并不只是存在于僅僅一臺(tái)計(jì)算機(jī)里面。一臺(tái)計(jì)算機(jī)里面的區(qū)塊鏈數(shù)據(jù)并不能騙到人,因?yàn)樗鼤?huì)被復(fù)制到網(wǎng)絡(luò)中每一個(gè)用戶的計(jì)算機(jī)里面去。

如果你加入了一個(gè)區(qū)塊鏈網(wǎng)絡(luò),那么你的計(jì)算機(jī)就會(huì)去下載這些區(qū)塊數(shù)據(jù),如果有人篡改了他擁有的版本,整個(gè)網(wǎng)絡(luò)也會(huì)考慮占多數(shù)的人的計(jì)算機(jī)上所擁有的版本才是正確的。

還有一件事,在一個(gè)區(qū)塊鏈網(wǎng)絡(luò)中,不僅是數(shù)據(jù),就連整個(gè)系統(tǒng)的程序都被復(fù)制到了所有的電腦中。

大多數(shù)互聯(lián)網(wǎng)應(yīng)用都是集中化的,比如 Facebook,她的數(shù)據(jù)和程序都被放在了她的服務(wù)器上,你的計(jì)算機(jī)會(huì)從 Facebook 的服務(wù)器上獲取到你一個(gè)人需要知道的信息。

但在區(qū)塊鏈的世界理,就沒(méi)有存在于中心的東西,它依賴的是用戶的計(jì)算機(jī)來(lái)容納自己的程序。這就意味著,如果整個(gè)區(qū)塊鏈網(wǎng)絡(luò)中的每一臺(tái)電腦都關(guān)機(jī)了,那么這個(gè)區(qū)塊鏈系統(tǒng)就死翹翹了。

公共區(qū)塊鏈

[[219573]]

這是不是就意味著區(qū)塊鏈系統(tǒng)其實(shí)就是由一群心懷善意自愿讓他們的計(jì)算機(jī)保持運(yùn)行的人來(lái)組成的呢? 還有這些防篡改的區(qū)塊是用來(lái)干嘛的呢?

區(qū)塊鏈網(wǎng)絡(luò)的功效不勝枚舉。比特幣是一種數(shù)據(jù)貨幣和一個(gè)支付系統(tǒng)。它所有的防篡改區(qū)塊中所保存的就是全部交易的分類(lèi)賬。那些貢獻(xiàn)了他們自己的計(jì)算機(jī)的人被稱(chēng)為礦工。系統(tǒng)會(huì)給他們提供比特幣作為獎(jiǎng)勵(lì)。

Ethereum 有一項(xiàng)附加功能。它可以承載你的代碼,從頭開(kāi)始發(fā)展出一個(gè)區(qū)塊鏈系統(tǒng)。

而要構(gòu)建一個(gè)屬于你自己的系統(tǒng)也許會(huì)非常地困難(記住這得看有人為你犧牲他們的計(jì)算機(jī)運(yùn)行能力才行哦)。Ethereum 就維護(hù)著這些耗損巨大的運(yùn)算能力,而你則需要為這些計(jì)算消耗買(mǎi)單。

區(qū)塊鏈應(yīng)用并不非得是支付系統(tǒng)或者加密貨幣。它可以是任何東西,像是一個(gè)社交網(wǎng)絡(luò),一個(gè)像 LiveEdu 這樣的學(xué)習(xí)平臺(tái),等等。

私有區(qū)塊鏈

[[219574]]

Bitcoin,Ethereum 等等這些都是公共區(qū)塊鏈的例子,任何人都可以成為其中的一分子。

那如果我們想要有一個(gè)私有的區(qū)塊鏈網(wǎng)絡(luò)該如何呢?有些人想要一個(gè)私有的區(qū)塊鏈?zhǔn)窍敫陕锬兀磕蔷蛠?lái)瞧瞧下面的故事吧。

Mark 和 Sara

Mark 已經(jīng)五個(gè)月沒(méi)交房租了,當(dāng) Sara 找他要的時(shí)候,他就說(shuō)晚點(diǎn)會(huì)給她。她付不起律師費(fèi),而法院強(qiáng)制執(zhí)行訴訟就需要 8 個(gè)月甚至一年,所以唯一的選擇就是去說(shuō)服 Mark。

Joe 的生意

Joe 是一個(gè)商人,他經(jīng)常要跟不同的公司做生意。幾個(gè)月之前他和一家零售商簽了一份合同,盡管合同條款都已經(jīng)履約了,可零售商卻拒絕付款。

這幫人利用法律制度中的漏洞來(lái)游說(shuō) Joe,想以此達(dá)到少付錢(qián)的目的。Joe 在這以前就是有這方面經(jīng)驗(yàn)的,在某些情況下,他會(huì)找法院求助,但這樣做所耗費(fèi)的時(shí)間和金錢(qián)卻要損失他自己的利潤(rùn)。

我們?cè)撊绾螏椭?Sara 和 Joe 呢?

我們是不是能在其他地方解決這個(gè)問(wèn)題呢? 在 Sara 遇到的這種情況中,我們需要讓 Mark  按月支付房租,這其實(shí)就是一個(gè)基于時(shí)間的觸發(fā)機(jī)制。你的日歷程序使用這樣的觸發(fā)器來(lái)給你提供預(yù)設(shè)事件的通知。

在 Joe 遇到的場(chǎng)景中,一旦合約中的條款都滿足了,當(dāng)事人就得付款,這其實(shí)就是一個(gè)基于條件的觸發(fā)機(jī)制。你想想上次從 Amazon 買(mǎi)電子書(shū)的時(shí)候,是不是得先確認(rèn)付款了,Amazon 才會(huì)把電子書(shū)發(fā)給你?

重點(diǎn)是,計(jì)算機(jī)程序會(huì)始終如一的執(zhí)行諸如此類(lèi)的指令。當(dāng)你點(diǎn)擊著這篇文章,向下滾動(dòng),諸如這類(lèi)的操作,它也會(huì)照著執(zhí)行不誤。為了能幫助到 Sara ,我們需要將合同的條款轉(zhuǎn)變成代碼。

Sara 和 Mark 之間所訂立的智能合同的偽代碼

  • If today’s date is 30th and rent is not paid then
  • Transfer $500 from Mark’s account to Sara’s account

可是我們?cè)谀膬翰渴疬@些代碼呢? 它就應(yīng)該被部署到所有參與者的計(jì)算機(jī)上。Sara 的還有 Mark 的銀行都會(huì)是這一個(gè)私有區(qū)塊鏈網(wǎng)絡(luò)的一部分。

Joe 和 Sara 會(huì)簽署一份編碼的協(xié)議(也就是智能合同),然后這份協(xié)議會(huì)被分發(fā)到網(wǎng)絡(luò)中去,Mark 的和 Sara 的銀行都會(huì)有一份拷貝。

在每個(gè)月的 30 號(hào),當(dāng)時(shí)鐘跳動(dòng)到 12 點(diǎn)整,協(xié)議好的金額就會(huì)從 Mark 的賬戶轉(zhuǎn)移到 Sara 的賬戶上去。Joe 也開(kāi)始使用智能合同來(lái)強(qiáng)制讓他的客戶支付協(xié)議好的貨款。

  • Sara 高興了,因?yàn)樗僖膊挥萌┬?Mark 會(huì)不會(huì)如約付房租了。Joe 也高興,因?yàn)樗膊挥谜曳ㄔ阂f(shuō)法了,省下這些精力,他可以繼續(xù)發(fā)展自己的生意了。

私有區(qū)塊鏈只限于業(yè)務(wù)中涉及到的相關(guān)各方,因此 Joe 不會(huì)是 Sara 和 Mark 所屬區(qū)塊鏈網(wǎng)絡(luò)的一部分。

前行之路

[[219575]]

現(xiàn)在你對(duì)此是不是已經(jīng)有點(diǎn)概念了?如果還是不理解,看看小編之前發(fā)布的文章技術(shù)人再不懂區(qū)塊鏈,你就OUT了?不過(guò)下面這篇文章也能讓你秒懂區(qū)塊鏈。

區(qū)塊鏈與裸照:一個(gè)去中心化的色情網(wǎng)站是什么樣的?

“區(qū)塊鏈”概念已火,雖然大部分人對(duì)“區(qū)塊鏈”好奇,甚至眼饞,但不少還處于不求甚解的懵逼階段.....正好最近我一直在研究區(qū)塊鏈,同時(shí)也見(jiàn)了幾個(gè)圈內(nèi)人深聊了下,就想為大家寫(xiě)一個(gè)“入門(mén)級(jí)”的區(qū)塊鏈介紹文章。

為了通俗易懂,我決定不惜自毀清譽(yù),用充滿荷爾蒙的比喻。因?yàn)榧祭顺泵看未_實(shí)都性感得讓人荷爾蒙爆炸啊,性(huang)感(bao)內(nèi)容開(kāi)始。

[[219576]]

以前,大家想看陳老師的裸照,都要去一個(gè)叫 1025 的網(wǎng)站,這就是中心化。

后來(lái),1025 網(wǎng)站被和諧掉了,大部分猥瑣男們傻逼了沒(méi)有網(wǎng)站看片了,因?yàn)樗麄兲嘈胖行幕M織了,還天天被 1025 彈窗“皇家澳門(mén)賭場(chǎng)”的小廣告真是活該啊。

不過(guò)沒(méi)關(guān)系,陳老師的 2100 張裸照,幸存在 100 萬(wàn)個(gè)猥瑣男的電腦里,除非地球毀滅,不然陳老師的裸照不可能絕跡。這就是去中心化,數(shù)據(jù)分布式存儲(chǔ)。

后來(lái),有個(gè)叫“中本粗”的超級(jí)猥瑣男,是陳老師 2100 張裸照的超級(jí)發(fā)騷友。為了2100張照片永遠(yuǎn)不消失,為世人所享用,他做了一個(gè)互聯(lián)網(wǎng)共享文件夾“陳老師plus”。

如果猥瑣男們想獲取“陳老師plus”2100 張的觀看權(quán),就必須加入一個(gè)電子協(xié)議中:不得復(fù)制、修改、P 任何“陳老師plus”中的照片,用戶在“陳老師plus”發(fā)生的任何行為,都會(huì)按時(shí)間戳記錄!

例如,“小張?jiān)?2018 年 1 月 9 日中午 12:00,查看了編號(hào)為 103 的照片,并在 13:00 刪除了編號(hào) 1-100 的 100 張照片.....”

小張的行為被記錄并廣播給其他 100 萬(wàn)個(gè)猥瑣男,“陳老師plus”的 2100 張照片會(huì)得到保護(hù),小張電腦中“陳老師plus”會(huì)按時(shí)間戳中最新記錄,同步其他 100 萬(wàn)個(gè)猥瑣男的電腦里的數(shù)據(jù),復(fù)原小張電腦中的數(shù)據(jù)...

小張永遠(yuǎn)別想對(duì)“陳老師plus”搞修改破壞,且所有行為都同步記錄在其他猥瑣男的電腦里。

這就是區(qū)塊鏈,數(shù)據(jù)分散存儲(chǔ),去中心化,按時(shí)間戳廣播記錄所有行為,無(wú)法修改、破壞數(shù)據(jù)源或造假,除非同一時(shí)刻炸掉 100 萬(wàn)個(gè)猥瑣男的電腦,或互聯(lián)網(wǎng)消失,或世界毀滅.....

當(dāng)然,也有唯一一種特殊情況,可以增加“陳老師plus”文件夾中的照片,這種情況叫做“區(qū)塊鏈共識(shí)層”,顧名思義,這是 100 萬(wàn)猥瑣男達(dá)成的增加照片共識(shí),你不能瞎增加的。

中本粗最初設(shè)定協(xié)議時(shí),把“猥瑣男們可以用 X 相機(jī),在每年 XX 時(shí)間,拍陳老師的裸照,前 100 張可以添加進(jìn)入‘陳老師plus’中增加作為文件夾照片”,那么,“陳老師plus”每年就可以增長(zhǎng) 100 張照片了。

當(dāng)然,你還可以給照片估價(jià)嘛,發(fā)行“陳老師plus”幣。因?yàn)椋?ldquo;陳老師plus”中每張照片都是不可造假破壞的,所以具有唯一性,還有單獨(dú)編號(hào),我們就給每一張照片估價(jià),它不就值錢(qián)了嗎?就像現(xiàn)實(shí)世界中無(wú)法復(fù)制的名畫(huà)一樣??!

怎么估值?就進(jìn)行所謂的 ICO(Initial Coin Offering)啊,就是我和李哭來(lái)老師成立一個(gè)基金,舉行一張發(fā)布會(huì),就說(shuō)我們給這 2100 張照片估值個(gè) 1.05 億!每張照片 5 萬(wàn)!

我們先丟 5050 萬(wàn)進(jìn)去認(rèn)購(gòu)前 1100 張,其他猥瑣男可以眾籌 5000 萬(wàn)買(mǎi)剩下的 1000 張照片,不想要了?賣(mài)給我和李哭來(lái)基金就行,我們認(rèn)它值錢(qián)啊,我們這么牛逼不會(huì)騙你的。

自從有了區(qū)塊鏈——我們?cè)僖膊慌?1025 們作惡,給我們彈窗小廣告,給我們下病毒了;再也不怕陳老師的照片丟失被破壞了,1984 老大哥復(fù)活都做不到.....

當(dāng)然,也有煩惱,就是有炒名畫(huà)的現(xiàn)在來(lái)炒“陳老師plus”照片了,把價(jià)格搞得很高。

還有的更猥瑣,為了賺錢(qián),自己拍了一堆裸照按照這個(gè)模式弄了個(gè)“某某老師plus”東施效顰收割韭菜,這就叫山寨幣,現(xiàn)在大概快一百種了吧。

看到這里,你肯定能明白區(qū)塊鏈了......最后,教大家怎么用 200 行 Go 代碼寫(xiě)一個(gè)自己的區(qū)塊鏈!

只用 200 行 Go 代碼寫(xiě)一個(gè)自己的區(qū)塊鏈

這篇文章就是幫助你使用 Go 語(yǔ)言來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的區(qū)塊鏈,用不到 200 行代碼來(lái)揭示區(qū)塊鏈的原理!

“用不到 200 行 Go 代碼就能實(shí)現(xiàn)一個(gè)自己的區(qū)塊鏈!” 聽(tīng)起來(lái)有意思嗎?有什么能比開(kāi)發(fā)一個(gè)自己的區(qū)塊鏈更好的學(xué)習(xí)實(shí)踐方法呢?那我們就一起來(lái)實(shí)踐下!

因?yàn)槲覀兪且患覐氖箩t(yī)療健康領(lǐng)域的科技公司,所以我們采用人類(lèi)平靜時(shí)的心跳數(shù)據(jù)(BPM 心率)作為這篇文章中的示例數(shù)據(jù)。

讓我們先來(lái)統(tǒng)計(jì)一下你一分鐘內(nèi)的心跳數(shù),然后記下來(lái),這個(gè)數(shù)字可能會(huì)在接下來(lái)的內(nèi)容中用到。

通過(guò)本文,你將可以做到:

  • 創(chuàng)建自己的區(qū)塊鏈
  • 理解 hash 函數(shù)是如何保持區(qū)塊鏈的完整性
  • 如何創(chuàng)造并添加新的塊
  • 多個(gè)節(jié)點(diǎn)如何競(jìng)爭(zhēng)生成塊
  • 通過(guò)瀏覽器來(lái)查看整個(gè)鏈
  • 所有其他關(guān)于區(qū)塊鏈的基礎(chǔ)知識(shí)

但是,對(duì)于比如工作量證明算法(PoW)以及權(quán)益證明算法(PoS)這類(lèi)的共識(shí)算法文章中將不會(huì)涉及。

同時(shí)為了讓你更清楚得查看區(qū)塊鏈以及塊的添加,我們將網(wǎng)絡(luò)交互的過(guò)程簡(jiǎn)化了,關(guān)于 P2P 網(wǎng)絡(luò)比如“全網(wǎng)廣播”這個(gè)過(guò)程等內(nèi)容將在下一篇文章中補(bǔ)上。讓我們開(kāi)始吧!

設(shè)置

我們假設(shè)你已經(jīng)具備一點(diǎn) Go 語(yǔ)言的開(kāi)發(fā)經(jīng)驗(yàn)。在安裝和配置 Go 開(kāi)發(fā)環(huán)境后之后,我們還要獲取以下一些依賴:

  1. go get github.com/davecgh/go-spew/spew 

spew 可以幫助我們?cè)?console 中直接查看 struct 和 slice 這兩種數(shù)據(jù)結(jié)構(gòu)。

  1. go get github.com/gorilla/mux 

Gorilla 的 mux 包非常流行, 我們用它來(lái)寫(xiě) Web handler。

  1. go get github.com/joho/godotenv 

godotenv 可以幫助我們讀取項(xiàng)目根目錄中的 .env 配置文件,這樣我們就不用將 http port 之類(lèi)的配置硬編碼進(jìn)代碼中了。比如像這樣:

  1. ADDR=8080 

接下來(lái),我們創(chuàng)建一個(gè) main.go 文件。之后我們的大部分工作都圍繞這個(gè)文件,讓我開(kāi)始編碼吧!

導(dǎo)入依賴

我們將所有的依賴包以聲明的方式導(dǎo)入進(jìn)去:

  1. package main 
  2.  
  3. import ( 
  4.     "crypto/sha256" 
  5.     "encoding/hex" 
  6.     "encoding/json" 
  7.     "io" 
  8.     "log" 
  9.     "net/http" 
  10.     "os" 
  11.     "time" 
  12.  
  13.     "github.com/davecgh/go-spew/spew" 
  14.     "github.com/gorilla/mux" 
  15.     "github.com/joho/godotenv" 

數(shù)據(jù)模型

接著我們來(lái)定義一個(gè)結(jié)構(gòu)體,它代表組成區(qū)塊鏈的每一個(gè)塊的數(shù)據(jù)模型:

  1. type Block struct { 
  2.     Index     int 
  3.     Timestamp string 
  4.     BPM       int 
  5.     Hash      string 
  6.     PrevHash  string 
  • Index 是這個(gè)塊在整個(gè)鏈中的位置。
  • Timestamp 顯而易見(jiàn)就是塊生成時(shí)的時(shí)間戳。
  • Hash 是這個(gè)塊通過(guò) SHA256 算法生成的散列值。
  • PrevHash 代表前一個(gè)塊的 SHA256 散列值。
  • BPM 每分鐘心跳數(shù),也就是心率。還記得文章開(kāi)頭說(shuō)到的嗎?

接著,我們?cè)俣x一個(gè)結(jié)構(gòu)表示整個(gè)鏈,最簡(jiǎn)單的表示形式就是一個(gè) Block 的 slice:

  1. var Blockchain []Block 

我們使用散列算法(SHA256)來(lái)確定和維護(hù)鏈中塊和塊正確的順序,確保每一個(gè)塊的 PrevHash 值等于前一個(gè)塊中的 Hash 值,這樣就以正確的塊順序構(gòu)建出鏈:

散列和生成塊

我們?yōu)槭裁葱枰⒘??主要是兩個(gè)原因:

  • 在節(jié)省空間的前提下去唯一標(biāo)識(shí)數(shù)據(jù)。散列是用整個(gè)塊的數(shù)據(jù)計(jì)算得出,在我們的例子中,將整個(gè)塊的數(shù)據(jù)通過(guò) SHA256 計(jì)算成一個(gè)定長(zhǎng)不可偽造的字符串。
  • 維持鏈的完整性。通過(guò)存儲(chǔ)前一個(gè)塊的散列值,我們就能夠確保每個(gè)塊在鏈中的正確順序。任何對(duì)數(shù)據(jù)的篡改都將改變散列值,同時(shí)也就破壞了鏈。

以我們從事的醫(yī)療健康領(lǐng)域?yàn)槔热缬幸粋€(gè)惡意的第三方為了調(diào)整“人壽險(xiǎn)”的價(jià)格,而修改了一個(gè)或若干個(gè)塊中的代表不健康的 BPM 值,那么整個(gè)鏈都變得不可信了。

我們接著寫(xiě)一個(gè)函數(shù),用來(lái)計(jì)算給定的數(shù)據(jù)的 SHA256 散列值:

  1. func calculateHash(block Block) string { 
  2.     record := string(block.Index) + block.Timestamp + string(block.BPM) + block.PrevHash 
  3.     h := sha256.New() 
  4.     h.Write([]byte(record)) 
  5.     hashed := h.Sum(nil) 
  6.     return hex.EncodeToString(hashed) 

這個(gè) calculateHash 函數(shù)接受一個(gè)塊,通過(guò)塊中的 Index,Timestamp,BPM,以及 PrevHash 值來(lái)計(jì)算出 SHA256 散列值。

接下來(lái)我們就能便攜一個(gè)生成塊的函數(shù):

  1. func generateBlock(oldBlock Block, BPM int) (Block, error) { 
  2.     var newBlock Block 
  3.  
  4.     t := time.Now() 
  5.     newBlock.Index = oldBlock.Index + 1 
  6.     newBlock.Timestamp = t.String() 
  7.     newBlock.BPM = BPM 
  8.     newBlock.PrevHash = oldBlock.Hash 
  9.     newBlock.Hash = calculateHash(newBlock) 
  10.  
  11.     return newBlock, nil 

其中,Index 是從給定的前一塊的 Index 遞增得出,時(shí)間戳是直接通過(guò) time.Now() 函數(shù)來(lái)獲得的,Hash 值通過(guò)前面的 calculateHash 函數(shù)計(jì)算得出,PrevHash 則是給定的前一個(gè)塊的 Hash 值。

校驗(yàn)塊

搞定了塊的生成,接下來(lái)我們需要有函數(shù)幫我們判斷一個(gè)塊是否有被篡改。檢查 Index 來(lái)看這個(gè)塊是否正確得遞增,檢查 PrevHash 與前一個(gè)塊的 Hash 是否一致,再來(lái)通過(guò) calculateHash 檢查當(dāng)前塊的 Hash 值是否正確。

通過(guò)這幾步我們就能寫(xiě)出一個(gè)校驗(yàn)函數(shù):

  1. func isBlockValid(newBlock, oldBlock Block) bool { 
  2.     if oldBlock.Index+1 != newBlock.Index { 
  3.         return false 
  4.     } 
  5.     if oldBlock.Hash != newBlock.PrevHash { 
  6.         return false 
  7.     } 
  8.     if calculateHash(newBlock) != newBlock.Hash { 
  9.         return false 
  10.     } 
  11.     return true 

除了校驗(yàn)塊以外,我們還會(huì)遇到一個(gè)問(wèn)題:兩個(gè)節(jié)點(diǎn)都生成塊并添加到各自的鏈上,那我們應(yīng)該以誰(shuí)為準(zhǔn)?這里的細(xì)節(jié)我們留到下一篇文章,這里先讓我們記住一個(gè)原則:始終選擇最長(zhǎng)的鏈。

通常來(lái)說(shuō),更長(zhǎng)的鏈表示它的數(shù)據(jù)(狀態(tài))是更新的,所以我們需要一個(gè)函數(shù)能幫我們將本地的過(guò)期的鏈切換成最新的鏈:

  1. func replaceChain(newBlocks []Block) { 
  2.     if len(newBlocks) > len(Blockchain) { 
  3.         Blockchain = newBlocks 
  4.     } 

到這一步,我們基本就把所有重要的函數(shù)完成了。接下來(lái),我們需要一個(gè)方便直觀的方式來(lái)查看我們的鏈,包括數(shù)據(jù)及狀態(tài)。通過(guò)瀏覽器查看 Web 頁(yè)面可能是最合適的方式!

Web 服務(wù)

我猜你一定對(duì)傳統(tǒng)的 Web 服務(wù)及開(kāi)發(fā)非常熟悉,所以這部分你肯定一看就會(huì)。

借助 Gorilla/mux 包,我們先寫(xiě)一個(gè)函數(shù)來(lái)初始化我們的 Web 服務(wù):

  1. func run() error { 
  2.     mux := makeMuxRouter() 
  3.     httpAddr := os.Getenv("ADDR"
  4.     log.Println("Listening on ", os.Getenv("ADDR")) 
  5.     s := &http.Server{ 
  6.         Addr:           ":" + httpAddr, 
  7.         Handler:        mux, 
  8.         ReadTimeout:    10 * time.Second
  9.         WriteTimeout:   10 * time.Second
  10.         MaxHeaderBytes: 1 << 20, 
  11.     } 
  12.  
  13.     if err := s.ListenAndServe(); err != nil { 
  14.         return err 
  15.     } 
  16.  
  17.     return nil 

其中的端口號(hào)是通過(guò)前面提到的 .env 來(lái)獲得,再添加一些基本的配置參數(shù),這個(gè) web 服務(wù)就已經(jīng)可以 listen and serve 了!

接下來(lái)我們?cè)賮?lái)定義不同 endpoint 以及對(duì)應(yīng)的 handler。例如,對(duì)“/”的 GET 請(qǐng)求我們可以查看整個(gè)鏈,“/”的 POST 請(qǐng)求可以創(chuàng)建塊。

  1. func makeMuxRouter() http.Handler { 
  2.     muxRouter := mux.NewRouter() 
  3.     muxRouter.HandleFunc("/", handleGetBlockchain).Methods("GET"
  4.     muxRouter.HandleFunc("/", handleWriteBlock).Methods("POST"
  5.     return muxRouter 

GET 請(qǐng)求的 handler:

  1. func handleGetBlockchain(w http.ResponseWriter, r *http.Request) { 
  2.     bytes, err := json.MarshalIndent(Blockchain, """  "
  3.     if err != nil { 
  4.         http.Error(w, err.Error(), http.StatusInternalServerError) 
  5.         return 
  6.     } 
  7.     io.WriteString(w, string(bytes)) 

為了簡(jiǎn)化,我們直接以 JSON 格式返回整個(gè)鏈,你可以在瀏覽器中訪問(wèn) localhost:8080 或者 127.0.0.1:8080 來(lái)查看(這里的 8080 就是你在 .env 中定義的端口號(hào) ADDR)。

POST 請(qǐng)求的 handler 稍微有些復(fù)雜,我們先來(lái)定義一下 POST 請(qǐng)求的 payload:

  1. type Message struct { 
  2.     BPM int 

再看看 handler 的實(shí)現(xiàn):

  1. func handleWriteBlock(w http.ResponseWriter, r *http.Request) { 
  2.     var m Message 
  3.  
  4.     decoder := json.NewDecoder(r.Body) 
  5.     if err := decoder.Decode(&m); err != nil { 
  6.         respondWithJSON(w, r, http.StatusBadRequest, r.Body) 
  7.         return 
  8.     } 
  9.     defer r.Body.Close() 
  10.  
  11.     newBlock, err := generateBlock(Blockchain[len(Blockchain)-1], m.BPM) 
  12.     if err != nil { 
  13.         respondWithJSON(w, r, http.StatusInternalServerError, m) 
  14.         return 
  15.     } 
  16.     if isBlockValid(newBlock, Blockchain[len(Blockchain)-1]) { 
  17.         newBlockchain := append(Blockchain, newBlock) 
  18.         replaceChain(newBlockchain) 
  19.         spew.Dump(Blockchain) 
  20.     } 
  21.  
  22.     respondWithJSON(w, r, http.StatusCreated, newBlock) 
  23.  

我們的 POST 請(qǐng)求體中可以使用上面定義的 payload,比如:

  1. {"BPM":75} 

還記得前面我們寫(xiě)的 generateBlock 這個(gè)函數(shù)嗎?它接受一個(gè)“前一個(gè)塊”參數(shù),和一個(gè) BPM 值。

POST handler 接受請(qǐng)求后就能獲得請(qǐng)求體中的 BPM 值,接著借助生成塊的函數(shù)以及校驗(yàn)塊的函數(shù)就能生成一個(gè)新的塊了!

除此之外,你也可以:

  • 使用 spew.Dump 這個(gè)函數(shù)可以以非常美觀和方便閱讀的方式將 struct、slice 等數(shù)據(jù)打印在控制臺(tái)里,方便我們調(diào)試。
  • 測(cè)試 POST 請(qǐng)求時(shí),可以使用 POSTMAN 這個(gè) chrome 插件,相比 curl它更直觀和方便。

POST 請(qǐng)求處理完之后,無(wú)論創(chuàng)建塊成功與否,我們需要返回客戶端一個(gè)響應(yīng):

  1. func respondWithJSON(w http.ResponseWriter, r *http.Request, code int, payload interface{}) { 
  2.     response, err := json.MarshalIndent(payload, """  "
  3.     if err != nil { 
  4.         w.WriteHeader(http.StatusInternalServerError) 
  5.         w.Write([]byte("HTTP 500: Internal Server Error")) 
  6.         return 
  7.     } 
  8.     w.WriteHeader(code) 
  9.     w.Write(response) 

快要大功告成了

接下來(lái),我們把這些關(guān)于區(qū)塊鏈的函數(shù),Web 服務(wù)的函數(shù)“組裝”起來(lái):

  1. func main() { 
  2.     err := godotenv.Load() 
  3.     if err != nil { 
  4.         log.Fatal(err) 
  5.     } 
  6.  
  7.     go func() { 
  8.         t := time.Now() 
  9.         genesisBlock := Block{0, t.String(), 0, """"
  10.         spew.Dump(genesisBlock) 
  11.         Blockchain = append(Blockchain, genesisBlock) 
  12.     }() 
  13.     log.Fatal(run()) 
  14.  

這里的 genesisBlock (創(chuàng)世塊)是 main 函數(shù)中最重要的部分,通過(guò)它來(lái)初始化區(qū)塊鏈,畢竟第一個(gè)塊的 PrevHash 是空的。

哦耶!完成了

你們可以從這里獲得完整的代碼:Github repo[1]

讓我們來(lái)啟動(dòng)它:

  1. go run main.go 

在終端中,我們可以看到 web 服務(wù)器啟動(dòng)的日志信息,并且打印出了創(chuàng)世塊的信息:

接著我們打開(kāi)瀏覽器,訪問(wèn) localhost:8080 這個(gè)地址,我們可以看到頁(yè)面中展示了當(dāng)前整個(gè)區(qū)塊鏈的信息(當(dāng)然,目前只有一個(gè)創(chuàng)世塊):

接著,我們?cè)偻ㄟ^(guò) POSTMAN 來(lái)發(fā)送一些 POST 請(qǐng)求:

刷新剛才的頁(yè)面,現(xiàn)在的鏈中多了一些塊,正是我們剛才生成的,同時(shí)你們可以看到,塊的順序和散列值都正確。

下一步

剛剛我們完成了一個(gè)自己的區(qū)塊鏈,雖然很簡(jiǎn)單(陋),但它具備塊生成、散列計(jì)算、塊校驗(yàn)等基本能力。

接下來(lái)你就可以繼續(xù)深入的學(xué)習(xí)區(qū)塊鏈的其他重要知識(shí),比如工作量證明、權(quán)益證明這樣的共識(shí)算法,或者是智能合約、Dapp、側(cè)鏈等等。

目前這個(gè)實(shí)現(xiàn)中不包括任何 P2P 網(wǎng)絡(luò)的內(nèi)容,我們會(huì)在下一篇文章中補(bǔ)充這部分內(nèi)容,當(dāng)然,我們鼓勵(lì)你在這個(gè)基礎(chǔ)上自己實(shí)踐一遍!

 

責(zé)任編輯:武曉燕 來(lái)源: 51CTO技術(shù)棧
相關(guān)推薦

2019-06-05 15:00:28

Java代碼區(qū)塊鏈

2020-09-06 08:20:10

區(qū)塊鏈分布式比特幣

2021-01-19 22:44:26

區(qū)塊鏈新基建數(shù)據(jù)

2019-07-29 15:11:04

區(qū)塊鏈網(wǎng)絡(luò)存儲(chǔ)

2018-03-05 18:30:27

區(qū)塊鏈側(cè)鏈共識(shí)算法

2018-04-02 16:35:57

區(qū)塊鏈數(shù)字貨幣比特幣

2021-07-29 16:58:22

區(qū)塊鏈比特幣數(shù)字貨幣

2021-09-23 22:40:10

區(qū)塊鏈比特幣技術(shù)

2018-03-19 17:40:10

Python區(qū)塊鏈

2018-05-15 10:26:10

區(qū)塊鏈數(shù)字貨幣比特幣

2018-08-20 20:22:05

區(qū)塊鏈互聯(lián)網(wǎng)未來(lái)

2018-03-27 09:52:30

區(qū)塊鏈數(shù)字貨幣比特幣

2018-04-13 10:31:14

2021-04-09 06:25:41

區(qū)塊鏈區(qū)塊鏈技術(shù)

2022-10-26 08:42:28

2017-07-19 07:27:39

區(qū)塊鏈ICO監(jiān)管

2018-03-30 10:10:11

區(qū)塊鏈數(shù)字貨幣記賬模式

2018-06-14 11:02:37

區(qū)塊鏈支付寶去中心化

2020-05-13 09:45:08

區(qū)塊鏈公共區(qū)塊鏈私有區(qū)塊鏈

2021-02-24 13:58:07

區(qū)塊鏈比特幣安全
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)