以前的章节已经比较粗略的解释了在Transaction体系当中的总体运做原理。接下来的章节会对这个体系进行分解,比较详细描述细节的构成。编程
本章将要详细分析bitcoin交易中的交易脚本-script究竟是什么东西。安全
在前面的文章中提到,在bitcoin的体系中,一个交易是被发布到比特币的总体系统中的,而可以操控以前交易的的TxOut(被锁住的coin),是须要可以操控这个TxOut的人提供"钥匙"来控制。就像前文描述的,coin在整个系统中是像流水同样的在体系中进行流通,而coin在其中在分叉点的时候会有一个像 “锁” 的东西把coin锁在这个节点上。而根据这个锁产生了一个新的交易,继续流通被这个锁所锁住的coin,是须要提供一个"钥匙"的。数据结构
因此这里的比喻:“锁”和“钥匙”就是比特币交易中的交易脚本Scriptide
其中函数
“锁” 对应着 scriptPubKey区块链
“钥匙”对应着 scriptSigui
可是单纯的把Script理解为“锁”和“钥匙”实在是太浅薄了。只能完成这点事情的并不能体现Script 的强大,也没法对后人创立“智能合约”有所启发。this
因此在我看来,比特币的Script其实是:加密
scriptPubKey 是上一个交易(out)提出的一个 “问题”spa
而
scriptSig 是我想使用上一个交易中钱,那么我就对你提出的这个问题提供个人“答案”
由于公私钥的关系,因此若是scriptPubKey 提出的问题是公钥相关的问题,那么很明显,只有持有私钥的人才能回答这个问题,因此就简化为刚才的所说的“锁”和“钥匙”的关系。
而另外一方面,如何确认提供的“答案”就是能回答“问题”的呢?这就说明Script是须要被执行验证的,并且这个验证的过程只须要txin提供的scriptSig 和验证者本身从本身的记录中找到的txout的scriptPubKey ,而这个验证者就是广大的矿工们。
整个系统精妙的地方就在于,scriptPubKey是验证者(矿工)各自独立持有的东西,其安全性由本身所保证的,而想要完成交易的人只须要提供scriptSig给广大验证者就行,不须要一些多余的上下文(能够理解为上下文由验证者本身持有,虽然你们都互不信任,可是对于最广大的人来讲,这个上下文都是相同的)。
另外一个方面不太被大多数人所注意到的是:
实际上刚才的模型简化为了“问题”和“答案”,可是这个“问题”可不是很容易提供的。
这个“问题”应该知足2个方面的要求:
而公私密钥的模式实际上是完美的符合了这2方面的要求的。
那么有没有其余的问题呢?那是固然有的,好比我提出了一个数学问题,这个问题的解是惟一的而且能够很容易的验证个人回答对不对
那么我就能够建立一笔交易,而这笔交易的txin就提供这个问题的答案,只要个人这个tx优先被矿工打包进入区块中,并成为最长链,那么这个问题下的钱就归我了。
这个场景就是符合正向很难,逆向容易的场景。
接下来就解释 比特币系统中的 CScript 究竟是怎么运做的。
在比特币源码当中,对于CScript 单独列出了 script.c/script.h 来实现这块体系(对比把tx,block等全部实现所有放在main.c/.h来讲),可见得中本聪在一开始设计这套体系的时候就把这块的内容看的至关的重要。事实上这套体系也确实很复杂,可是也是得益于这套体系,才能取得如今的地位,若是没有这个设计,比特币的实用性会被大幅度减弱。
class CScript : public vector<unsigned char> { // 把各类类型的数据序列化到 vector 中 CScript& operator<<(char b) { return (push_int64(b)); } CScript& operator<<(short b) { return (push_int64(b)); } CScript& operator<<(int b) { return (push_int64(b)); } CScript& operator<<(long b) { return (push_int64(b)); } CScript& operator<<(int64 b) { return (push_int64(b)); } CScript& operator<<(unsigned char b) { return (push_uint64(b)); } CScript& operator<<(unsigned int b) { return (push_uint64(b)); } CScript& operator<<(unsigned short b) { return (push_uint64(b)); } CScript& operator<<(unsigned long b) { return (push_uint64(b)); } CScript& operator<<(uint64 b) { return (push_uint64(b)); } CScript& operator<<(opcodetype opcode) CScript& operator<<(const uint160& b) CScript& operator<<(const uint256& b) CScript& operator<<(const CBigNum& b) CScript& operator<<(const vector<unsigned char>& b) { // } bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet) const