溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法

發(fā)布時(shí)間:2021-08-30 11:29:35 來(lái)源:億速云 閱讀:150 作者:chen 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹“區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法”,在日常操作中,相信很多人在區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

概念解讀

區(qū)塊鏈幾乎是數(shù)日間成為人盡皆知的名詞,這個(gè)名詞也勾起了我強(qiáng)烈的興趣,但是通過(guò)在網(wǎng)上搜羅資料,多方閱讀,發(fā)現(xiàn)很多介紹區(qū)塊鏈的文獻(xiàn)要么模棱兩可,要么作者本身的理解也很有限,導(dǎo)致很多關(guān)鍵的問(wèn)題敘述不清。本人花了一些時(shí)間總結(jié)歸納,希望可以給讀者一個(gè)比較全面清晰的認(rèn)識(shí)。

區(qū)塊鏈的官方定義是:一個(gè)分布式賬本,一種通過(guò)去中心化、去信任的方式集體維護(hù)一個(gè)可靠數(shù)據(jù)庫(kù)的技術(shù)方案。那么對(duì)于圈外人該如何理解呢?以下我會(huì)詳細(xì)描述一個(gè)區(qū)塊鏈的產(chǎn)生過(guò)程和實(shí)現(xiàn)意義,從而給大家構(gòu)建出一個(gè)清晰的區(qū)塊鏈概念。我們先講原理、再說(shuō)特點(diǎn)、然后論用途、最后回歸代碼,這樣你就會(huì)有一種恍然大悟的感覺(jué)。

我們以btc為例:“區(qū)塊鏈”,顧名思義,就是由一個(gè)個(gè)區(qū)塊依次連接起來(lái)組成的鏈條,可以類比為一條無(wú)限長(zhǎng)度的直線鐵鏈,每個(gè)鐵環(huán)就是一個(gè)區(qū)塊。那么區(qū)塊的內(nèi)容應(yīng)該是什么呢?區(qū)塊狹義上是有兩種的,一個(gè)是普通區(qū)塊,一個(gè)就是創(chuàng)世區(qū)塊。創(chuàng)世區(qū)塊就是一項(xiàng)區(qū)塊鏈項(xiàng)目中的第一個(gè)區(qū)塊,由于個(gè)人水平有限,對(duì)創(chuàng)世區(qū)塊沒(méi)有做過(guò)詳細(xì)研究,但是根據(jù)我的了解,創(chuàng)世區(qū)塊應(yīng)該是具備與普通區(qū)塊相似結(jié)構(gòu)的,但會(huì)肯定會(huì)加入一些創(chuàng)始人想說(shuō)的東西,并且在有些項(xiàng)目中可能會(huì)多一條記錄,就是coin的發(fā)行量,例如swtc的6000億數(shù)目就是寫(xiě)在創(chuàng)世區(qū)塊之中的,一旦發(fā)行,無(wú)法修改。

那么,一個(gè)普通區(qū)塊中到底有什么?

1.index:就是從0-n依次產(chǎn)生的數(shù)字,可以稱之為鏈高度。

2.hash:一個(gè)長(zhǎng)度為256位隨機(jī)數(shù),是這個(gè)區(qū)塊的唯一編號(hào)。

3.previous hash:上一個(gè)區(qū)塊的hash,一個(gè)普通區(qū)塊有且僅有一個(gè)previous hash,這就是區(qū)塊鏈之所以稱為鏈的原因,就是這么一環(huán)套一環(huán)鏈接而成的。

4.tempstamp:用于記錄該區(qū)塊誕生的時(shí)間。

5.difficulty:直觀體現(xiàn)創(chuàng)造該區(qū)塊的難度。

6.nonce:隨機(jī)數(shù),用于產(chǎn)生下一個(gè)區(qū)塊。

上述的都存在區(qū)塊頭中。

7.data:存儲(chǔ)的交易記錄。只有這個(gè)存在區(qū)塊體中。

Ok,上述提到了一個(gè)區(qū)塊需要具備的最基本的幾條要素,可能你現(xiàn)在還處于一臉懵逼的狀態(tài):這些東西到底是怎么工作的呢?下面我將一步步分析區(qū)塊鏈的工作過(guò)程,不過(guò),這里要先問(wèn)兩個(gè)問(wèn)題:為什么要產(chǎn)生新的區(qū)塊?怎么產(chǎn)生新的區(qū)塊?

為什么產(chǎn)生新區(qū)快?

之前說(shuō)了,一個(gè)區(qū)塊記錄的就是一份賬單,賬單中存儲(chǔ)著若干條交易記錄,是買賣雙方具體活動(dòng)的最有力的證明,例如我們?cè)谔詫毶系馁?gòu)買記錄,就是我們的消費(fèi)賬單。人們每天的消費(fèi)記錄是不斷增長(zhǎng)的,不可能永遠(yuǎn)放在一個(gè)區(qū)塊里,那么跟現(xiàn)在的中心化存儲(chǔ)機(jī)制還有什么區(qū)別?所以,隨著買賣記錄的不斷增加,就需要不斷產(chǎn)生新的區(qū)塊來(lái)存儲(chǔ)這些數(shù)據(jù)。

怎么產(chǎn)生新的區(qū)塊?

我相信,最近除了區(qū)塊鏈這個(gè)名詞如雷貫耳以外,“挖礦”應(yīng)該也沒(méi)少聽(tīng)吧。挖礦實(shí)際上就是由那些礦工來(lái)生成新的區(qū)塊的過(guò)程。在btc項(xiàng)目中,btc礦工挖礦成功(其實(shí)就是成功的創(chuàng)建了一個(gè)區(qū)塊)就可以獲得一定數(shù)量的被btc獎(jiǎng)勵(lì),所以btc數(shù)量是在一定范圍內(nèi)慢慢增加的。在一般允許挖礦的區(qū)塊鏈項(xiàng)目(也存在限制coin數(shù)量不允許挖礦的區(qū)塊鏈項(xiàng)目)中,礦工的數(shù)量一般會(huì)大于6個(gè),一般超過(guò)6個(gè)礦工認(rèn)可的新區(qū)塊就可以加入到區(qū)塊鏈中。到此為止,有人會(huì)說(shuō):哇!btc這么值錢,挖礦不是很爽?其實(shí)不然,如果區(qū)塊無(wú)限制的快速增加,會(huì)引起很大的問(wèn)題,根據(jù)中本聰?shù)脑O(shè)定,目前全網(wǎng)每10分鐘只能產(chǎn)生一個(gè)新區(qū)塊。而且這10分鐘不是靠自己掐表算的,生成新的區(qū)塊是需要大量的運(yùn)算的,這10分鐘是人家預(yù)先設(shè)計(jì)好的,讓計(jì)算量大到全網(wǎng)10分鐘一般只能產(chǎn)生一個(gè)。

好了,至此,區(qū)塊鏈的基本概念已經(jīng)介紹的差不多了,下面言歸正傳,講下區(qū)塊的工作流程:

1.如果A要和B達(dá)成一筆交易,比如A轉(zhuǎn)給B一個(gè)btc,B給A打10w的RMB。A首先將自己的btc來(lái)源信息、交易人等發(fā)送給B,同時(shí)還要拷貝一份發(fā)到全網(wǎng)。什么?這樣還有隱私可言嗎?當(dāng)然,聰明的中本聰當(dāng)然不會(huì)犯這么低級(jí)的錯(cuò)誤。在區(qū)塊鏈中,每個(gè)交易個(gè)體(也可以理解為每個(gè)網(wǎng)絡(luò)節(jié)點(diǎn))都會(huì)有一對(duì)公鑰和私鑰,公鑰相當(dāng)于一個(gè)“收款地址”,而私鑰是一個(gè)表明自己身份的256位的數(shù)字,目前一般是用sha265來(lái)生成的,這樣,別人并不知道交易的雙方是誰(shuí)。發(fā)送報(bào)文時(shí),發(fā)送方用一個(gè)哈希函數(shù)從報(bào)文文本中生成報(bào)文摘要,然后用自己的私鑰對(duì)摘要進(jìn)行加密,加密后的摘要將作為報(bào)文的數(shù)字簽名和報(bào)文一起發(fā)送給接收方,接收方首先用與發(fā)送方一樣的哈希函數(shù)從接收到的原始報(bào)文中計(jì)算出報(bào)文摘要,接著再用發(fā)送方的公鑰來(lái)對(duì)報(bào)文附加的數(shù)字簽名進(jìn)行解密,如果這兩個(gè)摘要相同、那么接收方就能確認(rèn)該數(shù)字簽名是發(fā)送方的。

2.那么此時(shí),這筆交易是否就完成了呢?如果這就算完成了,那跟A直接用包裹裝10w現(xiàn)金快遞給B有什么區(qū)別呢?此時(shí),全網(wǎng)的礦工都會(huì)得到這個(gè)交易記錄,那么全網(wǎng)的礦工都會(huì)為了若干獎(jiǎng)勵(lì)開(kāi)始創(chuàng)建區(qū)塊的工作,礦工會(huì)利用hash函數(shù)生成一個(gè)256位的唯一編號(hào)賦予這個(gè)區(qū)塊,但是這個(gè)編號(hào)并不是簡(jiǎn)簡(jiǎn)單單隨便生成的。編號(hào)是根據(jù)區(qū)塊的具體內(nèi)容如交易內(nèi)容、nonce等唯一確定的,換句話說(shuō),兩塊內(nèi)容相同的區(qū)塊所對(duì)應(yīng)的編號(hào)一定是唯一的??墒悄銜?huì)問(wèn):這又怎么了?并不難啊。錯(cuò)!中本聰為了控制區(qū)塊的生成時(shí)間,使區(qū)塊的生成速率滿足全網(wǎng)的每10分鐘一個(gè)的標(biāo)準(zhǔn),制定了嚴(yán)格的區(qū)塊生成校驗(yàn)規(guī)則,也就是說(shuō),能不能生成一個(gè)成功的區(qū)塊要看你的編號(hào)是否符合這個(gè)規(guī)則。例如:生成編號(hào)中的前n位必須為‘0’。

由于區(qū)塊的交易內(nèi)容是無(wú)法修改的,因此礦工們只能通過(guò)修改nonce去不斷嘗試這個(gè)函數(shù),直到生成了一個(gè)成功的區(qū)塊為止。如果當(dāng)區(qū)塊平均生成時(shí)間變快或者變慢,那么系統(tǒng)會(huì)對(duì)區(qū)塊校驗(yàn)規(guī)則進(jìn)行相應(yīng)的調(diào)整,從而使平均的生成時(shí)間能夠控制在規(guī)定范圍。

如果一個(gè)礦工完成了一個(gè)區(qū)塊,會(huì)立刻告知其他礦工,如果其他礦工此時(shí)沒(méi)有完成新的區(qū)塊生成,則會(huì)停下手頭的工作,對(duì)區(qū)塊進(jìn)行驗(yàn)證,需要確認(rèn)的信息主要有如下幾點(diǎn):

1).區(qū)塊的編號(hào)有效;這個(gè)只要將區(qū)塊放入哈希函數(shù)中,看產(chǎn)生的編號(hào)是否和該區(qū)塊中的編號(hào)一致即可。

2).區(qū)塊的前一個(gè)區(qū)塊有效;之前提過(guò),區(qū)塊是一個(gè)串聯(lián)的,每一個(gè)普通區(qū)塊都會(huì)記載前一個(gè)區(qū)塊的編號(hào),這需要其他礦工對(duì)比當(dāng)前的區(qū)塊鏈的最后一個(gè)區(qū)塊,看是否相同。

3).交易清單有效;就是說(shuō)要驗(yàn)證A到底有沒(méi)有這一個(gè)btc可以給B。在區(qū)塊鏈的交易信息中,會(huì)記錄交易中所有btc的前世今生,區(qū)塊鏈可以做到追本溯源,因此每一個(gè)btc在哪里,為什么在這里都可以一目了然,所以這點(diǎn)也沒(méi)問(wèn)題。

當(dāng)驗(yàn)證完一個(gè)全新的區(qū)塊后,全網(wǎng)就會(huì)認(rèn)為這個(gè)區(qū)塊有效,會(huì)將它添加到現(xiàn)有的區(qū)塊鏈末端,同時(shí)結(jié)束針對(duì)該區(qū)塊的挖礦工作,投入到下一個(gè)挖礦周期中。

3.但是不難想象,這樣的機(jī)制是存在沖突的隱患的,就是這么巧,兩個(gè)礦工同時(shí)制作了一個(gè)正確的區(qū)塊,那么此時(shí)不必二選一,可以將原來(lái)線性的區(qū)塊鏈改成樹(shù)狀:

區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法

區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法

但是這樣會(huì)導(dǎo)致未來(lái)在A、B后都會(huì)增加相應(yīng)的區(qū)塊,那么誰(shuí)長(zhǎng)誰(shuí)將作為主鏈延伸下去,另一個(gè)也許會(huì)漸漸被遺忘,除非哪天它變得更長(zhǎng)。

好啦,這就是區(qū)塊鏈最基本的知識(shí),接下來(lái)應(yīng)該談?wù)剝?yōu)缺點(diǎn)了。

世界上沒(méi)有一樣?xùn)|西可以稱為完美無(wú)瑕的,要知道區(qū)塊鏈一樣,雖然它被扣上了可以顛覆未來(lái)的帽子,但是仍然存在它的局限性:

1.時(shí)效性。很容易發(fā)現(xiàn),區(qū)塊鏈中存在很多的驗(yàn)證、傳遞環(huán)節(jié),這就會(huì)導(dǎo)致其時(shí)效性較差。

2、能耗,這點(diǎn)也是顯而易見(jiàn)的,區(qū)塊鏈需要大量無(wú)用計(jì)算來(lái)控制區(qū)塊的生成時(shí)間。所以區(qū)塊鏈不適用于高時(shí)效的網(wǎng)絡(luò)中。

至于區(qū)塊鏈的優(yōu)點(diǎn),諸如安全、去中心化等等在網(wǎng)絡(luò)上已經(jīng)描述的非常清楚,這里就不再贅述。接下來(lái)我用一段python代碼來(lái)簡(jiǎn)單實(shí)現(xiàn)一個(gè)挖礦的流程。

代碼示例

首先創(chuàng)建一個(gè)表示區(qū)塊鏈的類:

class BlockChain:
    def __init__(self, initialHash):
        # init block chain
        self.chain = []

        # init pitman
        self.pitmen = []
        for i in range(6):
            self.pitmen.append(Pitman)

        # collect mine results
        self.results = []

        # generate GenesisBlock
        self.new_block(initialHash)

初始化函數(shù)中的chain表示當(dāng)前的區(qū)塊鏈,我會(huì)在其中存儲(chǔ)區(qū)塊對(duì)象;pitmen表示為這個(gè)區(qū)塊鏈服務(wù)的礦工們,這個(gè)列表中也會(huì)存有礦工對(duì)象;results則會(huì)存儲(chǔ)每個(gè)階段產(chǎn)生的區(qū)塊;new_block方法是創(chuàng)建區(qū)塊的方法,如果當(dāng)前生成的區(qū)塊為第一個(gè)區(qū)塊,則產(chǎn)生創(chuàng)世區(qū)塊。

下面看看區(qū)塊鏈類型的方法:

@property
def last_block(self):
    if len(self.chain):
        return self.chain[-1]
    else:
        return None

last_block會(huì)返回當(dāng)前區(qū)塊鏈的最后一個(gè)區(qū)塊對(duì)象。

def get_trans(self):
    return json.dumps({
        'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
        'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
        'amount': random.randrange(1, 10000)
    })

get_trans方法則用來(lái)隨機(jī)生成一份交易信息。

def new_block(self, initialHash=None):
    if initialHash:
        # generate Genesis Block
        block = Block()
        block.index = 0
        block.nonce = random.randrange(0, 99999)
        block.previousHash = '0'
        block.difficulty = 0
        block.transactionData = self.get_trans()
        guess = f'{block.previousHash}{block.nonce}{block.transactionData}'.encode()
        block.hash = hashlib.sha256(guess).hexdigest()
        block.time = time()
        self.chain.append(block)
    else:
        for i in range(len(self.pitmen)):
            pm = MyThread(target=self.pitmen[i].mine,
                                  args=(self.pitmen[i],
                                        len(self.chain),
                                        self.last_block.get_block()['Hash'],
                                        self.get_trans()))
            pm.start()
            pm.join()
            self.results.append(pm.get_result())

        # show all blocks
        print("All blocks generated by pitmen:")
        for result in self.results:
            print(result[0].get_block())

        # get new block
        firstblock = self.results[0][0]
        mintime = Decimal(self.results[0][1])
        for i in range(1, len(self.results)):
            if Decimal(self.results[i][1]) < mintime:
                firstblock = self.results[i][0]
            else:
                continue
        self.chain.append(firstblock)
        self.results = []

這是生成區(qū)塊的核心部分,這個(gè)方法主要分成兩個(gè)部分:根據(jù)傳參區(qū)分是否是創(chuàng)世區(qū)塊,如果需要的是創(chuàng)世區(qū)塊,那就由該類型自動(dòng)生成一個(gè)區(qū)塊占據(jù)區(qū)塊鏈的頭一個(gè)位置。如果需要生成的是普通區(qū)塊,那么則會(huì)將一些基本信息分發(fā)給礦工們進(jìn)行挖礦操作。我在這里設(shè)置了6個(gè)礦工,為了公平起見(jiàn),這里也開(kāi)了個(gè)多線程盡量讓礦工們同時(shí)收到消息從而可以同時(shí)進(jìn)行挖礦操作。按理說(shuō),最先挖礦成功的礦工會(huì)將消息發(fā)給其他礦工,其他礦工會(huì)立刻停止進(jìn)行校驗(yàn),但由于時(shí)間有限,這一步校驗(yàn)環(huán)節(jié)我沒(méi)有實(shí)現(xiàn)。在這里,我允許所有礦工都完成工作,并提交成果和相應(yīng)的工作時(shí)間,生成耗時(shí)最短的區(qū)塊講作為正確的區(qū)塊添加到區(qū)塊鏈上。本質(zhì)上也是依照了“快者優(yōu)先”的區(qū)塊鏈生成原則。

說(shuō)了半天,區(qū)塊內(nèi)部到底是什么樣的呢?

class Block:
    def __init__(self):
        self.index = None
        self.time = None
        self.difficulty = None
        self.nonce = None
        self.hash = None
        self.previousHash = None
        self.transactionData = None

    def get_block(self):
        return {
            'Index': self.index,
            'Time': self.time,
            'Difficulty': self.difficulty,
            'Hash': self.hash,
            'Nonce': self.nonce,
            'PreviousHash': self.previousHash,
            'TransactionData': self.transactionData
        }

我用了一個(gè)相對(duì)簡(jiǎn)單的類型表示區(qū)塊,在這里區(qū)塊就是一個(gè)非常簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),這里的所有字段在上述中已經(jīng)有了詳細(xì)的說(shuō)明,因此不再贅述。

那么我們?cè)倏纯吹V工,畢竟礦工才是區(qū)塊鏈的生產(chǎn)者和推動(dòng)者,地位最為核心。礦工類中我設(shè)計(jì)了兩個(gè)方法,一個(gè)mine方法,也就是挖礦的意思,用來(lái)生成新的區(qū)塊,并會(huì)返回該區(qū)塊生成的用時(shí)長(zhǎng)短。

def mine(self, index, previousHash, transactionData):
    beginTime = time()

    block = Block()
    block.index = index
    block.previousHash = previousHash
    block.transactionData = transactionData
    block.difficulty, block.hash, block.nonce = self.generate_hash(previousHash, transactionData)
    block.time = time()
    endTime = time()

    return block, endTime - beginTime

另一個(gè)方法是hash生成的方法,生成原則我自己意淫了一個(gè),大家莫怪,因?yàn)楸救擞?jì)算機(jī)的實(shí)在不給力,區(qū)塊的成功標(biāo)準(zhǔn)很簡(jiǎn)單,就是用sha256生成的編碼最后結(jié)尾是0就滿足要求,如果改成00,那會(huì)半天看不到結(jié)果。

下面我們看下這套實(shí)例的運(yùn)行結(jié)果,我設(shè)置了一個(gè)長(zhǎng)度為6的區(qū)塊鏈,由于第一個(gè)區(qū)塊是創(chuàng)世區(qū)塊,所以真正開(kāi)始創(chuàng)建的區(qū)塊是從第二個(gè)開(kāi)始的,大家注意index。

這是6個(gè)礦工完成的第一區(qū)塊:

All blocks generated by pitmen:
{'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 2, 'Hash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'Nonce': 91554, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "OY8z0Rrx", "recipient": "iSGFJsEm", "amount": 8723}'}
{'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 5, 'Hash': 'c3ba406bad0d87f816f629830a15e2997638bfa230484c224e5470eaa24d8790', 'Nonce': 62372, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "9o8UMDLe", "recipient": "qTOQu7kv", "amount": 2746}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 5, 'Hash': '8ff243885e9017296aa2ef1a611ef5b3927ddce818cb7255a04ff3228c982c60', 'Nonce': 67644, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "kIqy1c8C", "recipient": "WSdK0EXh", "amount": 9329}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 3, 'Hash': 'ff9716bf9379e2ab7a8640419e7c7b7c7329a5e6e1bbf83a1249f49d070ca8b0', 'Nonce': 37336, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "vBwU0luH", "recipient": "d7o6cRCj", "amount": 5628}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 3, 'Hash': '3410c70c31f9bacbfcbd74d63f25f69f27d36075e2d44bddaa60bd72fa042e60', 'Nonce': 34617, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "yzcNpBnh", "recipient": "vbIr7SKo", "amount": 6387}'}
{'Index': 1, 'Time': 1516268156.5981123, 'Difficulty': 27, 'Hash': '91e3dc3ef1a151557a1edd837528410b916362bcfb77dbb14dc54c8929f5a0d0', 'Nonce': 49121, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "p1MguhVz", "recipient": "gVSom4D3", "amount": 7356}'}

很明顯前兩個(gè)是最快的,為了簡(jiǎn)單,我在最快的里面隨便選取一個(gè),意思到了就行。大家可以看到,難度值,根據(jù)上文所說(shuō),這是反應(yīng)一個(gè)區(qū)塊生成的難易程度的,難度高的,在我這里會(huì)表示這個(gè)礦工為了得到這個(gè)區(qū)塊進(jìn)行了多少次嘗試??吹竭@里也許你會(huì)問(wèn):為什么難度最大的時(shí)間并沒(méi)有明顯長(zhǎng)呢?也就是用時(shí)并沒(méi)有按照難度的增加而增加。我猜想應(yīng)該是因?yàn)槲业氖纠惴ê?jiǎn)單,因此結(jié)果也不是十分精確,如果計(jì)算量達(dá)到一定的規(guī)模,應(yīng)該會(huì)有明顯的差距。(如果有高人知道,可以回復(fù)我,在此謝過(guò)?。┑谌降诹鶄€(gè)的區(qū)塊創(chuàng)建結(jié)果格式是與之一樣的,就不刷屏了。

最后看下整個(gè)區(qū)塊鏈的結(jié)果:

{'Index': 0, 'Time': 1516268156.5971138, 'Difficulty': 0, 'Hash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'Nonce': 87688, 'PreviousHash': '0', 'TransactionData': '{"sender": "OuVCmHbs", "recipient": "kFxbwSLc", "amount": 503}'}
{'Index': 1, 'Time': 1516268156.5971138, 'Difficulty': 2, 'Hash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'Nonce': 91554, 'PreviousHash': '7532402844a1c130833a27600298d09a007d6124603cf44be9c05fcd5428c34a', 'TransactionData': '{"sender": "OY8z0Rrx", "recipient": "iSGFJsEm", "amount": 8723}'}
{'Index': 2, 'Time': 1516268156.5991132, 'Difficulty': 4, 'Hash': '098544436793881e8041c0c903c96c0055e16396113d73c63bc55e7ba78ec130', 'Nonce': 12875, 'PreviousHash': '01f505a276e3f55a868d9ee18f70bcff75429e1de70f5ab59471a3551cc67a30', 'TransactionData': '{"sender": "HJZSX1hk", "recipient": "j82k51yY", "amount": 3521}'}
{'Index': 3, 'Time': 1516268156.6001143, 'Difficulty': 27, 'Hash': '7c10243223caf39bc5a6067de8d93f6ea46bad62c4a0fbcc0aa4e086585d8200', 'Nonce': 18663, 'PreviousHash': '098544436793881e8041c0c903c96c0055e16396113d73c63bc55e7ba78ec130', 'TransactionData': '{"sender": "cJrGxN5R", "recipient": "wkZI8QCv", "amount": 1224}'}
{'Index': 4, 'Time': 1516268156.601114, 'Difficulty': 3, 'Hash': '60a099d3fe53e031800669fcc1d9b5ab6df1f80a40354135310a799892f1c3d0', 'Nonce': 51446, 'PreviousHash': '7c10243223caf39bc5a6067de8d93f6ea46bad62c4a0fbcc0aa4e086585d8200', 'TransactionData': '{"sender": "nCNJoy52", "recipient": "kYBT9f65", "amount": 3603}'}
{'Index': 5, 'Time': 1516268156.605163, 'Difficulty': 2, 'Hash': '765f69163cf95584721015e3ce819c1980ce33752f8a4dea553d3bedd39f8920', 'Nonce': 31804, 'PreviousHash': '60a099d3fe53e031800669fcc1d9b5ab6df1f80a40354135310a799892f1c3d0', 'TransactionData': '{"sender": "FqOkiTEu", "recipient": "y9EDcSYA", "amount": 4185}'}

這就是由這6個(gè)礦工依次創(chuàng)建的六個(gè)區(qū)塊,根據(jù)hash值環(huán)環(huán)相扣。

到底我想說(shuō)的基本就結(jié)束了,最后我想說(shuō)區(qū)塊鏈?zhǔn)莻€(gè)神奇的技術(shù),從聽(tīng)到它就深深的吸引著我,期望未來(lái)區(qū)塊鏈可以真的帶來(lái)巨大的變革。要知道,隨著AI的興起,區(qū)塊鏈的問(wèn)世,屬于程序員的數(shù)字時(shí)代會(huì)進(jìn)一步升華,互聯(lián)網(wǎng)時(shí)代只是一個(gè)開(kāi)始!謝謝閱讀,本人水平有限,如果您發(fā)現(xiàn)問(wèn)題或我理解偏差的地方可以及時(shí)指出,再次表示感謝。文章末尾會(huì)附上完整代碼。

import hashlib
import random
import string
import json
import threading
from decimal import Decimal
from time import time


class MyThread(threading.Thread):

    def __init__(self, target, args=()):
        super(MyThread, self).__init__()
        self.func = target
        self.args = args

    def run(self):
        self.result = self.func(*self.args)

    def get_result(self):
        try:
            return self.result
        except Exception:
            return None


class BlockChain:
    def __init__(self, initialHash):
        # init block chain
        self.chain = []

        # init pitman
        self.pitmen = []
        for i in range(6):
            self.pitmen.append(Pitman)

        # collect mine results
        self.results = []

        # generate GenesisBlock
        self.new_block(initialHash)

    @property
    def last_block(self):
        if len(self.chain):
            return self.chain[-1]
        else:
            return None

    def get_trans(self):
        return json.dumps({
            'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
            'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)),
            'amount': random.randrange(1, 10000)
        })

    def new_block(self, initialHash=None):
        if initialHash:
            # generate Genesis Block
            block = Block()
            block.index = 0
            block.nonce = random.randrange(0, 99999)
            block.previousHash = '0'
            block.difficulty = 0
            block.transactionData = self.get_trans()
            guess = f'{block.previousHash}{block.nonce}{block.transactionData}'.encode()
            block.hash = hashlib.sha256(guess).hexdigest()
            block.time = time()
            self.chain.append(block)
        else:
            for i in range(len(self.pitmen)):
                pm = MyThread(target=self.pitmen[i].mine,
                                      args=(self.pitmen[i],
                                            len(self.chain),
                                            self.last_block.get_block()['Hash'],
                                            self.get_trans()))
                pm.start()
                pm.join()
                self.results.append(pm.get_result())

            # show all blocks
            print("All blocks generated by pitmen:")
            for result in self.results:
                print(result[0].get_block())

            # get new block
            firstblock = self.results[0][0]
            mintime = Decimal(self.results[0][1])
            for i in range(1, len(self.results)):
                if Decimal(self.results[i][1]) < mintime:
                    firstblock = self.results[i][0]
                else:
                    continue
            self.chain.append(firstblock)
            self.results = []

    def show_chain(self):
        print('This is mine first block chain!')
        for block in self.chain:
            print(block.get_block())


class Block:
    def __init__(self):
        self.index = None
        self.time = None
        self.difficulty = None
        self.nonce = None
        self.hash = None
        self.previousHash = None
        self.transactionData = None

    def get_block(self):
        return {
            'Index': self.index,
            'Time': self.time,
            'Difficulty': self.difficulty,
            'Hash': self.hash,
            'Nonce': self.nonce,
            'PreviousHash': self.previousHash,
            'TransactionData': self.transactionData
        }


class Pitman:

    def mine(self, index, previousHash, transactionData):
        beginTime = time()

        block = Block()
        block.index = index
        block.previousHash = previousHash
        block.transactionData = transactionData
        block.difficulty, block.hash, block.nonce = self.generate_hash(previousHash, transactionData)
        block.time = time()
        endTime = time()

        return block, endTime - beginTime

    @staticmethod
    def generate_hash(previousHash, transactionData):
        difficulty = 0
        nonce = random.randrange(0, 99999)
        guess = f'{previousHash}{nonce}{transactionData}'.encode()
        myhash = hashlib.sha256(guess).hexdigest()
        while myhash[-1] != '0':
            difficulty += 1
            nonce += difficulty
            guess = f'{previousHash}{nonce}{transactionData}'.encode()
            myhash = hashlib.sha256(guess).hexdigest()
        return difficulty, myhash, nonce


if __name__ == '__main__':
    chain = BlockChain(1)
    length = 5
    for i in range(length):
        chain.new_block()
    chain.show_chain()

到此,關(guān)于“區(qū)塊鏈的概念以及用Python的實(shí)現(xiàn)方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI