木蚂蚁小程序

发现更多小程序的乐趣

比太钱包为什么从 Bitcoinj 切换到了 Bitherj ?比太钱包从 Bitcoinj 切换到了 Bitherj原因是什么?

文 / 天曼凝
2018-03-13 10:55

  精品推荐

比太钱包安卓版从v0.0.9开始不再基于Bitcoinj,而是使用了我们自行开发的Java语言比特币协议库Bitherj。这其实是个很无奈的选择,我们也不想“重新发明轮子”,不过没办法,因为“Too Fragile!”(借用Mike Hearn对bitcoind的评价),我们不得不开发一套全新的Bitherj来更好的为比太钱包用户提供服务,这很辛苦,但却值得。


Bitcoinj的问题如下:

1. 架构:

对于SPV轻钱包模型来说,普通用户并不关心整个区块链上的全部交易,而只关心与自己相关的(和依赖的)比特币交易。基于一点,在设计轻钱包架构时,应更多的考虑使用关系模型而非序列化模型存储数据。

但Bitcoinj并没有这么做,Bitcoinj的架构中,无论是缓存的区块链SPV头文件,还是钱包文件,都使用了谷歌自己的序列化方式进行读写,这其实是导致很多问题的根源。

2. 性能:

由于Bitcoinj的架构设计,使得所有钱包文件的读写都必须是通过谷歌的序列化方式全读、全写,这对于只有一个钱包、一个地址且交易很少的用户来说可能还好(出问题的概率会低得多),但对于有多个钱包、多个地址的用户来说,就可能会成为性能“灾难”,钱包越多、地址越多、交易越多,就越是灾难。

另外,由于Confidential模型的设计,使得在每一个新块到来的时候,所有钱包所有地址上的所有交易都需要进行更新,哪怕这个新块与任何一个地址上的任何一个交易都无任何关系,都需要把所有的钱包文件序列化的读到内存中,更新完所有的条目,再序列化的写回文件,这就是Bitcoinj性能问题的根源。

3. 错误:

因架构不合理所导致的性能问题,如果结果仅仅是性能较差,那还算是在可以忍受的范畴。可问题就在于,这种性能瓶颈可能会导致Bitcoinj的各种运行错误,某些情况下,甚至会出现“致命”的后果。

正因为意识到了严重的性能问题,Bitcoinj的作者不得不妥协的设计了两套独立的写文件线程,一套高优先级的写线程用于写入那些比较重要的数据(比如通过广播收到了新交易等),一套低优先级的写线程用于延时同步各个钱包文件与SPV区块头文件。

这使得Bitcoinj的钱包文件读写非常容易出错,经常是钱包文件与块头不一致,钱包文件内的交易之间状态不一致,各个交易的各种状态都频繁的处于正确、错误的来回切换之中,这次写文件没准给写对了,下一个延时的写操作没准又给改错了。

此类问题,对于开发人员来说是非常头疼的,因为你完全无法依赖某一个值是否可靠,你只能尽可能的用其它方式来判断钱包的状态、交易的状态是否正确,如果发现不正确,再想方设法的用绕过Bitcoinj的方式去修改数据甚至是重置区块链数据(ResetBlockchain)。

大部分人对于上述问题可能完全没有任何概念,但MultBit的开发者Jim618应该和我们团队一样,对这些问题深有感触。如果您阅读过一些MultiBit的代码或者比太钱包安卓版v0.0.8之前的代码,就会发现,我们都写了很多方法,专门用来绕过Bitcoinj中可能存在的缺陷,而这些缺陷都是明确的、可复现的、但却几乎不可能在Bitcoinj的架构上解决的(我们团队从MultiBit上借鉴了很多,特此感谢)。

MultiBit和比太都采用了非常多的迂回手段尽可能避开Bitcoinj中的架构陷阱,虽然已经能够在大部分情况下解决很多问题,但还是不能根治。而另一个基于Bitcoinj的安卓手机钱包Bitcoin-Wallet,因为它的单钱包、单地址模型,使得出现此类问题的概率大大降低(该应用的开发者本人甚至可能都不知道Bitcoinj会有这么多问题),开发者选择的解决方案是出现问题时重置区块链数据(ResetBlockchain)。

几个月前曾经发生过的MultiBit找零地址私钥丢失的问题,开发者Jim618也挨了不少骂,但他其实也挺冤的。您如果仔细看看代码就会发现,程序本身是完全不会发生私钥丢死的情况的。问题就在于,该用户有很多钱包文件,每个钱包文件又有很多地址,每个地址上的交易应该也不少,这就会放大各种问题出现的概率,因为会有更多、更慢的钱包文件全读、全写操作,以及频繁的修复数据和偶尔出现的ResetBlockchain操作,这其实才是导致此灾难的根源。

Jim618的最终解决方案是在新版MultiBit中提供了一个检测私钥的功能,我们团队则是在比太钱包v0.0.8及之前的版本中将加密后的私钥在手机ROM中额外备份一份,以保障用户的私钥安全,这都是不得不做的权宜之计。

因为Bitcoinj的架构会导致严重的性能问题,而性能为题又会导致很多“莫名其妙”的错误,小概率事件下甚至有可能会导致“灾难”,最终我们决定,重新设计并开发Bitherj。

Bitherj的架构是关系模型的(基于SQLite数据库引擎)、更稳定、更可靠、更高性能的Java语言比特币协议库,我们会尽可能保持它与Objective-C语言版本的Bitheri保持一致,并且不断改进和发展这两个库。

如果您也是一位比特币钱包开发者,在基于Bitcoinj开发时遇到了很多古怪问题,不妨与我们团队联系,我们在Bitcoinj上所纠结过的“坑”甚至比Jim618还要多,您所遇到的问题我们应该早就遇到、并尝试解决过,我们团队之前的经验应该能对您有所帮助。

如果您是位普通用户,您应该了解修复交易数据和重置区块链发生的原因,并保管好您的私钥。毕竟对于比特币来说,私钥意味着一切。

感谢您的阅读!

木蚂蚁小程序

发现更多小程序的乐趣