合约 - 比特币开发指南
原文链接: https://bitcoin.org/en/developer-guide#transactions
翻译: terryc007
版本:1.0
比特币开发指南
1.区块链
2.交易
3.合约
4.钱包
5.支付处理
6.工作模式
7.P2P网络
8.挖矿
合约是一种使用去中心化的比特币系统实施金融协议的交易。精心制作的比特币合约可以最小化依赖外部代理,比如法院,在金融交易里,处理未知实体时,它能极大的减低其风险。
本节讲述各种各样目前在用的比特币合约。因为合约不仅要处理交易,还包括真实的人,下面以故事的方式来讲解这些合约。
除了下面所提供的合约,很多其他合约类型已经被提议。其中一部分在比特币Wiki合约页面可以查到。
托管和仲裁
Charlie(作为消费者)想从Bob(作为商人)那里购买一个商品,但是他们彼此不信任,因此他们使用一个合约来帮助Charlie获得商品,Bob获得付款。
一个简单的合约可以描述:Charlie将要在一个输出上花掉satoshi,只要Charlie跟Bob都在输入上签名,这个输出才能被发掉。这意味着Bob不会获得付款,除非Charlie获得他的商品,但是Charlie不能获得商品,就可以保住自己的付款。
如果发生纠纷,这个简单的合约就帮不上忙了,因此Bob和Charlie就要Alice(作为仲裁者)来帮忙创建一个托管合约。Charlie支付他的satoshi到一个输出,这个输出只有当他们三人中的两个对输入进行签名,才能花掉这个输出。如果一切没问题,现在Charlie可给Bob付款,如果问题,Bob能退款给Charlie,或者如果有纠纷,Alice能仲裁且决定谁获得satoshi。
未来创建一个多重签名(mutilsig)输出,他们每个人需要其他人自己的公钥。让后Bob创建下面的P2SH多重签名redeem脚本。
OP_2 [A's pubKey] [B's pubkey] [C's pubkey] OP_3 OP_CHECKMULTISIG
(把公钥压入堆栈的操作符并未在上面显示出来)
OP_2
和OP_3
操作符会在堆栈中压入数字2,数字3. OP_2
指定需要2个签名;OP_3
指示提供了3个公钥(未被哈希)。这是个一个2-of-3多重签名公钥脚本,更一般的叫法是:m-of-n公钥脚本(m表示最少签名个数,n表示实际提供的签名个数)。
Bob把这个redeem脚本给Charlie, Charlie会检查并确保Bod的公钥,Alice的公钥在里面。然后他对这个redeem脚本进行哈希,并创建一个P2SH redeem脚本,同时支付satoshi给这个脚本。当Bob看到这个支付已经添加到区块链后,他再发货。
不幸的是,在运输途中,商品受了点损伤。Charlie想要退款,但是Bob认为10%的退款就足够了。他们向Alice寻求解决这个问题。Alice向Charlie索要了损坏的图片证明,一份Bob的redeem脚本,Charlie的检查。
看完证明后,Alice认为40%的退款是合理的,因此它创建一个带有两个输出的签名交易,一个60%satoshi给Bob的公钥,一个是剩下的40%satoshi给Charlie的公钥。
在签名脚本中,Alice把她的签名,Bob创建的未被哈希的序列化的redeem脚本的一份拷贝放入其中。她给Bob,Charlie给咱发了一份非完整的交易。他们中的任何一方可以在交易中加入自己的签名就可以完成这个交易。如下:
OP_0 [A's signature] [B's signature] [serialized redeem script]
(压入签名,redeem脚本的操作符在上面并没有显示出来。OP_O
是一个解决一个在比特币初始实现中,一位偏移错误给出的方案。为解决兼容必须保留它。注意的是签名脚本中提供的签名顺序必须跟redeem 脚本中出现的公钥顺序对应起来。具体情况OP_CHECKMULTISIG).
当这个交易被广播到比特币网络,每个节点会检查签名脚本,并与之前Charlie支付的输出对照,以确保redeem脚本跟之前提供的redeem脚本哈希值是匹配的。然后用作为输入的两个签名,对redeem脚本进行求值。假如这个redeem脚本是验证通过,这两个交易输出会以可用余额的方式在Bob,Charlie的钱包显示出来。
然而,如果Alice创建的签名交易,Bob,Charlie都不同意,比如把所有的satoshi支付给Alice自己,Bob和Charlie可以找一个新的仲裁,同时对一个把satoshi支付到另外一个2-of-3多重签名redeem脚本哈希的交易进行签名,这个交易包括了来自第二个仲裁的公钥。这就意味着Bob和Charlie永远不用当心他们的仲裁者会窃取他们的钱。
资源: BitRated使用一个HTML/JAVASCRIPT (GNU AGPL 协议)网站提供了一个多重签名仲裁服务接口。
微支付通道
Alice在业余时间帮Bob管理论坛发帖。每当有人在Bob的论坛发帖时,Alice会浏览下贴纸,以确保不是攻击性的,或者是垃圾帖子。可是,Bob经常忘记给Alice付款,因此Alice要求每审核一个帖子,就要求Bob给她支付。Bob说他不能这样做,因为上百条支付会扣掉很多交易费用,因此Alice建议使用微支付通道。
Bob向Alice要了她的公钥,然后创建了两个交易。第一个交易支付100 毫比特币给一个P2SH输出,这个输出是一个2-of-2的多重签名redeem脚本,需要Alice跟Bob两人的签名。这是一个组合交易。广播这个交易会让Alice持有这些质押的比特币,因此Bob让这个交易现在保持私密,同时创建第二个交易。
第二个交易花掉第一个交易中所有的比特币(扣除交易费), 通过采用锁定时间,24小时后,再退回给Bob。这是一个退款交易。Bob是不能自己来签名这个退款交易,因此他给Alice来签名,如下图所示:
Alice检查并且确认退款交易的锁定时间是24小时后,签名该交易,并给Bob一份拷贝。然后Alice向Bob索要Bond交易,同时检查退款交易花掉Bond交易的输出。 她现在可以广播Bond交易到整个网络,确保在未来支付他的比特币前,Bob必须等待锁定的时间。到目前为止,Bod实际上还没有花掉任何比特币,除了少量的交易费用,同时他可以在24小时后,广播全额退款交易。
现在,当Alice完成了一部分价值1 mBTC工作后,她要求Bob创建并签名一个新的退款交易。V2版本交易支付1mBTC给Alice, 99给Bob;这个交易没有锁定时间,因此Alice能够在任何时候对它签名并花掉它。(但她不会立刻这么做)
Alice和Bob重复工作-付款的步骤直到Alice完成一天的工作,或直到锁定时间到期。Alice签名最终版本的退款交易,并广播这个交易,支付给Alice,同时把剩下的余额退还给Bob。下一天,当Alice开始工作时,他们再创建一个新的微支付通道即可。
如果在交易锁定时间到期前,只要Alice一个退款交易广播失败,Bob就会广告第一个版本交易,并获得全额退款。这就是为什么微支付通道最适合小额支付 — 如果Alice的网络在快接近锁定时间到期时,断网几个小时,她的付款可能会被骗走。
交易的延展性,我们在前面交易章节有讨论过,它也是另外一个限制了微支付通道价值的原因。如果有人使用交易的延展性断开两个交易间的连接,Alice即使没做任何工作,也可以持有Bob的100 mBTC的质押金。
对于大额支付,比特币交易费用在整个额度中,其占比是非常低的,因此它对于保护,那些独立的,即时广播的交易的支付很有意义。
资源: [bitconj](http://bitcoinj.github.io/) 是个一个java库,它提供了一个完整的微通道函数,里面有一个实现微通道的例子,一个教程,他们是基于Apache协议许可的。
CoinJoin
Alice关心她的隐私。她知道每个加到区块链中的交易,因此当Bob和Charlie付款给她时,他们能容易的跟踪这些satoshis,并可以得知她支付用到的比特币地址,支付的数量,以及余额。
Alice不是犯罪份子,她仅想隐去她给谁付款了,还剩多少。因此她在她计算机上开始使用Tor匿名服务,并以“AnonGirl”用户登录进一个IRC聊天室。
通用在这个聊天室里面的“Nemo”和“Neminem”,他们集体同意彼此之间转移satoshis。因此没有人除了他们自己,是可靠的,能决定谁来控制satoshis。但是他们会遇到一个困境:谁第一个把satoshis发送给其他两个匿名用户的?CoinJoin合约,如下图所示就能很容易解决这个问题: 他们创建一个交易,同时花掉所有的satoshis,这样确保没人能够偷走别人的satoshis。
每个贡献者可以浏览其能花费的100mBTC UTXOs。然后他们给出生成一个全新的公钥,并把UTXO详细信息,公钥哈希值给协调者。 在这里,协调者是AnonGirl;她创建一个交易花掉每个人的UTXOs,并分成三等分输出。一个输出对应一个贡献者的公钥哈希。
然后AnonGirl使用SIGHASH_ALL
来签名她的输入,以确保没人能够改变输入或输出详情。 她把部分签名的交易给Nemo,Nemo用同样的方法对他的输入签名,然后传给Neminem,Neminem也用同样的方法签名。 Neminem把这个交易广播到比特币网络,把所有的毫比特币混合到一个交易里面。
如上图所示,没有人能决定谁接收哪一个输出,即使是AnonGirl,Nemo,Neminem也不行。因此他们每个人可以安心的花掉他们的输出而不被跟踪。
当Bob和Charlie试图通过区块链去跟踪Alice的交易时,他们也能看到Nemo,Neminem产生的交易。如果Alice做了一些CoinJoin,Bob和Charlie可能不得不要从上百人中所产生的交易中去猜测哪些是Alice产生的。
Alice的satoshis完整的历史记录会一直在区块链上,因此一个跟AnonGirl有CoinJoin交易的,有决心的调查者最终是可以找出她的satoshi来源,也有可能揭示AnonGirl就是Alice. 但是对于其他随意浏览区块链记录任何人而言,Alice获得了隐私保护。
上面讨论的CoinJoin技术,每个参与者需要支付一笔小额的交易费用。购买者CoinJoin, 作为另外一个选择, 实际上能省掉这笔费用,并且能提高隐私安全。
AnonGirl可以一直在聊天室潜水,直到她想买东西。她在聊突室里发布她想花掉satoshi的意图,并等待其他也想买东西的人(很有可能是一个不同的商人)。然后他们把他们的输入按上面的方式合并起来,但是把输出设置到单独的商人比特币地址上,这样没有人从区块链历史记录里面,能够独自地得出哪个人买了什么东西。
因为他们购买东西了,所以了就不得不要支付一笔交易费用,AnonGirl和她一起组图花费satoshi的人不需要在支付额外的费用 — 但是他们通过打包多个交易,减省了字节,降低了中间费用,他们能够支付一笔更小的聚合交易费用,也让每个人都省了一小比satoshis。
资源: 截止到写该文档,CoinMux Alpha版本实现了去中心化CoinJoin,目前在Apache协议许可下可用。
声明:
文中带有[?]的地方,表示我对此翻译明显感觉不太对的,后续会不断修正。
有些地方可能会翻译的不好,不地道,甚至错误,如果有发现,还请留言,指出,以便我好修正,谢谢!