My understanding on blockchain so far

December 23, 2017

Block chain has been talked a lot in the field of high tech industry. Being able to understand this decentralized technology is a plus for my career and able to implement it practicely will even better. I will talk about some information I have learnt so far in this post including the implementation of blockchain using javascript.

继上次写的一篇博文What is bitcoin mining?之后,这次继续写下关于bitcoin技术的笔记。

相信看这篇文章的读者们应该或多或少对blockchain和bitcoin有所了解了,如果这里面涉及到的一些术语觉得不理解,可以试图从reference那里找到答案,实在不行可以wiki之或者直接评论告诉我哦。那我主要在这里梳理一下blockchain到底解决什么问题和其中我认为很有趣的技术细节。
bitcoin要解决的问题是去交易的中介,类似于银行在传统的交易模型中的地位,这是一个很直观而且亟待解决的问题。这样做似乎很理想,但是有两个很明显的问题需要解决:

  1. 怎么确保每一笔先后发生的交易的先后顺序?
  2. 怎么确保在A到B的交易中,A有足够的金额发给B呢?

为了解决第一个问题,blockchain被提出来了。说白了就是一个double linked list,每个新加入的block被作为一个新的节点被加入现存在的blockchain里面。根据satoshi nakamoto提出的论文,每一笔交易在加入整个chain的时候需要经历6个步骤:

  1. 交易被发起并被广播
  2. 所有机器接收该交易并加入一个block里面
  3. 每台机器开始找proof-of-work的解
  4. 第一台找到解的机器也就是miner会得到相应的bitcoin奖励,并将该block广播给其他机器(这里把blockchain跟bitcoin结合起来了)
  5. 只有在该block里面的所有transaction都是valid并且未有输出的时候,其他机器才会达成一致意见,认为该block是可接收的
  6. 在接受了该block之后,其他所有机器会将这个block的hash值当作前向block的地址,继续append block

这里有个简单的流介绍transaction的运作: howBitcoinWork

一直都有听说加一个block到一个chain里面的时候要求解一个很困难的数学问题,那这个数学问题到底是什么呢?在bitcoin里面这个数学问题叫做proof-of-work,也就是步骤三种提到的,实际上就是一个暴力搜索hash值的过程(简单的一个for循环)。下面的源代码是block这个类的基类,正如注释说的一样,给定一个nNonce值,用一个for循环去找对应的hash值,如果该hash值的前nBits位都是0,则满足要求,表示这个proof-of-work得到了解决,对应的block就会被加入该链中。当否则该block就是一个无效的block。

/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
* requirements.  When they solve the proof-of-work, they broadcast the block
* to everyone and the block is added to the block chain.  The first transaction
* in the block is a special one that creates a new coin owned by the creator
* of the block.
*/
class CBlockHeader
{
public:
    // header
    int32_t nVersion;
    uint256 hashPrevBlock;
    uint256 hashMerkleRoot;
    uint32_t nTime;
    uint32_t nBits;
    uint32_t nNonce; 

    CBlockHeader()
    {
        SetNull();
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action) {
        READWRITE(this->nVersion);
        READWRITE(hashPrevBlock);
        READWRITE(hashMerkleRoot);
        READWRITE(nTime);
        READWRITE(nBits);
        READWRITE(nNonce);
    }

    void SetNull()
    {
        nVersion = 0;
        hashPrevBlock.SetNull();
        hashMerkleRoot.SetNull();
        nTime = 0;
        nBits = 0;
        nNonce = 0;
    }

    bool IsNull() const
    {
        return (nBits == 0);
    }

    uint256 GetHash() const;

    int64_t GetBlockTime() const
    {
        return (int64_t)nTime;
    }
};

以下是一个用javascript写的简单的实现,difficulty也就是前文的nBits,pattern表示一个含有difficulty个0的字串。可以看到当满足条件的时候就把这个block加入chain里面。(源码)

function mine(block, chain, isChain) {
  for (var x = 0; x <= maximumNonce; x++) {
    $('#block'+block+'chain'+chain+'nonce').val(x);
    $('#block'+block+'chain'+chain+'hash').val(sha256(block, chain));
    if ($('#block'+block+'chain'+chain+'hash').val().substr(0, difficulty) === pattern) {
      if (isChain) {
        updateChain(block, chain);
      }
      else {
        updateState(block, chain);
      }
      break;
    }
  }
}

attacker

这里有个很有趣的现象,当attacker想要修改某个block里面的值的时候,该block的总的hash值也就相应的改变了,从而不满足之前提到的hash值前若干位是0的情形,这个block的改变导致后面所有的block也变得不满足要求,因此整条链就作废了,也就是attacker需要re-mine后面所有的block。因此Bitcoin: A Peer-to-Peer Electronic Cash System一文中也提出了attacker应该权衡re-mine需要的资源和按规矩进行mine两者哪个得到的收益更大,显然后者更大,这也促使了玩家们按规定进行游戏。下面两个图展现了修改某个block的情况。 before after 可以看见修改之后该block也就变成无效的block了。感谢Anders在这里写了一个javascript的直观展示,之前用到的js代码也出自这里。结合bitcoin的论文,这个repo让我对blockchain有了更直观的认识。

回答第二个问题

其实在明白了前面的解释之后,第二个问题实际上很容易想明白了,只要在每个block记录下入账和出账就可以了,也就是在该double linked list里面再加一个额外的信息,入账大于出账,则block有效,否则无效。虽然具体的内容跟这个差别很大,但基本思想是这样。详细的内容可以查看文档。

Conclusion

总而言之,虽然bitcoin在中国已经被拒绝交易了,blockchain也越来越变成一种车大炮的话题,但是我觉得作为对世界充满好奇心的猴子,应该借由这个现象级的产品去观察背后的逻辑和实现,从而提高自己的视野。特别是像blockchain说白了就是数据结构里面很常见的double linked list,我就觉得这样淳朴的技术特别值得玩味,去看看人家是怎么用简单的数据结构玩出多种花样。 最后,我觉得所有希望了解bitcoin或者blockchain的小伙伴,应该去翻看一下源头的东西–Bitcoin: A Peer-to-Peer Electronic Cash System 毕竟擒贼先擒王嘛。也希望自己能多看一些源头的东西,少一虚的东西。那小伙伴们如果对我的理解又任何的意见或者建议,feel free to leave a comment below, until next time!

Reference