Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1362 lines (944 sloc) 93.3 KB

Hacash:一种大规模支付实时结算的加密货币系统(稿)

【摘要】

本文提出了一种运用通道链有序多签名实时冲销结算方法,可无上限扩充每秒交易量,能掠夺性惩罚不诚实一方从而确保资金安全和实时到账的加密电子货币发行支付及金融体系。内建复合签名地址和层级股权控制地址、多方签署交易结构、全类别支付协议及资产变更协议,满足现代金融、企业及个人的绝大部分支付需求。结合工作量证明、历史见证及分叉投票的抢占式记账权奖励分配方式,能有效规避双重支付、防范算力攻击和降低马太效应。并采取符合经济规律的货币发行、公账及通道手续费、通道利息和区块钻石等激励机制,无需信任委托于任何机构即可维持整个系统长期有效运行。

通道链结算网络的基本原理是:每两个账户各自锁定若干资金,组成一个支付通道,私下可双方签名多次支付,期间无需向全网广播确认交易,只需最后一次向主网提交最终的余额分配即可取回各自正确拥有的资金,从而极大地自由扩充整个系统的每秒交易数量;如果单方结束通道,则其资金会被锁定一段时间,如果另一方在此期间内向主网举证更新的余额分配而证实对方作假,则揭露方将会夺取对方全部资金,从而迫使双方保持诚实;只需将多个支付通道连接起来,并从收款方开始让所有资金流转方有序签名直至付款者最后签署,则所有相关方都将同时收到和支出钱款,从而确保支付完整、实时到账和资金安全;通道可收取微量手续费激励其提供稳定服务。

目录

一、前言

  1. 危机
  2. 货币的未来
  3. 我们需要什么

二、基本原理

  1. 技术理论
  2. 自利原则
  3. 不足

三、通道链结算网络

  1. 基本假设
  2. 主要原理
  3. 技术实现
  4. 通道关闭
  5. 仲裁保护
  6. 收付平账
  7. 反集中化
  8. 快速通道
  9. 资金计算

四、交易

  1. 基本数据结构
  2. 复合签名地址
  3. 层级股权控制地址
  4. 多方签署
  5. 支付类别
  6. 签名剥离
  7. 手续费
  8. 字段格式

五、激励

  1. 记账权竞争奖励
  2. 公账手续费
  3. 通道服务费
  4. 通道利息
  5. 区块钻石
  6. 数据服务

六、货币

  1. 总量及增长
  2. 无限分割
  3. 单位及符号
  4. 禁止人为货币政策

七、隐私

  1. 匿名
  2. 支付混搅
  3. 前置延期兑付
  4. 加密结算网
  5. 通道冲销

八、风险与防范

  1. 通道链延迟签名攻击
  2. 低成本通道欺诈
  3. 通道信用货币创造及违约
  4. 算力集中化、51%攻击和游击挖矿
  5. 价格极端波动

九、技术设计原则

  1. 简单直观
  2. 数据紧凑、执行高效
  3. 公账数据规模可控
  4. 数据剥离及压缩

十、结论

【附录】

  1. 参考引用
  2. 区块数据结构定义示例及注释
  3. 部分算法代码

第一章、前言

1. 危机

我们走到了货币体系变革的时代关口。

纵观历史,文明发展和经济进步总伴随一个前提:文化和金融自由。无论资本主义还是社会主义,无论发达国家还是发展中国家,周期性出现的经济危机却让人们对金融体系施行更加严厉管制的呼声越来越高。究其本源,不同的现代社会经济体制都有一个共同点:强制性主权信用货币和银行部分准备金制度。这本质上是一种欺诈,是金融不稳定的根源,是除暴力掠夺之外导致利益分配不公的最大缘由。随之必然而来的经济干预政策极尽推波助澜或矫枉过正,如同王朝更迭一样反复伤害本该渐进增长的经济体和人们的生活水平。

不稳定、不可预期、人为肆意干预和操控的金融环境,将使得大型资本在根本不必进入实体经济的情况下即可轻松获得超额增值。当资本特别是巨型资本的回报率超过甚至远超长期整体经济发展的平均回报水平时,贫富差距就会不可避免的地加速拉大,直至社会矛盾加剧、经济危机和动乱。如果某一代人刚好在长达十年甚至二十年的大萧条起始时成年,那么他们的命运将注定艰难困苦、碌碌无为。为了抹平这种周期性危机导致的严重代际不公(或许因此带来更严重的社会动乱、革命甚至战争),采取经济干预和刺激政策,注入兴奋剂成了一个痛苦的权宜之计。不过,面对不利的人口与债务趋势,不可能通过短期的刺激手段应对长期的结构性危机,这根本就是在自欺欺人。

对银行和大型企业的财政救助和货币流动性刺激其本质上是劫贫济富,是把成本和损失社会化,是让全体民众为一小部分人的贪婪和肆意妄为买单。我们需要能够从根本上解决问题,避免或大幅减少金融危机和经济崩溃,从而保卫金融弱势群体的利益不被裹挟和榨取。

中国北宋时由于政府在四川地区强制使用铁质钱币造成的笨重不便,民间出现了原始的纸币:交子。这似乎是一种货币金融的“进步”。当时的政权发现这简直是完美的税收工具,随即将纸币发行权收归国有。不用再耗费大量财力物力丈量土地、清点户籍、收钱造册,只需轻轻开动印刷机,就能源源不断悄无声息地从民间抽取大量财富。但随之而来的反复超级通货膨胀和经济崩溃打破了王朝的如意算盘,终于在明朝初年间人们彻底不再相信任何纸片,退回到了贵金属货币时代,甚至大家直接通过分割和称重散碎白银来进行交易。这种看起来像原始退化的货币状态却给了民间极大的金融和经济自由度,成就了中国历史上少有的金融稳定时期,普通百姓生活水平得到提升,这种情况一直持续到清朝后期。

货币来源于市场,并终将服务于市场。其形态本身并没有高低之分,其本质也无绝对的好与坏,只有是否更加适应及高效。我们需要一个自由竞争、适者生存的货币市场和开放透明、避免欺诈的金融环境。这个世界上的不公本质上是信息的不公,是金融的不公,解决这个问题的答案是大力发展开放金融,以开放实时审计破除任何准入限制。

2. 货币的未来

黄金本是地球上最适合作为货币的物品,但是人们现在却并没有使用它进行大规模的交易支付。主要原因有:1. 笨重不便于携带;2. 不可无限分割用于小额支付;3. 长期流通造成磨损耗费;4. 造假掺假技术越发强大。在欧洲历史上曾长期使用黄金作为储备的纸币进行流通,这种方式表面上兼具黄金的优点却规避了其作为日常支付手段的缺陷。只不过,没有任何个人和组织禁得住凭空创造钱的诱惑,无论承诺多么坚决,纸币总是会被超发。与历史上在金、银、铜币里掺杂其他金属故意造成贬值的情况别无二致,甚至由于发行成本的极度降低造成严重通货膨胀从而导致经济的崩溃。这种情况曾反复多次出现。

阻止黄金作为通用支付手段的另外两大具备争议的问题是:1. 储量位置分布不均,地下有金矿的国家相当于坐收全世界的铸币税;2. 无法在经济的增长率和规模大幅变动之时快速调节供应量,容易造成紧缩和钱荒。特别是关于第2点的争论已大量见于奥地利、现代货币和凯恩斯等各个经济学派的著作之中,其中一些认为信用扩张是经济危机的根源、是洪水猛兽,而另一些则坚定认为没有“弹性”的货币将会锁死整个经济的发展。

历史上,货币大致经历了如下几个种类或阶段(并不代表严格分类、出现的先后顺序或本质优劣):

1. 通用价值物(谷物、布帛、牛羊、香烟等)
2. 稀有稳态物(金、银、铜、宝石、贝壳等)
3. 信托账务凭证(存款证明、债务凭证、匿名支票、商品券、纸黄金等)
4. 主权信用符号(法币)

其中第1、2阶段由于无法满足现代商业支付需要而被逐渐淘汰,第3阶段似乎会造成信用膨胀和银行家欺诈带来的经济脆弱及崩溃,人们随即期望政府设立的央行体系解决问题,于是走入了第4个阶段,但效果如大家所见。

我们认为,货币的未来,也就是第5阶段的形态将会是「公认规则」为主体、骨干,「个体信用」为分支、补充的开放性电子网络体系,并且会在自由竞争的过程中持续改进和显现出最优的系统。这种「公认规则」不以任何人的意志为转移,不受强势利益集团的控制,就像没有人能够凭空创造黄金一样。公平的规则能让全世界有效的参与进来。货币远不止是一般等价物或会计单位,它更是一种信号,是经济运转的信息系统。我们可以忍受和修复局部信用失效,但绝对无法承担整体信用崩塌的后果。

2008年,比特币(Bitcoin)以及背后区块链技术的出现和十年来的有效运转为我们指明了方向。

3. 我们需要什么

区块链的核心价值并不在去中心化,也不在永久保存数据,更不在逃避监管,而是在于去信任化。

比特币的出现并不是为了提升局部暂时支付效率或者减少部分瞬时交易成本,而是为了避免或降低辜负我们信任的企业与机构作恶的后果。它的愿景是完全匿名与去中心点对点信任,而区块链的未来则是公开透明与分布式自审计信任,是通过消耗廉价算力资源来换取社会整体交易成本的降低和协商效率的提升。

正如互联网满足了人类信息通讯的基础需要一样,区块链是为了解决困扰人类几十万年的大问题:欺诈。我们历史上为此付出了巨大成本,消耗了无数资源,阻断了太多交易。所以我们不能在未来的货币体系中加入任何欺诈的可能性,上帝保证也不行。

我们需要一种货币和随之而来的金融体系,一种信任最小化的货币系统,没有人能肆意降低它的成色,也不用耗费过多信任成本,可以更好的维护经济系统的稳定发展,并且完全能满足现代商业支付、企业财账及金融清算的需要。

第二章、基本原理

1. 技术理论

货币需要相对的稀有排他性以履行其价值信号的功能,没有人会把水、土壤或者树叶作为交易媒介。然而在电子信息世界里,一切都几乎可无成本复制。那么以二进制数据为载体的货币就有着一个致命的本质缺陷:数量无限且真假难辨。如果我们仍然依赖一个在线发行机构或电子造币厂确保钱币的真实有效和数量上限,那么从历史经验来看,没有谁能忍受凭空创造钱的诱惑,最终大家手里的东西将会一文不值。

一种直观就能想到的解决方案是将每一枚电子货币都编上整数号码,并公布一个号码的上限(或者这个上限每年自动增长固定数额),然后用电子签名的方式标注上每一枚货币的拥有者(先忽略谁最先拥有这些货币的问题),然后每一枚货币在支付的同时,都将由当前拥有者用私钥签名接收者的公钥,表明此枚钱币已经支付给对方,并保留所有历史支付记录。如此则解决了电子货币复制造假和数量无限的问题。

但是上文提出的方案有几个显而易见的缺陷:

1. 不能被分割用作小额支付或找零;
2. 同一枚钱币可被同一时间支付给不同的两个人甚至更多人(双花);

缺陷1可以用足够小额的面值(编号上限足够大)来暂时缓解。而双花问题则比较麻烦,一种办法是让一个公共的中心数据库来保存及证明每一笔支付的记录,但却仍然依赖机构负责人的正直诚信,有被欺诈的可能。另一种办法是通过广播,让所有人都各自拥有一份账本,列出所有人每一笔支付的记录,当接收钱币时即在自己的账本上查询钱币的拥有者,以此避免双花。

每个人都有一份账本的方案看似解决了双花问题,但仍然具备很大的缺陷:

1. 维护一套账本不间断记录所有支付是需要耗费很大成本的,不经常收到钱币的个人实时维护一整套账本显然得不偿失。最后大家还是会依赖一些大的类似银行的机构出具的账本。
2. 当有一些支付因为广播的技术原因并未到达所有账本记录者(比如海底光缆被切断),大家各自的账本记录就会不一致。长时间便会形成大量的不同版本,大家彼此不相认同,最终支付体系崩溃。
3. 如果每个人花费很大成本维护账本只是为了自己在收钱时查询有效性,那么这种货币系统未免太过低效,并且最终会因为搭便车问题导致账本无人维护。

当然,还有一个最为关键的问题:谁应该最先拥有这些电子货币?

2. 自利原则

长期来看,任何单方面寄希望于对方的正直诚实和信守承诺,而没有其他激励和制衡的合作体系,终将不可持续。

不断地有效运转的社会合作系统,无一不是正确面对人性的贪婪和自利,并加以利用让其用于维护体系的自我运行。比特币走在了正确的道路上,并在为期十年的发展中越发壮大。它通过创造性地将账本记录和货币发行两者结合起来,为大家维护账本提供了充足的动机,并采取工作量证明竞争记账权的方式让所有人的账本始终保持统一,从而巧妙的解决了上文所面临缺陷。当然它也并没有使用为每一枚钱币编码的体系,而采用了未花费余额(UTXO)的方式支持小额支付和找零。关于比特币的详细理论这里并不过多介绍,大家请参阅中本聪的论文。

3. 不足

天下没有免费的午餐。正如我们上文一直以来的“提出问题-解决问题-遇到新问题”的推导一样,公开竞争记账的货币体系仍然有两个大家所诟病的缺点:

1. 通过哈希算法重复运算竞争一定时间内的账目记录权从而获得增发的货币奖励的方式耗费了大量的硬件及能源。
2. 由于需要向所有账本记录人广播每一笔支付并得到确认,导致总体支付效率非常低下(大约每秒7笔),也导致需要支付高昂的手续费,根本无法满足现代商业的需要。

严格来说,我们并不认为第1点是真正的缺点。除了短期内的投机和非理性繁荣,在一个没有强制的自由竞争领域,大家总会找到一个成本和收益的平衡点,我们使用了大量能源和精力,并不是因为我们疯了,而是这样做总体上有利可图,耗费的成本终将在其它方面更多的补偿回来。正如我们并没有用尽全力把地球上所有的石油和黄金全部都开采出来一样,因为这么做不经济。

认为一个货币系统应该尽可能少消耗能源的想法非常朴素原始,古人也有一个类似的疑问和偏见:商人只是把物品从一个地方搬到了另一个地方,并没有创造任何东西,那么他们凭什么赚这么多钱?

关于消耗能源(其他任何形式的资源)和避免受害这两者之间,只能做一个权衡:

1. 大家平时不必付出任何成本即可享受免费、方便的好处,代价是提供服务的中心机构可能被攻破利用,或者在暗处损害大家的利益。
2. 平时付出一定的成本(费用或精力),避免了有人或组织欺诈自己的风险。

如果有人宣称同时实现了以上两点(既完全免费又绝对安全),要么没能认识到问题的本质,要么就是不怀好心。

可暂时延缓第2个缺点最直观的办法是扩容,即扩充区块大小上限或减少区块生成间隔时间,但这无法从根本上解决问题。区块大小具备理论上限,数量太大会延长下载传输同步的时间,这进一步限制了区块间隔时间的上限。这是一个水涨船高的过程,新的交易总会填满扩充的空间,而全世界的交易支付量远大于当前受硬件体系制约的扩容理论上限。另一方面,数据量扩大到一定程度,也会导致普通个人计算机无法装下完整的账本,最终淘汰绝大部分参与者,数据向财力雄厚的某些大机构聚拢。

另一种某些改进者正在尝试的方案是:极度缩减账本记录者的总数量(比如21个或101个),对他们的工具性能提出比较高的要求,并将新增钱币给予他们以资鼓励,整个系统便能承载很大的交易量。这看起来令人欢欣鼓舞,然而如前文所说,这种形式有它不可避免的缺点,其本质与历史上的铸币厂分局体系无太多区别。

也有一些人希望通过容忍临时的数据不一致性,换来整体系统吞吐量的极大提升(广义的DAG结构),这只能应用于对数据真实性要求不严格或无需立等验证的场景,在一个小额即时支付系统里是完全不可靠的。

也许是不认为这是个麻烦,也许是暂时没考虑清楚而刻意略过,中本聪没有在论文中指明如何承载巨大交易量的解决方案。

第三章、通道链结算网络

1. 基本假设

参照显示世界的运转,成年健壮男子可轻松抢夺街上妇女儿童的财货占为己有,可多数人并没有这么做,是因为大家知道,背后的警察和法律体系将让其付出更大的代价,从而让这种作恶行为得不偿失。事实证明,就算存在风险,只要具备严格的惩罚机制,大家的理性驱利行为将维持系统总体有效运行。

我们提出,公共账本不应该包含全部的交易支付记录,而应该作为一个严格准确有效且不能被操控的仲裁体系和最终清算系统,保证在私下进行的支付行为不能欺诈,否则即给予严厉的惩罚,在无限次数重复对等博弈中,大家会倾向于保持诚实来长期合作。这种体系有着极大的伸展能力,可动态按需增加交易量,并在理论上没有上限,从而能完全应对现代商业发展的需要。

2. 主要原理

我们需要实现一个能实时到账、没有任何人会丢失资金的小额高频支付系统,可用于网络商城或实体商店中的购买行为。如果有中间人提供资金服务,那么所有人都应该同时保证收支的正确。要点在于,资金链条的结算应该是实时同步而不能为异步,否则将带来严重的中心化和资金安全问题。

首先,我们需要创建一系列的双向结算通道,他们分别是顾客和资金通道服务者(简称节点)、商家和节点,必要时顾客和商家可直接建立结算通道。发起支付时,由商家或服务商家的节点查询资金通道链条的路由,并建立整个链条的TCP连接,然后从所有节点处取得所有的通道ID、上一笔交易hash、交易序号、余额确认等信息后,建立一个完整的交易,并发送给所有参与方。接着从商家开始,按顺序,所有人将自己对这笔支付交易的签名发送给所有其他方,直到顾客的签名都被大家收到,此时商家签署交易确认的消息,从链条尾端依次关闭所有TCP连接。最终所有相关放都同时收到(和支出)了资金,支付交易完成。每个通道可收取微量的服务手续费用,以激励节点提供稳定的服务。

3. 技术实现

下文描述了所有的技术细节以及每一步完成后的数据状态。

1) 创建联对式结算通道

首先创建一笔联签交易:

{
    // 开启一条结算通道,fund1和fund2为出资双方
    // 通道一旦开启将扣除双方的余额,直到通道关闭
    // 结算通道单方终结的锁定期限(区块数量)
    lock: 2016, // 约等于于一周
    // 结算通道自定义id,随机生成
    channelId: 232353253456,
    fund1: {
        address: '1313Rta8Ce99H7N5iKbGq7xp13BbAdQHmD', // 出资地址
        amount: 1234, // 出资数量
    },
    fund2: {
        address: '19aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
        amount: 1234,
    },
}

双方都签署以上交易,将其广播到主网得到确认后,便可在私下进行不限次数和频率的双向支付,在这之后产生的所有交易,都无需向主网广播。

2) 私下结算

每一次支付,双方都同时签署结算信息并交换签名结果,交易结构类似于:

{
    // 【链下结算】阶段性余额分配确认
    // 如果在链上提交阶段性余额分配,地址将被锁定约定的时间,
    // 结算通道id
    channelId: 232353253456,
    //  上一笔确认的通道交易hash(首笔时本字段为交易通道开启所在交易的hash)
    prevTrsHash: Buffer.alloc(32),
    // 通道交易序号,自动增量
    autoincrement: 123135,
    // 冲销后资金分配确认(一方比另一方多出的部分)
    diffConfirm: {
        address: '1313Rta8Ce99H7N5iKbGq7xp13BbAdQHmD',
        amount: 1234,
    }
}

如果每位顾客和每家商店都签署结算通道,这样将过于麻烦,并且会锁定太多资金。我们设想一些可以专门提供通道连接服务的节点,并且相互组成通道链结算网络,商家和顾客只需要跟少量的两三个节点签署结算通道,就可通过此网络方便的与其他所有人进行交易支付,类似于访问互联网时你只需要接入一家宽带运营商,而无需和其他所有人各自单独拉一条网线。

3) 通道链路由

假设顾客A与节点甲签署了一个通道,商户D和节点乙签署了通道,而节点甲与节点乙也创建了结算通道。这时顾客若要支付给商户D,资金将通过一个A、甲、乙、D组成的链条流动到D的地址上,通过节点之间的询问查找(或第三方的路由查询,类似域名DNS服务器),找出一条可能的最短(或手续费最低)的路径,并按顺序组成TCP连接的双向通路:

A <=> 甲 <=> 乙 <=> D

4) 构建链式支付交易

由上面可以看出,顾客A的付款资金通过甲、乙两个节点,直到商家D要经过三个结算通道。此时,由商家的服务节点乙询问,或者各自主动双向广播的方式,所有参与方都获得了每一个结算通道的ID、交易序号、手续费、余额确认等信息,并进行了确认。然后,由商家D构建了一笔通道链支付交易,类似如下结构:

{
    // 通道转账交易
    amount: 1234, // 支付金额
    // 途径的通道
    channels: [
        {
            /**** 通道1:( A => 甲 )****/
            // 结算通道自定义id
            channelId: 232353253456,
            //  上一笔双方确认的交易hash
            prevTransactionHash: Buffer.alloc(32),
            // 通道交易序号,自动增量
            autoincrement: 123135,
            // 通道手续费,可以为零,也可为负
            fee: 12,
            // 本笔交易完成时的通道差额确认
            diffConfirm: {
                address: '19aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
                amount: 1234, // 金额
            },
        },
        {
            /**** 通道2:( 甲 => 乙 )****/
            /* ...略... */
        },
        {
            /**** 通道3:( 乙 => D )****/
            /* ...略... */
        }
    ],
}

// 以上数据仅为示例, `channels` 字段的数组元素数量将为三个,后两个格式相同,已省略

以上交易数据将广播到所有参与方,每一个通道只取channels数组中单独一个元素作为结算凭证。节点甲、乙因为同时各自拥有两条通道,即可同时收到和支出资金,保持了收付平衡,并且没有人会因为其他节点的故障或下线而丢钱。

5) 有序签名

四个参与方都收到了这笔交易,并进行了确认,如果有信息、资金或技术错误,任何一方都可断开TCP连接,从而关闭整个通道链,终止支付行为。

此时进入签名阶段:

1. 商家D首先用私钥签署这笔交易,然后将签名发送给节点乙
2. 节点乙收到D的签名,验证无误后转发给节点甲,然后自己也签署交易并将结果发送给甲和D
3. 接下来是节点甲,重复乙的行为,转发D、乙的签名,自己签署交易并发送
4. 此时包括顾客A在内的所有方都收到了D、乙和甲的签名,整个通道处于等待顾客A的签名的状态

必须从商家D开始按资金流动方向逆序签名的原因是:收款签名依赖于付款签名才能生效,节点必须先确认对方已经签署收到资金,才能签署付款,整个过程链式传递。而顾客和商家必须确认通道链中所有节点都签署了交易,付款后资金才能整体实时到账,否则有可能顾客已经签名付款,而商家却迟迟收不到钱。

6) 收款回执

整个交易和通道的状态此时依赖于顾客A的签名,A一旦签署便同时全部生效:

1. 顾客A收到了交易数据和商家D、乙、甲的所有签名,验证并确认无误
2. A签署交易,将签名结果发送给甲
3. 甲收到签名,转发给乙,乙转发给商家D,整个结算通道完成
4. D用私钥签署一条消息表示收到此笔付款并确认成功,将结果发送给节点乙,之后断开TCP连接
5. 乙将付款成功消息转发给甲,之后断开连接,甲转发给A,并断开连接
6. 顾客A收到商家D的回执,所有连接断开,整个通道链结算全部完成,支付成功

8) 通道各自结算及手续费

通道链中的每一个单独的通道,双方都收到了一个完整的交易,包含了资金在整个链条的所有流转记录。各自只需要去channels数组里面与自己匹配的通道做结算,结算金额为顾客A付款额度减去之前所有通道的手续费。

每个通道可以收取很少量的手续费(fee字段),以便偿付资金租借费用,类似于借贷利息的收益。通常手续费的比例取决于两点:1.支付资金的额度大小;2.硬件网络服务成本;手续费可以为零甚至可以为负。提供负手续费的通道签署一笔交易后收到的资金将小于同时的支出,这可视为一种吸引顾客开拓市场的补贴手段。

9) 错误处理

我们必须保证资金同步实时到账,并且没有人会因此可能受到损失。如果在支付的过程中,任何一方出现任何错误或问题,都将终止整个通道链的支付,断开所有连接:

1. 技术故障导致任何一方在拿到最终收款回执之前断开了连接,则通道链终止
2. 签名校验失败,终止
3. 支付额度或手续费不正确,终止
4. 交易序号、上一笔结算hash或余额确认不正确,终止
5. 签名超时,终止

节点或商家可自定义一个超时时间(比如3秒),过期没有收到后续签名或回执,则断开TCP,终止整个通道链。目的是避免不完整交易,从而导致某一方的资金丢失。

通过以上数据交换流程,我们完成了整个支付行为,各方都是实时安全到账。中间节点收取的微量手续费,可以激励其提供稳定的服务。

4. 通道关闭

一个通道在一段时间内会签署大量的支付,反复多次双向付款。如果双方对最终的余额分配没有争议,即可签署一条表示最后终止通道并提取各自余额的交易,广播给主网确认:

{
    // 双方确认余额,关闭结算通道
    // 余额分配立即生效,没有锁定期
    // 结算通道id
    channelId: 232353253456,
    // 确认余额分配 diffConfirm 为两者相差余额额度
    diffConfirm: {
        address: '19aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
        amount: 1234, // 金额
    },
}

以上交易在主网上一经确认,锁定在结算通道内的资金则立刻返回给双方。

5. 仲裁保护

由于结算通道是双方联对锁定资金,如果一方丢失私钥,将拖累另一方也无法将通道内自有的资金解锁提取。考虑到某一方恶意不签署关闭通道,或其他原因导致暂时无法合作,我们需要能够单方面终止通道的能力。

办法是将最近一笔通道链支付交易(或对账交易,且包含多方签名)通过引用方式广播给主网进行确认,通过交易内明确的余额,对方(被动终止方)将立即收到资金,而提起结束通道的一方(主动终止方)也解锁了资金,但代价是账户将锁定事先约定的时间(lock字段,例如一周),在此时间段内无法转出余额,作为避免单方面随意(恶意)结束通道的惩罚机制。

如果某一方向主网提交了不是最新的余额分配却对自己有利的一笔交易,想要单方面终止通道并侵占对方的资金,如上文所示提交方账户将被锁定而无法转出余额,此时另一方可以向主网提交最新的余额确认(通过交易自增序号autoincrement判断),一旦被证实则后者将立即夺取前者的所有资金,包括通道内的全部以及锁定的余额。通过严厉的作恶惩罚和举证奖励(后发优势对等博弈)让双方保持诚实。

考虑到消费或工资结算通道内的一方出资可能为0,或者最终一方支出了所有资金,那么作恶的成本为在主网提交通道交易锁花费的手续费,但一旦侵占成功则将获得很大收益,一些账户会在这种情况下选择作恶。此时可以采用账户锁定保证金的方式,在主网上锁定一定额度的资金作为多个结算通道的作恶赔偿金。

诚实的一方单方面结束通道,代价是账户被锁定约定的时间,而由于另一方无法给出(不存在)更新的余额分配,双方都不会损失资金。通过无限次重复对等博弈,大家都会倾向于选择诚实并合作。

6. 收付平账

设想如下情况:某商家首先与某通道服务节点签署了一个收款通道,接受付款。此时商家在此通道的出资应为零,顾客通过结算网络向商家进行支付。一段时间后,商家再与节点签署了一个付款通道,用于采购或支付工资,此时节点的通道出资应为零。

为了方便会计报表,这两个通道均为单向支付通道,一个仅用来收款,另一个仅支出。但通道锁定的资金是有上限的,而且为提高资金利用率,数量也不会太大。一段时间后通道内的资金将全部转移到了另一方账户导致交易无法继续,此时只能由另一方在主网上不断的追加通道资金,或干脆关闭后重新开启一个额度更大的结算通道。因为要等待主网的确认和支付不少的手续费,这将是非常低效的,而且将会锁定大量的越来越多的资金,长此以往整个系统将无法承受。

这个问题也会出现在个人的消费通道和工资通道分离的情况下。

我们使用一种通道对冲平账的方法来解决这个问题,底层技术原理与通道链支付交易相同。只是在这笔对冲交易中,仅包含收付两个通道,此时商家和节点(或个人与节点、节点与节点)之间同时互为支付方和收款方,交易结构类似于:

{
    amount: 1234, // 支付金额
    // 途径的通道
    channels: [
        {
            // 结算通道自定义id
            channelId: 1111,
            /**
             * 商家的收款通道,转移资金至节点
             */
        },
        {
            // 结算通道自定义id
            channelId: 2222,
            /**
             * 商家的支付通道,从节点把收款通道转出的资金再转回来
             */
        },       
    ],
}

这笔交易达成的结果为:商家的收款通道的余额被转移进了支付通道,而且是原子操作,双方都没有损失资金的风险。

结算网络的所有参与方,都可以定期进行对冲平账,不需要频繁与主网交互和锁定太多资金,从而让整个结算网络始终处于高利用率状态,只需少量资金便可支撑极大规模的支付交易。

7. 反集中化

规模优势和信息不透明致使我们无法完全避免金融与数据中介的存在,但准入制与垄断可以让马车夫摇身一变,成为拦路的山贼。过度集中化将导致严重的单点崩溃、抽税效应和信任危机。

如比特币的闪电网络,如果大部分交易都集中到少数几个中介点进行资金流转,那它们就成为了事实上的银行。一旦某个节点出现故障,将瞬间导致大量的交易无法进行,滞留在这些通道中的资金将爆炸性的向主网提交解锁,造成严重的拥堵和费用飙升,那些金额较低的通道甚至不足以抵扣提现的手续费。

我们应当尽量避免中心枢纽化,通道链结算网络有两点特性可规避此问题:

1) 链内资金结算整体实时到账

一旦付款方签署交易,所有参与方资金立刻全部同时到账和支出,不会滞留堆积在任何中间节点的通道内,就算技术故障或其它不可抗力导致节点下线,也不会影响在此之间已经达成的交易。

2) 通道签付锁定期

一条通道同一时间只支持单笔交易的达成,而无法做到并发收付,这在一定程度上降低了交易规模。但有几个极大的优势:1.资金安全保证;2.对账简便明确;3.交易不会堵塞;4.避免中心枢纽节点;

其中第4点的原理是:在连接TCP后至取得付款方最终签署交易的期间,相关通道一直处于锁定状态(此间无法同时支持其他交易,锁定时间可能为几十毫秒),单一通道的每秒交易量瓶颈,使得想要锁定巨量资金以满足大部分支付需求的枢纽通道变得极为不划算,最终会形成大量小额通道提供完全分散化服务的局面,从而避免了单点故障和中心化危机。

通道分散化、单通道金额的降低也带来了另外一个好处:让侵占资金的损人利己行为变得收益太小而不再具有吸引力。

8. 快速通道

通道锁定可以带来严格的安全保障,但却以降低交易吞吐量为代价。考虑到同一个节点可能设置不同的业务分部,不同节点之间也可能建立长期诚信合作关系,对于一些小微额度(例如买杯咖啡)支付,节点之间不需要完全实时对账。

我们可以采用延迟对账(比如一小时一次)的方式,极大地提升指定节点之间的交易吞吐量。从技术上来说,是将串行锁定的的交易验证,改为并发模式,即不为每一笔支付都双方确认余额的最终分配,而是先允许资金通过,后续再来检查账单。这种模式能让指定通道的每秒交易量从10来笔上升到2000笔以上(视设备性能而定)。

数据结构大致为:

{
    // 对账类型(1.实时对账  2.延迟对账)
    type: 2,
    // 资金流向
    side: 2, // foud1 => foud2
    // 8 type 结算通道id
    channelId: 232353253456,
    // 8 type 通道交易流水号,自动增量
    autoincrement: 123135,
    // 通道手续费
    fee: {
        unit: 8,
        amount: 1234,
    },
}

支持快速通道模式的节点之间,只需要过一段时间统一出示比较一下通道流水号列表和对应客户支付签名列表,即可确定相关交易是否成功,计算出各自正确的余额,并签署对账。

风险)

对于同一节点的业务分部来说,快速通道模式并没有任何安全风险。不论是节点、顾客或商户,都不会损失资金,因为账目对账延迟局限在节点内部,而外部则严格保持收支平衡。

对于密切合作的不同节点之间,则依赖于商业信誉和无限次重复合作博弈期望。由于并发支付,一段时间内通道某一方的实际金额可能是负值,也无法在签署对账之前进行主网提现。可以通过限制微小支付额度和提高对账频率,将风险限制在可接受的范围内。

商户、顾客和节点之间大规模采用快速通道模式造成的风险,将在第八章讨论。

9. 资金计算

假设平均一次支付要经过两个中间节点连接的三条通道,我们可以计算:

T:总锁定时间 = N:通道数量 * S:数据步骤 * ( t:TCP传输耗时 + c:验证计算耗时 )

代入数据 3 * 3 * (20ms + 15ms) 得 315ms,即表示一条通道链平均每秒可支持三笔交易(最差时)。如果有100个单位的资金被划入通道链网络,在全部采用对等出资的情况下,那么每天的交易量

(100:通道总额 / (3:通道数 * 2:双边对等出资)) * 3:每秒交易量 * 60 * 60 * 24 = 4320000单位

如果是具备收付平账的单向资金流动,最好的情况下资金流量会翻倍:8640000单位。资金利用率上限达到每日8.64万倍,每月260万倍,每年则超过3千万倍。意味着我们只需要锁定 0.0000116% 的资金,即可支撑一天内支付量与总发行量相当。

假设采用千万分之一的转账手续费比例,得出每天的费用总额为0.864单位,不算复利得年净收益率约为 315% 。

第四章、交易

1. 基本数据结构

为了保证系统运行的效率,交易的数据结构设计应该尽量简单和紧凑(stupid simple but efficient work),并让人类与机器都容易理解。(金融规则的人类可读性的重要将在设计原则一章讨论)

总体上可分为以下三个层级:

区块(Blocks) >> 交易、事务(Transactions) >> 功能、资产(Actions)

以 json 格式示例:

{
  version: 0, // 区块版本号
  height: 0,  // 区块高度
  timestamp: 0, // 区块时间戳

  prevHash: Buffer.alloc(32), // 前一个区块的 hash
  mrklRoot: Buffer.alloc(32), // 所有交易的梅克尔树根
  
  /* other extend field ... */

  transactions: [ // 区块包含的所有交易
    {
      type: 1, // // 交易类型
      timestamp: 12313423, // 交易时间戳
      address: "xxxxxxxxxxxxxxxxxx" // 交易的默认主地址(手续费支出地址)
      fee: { // 交易确认手续费
        unit: 248, // 手续费单位
        amount: 1234, // 手续费数
      },
      actions: [ // 交易的具体资产对象  或执行的动作
        {
          kind: 1, // 资产或动作类型(1 表示转账)
          bill: { // 转账总数量
            dist: 2, // 精度空间
            amount: new Buffer(), // 数额
            unit: 248, // 单位
          },
          address: "ooooooooooooooooo", // 转出地址
        }
      ],
      signs: [ // 签名
        {
          publicKey: Buffer.alloc(32), // 公钥
          signature: Buffer.alloc(64), // 签名值
        }
      ],
      multisigns: [ // 复合签名
        {
          publicKeyScript: Buffer.alloc(32, 96), // 公钥脚本
          signatureScript: Buffer.alloc(64, 192), // 签名结果脚本
        }
      ],
    },
  ],

}

可以看到,一笔交易大致分为 actionssignsmultisigns 三个部分。为何不采用智能合约等更加灵活和“先进”的交易结构,我们将在第九章进行讨论。

2. 复合签名地址

单一签名地址有秘钥丢失、被盗的风险,并且无法满足共同托管资金的需求。我们需要一种能让两个或三个私钥,以不同的权限配置来管理资金的功能,例如:

1. 甲和乙共同存款,需要两个人都提供签名才能取出资金
2. 夫妻联名账户,两人任意一个都能从共同账户支出
3. 交易所、在线钱包、离线私钥三者需要至少两方才能转出资金,以应对被盗和丢失的风险

交易结构中的 multisigns 复合名即支持二、三个私钥组成一个复合地址,那么可选的管理权限模式分别为 1/22/21/32/33/3 五种。以此类推,复合签名地址最多可支持200个私钥管理一个复合地址。

复合地址不存在保密的私钥,而有多个公钥拼合成一段数据,并由此计算生成一个公开的私钥。每次交易都需要提供这个拼合的公钥作为基础脚本,然后提供一个签名数据的拼合列表以供验证。

3. 层级股权控制账户

复合签名地址已经很好的解决了秘钥丢失、被盗安全和简单共同托管的需求,但面对复杂的经营结构(主要是受益权和投票权),我们需要一个能支持现代企业股权结构的账户体系。

此种账户必须满足以下特征:

1. 可由若干个私钥共同管理,避免安全性问题
2. 可更换(增、删、改)管理私钥,但地址固定不变
3. 一个可更改的投票生效比例
4. 支持同股不同权
5. 极端情况下避免丢失资金

1) 构建

由于以上特点,我们需要在主网上保存和管理账户。开启一个股权账户的交易类似于:

{
    // 1~10000 满足票数有效比例(万分比)(必须等于或大于此万分比值即可操作账户)
    validRightsRatio: 6666,
    // 组成列表
    forms: [ // 数量 200 个以内
      // 投票权 和 受益权 可以不等比(即同股不同权)
      {
          address: '19aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
          //   4 byte, 0~4294967295, 权益数
          rights: 1,
          //   4 byte, 0~4294967295, 投票权
          votes: 3,
      },
      {
          // 成员可以为复合地址
          address: '29aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
          rights: 3,
          votes: 5,
      },
      {
          // 成员也可以为其他股权账户
          address: '39aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
          rights: 2,
          votes: 3,
      },
    ]
}

主网确认这笔交易后,会在数据库能用forms提供的成员地址,加上交易时间戳,组成一段数据并由此生成私钥和公钥,作为新创建的股权账户。

股权账户的成员可以为普通地址、复合地址,也可以为其它股权账户,并指明相应的投票权和受益权。主网将会在数据库内储存所有的地址控制结构,每一个地址都有一个控制树。

2) 验证

检查一笔股权账户发起(或参与)的交易是否有效,需要从数据库内读取控制树,并从签名列表内检验是否具备足够票数的成员签名。在票数足够的情况下,可忽略后续的签名检查。

一个股权账户可能由其它多个股权账户控制,而上层的股权账户又包含更上层的股权账户成员,类似现实中公司之间的多层投资关系。如此一来一笔大型地址的交易甚至需要验证上百个签名,这将消耗很大的数据空间并拖慢交易确认速度。我们采取按交易数据空间大小来计算交易费用的方式可一定程度阻止超大股权账户的频繁交易。实际上,日常的普通支付大可授权给专门的财务账号,而需要股权账户签名的交易仅仅为类似重大行业投资这样极低频率的交易。

3) 管理

股权账户在主网注册后,可增删管理成员和更改权益。需要满足投票数的成员签署一笔更改交易即可完成。类似的,也可以更改生效票数比例。

成员及权益的可任意更改,股权账户的地址则保持不变。

4) 账户最低金

股权控制地址将占去很大的数据空间和验证时间,是非常珍贵的资源。为了避免浪费,在注册和增加(更改与减少除外)管理成员时,除了让交易验证者收取普通的交易确认手续费之外,还需要在账户内锁定与手续费相同的金额,作为账户的维护金。

在地址注册之前,需要先向待注册的股权账户内发送一定量的资金,用于确保账户最低金足额,才能完成注册。(在账户正式向主网注册之前,先在本地计算生成目标地址,并在主网向其转账)

5) 注销

为了避免状态数据库空间的膨胀和浪费,股权账户支持注销(删除对应的成员列表和控制树)。账户最低金在注销地址时返还给指定的其他账户。

5) 资金安全

考虑到可能由不可抗力导致的集体性私钥丢失,以至于无法凑足达到生效票数的签名数量,从而无法进行任何交易操作,组织的资金实际上永远丢失了。并且受益权较大而投票权较小的成员将蒙受更加严重的损失。我们需要在这种极端情况下能够将资金安全提取出来。

设计成可以由股权账户控制树中任意一个上层成员地址发起资金保护模式,发起的条件为自己账户需要锁定相比股权账户1%数额的资金,锁定期为半年。半年内如果有其他成员地址提起解除,或者股权账户相关私钥已经找回并发起一笔交易,则自动退出资金保护模式。

半年后,提起保护模式的账户可将股权账户内的资金,通过发起另外一笔交易提取到自己的账户内,从而避免极端情况的资金永久丢失。

4. 多方签署

设想一种股权投资的场景:一家公司(简称A方)接受出资者(简称B方)一万个单位的资金投入,出让20%的股权。此种情况下,A和B任何一方先行操作,都有被欺诈的风险:A先出让股份则B不注资,B先转账注资则A可能反悔而不出让股份。

我们需要一笔交易能同时完成注资和分股两个操作,其中任意一个操作失败,而另一个则也自动失败。这时就需要双方对一笔交易进行联合签署:

{
    type: 1, // 交易类型
    timestamp: 23423442, // 交易发起时间
    // 交易资产、动作
    actions: [
        {
            kind: 6, // from 给 to 转账
            from: 'xxxxxxxxxxxx', // address
            to: 'ooooooooooo', // address
            bill: { // 转账金额
                dict: 1,
                amount: 10000, // 数额
                unit: 248, // 单位
            }
        },
        {
          kind: 7, // 新增股权管理成员
          forms: [
              {
                  address: '19aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM',
                  rights: 3, // 收益权
                  votes: 3, // 投票数
              },
          ]
        }
    ]
}

此交易包含两个action,双方都签名后,将同时完成资金的转移和股权的分配。

但上述交易仍然有一个漏洞:如果公司在上述交易签名完成但未确认生效的期间内,抢先广播一条交易,将原先的股权增发一百倍给原来的股东,则这笔交易确认成功后,新的出资人的股份已经被稀释得微不足道了。我们还需要包含一个条件action

{
    kind: 9, // 表示对应地址的投票权和受益权必须在一定比例之上时,交易才能生效
    address: 'xxxxxxxxxxxxx',
    targetAddress: 'ooooooooooooo',
    rightPercent: 20, // 收益权%比例
    votePercent: 18, // 投票权%比例
}

此条件action排序在第三位,表示完成了上述注资和分股操作后,最终的股权比例要求不低于20%。

5. 支付类别

为适应现代金融支付的需要,我们应该支持基于UTXO和余额两种类别的多个支付方式,并且完全考虑到将来会出现一些支付服务商的角色,将提供的支付类型例如:

1. 自己支付给对方
2. 请求对方支付给自己(需要对方签名此笔交易)
3. 让甲支付给乙,而自己只是付出交易费用(需要甲签名)
4. 让 inputs 内各自指定的资金,支付给 outputs(需要inputs所有人签名)
5. 让 inputs 内包含的所有资金,支付给 outputs(需要inputs所有人签名)

对于股权账户来说,将有一些特殊的资产变更操作:

1. 将指定金额按收益权比例分配给所有成员(股份分红)
2. 将指定金额按投票权分配给持票人(管理层激励)

更多支付方式和数据结构细节将在附录给出。

6. 签名剥离

由于复杂的支付方式和股权控制体系的存在,一笔交易将包含大量的签名,一个区块甚至可能一半以上都是签名数据,为了节省空间和方便其他交易验证者快速同步数据,签名数据必须设计成可剥离的。

从技术上说,签名列表(包含多签和复合签)内的数据和顺序,不计算入最终交易的hash值。如此就能将交易的核心数据与签名数据分开储存或传输。

剥离后也能让一笔交易的多方参与者互不依赖地并行签名,有利于在商业行为中独立做出决策。

7. 手续费

考虑到大规模商业支付的需要,一些服务商会为顾客代理支付并免去交易确认手续费用,也可能出现一些打包或混搅的支付服务,应该将手续费支付方和普通交易参与方签名分隔。

具体在技术层面则是: 一笔交易仅包含一个手续费支付方式,他所签名的原始交易数据中包含 fee 字段,而其他人的签名则不包含手续费相关信息,只对自己的交易行为签署确认。

由于主网的交易费用始终处于不停的涨落状态,手续费支出方则可以随时调整费用并重新签名交易,从而取得一个更加经济适合的交易确认时间,并且无需麻烦每一个参与方多次重签。

对于交易确认者(矿工)来说,交易的唯一hash不包含手续费字段,能够剔除重复提交的交易,达到费用动态竞价的效果。

8. 字段格式

一个成熟的交易支付系统应该适应未来长期的需要,金额的表示方法及能够保留几乎无限的精度,又能够尽量节省空间:

{
    bill: {
        dict: 1, // 表示资金正负,和amount的空间大小
        amount: Buffer.alloc(), // 数额数量
        unit: 248, // 单位,代表amount后有几个零
    }
}

而对于手续费等数据来说,却没那么高的精度需求:

{
    fee: {
        amount: 1234, // 金额
        unit: 240, // 单位,十进制
    },
}

其他详细的字段格式及解释将在【附录】给出。

第五章、激励

一个经济系统能够长时间良好运转的理由很简单:1.让付出创造力和改善效率的人多挣钱;2.避免不劳而获。一切经济优势,都是规则优势,归根到底是制度优势。

一些学院派货币理论认为,货币是中性的,是一个可以被代入抵消的常量,并基于此谬误假设,放弃解答一个真实世界里几乎是最重要的问题:谁应该最先拥有货币?

货币要么本身是商品,要么是商品的代表。正如无法换取商品的货币不能成立一样,也不存在没有产权的商品。产权体系和市场经济是同一个事物的两面,没有清晰产权就不会有真实市场,公正和效率也是同一事物的两面,没有公正就没有效率。

产权的公正性是一切经济效率的前提。加密货币并不绝对公正,但它能极大促进这种公正。

1. 记账权竞争奖励

维护公共账本的正确和统一是电子货币系统中最重要的工作,我们应该给予足够的奖励。比特币创造性的将竞争记账与货币发行结合起来,成为系统有效运转的引擎。

我们设定每5分钟更新一次账本(产生一个包含新交易列表的区块,由特定哈希算法不断尝试直到找出满足难度要求的数据,称为 Proof of Work ,产生后立即广播给所有其他人),新区块内的第一笔交易产生一定数量的新货币,奖励给抢先计算出目标数据的账本验证者自己(简称矿工),其他验证者收到并检查新产生的区块其中的转账数额和签名是否正确,并在此区块后面重新开始计算,试图找出下一个满足难度的区块哈希数据并获得奖励。所有人都会通过计算一段时间内产生的区块数量自动调整目标难度值,以保证在计算能力变化时总能平均5分钟更新一次账本。

产生新货币的数量第一阶段每年调整一次,从1上升至13,;第二阶段每十年调整一次,从13下降至1,第三阶段为永久稳定在1个产出。76年后货币数量在3500万。详细的货币增发算法将在第六章给出。

2. 公账手续费

激励竞争记账产生新区块的同时,还需要鼓励区块中包含尽可能多的有效交易,否则账本系统就是在空转浪费资源。一笔交易需要包含一定量的手续费,由记录交易并产生区块的矿工获得,费用数量采用动态竞价机制。

并且,由于所有交易要让所有矿工验证,公共账本的记录能力和空间大小总是稀缺的。除了愿意付出的价格,我们无法准确判断交易的紧迫性和价值高低。支付更高手续费即能优先得到处理,是相对更有效率的识别方式。

3. 通道服务费

我们在第三章详述了通道链结算网络,并设想将会出现专门提供资金流转和支付服务的节点出现。节点收取的服务费数量取决于同业竞价、硬件网络费用和通道资金成本。

4. 通道利息

类似电话线路和互联网,足够数量的通道组成覆盖性网络,整个体系才能发挥最大的价值。需要鼓励大家将暂时用不到的多余货币放入通道中提供结算服务。

由于开启通道也要像普通交易一样支付确认手续费,我们设定按比例产生极少量的新货币奖励给锁定资金的通道双方,以冲抵其手续费损失。通过有限精度的数据格式(省略零头),让大资金量通道相比小型通道获得奖励更少,以刺激产生更多的通道。由于确认手续费和真实购买支付额度的限制,通道资金规模将保持在一个合适的范围内,不会太巨大,也不会太少。

设定从通道锁定成功开始算起,以双方锁定的总资金为基数,每5000个区块(约17天,不足则忽略)按复利结算一次利息,利率为万分之一,年利率即为大约0.21%。在终止通道产生新货币,按双方开启和结束通道时拥有资金的平均值按比例兑付。

5. 区块钻石

只存在于理论中的理想货币:无交易成本、总量随社会总财富的增长与消耗而实时变化。类似一种储量无限的虚拟黄金,当生产力提升时就挖掘出更多铸造成货币流通,生产力降低时由于挖掘成本而自动减少产量。如此就能避免货币剧变导致的通胀或通缩对经济体的伤害。艰难的是我们不得不面对现实的残酷和恶劣,永远达不到理论中的完美。

记账奖励和通道利息的产出数量都是固定的,不会随着生产力变化。我们需要一种能适应人口及技术周期涨落而自动调节产出的货币增长机制,当算力增加时产生更多的新币,并且其挖掘难度只会提升不会下降,以便在算力大幅降低时立即减少或终止新货币的产出。

我们约定区块钻石是一种由32位哈希值经过压缩计算而满足特定格式的一串数据,每个区块最多只能包含一颗钻石(也可以不包含,视算力而定),其生产算法为:

hash256((genesis_block_hash || prev_diamond_block_hash ) + belong_user_public_key + nonce_number) ==> length_16_string

具体是将 创世区块哈希 或 上一个包含钻石的区块哈希 加上 目标所属者的公钥 加上 任意随机数 进行哈希运算,得到一个64位字符串值,类似:

35534631f31dfcf12200cdbad65c66ffb9d3fbd3ac985aa8a401bc4c3616bab3

将上一步产生的结果进行特殊的压缩运算,每4位映射到字符列表 0WTYUIAHXVMEKBSZN 中,得到如下的16位字符串结果:

0NMSAK0ZYNSNBAZM  、 00000000IXVKHNHZ  或  0000000000UKNWTH

当结果满足至少前十位为0时且后几位不包含0时,即产生了一颗钻石。根据以上结果,我们称此颗钻石的字面量(标识符)为UKNWTH,且字面量唯一不重复。此时将这颗钻石打包进区块并广播,所有钻石生产者停止之前的计算,而采用此新区块的哈希值重新开始计算下一颗钻石的字面值。如果同一区块时间内产生多颗钻石,则由矿工决定打包哪一颗进区块(也许是给出手续费最高的)。

钻石的总量上限约1700万颗。每挖出一颗则整体挖掘难度将相应提高,随着采掘数量的增长成指数级上升,并最终趋近于无限大。

区块钻石是一种异质高维形态的货币,能够达到动态调节货币供应的效果。其价值由挖掘成本及市场公认而定。

6. 数据服务

除了以上描述的系统内部的奖励机制以外,我们还需要一些专门的数据计算商家提供的相关服务,他们将以此收取一些服务费用,例如:

1. 通道路由
2. 交易混搅打包
3. 交易确认查询
4. 通道恶意终止监控
5. 加密私钥托管
6. 信用审计
7. 数据安全审查

并且将可能产生交易签名机等用于通道链结算网络的专用硬件设备。

第六章、货币

最强大的技术始终要致力于满足最迫切的需求和解决最严重的问题。广义分布式公共账本技术如果无法首先改革世界货币体系以减少对金融弱势群体的掠夺、压迫和剥削,则遑论其他。

1. 总量及增长

在长期来看(静态均衡而非短期炒作),除去使用价值方面的影响,如果一种资产会鼓励囤积,那么它的升值率必须大于社会平均生产利润率,否则大家还是会将其拿去投资。而总量恒定的资产的升值率刚好等于社会生产率,那么只需引入少量的增发预期就不会抑制投资和消费。通缩陷阱的破坏力只会在强迫大家使用唯一一种货币并且由于通胀而借贷了巨量债务时才会出现。通胀还会逼迫穷人进行投资,由于不具备信息优势和风险不分散,从而被掠夺更多。

不像纸币或黄金,加密货币一旦遗失则不可能找回。总量若是恒定不变,长期来看将导致过度囤积和投机泡沫,从而损害其作为货币的核心职能。我们需要引入一个通胀预期来避免上述问题,哪怕实际的货币增发量并没有超过现实的经济增长率而不会真的贬值。

由于理论上不可能完全匹配经济交易规模的变化而精准调节流通货币供应(社会每多生产1单位的商品就增发1单位的货币只是一种美好的幻觉),我们只能尽量避免货币量级变动对经济活动的干扰。相对更可行的做法是给出一个可观测的增发预期,让所有人都能估算出一定时间内的货币增长量,配合市场价格指数和购买力指数,通过会计调整后合理安排消费、生产和销售活动。例如在货币购买力持续上升的情况下,只要升值率是稳定可预估的,那么企业发放的工资数额将随时间按比例降低而不是保持不变。工作者也可以接受这种方式,因为因为合约的选择受制于具体资产价格变动的局限条件。他也知道实际能买到的东西并没有减少,只不过长期以来的通胀让人们习惯于工资数额只涨不跌。

1) 记账奖励

我们采用斐波那契数列决定区块的货币奖励发放。第一阶段,每 10 万个区块约 0.95 年调整一次数量,奖励逐渐上升;第二阶段,每 100 万个区块约 9.5 年调整一次数量,奖励逐渐下降;第三阶段,最终恒定在每区块奖励1个单位:

1, 1, 2, 3, 5, 8, 8(十年), 5(十年), 3(十年), 2(十年), 1(十年), 1(十年), 1, 1, 1, 1, 1 ....

则前 66 年的总供应量为 2200 万单位:

(1 + 1 + 2 + 3 + 5 + 8 + 8*10 + 5*10 + 3*10 + 2*10 + 1*10 + 1*10 ) * 100000 = 22000000

此后的年增发比例 (1*100000)/0.95/22000000 约为 0.4785%,此后逐年递减(100年后约为0.3289%,200年后约0.2506%,500年后约为0.1462%),并无限趋近于零。

2) 通道利息

为促成通道链结算网络的大规模应用,我们设定以 2500 个区块约 8 天为一个结算周期,按复利奖励锁定在通道内的资金,比率为 0.01 % 。假定通道资金占总量的 1/2 ,得出年增发率约为:

(1+(0.0001*1/2)) ^ (365/(2500/12/24)) ≈ 1.0021  ( 0.21% )

加上记账奖励,平缓时期总的年均增发量粗略估计为 0.6885% ,并无限收敛至约 0.21% 。一个仅供参考的数据是1960年至2012年世界总平均GDP增长率大约为2%~4%。

3) 钻石采掘

钻石的字面值由 WTYUIAHXVMEKBSZN 16个字符组成,最终计算出的哈希值后6位为字母则是合法的字面值。其总数量为:

16^6 = 16777216

我们设定每5个区块约25分钟方能采掘一颗钻石,不考虑难度陡增,要挖掘出所有钻石至少需要:

16777216*5*5 / (60*24*365) ≈ 800 年

其中每天最多可挖出 60*24 / (5*5) 约 58 颗,每年最多出产大约 21000 颗。区块钻石是生产盈余的累积,是经济系统的财富仓库。

2. 无限分割

加密货币想要真正应用于商业支付领域,而不是像黄金一样成为收藏品,则必须满足能大规模安全实时交易结算、增量出产稳定及可无限分割。

无限分割保证无论经济发展到何等规模体量,始终能够进行小额支付。数字加密货币应该完全规避传统货币的实体形态所造成的交易费用问题。

3. 单位及符号

我们采用一种特殊的类似科学计数法的数据结构来储存资金数额:

bill: {
    //   1 byte, 0~255, 单位(后面跟了几个零)
    unit: 248,
    //   1 byte 表示所占空间及正负, 1~127为正 128~255为负
    dist: 1,
    //   1~127 byte 转账金额数量
    amount: Buffer.alloc(),
}

其中 unit 表示十进制的单位,比如 {amount: 1, unit: 4} 表示 1000, {amount: 137, unit: 8} 表示 13700000000。

我们设定 unit=248 时为1货币,并以1亿为进制,1 = 1亿,以此类推设立五个单位:

1. unit:248 为 1枚 = 10^8铢
2. unit:240 为 1铢 = 10^8烁
3. unit:232 为 1烁 = 10^8埃
4. unit:224 为 1埃 = 10^8渺
5. unit:216 为 1渺

在日常记账中,可将 273.58铢 记为 ㄜ273.58:240 ,而 1枚 记为 ㄜ1:248

引入unit单位意味着,我们可以将一枚货币分割成 1亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿亿 分之一(10^248),而可观测宇宙中原子数量级约为 10^80 个。

4. 禁止人为货币政策

货币不应该用来调控经济,这是一种懒惰,并且太危险了。

现代商业经济生态系统越发复杂,已经从稀树草地向亚马逊雨林发展,而采用货币政策调节经济类似于用降水量调控雨林的生长。草地只要有水就能繁荣,而雨林的形成则需要太多的条件和时间,事情并没有看起来这么简单。健康的经济生态只能在合适的条件下生长和进化,而无法被精确设计出来。

人们总是对自己过分自信,但却又无法理解某些复杂系统的涌现规律不能完全被解构建模。加密货币的出现并不是为了取代法币,而是要在一个全新的地方创造全新的金融规则和商业模式。将传统货币金融系统的顽疾硬套在加密货币体系上是无的放矢。金融和经济规则长期从来都是被强势利益集团所裹挟,我们需要为金融弱势群体而抗争,保护勤劳工作的果实不被肆意欺诈篡取。值得注意的是,大规模长时间的货币政策调控的最终受益者一定是离钱和权最近的人,这就会导致贫富差距不可避免的拉大,穷人将在贫穷的泥潭中越陷越深,以至于完全无法凭自己的努力跳出陷阱。人们此时就会期待一个更强有力的政府来进行强制再次分配,社会文化和经济生产将跌到谷底甚至倒退十数年,最终将导向灾难性的人间悲剧。

让某些掌握大量话语权的人或组织投票商议来改变货币体系的核心价值参数的行为和想法是非常愚蠢的,例如修改货币增发的算法、数量或速度。这不是一种类似于宗教原教旨主义的自负行为,而是未来货币系统的关键就在于向大家提供一个不可操控的稳定预期。如果在某些核心价值参数上的设置极不合理或不适应,那就让更好的来取代。

第七章、隐私

似乎有些人无法理解,我们行事光明,但还是不愿让人知晓。最大的问题是,窃取消费数据的商家会分析历史购买行为,从而为每一个人给出一个高到刚好能接受的价格,这将极大的损害我们的利益,如果提供的产品是垄断的,后果可想而知。

1. 匿名

在公共账本之中,匿名其实是一种假名,并不能始终保持隐匿。由于在某些环节我们总要主动或被迫亮明身份,那么实际上就可通过追溯整个转账链条,暴露所有隐私。匿名地址只是基础,我们需要另一些措施,能够切断支付与收款账户之间的直接联系,从而避免被追踪。

2. 支付混搅

通常的转账交易中,付出与收款一一对应,是一个人对另一个人发起支付,而且公开广播,这样很容易推断出两者之间的必然联系。

一个可行的解决方案是,由一群人向另一群人共同发起相同数额的转账,这样就无法将收款方与支付方精确匹配起来,参与转账的人数越多则隐私保护的效果越好,称为定额支付混搅。其交易结构大概为:

{
    // 定额支付混搅
    kind: 6,
    fee: { // 每一个地址单独收取的服务手续费,可为零,甚至可为负
        amount: 1234,
        unit: 248,
    },
    bill: { // 统一转账数额
        dist: 1,
        amount: Buffer.alloc(),
        unit: 248,
    },
    addressCount: 100, // 参与混搅地址数量
    inputAddresses: ["1313Rta8Ce99H7N5iKbGq7xp13BbAdQHmD", "..."], // 多个付出地址
    outputAddresses: ["19aqbMhiK6F2s53gNp2ghoT4EezFFPpXuM", "..."], // 多个收款的地址
}

这种混搅方式无需依赖环签名等复杂的技术,简单易行,有如下优点:

1. 能压缩交易数据的大小,提升主网吞度量,节约手续费
2. 一些隐私需求强烈者可能通过零手续费甚至补贴来吸引足够的混搅参与者,多方共赢
3. 无需收款方参与签名(离线到账)

相应的,也具备一些缺点:

1. 转账金额高度统一,难以用于通常的商品购买
2. 为适应不同体量的转账,需要分成多个整数梯度进行混搅,从而更难集齐足够数量的参与者
3. 仍然有被追踪的可能,虽然能通过多次混搅将这种概率降到极低

3. 前置延期兑付

支付混搅是从“空间”上模糊了资金发送者和收取者之间的直接联系(同时收付而次序打乱),我们需要更多的保证,那就是从“时间”上切断资金的去向,原理是借助中间人立即转出但延期收取资金,从而在一段时间内无法得知交易的最终接收者。

假定付款者为A,中间人为B,最终收款者为C,转账金额为100单位,则基本步骤为:

1. B 创造一笔向 C 转账 100 单位的交易 trs1, 将其发送给 A 
2. A 收到交易 trs1 后,创造一笔特殊交易 trs2 将 101 单位(包含1单位的手续费) 资金发送到一个加密的临时地址 addrx,其中规定了在 trs1 生效一段时间后才能由 B 从临时地址内领取出 101 单位的资金,并将 trs2 展示给 B ,使 B 可以确保资金的安全
4. A 将 trs2 签署,并广播至主网并确认生效
5. B 将 trs1 签署,并广播至主网并确认生效,C 收到了 100 单位资金并立即可用
6. 一段时间后(例如6个月),B 发起一笔交易 trs3 从临时加密地址 addrx 中取出 101 单位资金,整体交易完成

以上方法由于资金的发送和收取有先后顺序,隐含了一个安全风险:A 将资金发送到加密地址,但 B 却由于私钥丢失而不能签署 trs1 交易,实际上导致 A 丢失了 101 单位的资金。

需要注意的是 B 并不存在蓄意不签署的利益动机,因为 B 完成整个交易能获取相应的手续费,就算 B 账户余额不足仍然可以向朋友借贷,待取回资金和手续费后立即返还。有两种情况可能触发丢失:1. B秘钥丢失或因不可抗力无法签署;2.B单纯恶意想让A损失;

规避这个安全风险的办法是,A 在构造 trs2 时加入一个条件:如果超时(比如一年)后 B 仍然未能领取资金,则 101 单位的资金可以返回至 A 账户。此时的风险转移到 B 的头上:需要在 6 个月的窗口时间期内领取资金,否则就会有损失 100 单位的可能。由于 B 赚取了手续费则可以从收益上对冲掉这种风险。

trs1 为一笔普通转账交易,trs2 的交易数据结构为:

{
    // 发送资金至一次性加密地址
    kind: 9,
    bill: { // 数额
        dist: 1,
        amount: Buffer.alloc(),
        unit: 248,
    },
    // 32位的哈希作为加密地址 = sha3-256(前置交易哈希 + 交易确认区块 + 指定领取地址)
    hashaddr: Buffer.alloc(32),
    // 超时取回,表示一年后未成功则可自己取回资金
    overback: 105120, // 区块数量,设置为零则永久有效
}

从加密地址取出资金的 trs3 交易数据结构为:

{
    // 从一次性加密地址取出资金
    kind: 10,
    // 被取出的加密地址
    hashaddr: Buffer.alloc(32),
    // 必须已经存在的交易哈希(取出资金的前置条件)
    existTransaction: Buffer.alloc(32), // 为上文 trs1 的哈希
    // 前置交易被确认区块数
    confirm: 50000, // 约半年
    // 指定领取地址为手续费支出地址,并与existTransaction及confirm计算出哈希必须与hashaddr相等,即证明有领取权限
}

前置延期兑付除了有锁定资金的风险,并不会让任何人损失资金。在有足够信任的条件下(比如 trs1 和 trs2 现场实时签署), trs2 可设置为永久有效,这可以让中间人 B 只在实际需要时,才会将 trs3 交易广播,这个时间可能会很长(例如5年),从而更大地确保了 A 的隐私安全。

4. 加密结算网

支付混搅虽然能降低被追踪的概率,但交易仍然被公之于众,如果某个企业机构掌握了大量账户地址对应的身份信息进行大数据分析,我们事实上仍然处于风险之中。

加密的通道链结算网络除了能够按需扩张交易吞吐量,由于几乎所有的支付数据都在链下传播而不公之于众,其也能够一定程度保护我们的隐私。通常的支付通道节点也许会被要求提供所有接入的客户的身份信息,并有泄露每一笔消费数据的可能。

一种可行的方案是将通道链交易用支付参与者(包含支付方、收款方和中间节点)的公钥进行加密,从而避免被无关方截取导致信息泄露。不足之处在于,此方案仍然依赖于节点的安全技术措施和保密强度。

5. 通道冲销

通道冲销严格来说只是在每一笔具体的通道链支付中,向普通消费者隐藏了节点双方在通道内的实际拥有资金数额,并没有从技术上保证。不怀好意者仍然能够通过扫描主网注册的通道,从而计算出各自拥有的资金。

但在快速通道中,由于不需实时确认资金额度,除非取得通道在一个结算周期内所有的交易,否则 无法得知通道双方的资金数额。

我们需要保护消费者隐私和必要商业机密,但并没有提供绝对的反审查功能,因为后者将消耗几倍于前者的数据空间和计算资源,并容易成为勒索病毒、挖矿木马等恶意有害行为的保护伞。我们将在第九章设计原则中讨论。

第八章、风险与防范

本章将讨论系统的依赖条件和可能出现的风险,以及对应防御措施的安排和重点注意。

1. 通道链延迟签名攻击

通道链(特别是使用快速通道后)能够极大地提升整个系统的交易吞吐量,在较为成熟的阶段,几乎所有通常的商品支付和转账都通过结算网络进行。

为了确保陌生即时支付的安全和实时到账,一般将在通道建立直到签署最终收款回执期间保持锁定,根据网络条件可能长达100毫秒至两三秒不等。这段时间由于通道处于排他状态,无法处理另外的交易。如此一来,服务节点的商业竞争对手或者恶意破坏者,可以针对特定的通道发起海量的极小额度支付,并且故意拖延付款签名,每次都到锁定超时时间临期之时,那么被攻击的通道将被大量的小额支付长时间堵塞(类似于互联网的DDoS攻击),无法处理其他正常的商业支付。

办法是每一个节点都记录一个临时的缓存数据,用于记录支付者的地址和累计支付额度和占用的总锁定时间,将二者相除得到一个分数,表示单位时间通道利用率得分,如果此分数相比较特别低或明显异常,即可限制对应地址的支付频率或者干脆拒绝服务,从而防范此类攻击。

2. 低成本通道欺诈

通道链结算网络的正常运行依赖于一个严厉惩罚威胁:一旦作恶将被夺取所有账户资金。考虑到在某些时候,通道单一侧方的实际资金余额极低或为零,那么这一方就有利益动机将对己方有利的余额分配广播给主网,如果对方没有对此进行严格的监控,一段时间后就会损失资金,而作恶方的成本仅仅为公账确认手续费。

要解决此诚信问题仍然无法通过纯粹的技术手段,而只能采取某一些保险和惩罚机制:

1. 约定各自账户保留一定的风险抵押金,可同时为多个通道做保险,一旦其中任意一个通道违约,将被夺取风险抵押金,此时其他所用通道都将关闭,防止破坏行为再行实施
2. 商业服务节点之间可互相披露旗下通道列表和身份信息,一旦某一方有违约行为,可终止所有通道的合作,并将其作恶行为广而告之,从而形成严厉惩罚。

我们可以将通道违约的风险及损失限制在一定范围内,不会对整个结算网络形成系统性威胁。

3. 通道信用货币创造及违约

跨数量级提升交易吞吐量的办法本质上只有两种:1.数据及服务中心化;2.容许临时局部数据不一致;通道链中的快速通道原理上属于后者,即推迟对账时间和减少对账次数。

如此将导致在特定时间某个通道的支出超过了一开始的锁定额度,其可用余额实际上为负。通道中的额度包含实际锁定的的资金加上一方对另一方的债务,这时信用货币产生了,即类似于银行的部分准备金制度引致的信贷扩张,整个系统无中生有地创造了大量新货币!

我们应该极大地注意此时支付网络的系统性风险,当某些通道方负债巨大而无法继续还款时,将会导致连锁违约反应,此时传统意义上的金融危机和经济崩溃在加密货币体系内出现了。

但是,我们猜断,在没有中央银行(最终贷款人)的加密货币系统内,大家并不会过度举债(或者不会容许对方借太多钱却明显还不起),因为所有行为最终买单的只能是自己,而无法通过所谓的量化宽松政策或者金融救助,将损失转移化、社会化,最终让大量无关的普通人特别是穷人来承担。

另一个需要仔细考察和防范的是中心化加密货币交易所,如果我们使用通常的方式将加密货币委托于其长期管理,那么它们将成为事实上的银行。我们需要建立足够广泛的通道链结算网络,从而取代银行在传统经济体中发挥的作用。重要的是,需要确保没人能够盗取我们的钱财,无论直接还是间接。如果网络加密货币体系中出现了限制准入性银行和部分准备金制度,这将是对所有人最大的讽刺。

4. 算力集中化、51%攻击和游击挖矿

比特币想要避免权利太过中心化而摒弃了基于IP地址的投票算法,选择了CPU运算竞争的方式,但却没料到定制化芯片(ASIC)的极大优势最终还是造成了严重的算力集中化。在一个开放准入的自由竞争领域内,资源和人员的逐渐集中似乎不可完全避免,因为这在经济上具备规模效应从而成本更低更具竞争力。事实上,我们并不担心算力集中化本身,而是担心由此滋生的掠夺、欺诈和破坏。相应的,我们也并不真的害怕垄断,而应该恐惧被限制准入。例如微信事实上垄断了移动端即时通讯领域,但用户并没有觉得有什么不好,这是因为后面还有一大批饿狼般的互联网企业只等着微信犯错然后冲上去撕咬瓜分。

加密货币领域的发展愈发成熟,专业化趋势越发明显,几乎所有的挖矿算力都能付费临时租用,这种游击挖矿的行为将使一些市值及算力较小的币种面临极大的算力波动,并处于严重的51%攻击风险之中,这将导致刚刚脱颖而出的更优质货币处于被劫掠的境地中难以发展壮大,而让差强人意但却因先发优势保持巨型体量的古老货币大者恒大。理论上来说,51%攻击主要是中心化的交易所而非个人,因为它们有足够大额的资金操作,足够攻击者冒险一搏。如果大家都使用通道链网络来组建交易所,那么这种攻击将失去目标。

本质上,我们无法完全解决这个问题,只能尽力改良以规避。有几种办法可以起到作用:

1. 发明新的挖矿算法,避免或延缓专用硬件设备的出现导致的算力集中趋势
2. 适当抵押一部分资金才能被认可为矿工,让其成为事实上的利益一致者,从而减少作恶动机
3. 让“真实用户”投票“倡议”所有诚实矿工选择“正确”的分叉

1) X16RS 哈希算法

X16RS 是 X16R 算法的升级版,基础原理是随机组合16中不同的哈希算法,从而抵抗ASIC的优势。X16RS 改进的地方在于,将原有的每区块确定一次哈希组合,变成每一步哈希都重新随机选择算法,从而增加FPGA设计运行的难度。

2) 历史见证路径选择

51%攻击是阻碍加密货币大规模使用和普及的最大阻碍之一。特别是对于一些算力规模较小的新创加密货币来说,潜在的51%攻击风险会将机制设计更有效的新货币扼杀在摇篮中,市场从而被先发优势所统治,我们不得不长期忍受差强人意的古老货币,无法充分竞争和自由选择出最优质的加密货币。

PoW 挖矿算法解决了一个共享货币系统中最为核心的问题:谁拥有下一批新发行的货币。也就是说,PoW的竞争机制决定了未来。

51%攻击的原理是:一个(或数量极小)的矿工,悄悄运用高于其它所有矿工加总的算力,计算一条更长的链条,但不让任何人知晓。一段时间后(几个区块后)突然将更长的链条广播给全网,导致大家被迫放弃已经公认的链条,转到攻击者的分叉上来,从而让攻击者可以撤回已经生效的交易(双花)。

也就是说,51%攻击本质上是篡改历史。

攻击者和诚实矿工的唯一区别在于,是否将挖出的区块立刻广播给全网所有人,如果没有人隐瞒新挖出的区块,就不存在攻击。那么问题的关键在于,如何让从利益或惩罚机制上迫使大家及时广播区块,或者设计一种机制,让被隐瞒的区块不被大家所认可。

为了达成这个目的,我们发明了一种历史见证的机制算法。其原理是让网络中拥有货币最多的若干账户,自愿为广播出的区块hash签名(拥有货币最多的账户会最有足够的利益动机维护系统不被攻击),并加总所有参与见证的账户资金余额,计算出一个“见证值”写入公开广播的链条中。诚实的旷工会尽力将自己的区块广播给这些见证者,取得其见证证明,从而避免自己挖出的区块被回退而白白消耗算力资源。我们用“见证值”来代表一个区块(实际上是一条挖矿路径)被广播的程度(“见证值越高表明广播的越充分”)。当攻击者隐瞒悄悄挖出的链条并在一段时间后广播到全网,这时所有的矿工将对比两条分叉的总“见证值”,并选择“见证值”更大的一条继续挖矿。由于51%攻击的本质特征是隐瞒区块不让大家知晓,从而其“见证值”不可能超过被充分广播的分叉链条,从而让攻击行为不成功。

如上所述,我们引入了一个“见证值”迫使所有挖矿参与者必须及时广播新挖出的区块,避免私下隐瞒挖矿链条,从而用极小的系统开销规避了51%算力攻击的问题。其本质是:PoW算法决定未来,但未来可能有多种情况(分叉),为避免“未来被篡改”,运用资金见证机制(无货币奖励的PoS)确保分叉不可被回退。也就是说,PoW决定未来,PoS决定历史。

这时攻击者要攻击成功,理论上必须同时拥有50%以上的算力资源和50%以上的货币资金。而如果存在一个这样的矿工,其理性的最大得益行为是维护整体系统的安全运行,而不是攻击它从而让自己的利益受损。实际上,一个充分被大家知晓和使用的加密货币,长期来说不会有单个节点同时掌握50%以上的算力和资金,也就不会有事实上的攻击产生。

但是,这个方案的仍然有两个缺陷:

1.见证者除了利益共同体之外,没有货币奖励;
2.见证者需要实时保持在线,从而可能有被攻击盗窃的安全问题。

第一点事实上是有意的设计,因为见证者和矿池之间可以签订私下的利益分配合约,更高效的解决定价问题,从而没必要放在公共协议里消耗共识资源。

第二点风险的规避,需要借助商用签名硬件设备的改进和普及。由于是为区块的哈希签名,是固定不变的结构化数据,硬件设备能很好的处理这种情况,而不能被从外部攻破,从而实时在线又确保私钥安全。

我们在去块头中采用一个 uint16 (两个字节)的数据来储存“见证值”:

type Block_v1 struct {
	// Version   fields.VarInt1
	Height           fields.VarInt5
	Timestamp        fields.VarInt5
	PrevHash         fields.Bytes32
	MrklRoot         fields.Bytes32
	TransactionCount fields.VarInt4
	// meta
	Nonce        fields.VarInt4 // 挖矿随机值
	Difficulty   fields.VarInt4 // 目标难度值
	WitnessStage fields.VarInt2 // 见证数量级别 【表示 2^X 次方的资金量】
	// body
	Transactions []typesblock.Transaction
}

WitnessStage 表示2的指数。

3) 投票选择分叉

理论上说,这不是一个技术保证而是一种威慑。投票的结果也不是强制性的,选择哪一条分叉的权力仍然在全体矿工手里。这里仍然有一个假设的前提:大多数量的矿工和用户仍然诚实且愿意合作维护系统的正常运行。

我们设定将资金长时间锁入通道中的用户是系统的真实有效和利益最相关联的用户,并赋予他们与通道资金等比例的投票权。当系统遭受51%双花攻击时,在10000个区块(约35天)前建立的通道具有投票资格,他们将广播一条投票交易给所有诚实的矿工:

/////////////////  防51%攻击投票  /////////////////
{
    // 用来投票选举链条,呼吁矿工转换到大家公认的链条上来
    // 以通道锁定资金为票数,达到一定票数(矿工决定)才开启转换
    // 以此纠正被 51%攻击的分叉,平时不启动,关键时刻才生效
    // 只有10000个区块(35天)前的有效通道才有资格投票
    kind: 19,
    // 链条必须包含的区块哈希,一般是分叉起始块
    // 必须是本链条历史上已经存在的hash
    targetHash: Buffer.alloc(32),
    // 参与投票的通道列表 id
    channelIds: [
        232353, 
        3847658374,
        874568376455,
    ],
}

诚实的矿工收到若干条以上的交易,并累计总的资金作为票数,当票数达到一个协商的阀值,所有矿工将转换到诚实的链条继续挖矿。

攻击者考虑到就算花费大量算力51%攻击成功,也可能有其他诚实矿工和用户联合投票裁决撤销攻击产生的分叉的风险,导致实际上只有自己认可自己的分叉,无法篡取任何经济利益,从而就不会轻易发动攻击。分叉投票是一种权益威慑,是会损伤自身的核武器。我们应该始终做好风险监控和投票准备,从而让潜在的破坏者无机可乘,但不要轻易使用。

以上办法可以一定程度降低算力中心化、游击挖矿和51%攻击的风险。

5. 价格极端波动

加密货币首先应该是一种商品,其不可避免的将面临相对价格波动,无论是相对于法币还是一篮子商品。但货币作为结算单位和价值储藏的功能,需要通过较稳定的相对价格来保证。

导致加密货币价格极端波动的原因大致有:

1. 新事物的投机狂热
2. 货币增发算法容易引致囤积和炒作
3. 大量货币集中在少数人手里,价格被操控
4. 技术或机制错误导致信心崩溃

其中2、3两点可以通过更合理的新货币发行算法得以规避。我们在设计三个阶段的货币增发机制时,充分考虑了两个目标:1.尽可能让货币分散在大量的个人用户手中;2.货币的增长符合经济规律而避免过度囤积;

我们已经阐述过人为控制发行量,让某些机构负责人自由裁量来保持货币价格稳定的不可行性。除此之外,只能期待其市值成长到足够庞大的规模,能够消化及抵消局部的冲突预期和价格波动,以及借助于期货市场的套期保值。与普通的商品一样,价格波动的风险无法被完全消除,只能依赖于丰富而发达的金融市场进行对冲,虽然这将带来额外的会计成本。

所有的货币都是不完美的,但其中一些能够更有效地工作。

第九章、技术设计原则

1. 简单直观

金融系统软件无法承担软件漏洞带来的损失。特别是在一个开放共享的系统中,没有人为你的损失负责。“智能合约”具备潜在漏洞的风险非常高,使其无法大规模用于金融交易。“智能合约”的另一个更大的问题是,一般人无法理解合约代码中的行为事项,需要始终求助于专业编码技术人员的解释,这极大地限制了其应用场景,将门槛提升到普通人根本无法使用的程度。

对于一个开放共享金融软件系统,我们需要一套标准化、人类可读的指令,从而让无技术背景的使用者轻松理解协议合同的内容细节,并且没有任何潜在的漏洞。其中,人类可理解性的直观程度是关键。

2. 数据紧凑、执行高效

必须权衡好协议的通用性和效率之间的关系,甚至要考虑节省每一个字节的空间和每一条指令的耗时。程序模块体系设计上的优雅在核心关键部分应该让位于效率。

语言设计无比优雅的Lisp计算机和一切皆对象的SmallTalk操作系统双双走向失败,历史选择了充满权衡、妥协和“肮脏实现”的 C 语言和 UNIX 机,其背后的根本原因在于经济学的第一大原则:成本与效率。

3. 公账数据规模可控

将区块空间大小和出块频率提升到一个普通设备无法支撑的程度,这将导致事实上的账本记账权力集中化,从而危害整个系统的安全。

我们需要一个可控的数据增长计划和交易处理计算资源的规模可控,从而确保账本的处理和记录足够去中心化。

4. 签名剥离及数据压缩

经历足够长的时间后(比如一年),区块事实上不能被回退,历史上的交易从而成为了一种无可辩驳的存在。此时我们应该支持将占据区块数据中很大一部分的签名剥离开来,并且压缩交易数据并储存,从而支持在硬件性能或储存空间更低的设备上更新和查询账本。

第十章、结论

我们在此提出了一种可用于大规模支付实时结算的加密货币发行支付系统。首先讨论了通道链结算网络的基础原理和技术实现细节,我们认为一个包含利益激励的全局公账作为最终的仲裁和清算保证,在具备严厉的失信惩罚机制的情况下,能够支撑海量支付在私下顺利进行,从而极大地节省交易费用和信任成本。该系统的特点在于非常合乎经济规律的新货币奖励发放模式,以及严格的资金安全和实时到账保证,并且不依托于任何中心机构。我们充分考虑在成熟商业环境下的分工合作和权益控制,设计了丰富的交易类别和简单直观无潜在漏洞的技术协议。另外论述了货币发行规则、隐私的重要性以及对金融弱势群体的保护,并且讨论了相关可能的风险和防范。本框架包含了一个公平高效可用的电子货币发行体系和大规模支付系统所需要的全部规则和激励措施。

【附录】

1. 参考引用

  1. Adam Back, "Hashcash - A Denial of Service Counter-Measure", http://www.hashcash.org/papers/hashcash.pdf, 2002.
  2. Satoshi Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System", https://bitcoin.org/bitcoin.pdf, 2008.
  3. Ludwig von Mises, "Theory of Money and Credit", https://mises.org/sites/default/files/The%20Theory%20of%20Money%20and%20Credit_3.pdf, 1912.
  4. Friedrich August von Hayek, "Individualism and Economic Order", http://www.library.fa.ru/files/Hayek-Individualism.pdf, 1948.
  5. J.Huerta de Soto, "Money,Bank Credit and Economic Cycles", https://mises.org/sites/default/files/Money_Bank_Credit_and_Economic_Cycles_De%20Soto.pdf, 1997
  6. Joseph Poon, Thaddeus Dryja, "The Bitcoin Lightning Network: Scalable Off-Chain Instant Payments", https://lightning.network/lightning-network-paper.pdf, 2016.

2. 区块数据结构定义示例及注释

3. 部分算法代码

1) X16RS 哈希算法

function X16RS_HASH( prevhash_buf, stuff_buf )
{
    function SHA3_256(a){ return crypto.randomBytes(32) } // suppose
    var hashfuncs = [ // suppose 
        function Blake(a){ return crypto.randomBytes(32) },
        function BMW(a){ return crypto.randomBytes(32) },
        function Groestl(a){ return crypto.randomBytes(32) },
        function Jh(a){ return crypto.randomBytes(32) },
        function Keccak(a){ return crypto.randomBytes(32) },
        function Skein(a){ return crypto.randomBytes(32) },
        function Luffa(a){ return crypto.randomBytes(32) },
        function Cubehash(a){ return crypto.randomBytes(32) },
        function Shavite(a){ return crypto.randomBytes(32) },
        function Simd(a){ return crypto.randomBytes(32) },
        function Echo(a){ return crypto.randomBytes(32) },
        function Hamsi(a){ return crypto.randomBytes(32) },
        function Fugue(a){ return crypto.randomBytes(32) },
        function Shabal(a){ return crypto.randomBytes(32) },
        function Whirlpool(a){ return crypto.randomBytes(32) },
        function SHA512(a){ return crypto.randomBytes(32) },
    ]
    var hashloopnum = hashfuncs.length
    , stephashs = []
    for(var i=0; i<hashloopnum; i++){
        var funcidx = prevhash_buf.readUInt8(31) % hashloopnum
        // console.log(funcidx)
        prevhash_buf = stuff_buf = hashfuncs[funcidx](stuff_buf)
        stephashs.push(stuff_buf)
        // console.log(stuff_buf.toString('hex'))
        // console.log('----')
    }
    stuff_buf =  Buffer.concat(stephashs, hashloopnum*32)
    return SHA3_256(stuff_buf)
}

2) 区块奖励新货币数量

function calcBlockCoinBaseReward(block_height)
{
    var rwdns = [1,1,2,3,5,8,8,5,3,2,1,1] // length must uneven number
    , frix = parseInt(rwdns.length / 2)
    , pos = parseInt(block_height / (10000*10)) // almost 1 year
    // console.log(frix, pos)
    if(pos < frix){
        return rwdns[pos]
    }else if(pos < frix+((frix+1)*10)){
        return rwdns[frix + parseInt((pos-frix)/10)]
    }else{
        return rwdns[rwdns.length-1]
    }
}

3) 区块钻石哈希算法及判定规则

function hash17diamond( buffer ){
    // console.log(str.length)
    if (buffer.length !== 32){
        throw new Error("buffer must be hash256")
    }
    let stuff = '0WTYUIAHXVMEKBSZN'
    , total = 16
    , hhlen = stuff.length
    let diamond = []
    , fv = 0
    for(let step=0;step<total;step++)
    {
        let i = step * 2
        , n1 = buffer[i]
        , n2 = buffer[i+1]
        fv = (fv + n1 + n2) % hhlen
        diamond.push( stuff.charAt(fv) )
    }
    return diamond.join('')
}

function checkDiamond(stuff) {
    let chars = '0WTYUIAHXVMEKBSZN'
    if(stuff.length == 16 && stuff.startsWith('0000000000')){
        var sarys = stuff.substr(10).split('')
        , first = true
        // console.log(sarys)
        while(true){
            var l = sarys.shift()
            , idx = chars.indexOf(l)
            if(!l){
                return first ? false : true
            }
            if(idx==-1){
                return false
            }else if(idx==0){
                if(first){
                    continue
                }else{
                    return false
                }
            }else{
                first = false
            }
        }
    }else{
        return false
    }
}
You can’t perform that action at this time.