区块链数据“全球一致”和“难以篡改”的特性已经广为人知,它们是区块链创造“信任”的基石。为了实现这两个效果,区块链的共识、同步、验证等技术细节足以写一本书,本文将从“我篡改了区块链数据”开始。“我篡改了区块链数据。”FISCOBCOS开源联盟链社区现在相当活跃,每天都有很多讨论。大家也会有兴趣研究和挑战区块链如何做到“难以篡改”。我们注意到,尤其是在FISCOBCOS支持MySQL数据库作为数据存储引擎之后,一段时间后,有同学在群里提问:“我手动修改了我节点连接的数据库中的某个状态数据,这只是篡改吗?”区块链数据呢?”直观来说,比如链上有智能合约管理某个特定资产的余额,在数据库合约表中,Alice共识后的余额本来是100,有人打开MySQL客户端。找到那个合约对应的表,把Alice的余额更新为10000。这时候他说:“你看,我调用了合约的查询接口,发现Alice的余额确实是10000,这是错误的。而且链上还在生产区块,根本就不是防篡改的!”初步分析及解答为什么最近这类问题越来越多?我们分析猜测,主要原因是MySQL数据库拥有良好的用户基础以及相对成熟的系统,为用户提供友好的命令行或图形交互工具,FISCOBCOS提供了表式合约开发模型,表结构设计清晰直观,对于用户来说,一方面更容易理解和管理,另一方面,更新甚至删除它都是微不足道的。下图只是一个示例数据。使用KVTable合约方法,创建一个名为t_kv_node的合约表。系统自动添加前缀u_。它可以可以看出表结构和数据一目了然,之前只有LevelDB或者RocksDB作为存储引擎,这两个文件型数据库的交互工具比较少,没有一个在用户面前存在感强,操作相对隐蔽。它们主要通过API编程来访问。地址,手动修改数据库的情况较少(但不是不可能)。所以热点问题浮出水面,前提是用户可以更方便的修改底层数据,而不是之前不存在这个问题。这时候我们会建议用户试用,对Alice的余额发起交易,比如给Alice充值,或者让Alice转账。此时,修改数据的节点将无法参与共识。因为Alice在这个节点上计算出的余额和其他节点的结果不一样,所以其他节点还是用100的余额来计算,而不是10000,显然结果是不对齐的。回顾PBFT的容错模型:定义f为容错节点数,网络中共识节点总数应等于或大于3f+1。即当链上有4个共识节点时,容错f=1;当共识节点总数为7时,f=2,以此类推。如果数据未修改的节点数满足PBFT要求的2f+1个数,链仍然可以出块。但是,修改节点一旦发生涉及脏数据的交易,就如同踩了雷,将无法再与链上达成共识和同步,相当于被抛弃。这样的节点可以称为“拜占庭节点”,即作恶或犯错的节点。具有节点访问控制能力的联盟链甚至会隔离拜占庭节点。还有一种可能是数据库中的数据被人为修改了,但是节点内存中只是缓存了一份,并没有被修改过,所以通过节点查询和交易这些数据还是正常的,甚至使用正确的结果是覆盖数据库中被篡改的数据,但这是一个概率事件,取决于缓存的大小和当时包含的数据项。*注:对于使用PoW或其他共识机制的链,容错模型不同,但如果在容错范围内的少数节点被篡改,不会影响链的共识。“整个联盟链可以被篡改吗?”可能有同学会继续问:“那我修改几个节点的数据,会不会被篡改?”一般问这个问题的同学都是面向自己部署的开发测试环境的。所有节点都在他手上,可以随意更改。在真实的联盟链环境中,节点掌握在不同的组织手中。要修改它们,必须先侵入别人的网络,获得服务器和数据库权限,发起修改,然后彻底撤退。事实上,在注重安全保护的商业环境中,这是非常困难的,几乎是不可能的。从机构粒度来看,单个机构掌握的节点数量应该低于容错共识算法的数量。比如链上共有7个共识节点,那么单个组织的共识节点不要超过2个,这样可以防止组织强行修改自己拥有的节点数据,或者一个组织的所有节点不小心去错误或掉线(比如机房光纤被挖掉),导致链无法出块。真的没有办法防止“局部篡改”吗?考虑区块链数据本地验证的机制,如区块间的Hash关系、状态的Merkle树结构、共识节点的签名等,根据数据的相互验证关系进行检测,它似乎有一定概率可以在本地检测到数据异常。但进一步思考,对于某个数据的查询,区块链本地的验证范围是有限的,一般不会超过单个区块或Merkle树,所以如果篡改者对区块链数据的结构比较熟悉并且本地的验证逻辑也可以遵循数据验证关系,从状态值开始,改变所有的Merkle树和区块Hash等关键数据。更彻底的,从创世块开始,改变所有的块,系统配置(对于PoW,可以修改挖矿难度来加快出块速度),PBFT共识列表等等,按照他的逻辑,这样,这个本地数据链仍然是经过验证和自洽的,但无法与其他节点达成共识。这种修改听起来很费力,但对于一个有决心有能力的篡改者来说,修改本地数据其实并不难。难点在于修改其他组织的数据。为此,就相当于一个人决心要“自欺欺人”,连神明都没有办法。一旦修改本地数据的权限给了不合适的人,最坏的情况下,整个链条没有一个字节是正确的。但是,本地数据再错误,也只会影响到你,不会影响到其他人。一旦与其他节点达成共识,就会被发现甚至受到惩罚。整个效果会有点欺骗。“为什么区块链不能阻止我篡改数据?”更进一步,学生又会问:“为什么区块链不能立即发现并阻止我篡改数据?也许我只是不小心弄错了。”坦率地说,这对区块链的期望有点过高。区块链系统不是万能的,它不会无所不能。区块链不会阻止用户对自己的服务器、软件、数据库等进行强加操作,就像法律不能也不应该阻止你在家里打破杯子一样。本质上,区块链的一致性和篡改难度是面向“全球形势”,通过多方博弈和协作实现的。当链上交易涉及错误数据时,共识机制可以检测并拒绝被篡改的数据。确保链上大部分剩余的健康节点继续以共识方式生产区块。但本地节点不参与共识数据,共识机制遥不可及。那么,区块链为什么不能主动检测和纠正错误,保证各个节点上的数据一致性呢?首先,链上数据非常复杂。用户直接登录数据库手动修改少量数据。区块链节点不知道哪些数据被修改了,无法触发校验。如果区块链系统定期检查所有数据,并将所有数据与其他节点进行比较,可想而知,网络、磁盘和计算开销将非常大。关键是这并没有解决问题,因为即使脏数据在数据被篡改到被检测到的时间窗口中只存在几十毫秒,如果有不幸的应用程序查询此时,仍然会得到被篡改的数据。结果。对于要求高的业务来说,事后检测未必是最好的选择,因为业务损失可能已经造成,那时候能做的最多就是预警和纠正。当然也可以结合数据库运行监控、binlog等辅助机制来加快响应速度和检测效率。方法还是有的,就是上面说的,但是比较划算,并不能彻底解决问题。只有在数据修改极其敏感,业务接受延迟发现和修改的特定场景下,才会考虑作为补救措施。我们将这部分归类到运营管理工具中,根据场景需求实现。还有另一种方法可以部分解决查询问题:f+1查询。即在查询数据时,无论是查询区块数据还是合约状态数据,都不妨多查几个节点,查询节点的个数要多于f。例如,当链上有7个节点时,f=2,用户除了查询自己的节点外,还继续发送网络请求查询其他组织的2个节点,一共查询了3个节点。如果得到的数据是一致的,那么说明数据一定是正确的,否则,这三个节点肯定有问题。但是,要进行f+1查询,前提是其他机构开通了查询接口权限,让你连接查询。在很多安全保护严格的联盟链上,一般只开放节点间P2P互联的网络端口,不会轻易向其他组织提供数据查询权限。此外,在网络上发起多次查询,其异步性、时效性、成功率、性能等都会带来更多变数。综上所述,对于节点的本地数据,就像打地鼠一样,topones(发送交易参与共识,或者进行f+1查询),节点的全局共识和容错机制区块链是可以找到的,没有top的,只是蹲在用户的硬盘里,只有用户负责。结论区块链通过网络博弈和多方验证实现全网的容错和防恶,而区块链同步提供给各节点的本地数据需要用户妥善管理和存储。从信任传递的角度来看,首先,用户要“信任自己”。如果他们连自己都不能相信,那就说明系统和数据管理都存在漏洞,更别说修改数据了。在本地系统的整个链路上,包括区块链软件、SDK、业务服务都有可能出错,篡改欺诈。在这样的环境中怎么会有信任?节点持有者必须非常谨慎,首先不要手痒或误改数据,其次关键是建立一个完善的体系,包括管理策略和技术保护,如主机访问控制、数据库登录和操作权限控制、操作审计、日志审计等,防止组织内人员访问、守护、窃取或被外界渗透。在数据错误的情况下,区块链比中心化系统更好,因为它可以通过与其他节点的相互验证来检测。这时候要进行告警、查证、纠错、问责,条件和条件,用好f+1查询方式,为查询操作加一点保险。另外,建议定期将节点数据备份到安全的离线设备,这样无论出现意外还是人为的数据问题,仍然可以从冷数据中快速恢复,保证一定的RTO(Recovery时间目标)和RPO(恢复点目标)。区块链的健壮性在于无论单个角色如何折腾自己的节点和数据,都不会影响全局,损坏的只是修改器本身。即使巢穴倒转,链条依然风平浪静,其“全球一致”和“难以篡改”的规律依然成立,链条依然是信任的锚点。这就是区块链的魅力。
