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要解决的问题是去交易的中介,类似于银行在传统的交易模型中的地位,这是一个很直观而且亟待解决的问题。这样做似乎很理想,但是有两个很明显的问题需要解决:
- 怎么确保每一笔先后发生的交易的先后顺序?
- 怎么确保在A到B的交易中,A有足够的金额发给B呢?
为了解决第一个问题,blockchain被提出来了。说白了就是一个double linked list,每个新加入的block被作为一个新的节点被加入现存在的blockchain里面。根据satoshi nakamoto提出的论文,每一笔交易在加入整个chain的时候需要经历6个步骤:
- 交易被发起并被广播
- 所有机器接收该交易并加入一个block里面
- 每台机器开始找proof-of-work的解
- 第一台找到解的机器也就是miner会得到相应的bitcoin奖励,并将该block广播给其他机器(这里把blockchain跟bitcoin结合起来了)
- 只有在该block里面的所有transaction都是valid并且未有输出的时候,其他机器才会达成一致意见,认为该block是可接收的
- 在接受了该block之后,其他所有机器会将这个block的hash值当作前向block的地址,继续append block
这里有个简单的流介绍transaction的运作:
一直都有听说加一个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的情况。 可以看见修改之后该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
- http://scet.berkeley.edu/wp-content/uploads/BlockchainPaper.pdf
- https://bitcoin.org/bitcoin.pdf
- https://anders.com/blockchain/block.html
- https://bitcoin.org/en/developer-guide