科技: 人物 企业 技术 IT业 TMT
科普: 自然 科学 科幻 宇宙 科学家
通信: 历史 技术 手机 词典 3G馆
索引: 分类 推荐 专题 热点 排行榜
互联网: 广告 营销 政务 游戏 google
新媒体: 社交 博客 学者 人物 传播学
新思想: 网站 新书 新知 新词 思想家
图书馆: 文化 商业 管理 经济 期刊
网络文化: 社会 红人 黑客 治理 亚文化
创业百科: VC 词典 指南 案例 创业史
前沿科技: 清洁 绿色 纳米 生物 环保
知识产权: 盗版 共享 学人 法规 著作
用户名: 密码: 注册 忘记密码?
    创建新词条
科技百科
  • 人气指数: 2175 次
  • 编辑次数: 2 次 历史版本
  • 更新时间: 2011-12-05
高兴
高兴
发短消息
高兴
高兴
发短消息
相关词条
Kreditech
Kreditech
P2P网贷危机频发
P2P网贷危机频发
未来金融趋势
未来金融趋势
网贷的灰色游戏
网贷的灰色游戏
Smallknot
Smallknot
追梦网
追梦网
微资源与大规模协作学习
微资源与大规模协作学习
收银台革命
收银台革命
P2P网络借贷解密
P2P网络借贷解密
Kabbage
Kabbage
推荐词条
希拉里二度竞选
希拉里二度竞选
《互联网百科系列》
《互联网百科系列》
《黑客百科》
《黑客百科》
《网络舆情百科》
《网络舆情百科》
《网络治理百科》
《网络治理百科》
《硅谷百科》
《硅谷百科》
2017年特斯拉
2017年特斯拉
MIT黑客全纪录
MIT黑客全纪录
桑达尔·皮查伊
桑达尔·皮查伊
阿里双十一成交额
阿里双十一成交额
最新词条

热门标签

微博侠 数字营销2011年度总结 政务微博元年 2011微博十大事件 美国十大创业孵化器 盘点美国导师型创业孵化器 盘点导师型创业孵化器 TechStars 智能电视大战前夜 竞争型国企 公益型国企 2011央视经济年度人物 Rhianna Pratchett 莱恩娜·普莱契 Zynga与Facebook关系 Zynga盈利危机 2010年手机社交游戏行业分析报告 游戏奖励 主流手机游戏公司运营表现 主流手机游戏公司运营对比数据 创建游戏原型 正反馈现象 易用性设计增强游戏体验 易用性设计 《The Sims Social》社交亮 心理生理学与游戏 Kixeye Storm8 Storm8公司 女性玩家营销策略 休闲游戏的创新性 游戏运营的数据分析 社交游戏分析学常见术语 游戏运营数据解析 iPad风行美国校园 iPad终结传统教科书 游戏平衡性 成长类型及情感元素 鸿蒙国际 云骗钱 2011年政务微博报告 《2011年政务微博报告》 方正产业图谱 方正改制考 通信企业属公益型国企 善用玩家作弊行为 手机游戏传播 每用户平均收入 ARPU值 ARPU 游戏授权三面观 游戏设计所运用的化学原理 iOS应用人性化界面设计原则 硬核游戏 硬核社交游戏 生物测量法研究玩家 全球移动用户 用户研究三部曲 Tagged转型故事 Tagged Instagram火爆的3大原因 全球第四大社交网络Badoo Badoo 2011年最迅猛的20大创业公司 病毒式传播功能支持的游戏设计 病毒式传播功能 美国社交游戏虚拟商品收益 Flipboard改变阅读 盘点10大最难iPhone游戏 移动应用设计7大主流趋势 成功的设计文件十个要点 游戏设计文件 应用内置付费功能 内置付费功能 IAP功能 IAP IAP模式 游戏易用性测试 生理心理游戏评估 游戏化游戏 全美社交游戏规模 美国社交游戏市场 全球平板电脑出货量 Facebook虚拟商品收益 Facebook全球广告营收 Facebook广告营收 失败游戏设计的数宗罪名 休闲游戏设计要点 玩游戏可提高认知能力 玩游戏与认知能力 全球游戏广告 独立开发者提高工作效率的100个要点 Facebook亚洲用户 免费游戏的10种创收模式 人类大脑可下载 2012年最值得期待的20位硅谷企业家 做空中概股的幕后黑手 做空中概股幕后黑手 苹果2013营收 Playfish社交游戏架构

P2P电子货币系统内幕 发表评论(0) 编辑词条

目录

开源Bitcoin P2P电子货币系统内幕编辑本段回目录

开源 Bitcoin P2P电子货币是点对点的电子现金系统,创建于2009年[http://en.wikipedia.org/wiki/Bitcoin]。无需金融机构直接点对点支付。该电子货币系统的特色是无需信托中间人,能够方便的进行互联网上的汇款。第三方不能够控制或者阻止您的交易。Bitcoin 交易几乎免费, 而信用卡的网上在线支付系统通常收取 1-5% 的交易费用,加上其他各种费用高达数百美元。避免了中央储备银行的不良政策和不稳定性所造成的安全隐患. Bitcoin系统的有限货币通胀是均匀分布(由CPU决定)于整个网络, 而不是由银行垄断。

这被某些人认为是最危险的开源项目,但我觉得恰恰相反,这是有史以来最令人兴奋的开源项目。这样发行的币才是真正的“人 民 币”,人民才是被服务,而不是被管理。P2P必将从商业、政治、生活各个方面重新定义新的更加公平公正的意识形态。

名词解释以及背后的技术

Bitcoin涉及到很多有意思的技术,要想搞懂bitcoin首先必须对这些技术理解和把握然后是对Bitcoin术语的理解,bitcoin最重要的技术支撑是P2P,数字签名(EC DSA),散列(SHA256, RIPEMD-160), POW,和HashCash。而术语则是:transaction, block,  address, Merkle Tree.

工作证明 POW(Proof-Of-Work)机制

工作证明POW系统是要求对方服务前,必须要出据某种工作证明的机制。主要用于防止拒绝服务攻击和反垃圾信息。通常这种“工作证明”会花费一定的时间计算才能得到。最常见的例子是CAPTCHA。另外用于防止DoS和垃圾信息的机制是HashCash,bitcoin使用的原理就类似于HashCash.

HashCash 机制

hashcash 的灵感来自于这样一个想法,即一些数学结果难于发现而易于校验。一个众所周知的例子是因数分解一个大的数字(尤其是因数较少的数字)。将数字相乘来获得它们的积的代价是低廉的,但首先找到那些因数的代价却要高得多。

对交互式质询来说,因数分解足以胜任。比如,希望客户端能象征性地为其付出代价方能访问在线资源。这个时候可以定义协议,首先服务器向客户端发送一个消息,说“只要您能因数分解这个数,我将让您得到这个资源”。没有诚意的客户端将无法得到我的资源,只有那些能够证明自己有足够的兴趣、付出一些 CPU 周期来回答这个质询的才能得到这个资源。

不过,有一些资源无法很方便地进行交互式协商。比如电子邮件反垃圾或者支付交易,怎么才能避免邮箱不被垃圾邮件所占据?“我并不介意陌生人给我写信,但是,我希望他们能以稍微认真的态度,亲自通过对我有价值的邮件与我取得联系。至少,我不希望他们是垃圾邮件制造者,那些人向我和上百万的其他人发送包含同样消息的邮件(double-spending),期望我们中的某些人能购买某种产品或者落入一个骗局。”而对于电子货币,内容的复制几乎是没有代价的,如何保证电子货币(内容)没有被交易(发送)多次?这和反垃圾邮件是同样的问题。

hashcash的解决之道就是:在电子邮件的消息头中,增加一个 hashcash 戳记(hashcash stamp)散列值;该散列中包含收件人地址,发送时间,salt,该散列值特别之处在于它至少前20位必须是0才是一个合法的hashcash戳记。为了得到合法的散列值,发送者必须经过许多次尝试(改变salt值)才能获得。一旦生成戳记,不希望每一个给我发送邮件的垃圾邮件制造者都能重复使用它。所以,hashcash 戳记要带一个日期。这样可以指定时间更早的戳记是非法的。另外 hashcash 的接收端要实现一个double-spending数据库,用来记录戳记的历史信息。

Bitcoin中的术语解释

散列:bitcoin在计算散列时一般会计算2次。第一轮总是使用SHA-256散列,而第二次在大多数情况下,也是使用SHA-256散列,但用于生成较短的散列(例如生成 bitcoin接收地址的时候)会用RIPEMD-160散列。

hello 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 ( sha-256) 9595c9df90075148eb06860365df3
3584b75bff782a510c6cd4883a419833d50 (sha-256)

生成比特币地址时(RIPEMD-160):

hello 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 (sha-256) b6a9c8c230722b7c748331a8b450f05566dc7d0f (ripemd-160)

Addresses: Bitcoin Address是ECDSA公钥(public key)的散列,计算方法如下:?

1
2
3
4
5
6
7
8
9
10
if 正式网络
  Version=0x00
else if 测试网络
  Version=0x6F
end
key_hash=Version+RIPEMD-160(SHA-256(public_key))
Checksum = SHA-256(SHA-256(Key hash))[0..3#取两次散列值后的前4位
Bitcoin_Address = Base58Encode(Key_hash+Checksum)
#Base58编码做了特殊处理,与通用的base58有一些区别:转换的时候
#前面的0被作为单个0保留。

Bitcoin 电子货币系统的核心功能是面对面(点对点)支付,就像真实货币一样,无需中间人,几乎不需要交易费。它背后的技术实现是很巧妙的通过将造币(Mint),交易(transaction,这里提到的交易都是特指的支付),交易验证(transaction verifiction)交织在一起,形成一个完美的圆。所以要想把它的机理理解清楚,就必须同时理解bitcoin的电子货币,交易,造币的确切含义。

首先从电子货币谈起。

电子货币和交易单(Transaction)

Bitcoin电子货币解决的是:

  1. 任意造币的问题:通过“挖矿”机制保证了不能任意造币。
  2. 重复花钱的问题(Double-Spending):利用P2P网络,通过HashCash的机制。

事实上Bitcoin系统中不存在独立的电子货币,货币值是依附于交易单存在的,所以在bitcoin中的电子货币的实质就是交易单,确切的说是货币交易(Transactions)的 数字签名链,它的数字签名算法使用的是ECDSA(椭圆曲线数字签名算法 secp256k1曲线)进行签名的。
交易单的数据如下:

In:Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac98064
3b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501
Out:
Value: 5000000000scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d OP_EQUALVERIFY OP_CHECKSIG

交易单记录的是本次交易的收入来源(in)和支出(out)。当你支出(给)一笔钱的时候,首先在交易单中就要描述清楚你要支出(out)的钱的收入来源(in),然后在支出(out)项中,指明要支出的金额,以及通过脚本的形式写明接收者的公钥,然后用自己的私钥签名(scriptSig)认可该笔交易,最后将交易单广播到网络。

收入来源(in):

  • Previous tx: 为收入来源交易单的散列值,也就是待支付的钱是谁给你的,经常会有多个收入来源被列在交易单中
  • index: 指明是收入来源交易单中具体哪一个out,也就是Previous tx交易单中的out索引值(因为out也可以有多个)。
  • scriptSig: 拥有者对该交易的ECDSA签名认可。

接收对象(out):

  • Value: 发送的币值,以Satoshi 为单位,1BTC = 100,000,000 Satoshi
  • scriptPubKey: 接收方的公钥脚本。

in与out的关系:

  • 每一笔交易,out的总额应该等于in的总额。但是,在这个交易单里,只会有out的Value,没有in的Value,而是通过in的Pervious与index,追溯到上一个交易单的某一个out,获得Value。
  • 一次send bitcoin,剩下的钱,应该out给自己,否则这个钱就丢了。

情况列举:

  • 我有10个BTC,是某一次交易获得的,我要送给朋友A,10个BTC。这时候,有一个in,一个out。
  • 我有10个BTC,是某一次交易获得的,我要送给朋友A,5个BTC,这时候,有一个in,两个out,一个指向朋友5个BTC,一个指向我自己,得到剩下的5个BTC。
  • 我有10个BTC,是以前的两次交易获得的,我要送给朋友A,10个BTC,这时候,有两个in,一个out。
  • 我有10个BTC,是以前的两次交易获得的,其中一次获得了6个BTC,另一次获得了4个BTC,我要送给我的朋友7个BTC,这时候,有两个in,两个out。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/
// An input of a transaction.  It contains the location of the previous
// transaction's output that it claims and a signature that matches the
// output's public key.
//
class CTxIn
{
public:
    COutPoint prevout;
    CScript scriptSig;
    unsigned int nSequence;
    ....
}
  
//
// An output of a transaction.  It contains the public key that the next input
// must be able to sign with to claim it.
//
class CTxOut
{
public:
    int64 nValue;
    CScript scriptPubKey;
    ....
}
  
//
// The basic transaction that is broadcasted on the network and contained in
// blocks.  A transaction can contain multiple inputs and outputs.
//
class CTransaction
{
public:
    int nVersion;
    std::vector<CTxIn> vin;
    std::vector<CTxOut> vout;
    unsigned int nLockTime;
  
    ....

每一笔交易单验证追查到最后,第一笔总是“挖矿”所得,这被称为coinbase。
如果是第一次“挖矿”所得,电子货币的内容用JSON格式表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "hash":"b3141455cb397e42665b90b3726c4770fd36101715618718111403bc780ceaa2",
  "ver":1,
  "vin_sz":1,
  "vout_sz":1,
  "lock_time":0,
  "size":135,
  "in":[
    {
      "prev_out":{
        "hash":"0000000000000000000000000000000000000000000000000000000000000000",
        "n":4294967295
      },
      "coinbase":"042194261a02f200"
    }
  ],
  "out":[
    {
      "value":"50.01000000",
      "scriptPubKey":"0452d1a02ffeacfc0c78fcf2ceeaf04d5416c15af1c65da13d9cdaa56844c825c1aa2f540e94
39bf38a43419002d8441eea627cb56d6ed51e7848da5c3f6eee6ec OP_CHECKSIG"
    }
  ]
}

每一笔交易都会向整个P2P网络广播该货币的交易记录。通过投票机制,来决定该支付交易是否正常。如节点认为该交易记录是正常的那么就通过CPU计算POW(Proof-of-Work),然后广播,其它节点收到这个POW可以继续投票,形成Block 链(见挖矿)。如果节点收到不一致的两个交易记录,那么只信任链最长的。如果一笔Bitcoin被支出两次的情况广播出来,那么某些节点将先看到它第一次发生的支付交易,其他节点则看到的是它第二次发生的支付交易。究竟是哪一个支付交易“赢”了,则是由恰好创建了下一个block的那个节点来决定 —— 无论是哪个节点找到了“小的散列值”, 它的block中包含的那个支付交易被判断为有效的,其他的支付交易被视为无效。


前面讲了交易单,接下来讲讲交易单的类型和交易验证的实现细节。

交易的类型与验证

交易单(Transaction)目前被bitcoin分为3种:

  1. 按IP地址转账(Transfer)
  2. 按接收地址转账(Transfer)
  3. 造币(Generation)

通过前面对交易单的描述,我想大家应该已经知道,交易的验证是通过不断的追溯交易单来完成的。那么交易验证的细节是如何实现的,bitcoin的交易验证的实现细节是很意思的,它是通过脚本来实现验证的,这样bitcoin就实现了一个可被脚本扩展的行为,更加广义的”交易”,这可以保证足够的灵活性和可扩展,可以想象也许以后会有真正的分布式计算任务跑在上面作为一笔交易。因此要想讲清楚验证的细节,就不得不从脚本系统讲起了。

脚本系统

Bitcoin的脚本系统是使用类FORTH语言(FORTH在嵌入式设备中是我最喜欢的一种语言)实现的,FORTH系统是面向栈的“高级机器”语言,它兼具了高级语言的特性(面向WORD)和机器语言的高性能与小尺寸,唯一的缺点就是可读性不高,基本上可以把FORTH当一种高级的机器语言吧。Bitcoin在实现上做了许多简化和特殊实现,所以只能算是类FORTH的系统。

FORTH系统中所有的命令(函数)都被称为单词(WORD),所有数据的处理都要压入数据栈上进行,所以FORTH被称为面向栈的语言。
比如 1和2相加,在FORTH系统中则是 1 2 +,数字 1,2 表示将它们压入到数据栈中(在FORTH解释器执行后实际指令会有OP_PUSH),+的操作则是将栈顶和次栈顶的数字取出并相加,并将结果压回数据栈。

Bitcoin的脚本系统的所有的操作指令(单词)见后面的附录,不是所有的操作指令都能被执行支持,因为安全上的考虑有的操作指令被禁止掉了,比如大多数的字符串操作和乘除运算。

在FORTH系统中一般会定义该系统是8位FORTH, 16位FORTH还是32/64位FORTH,这和数据栈的值长有关。在Bitcoin中的脚本系统使用的堆栈是用(vector<vector<unsigned char> >)来模拟的,它在数据栈的每一项都是以字符串的形式存放,它的数值是统一用CBigNum来运算的(读到这里应该明白为啥bitcoin会限制乘除运算了),每一次从数据栈中压入(CBigNum.getvch())或者取出数值(CastToBigNum(stacktop[-1]))都要进行一次转换。看着这样的实现,让我有点发怵,本能的不喜欢,怎么能把高效的FORTH搞成这个样子。Bitcoin的脚本系统与FORTH一样,有两个堆栈,一个数据栈,在Bitcoin中被称为main stack,一个返回栈,在Bitcoin中被称为alt stack(事实上在Bitcoin中将alt stack作为数据栈的中转而还没有作为FORTH意义上的返回栈). Bitcoin的脚本系统没有实现单词定义,流程跳转,循环控制(FOR, WHILE),对IF的实现非常丑陋。事实上我对Bitcoin的脚本实现不是十分认可,堆栈采用变长的数据值,直接将big number 作为opcode,导致每一次opcode执行开销无法控制,由于没有完整实现FORTH的控制指令,导致用trick的方式来实现IF指令,在bitcoin中也因此无法定义新的WORD。总之我很不喜欢bitcoin的这个脚本引擎实现(参见script.cpp)。

下一篇将接着介绍下和交易验证相关的几个操作符:OP_DUP, OP_HASH160, OP_EQUALVERIFY , OP_CHECKSIG 的功能,现在有点倦了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
enum opcodetype
{
    // push value
    OP_0=0,
    OP_FALSE=OP_0,
    OP_PUSHDATA1=76,
    OP_PUSHDATA2,
    OP_PUSHDATA4,
    OP_1NEGATE,
    OP_RESERVED,
    OP_1,
    OP_TRUE=OP_1,
    OP_2,
    OP_3,
    OP_4,
    OP_5,
    OP_6,
    OP_7,
    OP_8,
    OP_9,
    OP_10,
    OP_11,
    OP_12,
    OP_13,
    OP_14,
    OP_15,
    OP_16,
  
    // control
    OP_NOP,
    OP_VER,
    OP_IF,
    OP_NOTIF,
    OP_VERIF,
    OP_VERNOTIF,
    OP_ELSE,
    OP_ENDIF,
    OP_VERIFY,
    OP_RETURN,
  
    // stack ops
    OP_TOALTSTACK,
    OP_FROMALTSTACK,
    OP_2DROP,
    OP_2DUP,
    OP_3DUP,
    OP_2OVER,
    OP_2ROT,
    OP_2SWAP,
    OP_IFDUP,
    OP_DEPTH,
    OP_DROP,
    OP_DUP,
    OP_NIP,
    OP_OVER,
    OP_PICK,
    OP_ROLL,
    OP_ROT,
    OP_SWAP,
    OP_TUCK,
  
    // splice ops
    OP_CAT,
    OP_SUBSTR,
    OP_LEFT,
    OP_RIGHT,
    OP_SIZE,
  
    // bit logic
    OP_INVERT,
    OP_AND,
    OP_OR,
    OP_XOR,
    OP_EQUAL,
    OP_EQUALVERIFY,
    OP_RESERVED1,
    OP_RESERVED2,
  
    // numeric
    OP_1ADD,
    OP_1SUB,
    OP_2MUL,
    OP_2DIV,
    OP_NEGATE,
    OP_ABS,
    OP_NOT,
    OP_0NOTEQUAL,
  
    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_MOD,
    OP_LSHIFT,
    OP_RSHIFT,
  
    OP_BOOLAND,
    OP_BOOLOR,
    OP_NUMEQUAL,
    OP_NUMEQUALVERIFY,
    OP_NUMNOTEQUAL,
    OP_LESSTHAN,
    OP_GREATERTHAN,
    OP_LESSTHANOREQUAL,
    OP_GREATERTHANOREQUAL,
    OP_MIN,
    OP_MAX,
  
    OP_WITHIN,
  
    // crypto
    OP_RIPEMD160,
    OP_SHA1,
    OP_SHA256,
    OP_HASH160,
    OP_HASH256,
    OP_CODESEPARATOR,
    OP_CHECKSIG,
    OP_CHECKSIGVERIFY,
    OP_CHECKMULTISIG,
    OP_CHECKMULTISIGVERIFY,
  
    // expansion
    OP_NOP1,
    OP_NOP2,
    OP_NOP3,
    OP_NOP4,
    OP_NOP5,
    OP_NOP6,
    OP_NOP7,
    OP_NOP8,
    OP_NOP9,
    OP_NOP10,
  
    // template matching params
    OP_PUBKEYHASH = 0xfd,
    OP_PUBKEY = 0xfe,
  
    OP_INVALIDOPCODE = 0xff,
};

附录Bitcoin脚本系统单词列表

参见:https://en.bitcoin.it/wiki/Script

常量

常量就是用来把数据压入栈中的单词:

单词虚拟指令(opcode)输入输出Description
OP_0, OP_FALSE0Nothing.0压入数字0到栈中
N/A1-75(special)data将紧随 opcode 的data数据 opcode个字节压入到堆栈。opcode兼作数据长度指示。
OP_PUSHDATA176(special)data紧随该指令的下一个字节是被压入数据大小,然后是被压入数据
OP_PUSHDATA277(special)data紧随该指令的两个字节是被压入数据大小,然后是被压入数据.
OP_PUSHDATA478(special)data紧随该指令的4个字节是被压入数据大小,然后是被压入数据.
OP_1NEGATE79无.-1压入-1
OP_1, OP_TRUE81无.1压入1.
OP_2-OP_1682-96无.2-162-16被压入.

控制流

单词Opcode输入输出描述
OP_NOP97空指令.
OP_IF99<expression> if [statements] [else [statements]] endifIf 判断指令,取出栈顶值,如果栈顶值为1, 则if后面的语句被执行,否则else中的语句被执行。
OP_NOTIF100<expression> ifnot [statements] [else [statements]] endifIfnot 判断指令,取出栈顶值,如果栈顶值为0, 则if后面的语句被执行,否则else中的语句被执行。
OP_ELSE103<expression> if [statements] [else [statements]] endif放置在 OP_IF 或OP_NOTIF 后的指令,当前面的条件不满足的时候执行
OP_ENDIF104<expression> if [statements] [else [statements]] endif结束  if/else 执行块.
OP_VERIFY105True / falseNothing / False标记交易单无效
如果栈顶值不为真。当栈顶值为真,移除该栈顶值,否则保留该值。
OP_RETURN106NothingNothing标记交易单无效.

堆栈操作

WordOpcodeInputOutputDescription
OP_TOALTSTACK107x1(alt)x1从数据栈中弹出栈顶 数据,压入辅助栈。
OP_FROMALTSTACK108(alt)x1x1从辅助栈弹出栈顶数据压入到数据栈
OP_IFDUP115xx / x x如果栈顶非0则复制栈顶
OP_DEPTH116Nothing<Stack size>获取堆栈数据个数
OP_DROP117xNothing丢弃栈顶数据.
OP_DUP118xx x复制栈顶数据.
OP_NIP119x1 x2x2丢弃次栈顶数据
OP_OVER120x1 x2x1 x2 x1复制次栈顶数据到栈顶.
OP_PICK121xn … x2 x1 x0 <n>xn … x2 x1 x0 xn复制第n项数据到栈顶.
OP_ROLL122xn … x2 x1 x0 <n>… x2 x1 x0 xn将第n项数据移到栈顶.
OP_ROT123x1 x2 x3x2 x3 x1栈顶3项数据向左旋转.
OP_SWAP124x1 x2x2 x1栈顶2项数据交换.
OP_TUCK125x1 x2x2 x1 x2栈顶数据复制并插入到次栈顶数据前
OP_2DROP109x1 x2Nothing同 DROP,只是数据项是2项.
OP_2DUP110x1 x2x1 x2 x1 x2同 DUP,只是数据项是2项.
OP_3DUP111x1 x2 x3x1 x2 x3 x1 x2 x3同 DUP,只是数据项是3项.
OP_2OVER112x1 x2 x3 x4x1 x2 x3 x4 x1 x2同 OVER,只是数据项是2项.
OP_2ROT113x1 x2 x3 x4 x5 x6x3 x4 x5 x6 x1 x2同 ROT,只是数据项是2项.
OP_2SWAP114x1 x2 x3 x4x3 x4 x1 x2同 SWAP,只是数据项是2项.

字符串处理

字符串处理的大多数指令都被禁止了。

WordOpcodeInputOutputDescription
OP_CAT126x1 x2outConcatenates two strings. [禁止]
OP_SUBSTR127in begin sizeoutReturns a section of a string. [禁止]
OP_LEFT128in sizeoutKeeps only characters left of the specified point in a string. [禁止]
OP_RIGHT129in sizeoutKeeps only characters right of the specified point in a string. [禁止]
OP_SIZE130inin size返回字符串长度

位运算

WordOpcodeInputOutputDescription
OP_INVERT131inoutFlips all of the bits in the input. [禁止]
OP_AND132x1 x2outBoolean and between each bit in the inputs. [禁止]
OP_OR133x1 x2outBoolean or between each bit in the inputs. [禁止]
OP_XOR134x1 x2outBoolean exclusive or between each bit in the inputs. [禁止]
OP_EQUAL135x1 x2True / falseReturns 1 if the inputs are exactly equal, 0 otherwise.
OP_EQUALVERIFY136x1 x2True / falseSame as OP_EQUAL, but runs OP_VERIFY afterward.

数学运算

WordOpcodeInputOutputDescription
OP_1ADD139inout1 is added to the input.
OP_1SUB140inout1 is subtracted from the input.
OP_2MUL141inoutThe input is multiplied by 2. [禁止]
OP_2DIV142inoutThe input is divided by 2. [禁止]
OP_NEGATE143inoutThe sign of the input is flipped.
OP_ABS144inoutThe input is made positive.
OP_NOT145inoutIf the input is 0 or 1, it is flipped. Otherwise the output will be 0.
OP_0NOTEQUAL146inoutReturns 1 if the input is 0. 0 otherwise.
OP_ADD147a bouta is added to b.
OP_SUB148a boutb is subtracted from a.
OP_MUL149a bouta is multiplied by b. [禁止]
OP_DIV150a bouta is divided by b. [禁止]
OP_MOD151a boutReturns the remainder after dividing a by b. [禁止]
OP_LSHIFT152a boutShifts a left b bits, preserving sign. [禁止]
OP_RSHIFT153a boutShifts a right b bits, preserving sign. [禁止]
OP_BOOLAND154a boutIf both a and b are not 0, the output is 1. Otherwise 0.
OP_BOOLOR155a boutIf a or b is not 0, the output is 1. Otherwise 0.
OP_NUMEQUAL156a boutReturns 1 if the numbers are equal, 0 otherwise.
OP_NUMEQUALVERIFY157a boutSame as OP_NUMEQUAL, but runs OP_VERIFY afterward.
OP_NUMNOTEQUAL158a boutReturns 1 if the numbers are not equal, 0 otherwise.
OP_LESSTHAN159a boutReturns 1 if a is less than b, 0 otherwise.
OP_GREATERTHAN160a boutReturns 1 if a is greater than b, 0 otherwise.
OP_LESSTHANOREQUAL161a boutReturns 1 if a is less than or equal to b, 0 otherwise.
OP_GREATERTHANOREQUAL162a boutReturns 1 if a is greater than or equal to b, 0 otherwise.
OP_MIN163a boutReturns the smaller of a and b.
OP_MAX164a boutReturns the larger of a and b.
OP_WITHIN165x min maxoutReturns 1 if x is within the specified range (left-inclusive), 0 otherwise.

加密相关

WordOpcodeInputOutputDescription
OP_RIPEMD160166inhashThe input is hashed using RIPEMD-160.
OP_SHA1167inhashThe input is hashed using SHA-1.
OP_SHA256168inhashThe input is hashed using SHA-256.
OP_HASH160169inhashThe input is hashed twice: first with SHA-256 and then with RIPEMD-160.
OP_HASH256170inhashThe input is hashed two times with SHA-256.
OP_CODESEPARATOR171NothingNothingAll of the signature checking words will only match signatures to the data after the most recently-executed OP_CODESEPARATOR.
OP_CHECKSIG172sig pubkeyTrue / falseThe entire transaction’s outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise.
OP_CHECKSIGVERIFY173sig pubkeyTrue / falseSame as OP_CHECKSIG, but OP_VERIFY is executed afterward.
OP_CHECKMULTISIG174sig1 sig2 … <number of signatures> pub1 pub2 <number of public keys>True / FalseFor each signature and public key pair, OP_CHECKSIG is executed. If more public keys than signatures are listed, some key/sig pairs can fail. All signatures need to match a public key. If all signatures are valid, 1 is returned, 0 otherwise.
OP_CHECKMULTISIGVERIFY175sig1 sig2 … <number of signatures> pub1 pub2 … <number of public keys>True / FalseSame as OP_CHECKMULTISIG, but OP_VERIFY is executed afterward.

伪词(Pseudo-words)

下列词汇用于在内部使用,在脚本系统中实际上不存在的词。

WordOpcodeDescription
OP_PUBKEYHASH253表示OP_HASH160 后的公开密钥散列
OP_PUBKEY254表示一个公开密钥(可以被 OP_CHECKSIG).
OP_INVALIDOPCODE255

保留词(Reserved words)

没有被定义的opcode被保留以后使用,如果在脚本中使用这些保留词,要么被忽略,要么使得交易无效。

WordOpcodeWhen used…
OP_RESERVED80Transaction is invalid
OP_VER98Transaction is invalid
OP_VERIF101Transaction is invalid
OP_VERNOTIF102Transaction is invalid
OP_RESERVED1137Transaction is invalid
OP_RESERVED2138Transaction is invalid
OP_NOP1-OP_NOP10176-185The word is ignored.

Ok,接着描述交易验证的具体的过程。

涉及的脚本命令(操作符)

首先讲讲涉及到的脚本命令(操作符),描述栈顶项的变化方式如下:(n1 n2 — ) 用 “–”分隔操作符执行前后的栈中元素的变化,左边表示操作前,右边表示操作后。最右边的项表示栈顶元素。这里例子中,n2 表示栈顶,n1表示次栈顶,操作后n1,n2均被弹出。

  • OP_EQUAL(n1 n2 — true/false): 判断栈顶两项是否相等的脚本命令,如果相等则压入true,否则false
  • OP_VERIFY(true/false — NOTHING/false): 如果栈顶项为true,标记改交易单为有效,否则失败,压入false并返回
  • OP_CODESEPARATOR( — ): 将当前执行PC(ProgramCount)保存到变量: pbegincodehash
  • OP_CHECKSIG(<sig> <pubKey>– true/false): 校验收入来源(in)的签名是否有效。栈顶是公开密钥(PubKey),次栈顶是签名(Sig)。如果验证通过会压入True,否则压入False。
  • OP_EQUALVERIFY(n1 n2 — NOTHING/false): 等于 OP_EQUAL OP_VERIFY 两个操作符的联合。

交易验证

以最常见的接收地址交易转账为例描述交易验证的过程(SendMoneyToBitcoinAddress)

首先示例交易如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "hash":"23c9e8a3140938a65c73fa0712b1d8614c8eeef486a4ab14107fcce54fbf768c",
  "ver":1,
  "vin_sz":1,
  "vout_sz":2,
  "lock_time":0,
  "size":258,
  "in":[
    {
      "prev_out":{
        "hash":"0740c9ecdef03e46e4c0f74833db5af3cb24c7d48810ef73411662252046f9c6",
        "n":0
      },
      "scriptSig":"304502204028931b310bfec094bbd04275f69beba6bf5f44ab3dbbec9564c34ef9bc1ddc022100d37c214e
978808099fc96006b41244d31b203eb4b1c69be9d57b0e2f843ad93501
      0481f6d0a51bfecb5112f223807ba668c67ac975fb096d07ef65b852a6864d9e9c18c9c16e5887c3f03be519fd42cae52f6d1a05d10a2fa7c783b19e9b74be07d6"
    }
  ],
  "out":[
    {
      "value":"12.99000000",
      "scriptPubKey":"OP_DUP OP_HASH160 ef055cb1e8e192cbd8b6a89ccf1eb73552d9764b OP_EQUALVERIFY OP_CHECKSIG"
    },
    {
      "value":"17.00000000",
      "scriptPubKey":"OP_DUP OP_HASH160 923f3cdf648c1755455a17097d22f0be6add7c7c OP_EQUALVERIFY OP_CHECKSIG"
    }
  ]
}

ScriptSig(<sig> <pubKey>): 中有两个值,一是当前拥有者的该交易单的签名,二是拥有者的公开密钥(用来验证签名)。

1
2
3
4
5
6
7
Sig: 304502204028931b310bfec094bbd04275f69beba6bf5f44ab3dbbec9564
c34ef9bc1ddc022100d37c214e978808099fc96006b41244d31b203eb4b1c69
be9d57b0e2f843ad93501
  
PubKey:0481f6d0a51bfecb5112f223807ba668c67ac975fb096d07ef65b852a6
864d9e9c18c9c16e5887c3f03be519fd42cae52f6d1a05d10a2fa7c783b19e9b7
4be07d6

脚本执行验证过程:

  • 执行 scriptSig:
    • 压入 <sig> 和 <pubKey> : <sig> <pubKey>
  • 执行 scriptPubKey:
  • OP_DUP 复制栈顶<pubKey>: <sig> <pubKey> <pubKey>
  • OP_HASH160 对栈顶项做HASH160(RIPEMD-160(SHA256(<pubKey>))散列: <sig> <pubKey> <pubKeyhashA>
  • <pubKeyHash> : 压入 <pubKeyHash>
  • OP_EQUALVERIFY: 对栈顶两个元素 <pubKeyHashA> <pubKeyHash> 做是否相等校验,如果不相等那么标记交易单无效并返回,如果等于继续: <sig> <pubKey>
  • OP_CHECKSIG: 校验收入来源的In的签名是否有效,根据pubKey去校验签名<sig>,签名的内容为交易单的Ins, Outs和脚本(从最近一次的 OP_CODESEPARATOR 到脚本结束的位置)的散列。 PubKey.Verify(SignatureHash(scriptCode, nIn, Outs), Sig)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//nIn 当前的交易单的in的索引号
//scriptCode: 保存的当前执行的代码从OP_CODESEPARATOR(如果没有就从脚本开始) 到脚本结束。
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
    if (nIn >= txTo.vin.size())
    {
        printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
        return 1;
    }
    CTransaction txTmp(txTo);
  
    // In case concatenating two scripts ends up with two codeseparators,
    // or an extra one at the end, this prevents all those possible incompatibilities.
    scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
  
    // Blank out other inputs' signatures
    for (int i = 0; i < txTmp.vin.size(); i++)
        txTmp.vin[i].scriptSig = CScript();
    txTmp.vin[nIn].scriptSig = scriptCode;
  
    // Blank out some of the outputs
    if ((nHashType & 0x1f) == SIGHASH_NONE)
    {
        // Wildcard payee
        txTmp.vout.clear();
  
        // Let the others update at will
        for (int i = 0; i < txTmp.vin.size(); i++)
            if (i != nIn)
                txTmp.vin[i].nSequence = 0;
    }
    else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
    {
        // Only lockin the txout payee at same index as txin
        unsigned int nOut = nIn;
        if (nOut >= txTmp.vout.size())
        {
            printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
            return 1;
        }
        txTmp.vout.resize(nOut+1);
        for (int i = 0; i < nOut; i++)
            txTmp.vout[i].SetNull();
  
        // Let the others update at will
        for (int i = 0; i < txTmp.vin.size(); i++)
            if (i != nIn)
                txTmp.vin[i].nSequence = 0;
    }
  
    // Blank out other inputs completely, not recommended for open transactions
    if (nHashType & SIGHASH_ANYONECANPAY)
    {
        txTmp.vin[0] = txTmp.vin[nIn];
        txTmp.vin.resize(1);
    }
  
    // Serialize and hash
    CDataStream ss(SER_GETHASH);
    ss.reserve(10000);
    ss << txTmp << nHashType;
    return Hash(ss.begin(), ss.end());
}


bitcoin

挖矿与块(Blocks)

接下来讲的是什么是挖矿,以及交易单在P2P网络上的存放,其实这个过程也是挖矿的过程。

所有的交易单是以Block的形式在Bitcoin P2P网络上存放的。每一个Block包含了最近所有的有效交易单。Block中最为重要数据为:

  • 最近交易单集合
  • Nonce随机数
  • 前一个块的散列值

在造币的Node总在侦听网络,接收信息,然后各自将接收到的新交易打包到一个新block(CBlock Class in main.h)。在块交易单集合中的第一个交易单总是“造币单”:给创建该块的人以新的货币,节点只需要校验货币金额是否合法即可:形成一个合法的新块得到的回报是初始金额为50BTC,每产生210,000块的时候这个金额减半(大约每隔4年会发生一次)。产生合法的新块是不容易的,需要通过无数次的计算尝试得到,另外如果大家都在计算同一个新块,那么还存在竞争关系,这个时候只有最困难(Difficulty)的那个块(指整个块链的困难度值加起来最大的)才会被网络认可。另外如果块中的某笔交易size大于该块中交易单的平均size,那么该笔交易单会被收取一笔小的交易费用。

块的数据结构

块的数据结构可以分为块头(block header)和块体(block body)

块头(Block Header)

块头的数据是用于校验块、产生块ID(256位散列值),这个块ID也是决定块是否合法的数字。计算块ID的公式如下:

1
BlockID = SHA256(SHA256(Block_Header))

块头(Block Header)的内容如下:

  • ver: 版本号(4字节)
  • prev_block: 前一个块的256位散列值
  • mrkl_root: 所有交易单的256位散列
  • time: 时间戳(4字节)
  • Bits: 一个紧凑格式的4字节的数字,它表示一个256位的当前目标(Target)数值,这也表示困难度(Difficulty),最后产生块的ID值必须不大于目标值才能被接受(如果有多人同时产生同一个块,那么最困难的将被接受)。这个数值会每隔2016个block(网络大约每小时创建6个块,创建2016块大约2周)调整一次,当产生前一个2016块的时间大于2周的时候,难度值将会被调低,当小于两周的时候难度值将被调高(关于Target和Difficulty详见后述)。
  • nonce: 32位随机数。节点在产生Block的时候,会增量尝试改变nonce的值,直到产生的块的散列值符合bits的要求

计算目标(Target)和困难度(Difficulty)

计算目标(Target)

计算目标(Target)是一个256位的数值,块的散列值ID必须小于或等于该目标数值,放可被接受。块头中的BITS是一个用紧凑的4字节格式表示的目标(Target)数值,它表示一个256位的当前目标数值,方式如下:

1
2
3
4
//假设BITS为:
BITS = 0x1B0406CC
//那么target的数值则是:
Target = 0x0406CC * 2^(8*(0x1B-3))= 0x00000000000406CC000000000000000000000000000000000000000000000000

当前网络的目标值为:Current target

困难度(Difficulty)

困难度(Difficulty)表示该块ID的计算难度,值越大表示越困难,1表示最容易。

1困难度(Difficulty)的Target被定义为:

1
0x1D00FFFF(BITS)

展开后:

1
0x00FFFF * 2^(8*(0x1D - 3)) = 0x00000000FFFF0000000000000000000000000000000000000000000000000000

因此困难度的计算公式为:1 困难度(Target) / 当前目标

我们可以在这里查看当前网络的困难度:Current difficulty(BitCoin的 getDifficulty 接口输出)。也可以通过这个网站查看困难度值的变化情况图:Graphs

块体(Block Body)

Block Body 实际上就是交易单的集合。

你可以在这个网站上看到当前网络所有的交易单(Blocks):  https://blockexplorer.com/

一个具体的块的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
{
   //hash: 自身ID的sha256散列值
  "hash":"0000000000001470ed62a9d73c1c74a4b3754e18db0abb057be5ad5ffed659bb",
  "ver":1,
  "prev_block":"000000000000158a4051185f339d59227b776ac6bfe6120fa18293b5c08644a8",
  "mrkl_root":"c5341062635c427b79a730dca8d4a5eb6a482fa21f82cc37c84ae01ea5945fc3",
  "time":1307565484,
  "bits":438145839,
  "nonce":2323396371,
  //交易单数量
  "n_tx":6,
  "size":2193,
  "tx":[
    {
      "hash":"67dbdbc6c4a49bc3364d34aebe76b6f470ced66eb731f9d099d0da6c58e466cf",
      "ver":1,
      "vin_sz":1,
      "vout_sz":1,
      "lock_time":0,
      "size":135,
      "in":[
        {
          "prev_out":{
            "hash":"0000000000000000000000000000000000000000000000000000000000000000",
            "n":4294967295
          },
          "coinbase":"042f931d1a022301"
        }
      ],
      "out":[
        {
          "value":"50.04000000",
          "scriptPubKey":"049db428c19890bb7706bebdcf69a93c192daef8a73eb7035e2600468b4e1f83d4c2134640f6c619e5521c2050ebc9be9e9c502fda
b655a570236418e5c2e95137 OP_CHECKSIG"
        }
      ]
    },
    {
      "hash":"c96eb8f874d105e24121cdc5918440c85af27b797013679796fcc26e40938ad2",
      "ver":1,
      "vin_sz":1,
      "vout_sz":2,
      "lock_time":0,
      "size":258,
      "in":[
        {
          "prev_out":{
            "hash":"c8caedb7edb2665b8543916a1e6b1dee2bf1733f75b4604c423db08efa570d65",
            "n":0
          },
          "scriptSig":"3045022100b47c10ebd2413c575510563363fe9cad7f0fdcbefca9dd219bd345bcfeff98a1022049d7037c0be3493650
cb2a410a655394678e75a28b8f4cd587644813ccee383801
          041f5853d9d43b81af0999a4add012e6580db5edc7dabf99bc2aff1a01b1296e7004b73b10a9e2d3ebe0d7377c545aacc56e24aff1c9b130e0721332315e414f72"
        }
      ],
      "out":[
        {
          "value":"3.98000000",
          "scriptPubKey":"OP_DUP OP_HASH160 22718315d786b8f64510be88ad590760de676a59 OP_EQUALVERIFY OP_CHECKSIG"
        },
        {
          "value":"0.01000000",
          "scriptPubKey":"OP_DUP OP_HASH160 d52804c9bc12e7a7186e53b41784dcd2afed9a92 OP_EQUALVERIFY OP_CHECKSIG"
        }
      ]
    },
    {
      "hash":"cd74421dd3d32346bdbef02cde4bc0ed19b5cc15621f761b465a869b2f51287c",
      "ver":1,
      "vin_sz":2,
      "vout_sz":2,
      "lock_time":0,
      "size":437,
      "in":[
        {
          "prev_out":{
            "hash":"e38b71a89071be2820ce95841da03ba8bac77d536d9ac5fe5347136e9bbca104",
            "n":1
          },
          "scriptSig":"3045022100ed5c3626adf84a6d364d7b58fb182ee3bd35758a883ebe2e642e83f4103e91cd022063f61a1d89c1a30f713c2ca277c08c
1c4ceb585babef82301f738fdc2312329d01
          047b4277bb4c23988986c44552156130d4155a1020ec411ca4a07904191d9054de705ec2b79a46155a0d59e8a39b5d450ac73d485b082789b6dad55d5e2230f597"
        },
        {
          "prev_out":{
            "hash":"a6fc46a5a4a6b202c644cc4854feb2d8cf7befcf695ad810346c8dfb4cc18138",
            "n":1
          },
          "scriptSig":"304402207de219304bfca0e2d93524a2547767ce5044501bb0d9107e04d35cf3d644136d02201244a1ce47c2f3aab6c205e75e433371efb01
dad5073d316bf68488ea1ad064301
          04d74d74c0f2bd415a94090c83bbe10b4949c7ee8f3bb957352d02fb50f3e1ddc5ab79a28b1228eaf2986339a3735e32869019d4894f34a46645288a68900ef6a5"
        }
      ],
      "out":[
        {
          "value":"0.01000000",
          "scriptPubKey":"OP_DUP OP_HASH160 e95281e139fc37bb2aabd84028835c6513a6ac99 OP_EQUALVERIFY OP_CHECKSIG"
        },
        {
          "value":"2.01000000",
          "scriptPubKey":"OP_DUP OP_HASH160 234c6c8644008de240d90753904789868100786c OP_EQUALVERIFY OP_CHECKSIG"
        }
      ]
    },
    {
      "hash":"9d4f130995dbc1ddc5346c109992c0779aa44122195eff51dc00109afc5cad7d",
      "ver":1,
      "vin_sz":1,
      "vout_sz":2,
      "lock_time":0,
      "size":258,
      "in":[
        {
          "prev_out":{
            "hash":"d84cd74d4b470f96379fa9737c43be544e4e57f33e83fc8bf26f232ec5ea97b5",
            "n":0
          },
          "scriptSig":"3045022100d8f3bbb19b4d2593649b4f6ac0074a772ff78fce1fb60e7957c7d99d2627931802205ad4774f58af0b52e37f875
92bea7bae84c883c9230e722962f2e52e7eb061e201
          04732060c3f57ccc0703e05f86f442e45617b446ebca7e9f6c96ca1ec754b9d8a9f2bd727a15c7821cbca0498c2b7f60081873a450f29c5937e9593407166dc71b"
        }
      ],
      "out":[
        {
          "value":"30.26538895",
          "scriptPubKey":"OP_DUP OP_HASH160 7fa1d78819360231c6bc1b23ff644e9124da075f OP_EQUALVERIFY OP_CHECKSIG"
        },
        {
          "value":"4.76000000",
          "scriptPubKey":"OP_DUP OP_HASH160 847f4729a1464d7a2103796cca32022fe0481d58 OP_EQUALVERIFY OP_CHECKSIG"
        }
      ]
    },
    {
      "hash":"68050dc3810310e1e5e9eb3464b1581a353de523a6f26d8b978370bd63880eb7",
      "ver":1,
      "vin_sz":4,
      "vout_sz":1,
      "lock_time":0,
      "size":766,
      "in":[
        {
          "prev_out":{
            "hash":"07a39559553efb329af1538e0fc8a037f20048a83b2278a5041975054e425c3e",
            "n":17
          },
          "scriptSig":"3046022100c3ce1ee6c222d74ff9c97d5729e5c6702c3cabdb61ea0fb3ae8632eae36f03fb0221009cea5a9f94fe14e4673fd87
f75750e1d151f6e846c371d8e4af72b5d213bb5c001
          04ee9e80055248ed804ca6724b2d784c91eec04abdc4ec00b14dc01e56c90513a85453026acf90f1cb1bdd3e3ca07035be40d0b3e3ac6076b5b12bd3234ac8c20b"
        },
        {
          "prev_out":{
            "hash":"07f95bfdd09e98bf7ce0543e8fdd82f9e8532449ab7167f69aa3d1f030399b96",
            "n":0
          },
          "scriptSig":"3044022011f922460d01986255a6f5e5ce88586bb3a9a32edc836e420d2347dae9df12e1022018d9d4e48dea2b821e01d3253dfaa03af801
d01e79ab4eb3ef48f22f84f196aa01
          04398f321ea6140c6ad51fea724f7c13e1df6c43afb8e4f6f9ab2385b6e18d8eae52516a0b3487512a3dbeb36109d3fcb6391fbc156518c96f57467f97dc55d0a3"
        },
        {
          "prev_out":{
            "hash":"6c93900990b712fbf2a386ba53bc3aad8f5bcdda73b855a24628d7eae80cf3f9",
            "n":0
          },
          "scriptSig":"3046022100b688feeb1012f913b6366b5b9bd5313238d00b61b48a0e3956c33d1dffc9a1f2022100ed159808e8a732e646ba5af7ed
5a0d896c7db0a10757aeccc9c58a67ec42ec7501
          047e79adbe50ae668041d2b08702c12de83fdaecb866b261755cbba27fe344c6fc67f3fc2593edc0bb053b0fde62c4d42d152b6525c10bde365d80a8d2d8d77a85"
        },
        {
          "prev_out":{
            "hash":"ed416acb1373bcce28ec63e6e600e0da7f8892b557591bc0386210c56e8c034f",
            "n":1
          },
          "scriptSig":"3046022100c1ffdf383d108a9b1e8e33ed3ef8bd6b368b1ed0584ac187eb0897c90422fc5b022100f7bfb8f0b17c3b1
21943622a4d04a8a818391c68028b6a63d9cd2536d9f3714501
          04ee9e80055248ed804ca6724b2d784c91eec04abdc4ec00b14dc01e56c90513a85453026acf90f1cb1bdd3e3ca07035be40d0b3e3ac6076b5b12bd3234ac8c20b"
        }
      ],
      "out":[
        {
          "value":"1.69000000",
          "scriptPubKey":"OP_DUP OP_HASH160 71b9ea593ba56d1159493cb2b37a03f368fb6c40 OP_EQUALVERIFY OP_CHECKSIG"
        }
      ]
    },
    {
      "hash":"4e6e47f0fa7a559219be309db20c5c17296956304cf47dc8c52910c24b505a92",
      "ver":1,
      "vin_sz":1,
      "vout_sz":2,
      "lock_time":0,
      "size":258,
      "in":[
        {
          "prev_out":{
            "hash":"897f67e6ec0b5a64b511c2052d05f0e2437811260041bb0915f2c40879025215",
            "n":1
          },
          "scriptSig":"304502200dbe53f77f947b12dfabb737e0862c1f2d37515f6293b06c08710ccdb69419d6022100b379ab597d8d17034f1654f20e
68c72930050342884743869b6421ee7eaad83801
          04bdd996cd29ca3d34604306de8983d1fadf978ae43c12c1e832ce803ae57241cd7762a40dc1e5f6176ca3b0caac622c82e271b59c66fb1f8fa8225930a8807edf"
        }
      ],
      "out":[
        {
          "value":"0.04000000",
          "scriptPubKey":"OP_DUP OP_HASH160 50e44bb02555c7084e08cda95eb43a9c621fa0ac OP_EQUALVERIFY OP_CHECKSIG"
        },
        {
          "value":"0.03000000",
          "scriptPubKey":"OP_DUP OP_HASH160 ecd8f97222481950eed4f98db82455635ccb86b4 OP_EQUALVERIFY OP_CHECKSIG"
        }
      ]
    }
  ],
  "mrkl_tree":[
    "67dbdbc6c4a49bc3364d34aebe76b6f470ced66eb731f9d099d0da6c58e466cf",
    "c96eb8f874d105e24121cdc5918440c85af27b797013679796fcc26e40938ad2",
    "cd74421dd3d32346bdbef02cde4bc0ed19b5cc15621f761b465a869b2f51287c",
    "9d4f130995dbc1ddc5346c109992c0779aa44122195eff51dc00109afc5cad7d",
    "68050dc3810310e1e5e9eb3464b1581a353de523a6f26d8b978370bd63880eb7",
    "4e6e47f0fa7a559219be309db20c5c17296956304cf47dc8c52910c24b505a92",
    "f4462bd30c529d154dc1b35d8f68961441e09ffaceaa25da17eb1814101f8ad5",
    "1961263895b63d4760f81eda7ae94848eb68e2170b79a224ba704a3c21fd6feb",
    "0427a2dbd54fa6ec034d704336fa255f6c139e6d7b9bf803714cfbc9dcc61b85",
    "42441420d09c91336e69bae9f7eb39b1c6d90562028de3094bea5f675a25a082",
    "4af79ccb4bf857df3e75a50106b15ef35aa73a209efa5089f2f2193ff70ab93d",
    "c5341062635c427b79a730dca8d4a5eb6a482fa21f82cc37c84ae01ea5945fc3"
  ]
}

趁今早,把以前零碎的分析给整理出来,就算对开源Bitcoin P2P 电子货币系统内幕最后一篇的小结。

问题

Bitcoin目前存在的问题其实是非常多的,目前Bitcoin的主要成就是解决了数字货币的两个核心问题,并在线上做了验证,取得了一定的实际经验。

已经解决的问题

Bitcoin 目前较好的解决了数字货币的两个核心问题:

  • * 货币伪造复制
  • * 货币重复花费

尚未解决的问题

在我看来 Bitcoin 其实只是一次试水,看看方案到底是否可行,从当前的试验结果看来,方案是可行的。这已经令人非常high了,但是这个方案现在看来还是比较粗糙的,许多细节需要完善,这里只提下最严重的问题。目前随着交易量的日益增加,当下最为严重的两个问题是关于存储和流量。

存储和流量问题

* 存储:目前每个节点上文件数据是684M(我记得上个月已经上G,初步猜测脚本算法终于增加了pruning算法,把存储和流量给降了下来),但是这始终会随着交易量的增加而持续增加的。
* 流量:上个月,当连接数在115-130的时候,节点3小时内的流量大约143M。当在PC新安装Bitcoin客户端后全部获取900M交易单信息花了8小时。这个月因为算法改进,有所好转。
不过一旦参与的人数越来越多,交易日益频繁,这个上限依然存在。

目前Bitcoin网络上Block的总数为:137741 http://blockexplorer.com/q/getblockcount
平均块大小为:25460 http://blockexplorer.com/q/avgblocksize
那么所有块的总大小为:137741*25460=3506885860(bytes)=3344.427MB =3.266GB

Visa组织目前平均每年大约处理28.4*1000000000(Billion)笔交易,也就是平均每秒大约处理54000笔交易(参阅此处)。
而Bitcoin网络目前的最大处理能力只有每秒7笔交易。如果按照目前的处理方式,假设要每秒处理2000笔交易,
那么每秒的数据流量就会达到大约1G Bytes的样子。(参阅此处)

存储和流量问题的根本原因在于:目前是完全对等的P2P交易系统,对于交易并没有分布式处理机制,
每一个节点都必须保持所有的历史交易单,而不是每一个节点上分担一部分。

这需要采用分布式处理(Map-Reduce)方式对交易进行处理,不需要所有的节点都保持所有的数据。
我以为可以设定如下的分布Mapping方式:
1、保持自己相关的交易数据:只保持自己钱包中的货币相关交易。
2、保持临近节点的交易数据:只对邻居节点服务
3、保持交换的交易数据信息:如果对方节点保存了自己的相关交易则也为对方他的交易数据
4、按远近程度决定服务对象:越远服务费高
5、按远近切分成若干小网络:形成当地BTC货币,通过兑换维持各个网络之间的流通

断网的疑问

这是曹晓刚同学提出的,善意的说就是当海底光纤断掉后,两个网络之间没有别的连接通道的情况下
的重复花费问题。很遗憾,目前的Bitcoin体系中没有解决这样的问题。问题简化描述如下:

1A  2A|   |1B--2B|   |1C  2C

比如将节点1A上的钱包有25000BTC数据复制到了节点2A。
1A,1B,1C和2A,2B,2C两个网络之间仅仅通过节点1B和2B连接。现在1B,2B之间的连接断了。
在1A上的花费,和在2A上的花费就成了重复花费。

可能的解决办法:

1. 1A上得来的钱,广播验证,首先是本网络的节点做的验证居多。那么如果移到2A,并且断网,大部分验证的节点必然就不再存在。
2. 实名交易
3. Bitcoin 不再是一个大网,而是按网络远近切分的若干小网,见上述的分布式处理机制方案

通过兑换机制: A1B1C1产生的独立货币1,A2B2C2产生独立货币2,自由兑换。

囤积操纵市场问题

这几乎不算一个严重的问题,不过如果是限制了BTC总量(目前的算法是这样做的)。那么如果BTC被囤积操作市场,总感觉不对。
如何避免被BTC囤积?另外,Bitcoin币仅仅存在于wallet.dat文件中,如果该文件丢了,那么该wallet中的所有货币也就丢了。
如果足够长的时间内某一笔货币没有交易流通,那么就可以等效于失去了。
1. 也许回收长时间没有流通的BTC币是一个法子。
2. 也许刺激赋予活跃度高的BTC更高的价值也是一个法子。
3. 也许不应该限制BTC 总量,只需要能在网络中调控保持稳定的增加速率即可。

不过,这一块也许专门研究货币金融的专家才更有资格说话。

展望与未来

目前Bitcoin进入现实货币体制并能取代之,还为之过早,不过在私下的一些特殊场合可以取得一定现实货币的地位。

类似Bitcoin P2P虚拟货币体系的目前最大的应用场景也许是在游戏(非实体)世界上。这样使用者的利益可以得到最大限度的保障,不用担心公司的倒闭,也不用担心公司随意增发虚拟货币。更加方便快捷,可以在任意的游戏或者非实体体系中使用。

  1. 游戏(虚拟)世界的主流货币
  2. 分布式计算能力交换的计量单位
  3. 自动化的分布式的兑换体系
  4. 去中心化的钱包(decentralized wallet)
  5. P2P的担保人(中间人)体系
  6. 去中心化的认证体系(Decentralized OpenID)

参考文献编辑本段回目录

http://www.showmuch.com/article/article_117.html

→如果您认为本词条还有待完善,请 编辑词条

词条内容仅供参考,如果您需要解决具体问题
(尤其在法律、医学等领域),建议您咨询相关领域专业人士。
0

标签: P2P电子货币系统内幕

收藏到: Favorites  

同义词: 开源Bitcoin P2P电子货币系统内幕,开源Bitcoin P2P电子货币

关于本词条的评论 (共0条)发表评论>>

对词条发表评论

评论长度最大为200个字符。