一个P2P电子货币可以进行点对点的线上支付,不需要经过银行。数字签名提供了一部分解决办法,但是如果保留TTP(可信第三方)来防止双重支付的话,就会失去其主要优势。我们提出一种用P2P网络来解决双重支付的方案。网络时间戳通过将它们散列到正在进行的基于散列的工作证明链中进行交易,形成一条记录,除非重做工作量证明,否则就无法更改。最长的链不仅可以作为事件发生序列的证据,而且可以证明它来自最大的CPU计算量。只要大部分CPU计算力不是由攻击者控制,他们将生成最长的链并让攻击者无计可施。网络本身需要最小的结构。消息会进行有效的传播,节点可以随意离开或加入网络,用他们离开时的最长链证明他们不在时发生的事。
互联网商业几乎完全依赖于可信第三方的金融机构来处理电子支付。尽管该系统对大多数交易没问题,但基于信任模型的固有弱点无法避免。完全不可逆交易实际上是不可能的,因为金融机构无法避免纠纷调解。调解成本增加了交易成本,因此会限制实际的交易规模,无法进行临时小规模交易,并且丧失了不可逆支付能力再支持不可逆服务成本会更高。由于可能出现可逆交易,人们就更需要信任。商家必须警惕他们的客户,骚扰他们获取比他们原本需要的更多信息。一定比例的欺诈是不可避免的。这些成本和支付不确定性可以通过使用真实货币避免,但是没有机制可以在没有可信方的情况下通过通信渠道进行支付。
我们需要一个具备基于加密证明而不是信任机制的电子支付系统,允许两个交易者不通过第三方信用机构直接进行交易。计算上不可逆的交易将保护卖方免受欺诈,实施传统的托管机制以保护买方。在本文中,我们提出了使用分布式P2P时间戳服务器来生成交易时间顺序的计算证明,以此解决双重支付。只要诚实的节点控制比攻击者节点更多的CPU计算力,该系统就是安全的。
我们定义了一种像数字签名链的电子货币,每个拥有者通过对上一个交易的Hash和下一个拥有者的公钥进行签名,并加在货币尾部,来转移给下一个。收款人可以通过验证签名来验证链的所有权。
问题是收款人无法验证所有者有没有双重支付。一个常见的解决方案是引入一个可信赖的授权中心或铸币厂,它检查每笔交易是否存在双重支出。在每次交易之后,必须将货币返回铸币厂以发行新货币,并且只有直接从铸币厂发出的货币才会被信任。这个解决方案的问题在于,整个货币体系都依赖于铸币厂,每笔交易都必须通过它们,和银行没什么两样。
我们需要一种方法让收款人知道所有者以前没有签署任何交易。最早的交易是重要的交易,所以我们不关心之后的交易是否存在双重交易。确认交易是否缺失的唯一方法是了解所有交易。在铸币模型中,铸币厂知道所有交易,并决定哪个是第一个。为了在没有可信第三方的情况下实现这一目标,必须公开宣布交易,并且需要一个系统让参与者能达成一致的单一历史顺序。收款人需要在每次交易时证明,大多数节点同意它是第一次收到的。
方案从时间戳服务器开始,时间戳服务器为一些被打时间戳的项目块做散列,并将这个散列像报纸一样传播出去。时间戳证明了数据在当时存在,每一个时间戳中也包含了链上前一个节点时间戳的哈希,如此往复。
要在P2P的基础上实现分布式时间戳服务器,我们需要使用类似于Adam Back的Hashcash的工作量证明系统,而不是报纸。工作量证明需要对数据进行哈希扫描(这是啥),当进行散列时,例如SHA-256,散列以多个0bit位位开始。所需的平均工作量是所需的0bit位数的指数,并且可以通过执行单个散列来验证。
对于我们的时间戳网络,我们通过在区块中递增一个随机数来实现工作量证明,直到找到一个hash值与所需要的0bit位数相同。一旦CPU工作量满足工作量证明,就不能再更改该区块,除非重做工作。由于后面有后续的区块被链接在其后,更改该区块的工作将包括重做之后的所有区块。
工作量证明还解决了多数决策中的投票表示的问题。一般如果一个IP地址投一票,那么人就可以用多个IP投票来破坏规则。工作证明基本上是一个CPU一票,多数决策由最长的链表示,因为其中投入的工作量最大。如果大部分CPU计算力由诚实节点控制,那么诚实链将增长最快并超过任何其他链。要修改过去的区块,攻击者必须重做该区块以及之后的所有区块的工作证明,然后赶上并超越诚实节点的工作。我们稍后会说明,随着后续区块的添加,速度慢的追赶者的超过的概率会呈指数级递减。
为了补偿随着时间推移而增加的硬件进步和对运行节点的增加,工作量证明难度由根据每小时区块产生的平均值确定。如果它们生成得太快,则难度会增加。
运行网络的步骤如下:
新交易将广播到所有节点。
每个节点都将新交易收集到一个区块中。
每个节点都在为其区块进行工作量证明。
当节点完成工作量证明时,它会将该区块广播到所有节点。
仅当区块中的所有交易都有效且尚未使用时,节点才接受该区块。
节点通过使用接受该区块的hash作为前一个hash来创建链中的下一个区块来表示它们接受该区块。
节点始终认为最长的链是正确的,并继续扩展它。如果两个节点同时广播了两个不同的区块,则其他节点可以选择接收一个或另一个。在这种情况下,他们按他们收到的第一个工作,但保存另一个作为分支,以防它会变得更长。当完成下一个工作量证明并且这两个分支中的一个变长时,将打破平局。 然后,所有节点将切换到较长的节点上工作。
新的交易不一定需要广播到所有节点。只要它们到达许大部分节点,它们就会很快进入一个区块。区块广播也容忍消息丢弃。如果一个节点没有收到一个区块,它会在收到下一个区块时发现它丢失了一个区块,并请求它。
按照惯例,区块的第一个交易是特殊的,该区块的创造者拥有了一个新的货币。这对节点支持网络之一种鼓励,而且由于没有中心机构发布他们,并且可以初步将币分配到流通中。这种持续不断稳定产生新的货币的方式很像花费资源挖掘黄金的过程。这里,CPU的时间和电费就是一种花费。
奖励也可以通过交易费来获得资金。如果交易的输出值小于其输入值,则其差值就作为交易费添加到包含该交易的块的激励值。一旦预定数量的币进入流通,激励就可以完全转换为交易费用并且完全没有通货膨胀。
激励措施可能有助于鼓励节点保持诚实。如果贪婪的攻击者能够比所有诚实的节点组装更多的CPU功率,他可以选择使用它偷回自己的付款,或者使用它来生成新的币。他会发现遵守规则更有利可图。这些规则会给他更多的货币,这比破坏系统和自己财富的有效性更有利。
一旦最新的交易中,一个币被埋在在足够多的块下,则之前的花费交易就可以丢弃以节省磁盘空间。为了在不破坏块的散列的情况下实现,交易都被散列到一个Merkle Tree树上,只有根节点包含在区块的散列中。然后可以通过截断树的分支来压缩旧块。内部的Hash值不需要被保存。
一个没有交易的区块头大约80bytes。如果我们假设每10分钟生成一个块,则每年生产80字节* 6 * 24 * 365 = 4.2MB。按照计算机系统在2008年一般为2GB 内存的情况下,且摩尔定律预测当前每年增长1.2GB,即使区块头必须保存在内存中,存储也不应成为问题。
其实无需运行所有网络节点即可完成支付验证。用户只需要保留最长工作证明链的区块头的副本,他可以通过查询网络节点获得它,直到他确信他拥有最长的链,并获得将该交易链接到区块的Merkle分支。它是时间戳的。他不能自己检查交易,但是通过将其链接到链中,他可以看到一个网络节点已接受它,并且进一步确认网络已经添加了新的区块。
因此,只要诚实节点控制网络,验证就是可靠的,但如果网络被攻击者控制,验证会更脆弱。由于网络节点可以自己验证交易,只要攻击者可以继续控制网络,攻击者就可以伪造交易欺骗这种简化的验证方法。防止这种情况的一种策略是在网络节点检测到无效区块时接受来自网络节点的警告,提示用户的软件下载完整区块和被警告的交易以确定不一致处。企业频繁收到付款,可能仍希望运行自己的节点以获得更加独立的安全性和更快的验证。
尽管货币可以单独处理,但如果交易中的每一分钱都分开转移效率会很低。为了能够合并和拆分,交易是多重输入和输出。一般会是来自较大的先前交易的单个输入或多个较小金额的多个输入,并且最多两个输出:一个用于支付,一个找零(如果有的话),找零返回给发送者。
有可能一个交易依赖于其他几个交易,这些交易又依赖于其他更多的交易。这里不用在意扇出,不需要为交易历史提取出一个完整的副本。
传统的银行模式通过限制对相关方和可信第三方的信息的访问来实现一定程度的隐私。我们所提出的这种方法公开发布所有交易,但仍可以通过匿名公钥来维护隐私。公众可以看到有人向其他人支付,但没有信息知道交易的人是谁。这类似于证券所发布消息的级别,人们知道交易的时间和交易的金额,但不知道交易的双方是谁。
另一道防火墙,每一次交易都应生成新的密钥对防止交易与普通所有者关联。一些多输入交易需要分辨哪些输入来自同一个拥有者,就不可避免的会存在这种链接。这里的风险在于,一旦拥有者的一个密钥被发现,就可以查看到该拥有者的其他交易。
我们考虑攻击者试图生成比诚实链更快链以替代诚实链的情景。即使这已经完成,它也不会使系统就可以任意改变,例如凭空创造价值或从不属于攻击者的钱。节点不会接受无效的交易支付,诚实的节点永远不会接受包含这些交易的区块。攻击者只能尝试更改自己的一笔交易以收回他最近花的钱。
诚实链和攻击链之间的竞争可以表示为二项式随机游走(Binomial Random Walk)。成功事件是诚实链扩展一个块,其领先优势增加+1,失败事件是攻击者链延长一个块,将差距缩小-1。
攻击者从特定赤字中赶超的可能性类似于赌徒破产问题(Gambler's Ruin problem)。假设一个拥有无限信用的赌徒开始出现赤字并且可能会进行无数次试验以达到盈亏平衡。我们可以计算他达到盈亏平衡的概率,或者攻击者超过诚实链的概率如下:
p:诚实节点发现下一个节点的概率
q:攻击者节点发现下一个节点的概率
qz:攻击者总是赶上第Z块的概率
假设p>q,随着攻击者必须赶上的区块数量增加,概率呈指数下降。如果他没有能够在早期进行一次幸运的冲刺,那么他的机会就会变得越来越小。
我们现在考虑新交易的接收者需要等待多长时间才能充分确定发件人无法更改交易。我们假设发件人是一名攻击者,他希望让收件人相信他已经支付了一段时间,然后在一段时间过后又将支付的钱返回给自己。接收者会在发生这种情况时收到警报,但发件人希望这个时间会很晚。
接收方生成的密钥对,并在签名前不久才将公钥提供给发件人。这可以防止发送者提前准备一系列的区块并领先,若是在那一刻执行交易,一旦发送了交易,不诚实的发件人就会在包含其交易的备用并行链上开始秘密工作。
收件人等待直到事务已添加到区块而且之后已经链接了z个区块。他不知道攻击者所取得的确切进展,但假设诚实的区块占用了每个区块的平均时间期望,攻击者的进展为预期值的泊松分布(Poisson distribution):
为了获得攻击者现在仍然能够赶上的概率,我们将泊松密度函数(Poisson density)乘以每一个他可以从该点赶上的概率:
调整公式避免分布的无穷大尾部:
转换为C代码:
#include
#incldue
double AttackerSuccessProbability(double q,int z)
{
double p = 1.0 - q;
double lambda = z *(q / p);
double sum = 1.0;
int i,k;
for(k = 0; k <= z; k ++)
{
double poisson = exp(-lambda);
for(i = 1; i <= k; i ++)
poisson * = lambda / i;
sum - = poisson *(1 - pow(q / p,z - k));
}
return sum;
}
运行一些结果如下,可以看到概率随z呈指数下降
q = 0.1
z = 0 P = 1.0000000
z = 1 P = 0.2045873
z = 2 P = 0.0509779
z = 3 P = 0.0131722
z = 4 P = 0.0034552
z = 5 P = 0.0009137
z = 6 P = 0.0002428
z = 7 P = 0.0000647
z = 8 P = 0.0000173
z = 9 P = 0.0000046
z = 10 P = 0.0000012q = 0.3
z = 0 P = 1.0000000
z = 5 P = 0.1773523
z = 10 P = 0.0416605
z = 15 P = 0.0101008
z = 20 P = 0.0024804
z = 25 P = 0.0006132
z = 30 P = 0.0001522
z = 35 P = 0.0000379
z = 40 P = 0.0000095
z = 45 P = 0.0000024
z = 50 P = 0.0000006
求解P<0.1%
P <0.001
q = 0.10 z = 5
q = 0.15 z = 8
q = 0.20 z = 11
q = 0.25 z = 15
q = 0.30 z = 24
q = 0.35 z = 41
q = 0.40 z = 89
q = 0.45 z = 340
我们提出了一种不依赖信任模型的电子交易系统。我们从通常的数字签名框架的货币开始,它提供强有力的所有权控制,但是没有解决双重支付,所以还不是很完整的。为了解决这个问题,我们提出了一种使用工作量证明来记录交易历史的P2P网络,只有诚实节点控制大部分CPU计算力,攻击者想要动手脚很快就会在计算上不可行。该网络非结构化且简单,节点之间几乎没有协作。它们不需要被识别,因为消息不会被路由到任何特定的地方,只需要尽力使发送效率最高。节点可以随意离开或加入网络,接受他们离开时的最长链证明他们不在时发生的事。他们用他们的CPU计算力进行投票,通过扩展它们表达他们对有效块的接受,通过拒绝对扩展来拒绝无效区块。任何所需的规则和激励措施都可以通过这种共识机制来实施。