UP | HOME

区块链的简单尝试

目录

1 前言

昨晚, 我再一次浏览了有关于区块链技术的博客。

然后, 我便惊喜的发现了这一篇博客: 区块链入门教程

之前看了很多博客, 但一直让我很捉急的便是, 对于实现部分, 对于为何会花那么多算力的部分, 讲解的不是很清楚。

我知道, Hash 算法耗费算力, 但我平时用 Hash 算法的时候, 花费的时间也不多啊 !

在看了这篇博客之后, 突然明白, Hash 计算并不是只有一次, 而是由很多次计算得来的。

难度系数 影响了计算所需要的次数。

终于, 一个一直困惑我的部分得到了解答。

但是, 我还是想尝试一下, 具体怎么个耗时法。

2 代码尝试

得益于看到的博客, 我从相关链接中, 看到了一篇很简洁但很精辟的示例: How does blockchain really work? I built an app to show you.

这是一篇很好的文章, 模仿文中的代码, 我用 Python 写了一个小脚本来测试:

# -*- coding: utf-8 -*-

from __future__ import print_function

import time, random

from hashlib import sha256


class BlockChain(object):
    """ 区块.

    :param index: 当前区块的 `index`.
    :type index: int
    :param pre_hash: 前一个区块的 `hash`.
    :type pre_hash: str
    :param data: 当前区块要储存的信息.
    :type data: str
    """
    def __init__(self, index, pre_hash, data):
        self.index = index
        self.pre_hash = pre_hash
        self.time = time.ctime()
        self.data = data
        self.hash = None
        self.nonce = 0      # 计算 `hash` 的次数

    def calc_hash(self, difficulty):
        """ 计算 `hash`.

        :pparam difficulty: 计算难度.
        :type difficulty: int
        """
        def is_vaild_hash(hash, difficulty):
            """ 判断算的的 `hash` 是否有效.
            """
            for i in range(len(hash)):
                if not hash[i] == '0':
                    break
            return i >= difficulty

        input = str(self.index) + self.pre_hash + \
                self.time + self.data + str(self.nonce)
        self.hash = sha256(input).hexdigest()

        while not is_vaild_hash(self.hash, difficulty):
            self.nonce += 1
            input = str(self.index) + self.pre_hash + \
                    self.time + self.data + str(self.nonce)
            self.hash = sha256(input).hexdigest()


def genesis_block():
    """ 获取创世区块.
    """
    first_block = BlockChain(0, '0', 'My first block')
    first_block.calc_hash(random.randint(1, 4))
    return first_block


def print_block(block):
    """ 输出区块信息.
    """
    print('index: %s' % block.index)
    print('hash: %s' % block.hash)
    print('nonce: %s\n' % block.nonce)


if __name__ == '__main__':
    print('Genesis block:')
    first_block = genesis_block()
    print_block(first_block)

    pre_block = first_block

    while True:
        data = raw_input('Input data: ')
        if data:
            cur_block = BlockChain(pre_block.index + 1, pre_block.hash, data)

            difficulty = random.randint(1, 4)    # ..., 难度稍微大一点居然都要算半天...
            print('difficulty: %s' % difficulty)

            cur_block.calc_hash(difficulty)
            print_block(cur_block)

            pre_block = cur_block

        else:
            break

    print('over')

代码比较粗糙, 但是并不妨碍我进行测试:

Genesis block:
index: 0
hash: 000a630deaf076650dc5ee90490ee1d16b3bc5a36ababcce68b807a32f16bfbd
nonce: 491

Input data: 第二个区块
difficulty: 3
index: 1
hash: 000da279af9350e82481bbcfbdec65ba47b5f79fbfb3439734cae69056bc8315
nonce: 6947

Input data: 难度是 ?
difficulty: 3
index: 2
hash: 000a4699eb0d5e74d15833c383a6c191a40fee89b804a792aa1ecbfecc3cf98a
nonce: 3725

Input data: 再一次测试
difficulty: 4
index: 3
hash: 0000f2d8aadd829dadb048d2624d155729d06b258dc7013ac31621ac515eb644
nonce: 37817

Input data: 再来一次
difficulty: 4
index: 4
hash: 00002863448497e9e4028d0875b7624d5172e952fc0ab128b336b20abe7df95e
nonce: 84479

Input data: github
difficulty: 4
index: 5
hash: 00001c6ce47f2e7d66f7a75a12f5de390a8456cfb734c3679af3750ee2917425
nonce: 53565

这是测试过程, 当然不是最开始的。

最开始的时候, 难度系数生成的代码是: random.randint(1, 24).

然后, 上来就是一个难度 7, 结果便是, 我去上了个厕所回来那一个区块还没出来……

于是, 我默默的将代码改为了: random.randint(1, 4).

但是, 这个计算次数还是让我很惊讶。轻轻松松上万。

3 相关链接

版权声明:本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可