BitcoinSPV
BitcoinSPV是一个用Objective-C编写的本机比特币SPV(简单支付验证)客户端库,适用于iOS。它方便地支持Bloom过滤器(BIP37)和分层确定性钱包(BIP32)。
BitcoinSPV仍然是实验性的,您现在绝对不希望在生产环境中使用它。
结构
该库功能全面,具有高度的粒度来隔离比特币协议的细微部分。许多原子类以 tiny 的步骤组成整个系统,同时将用户从不需要关注的领域解耦,因为文件之间的依赖性保持在最低。
按区域分组
-
全局
- 比特币生态系统的常量值。
- 与比特币无关的特定库设置。
- 在由库返回的
NSError
对象中找到域和代码。 - 有用的宏,用于频繁操作。
-
参数
- 在这里您可以找到特定于网络的小魔数和参数。
-
核心
- 通用二进制数据(序列化/反序列化)(WSBuffer)。
- 用于所有交易和区块ID、地址、校验和等的哈希(WSHash256、WSHash160)。
- ECDSA密钥包装器,能够导入WIF私钥(WSKey、WSPublicKey)。
- 脚本,是比特币交易系统的关键部分(WSScript)。
- 事务家族类可以帮助您解码二进制交易或从输入、输出和密钥构建/签名您的个人交易(WSTransaction)。
- 地址只是以更简短的方式可视化交易脚本,支持所有标准形式(P2PK,P2PKH,P2SH)(WSAddress)。
- 对BIP32 HD钱包的大量实现(WSHDKeyring)。
-
区块链
- 在网络数据中看到的完整区块,标题和交易之间有清晰的分隔(WSBlockHeader,WSBlock)。
- 经过部分默克尔树验证的(默克尔)区块(WSFilteredBlock,WSPartialMerkleTree)。
- 用作跟踪和保存区块的区块链存储(WSMemoryBlockStore)。
- 执行所有区块连接逻辑、验证和重组的区块链商业包装器(WSBlockChain)。
-
协议
- 几乎在这里定义了所有协议消息,每条消息一个类。
- BIP37定义的布隆过滤器(WSBloomFilter)。
-
网络
- 进入P2P比特币网络(WSPeerGroup)。
- 从网络上下载区块链(WSBlockChainDownloader)。
- 在处理多个对等方时连接池(WSConnectionPool)。
- 使用布隆过滤器进行低带宽使用的区块链SPV同步。
-
钱包
- 通用钱包表示。
- 完全符合BIP32的HD钱包(WSHDWallet)。
-
货币
- 帮助进行货币转换的类(WSCurrency)。
- 比特币货币变体(比特币、毫比特、聪)(《WSBitcoinCurrency》)。
-
Web
- 借助第三方网络服务完成的有用操作。
- 提供方的探索类(《WSWebExplorer》)。
- 股票类和统一价格监控(《WSWebTicker》,《WSWebTickerMonitor》)。
- 清扫外部私钥(例如,纸钱包),无论是纯文本还是密码加密(BIP38)。
-
BIPS
- BIP21:“bitcoin:” URL的解析和构建。
- BIP32:分层确定性钱包。
- BIP37:快速区块链同步的布隆过滤器。
- BIP38:密码保护的私钥。
- BIP39:确定性密钥的助记词。
- BIP44:确定性钱包的多账户分层。
安装
BitcoinSPV依赖于四个知名的库
由于出色的CocoaPods实用工具,设置很简单。我通常在iOS 7上测试软件,但所有内容都应该在6.x版本上运行良好。
Podfile
添加以下行
pod 'BitcoinSPV', '~> 0.7.1'
并在终端上运行
$ pod install
请注意,CocoaPods的一些最新版本可能会破坏静态链接,除非您从Pods/Pods.*.xcconfig
配置文件中删除以下行。
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
导入
所有导入均为公开,但是您通常需要的导入是#import "BitcoinSPV.h"
。
测试
BitcoinSPVTests
目标附带一些自动化测试。它们并不完全测试所有库功能(特别是网络区域),但它们确实是为了成功所需。单次失败保证某些内容已损坏。
一些测试将在iPhone模拟器的全局Library/Caches
中写入文件。您可以在BitcoinSPVTests
子目录下找到它们。
基本用法
熟悉bitcoinj的开发者可能会记得以下代码片段中的某些类名。
创建新钱包
#import "BitcoinSPV.h"
- (void)createWallet
{
WSParameters *parameters = WSParametersForNetworkType(WSNetworkTypeTestnet3);
WSSeed *seed = [[WSSeedGenerator sharedInstance] generateRandomSeed];
// now's the time to backup the seed somewhere, show it to the user etc.
id<WSBlockStore> store = [[WSMemoryBlockStore alloc] initWithParameters:parameters];
WSHDWallet *wallet = [[WSHDWallet alloc] initWithParameters:parameters seed:seed];
WSBlockChainDownloader *downloader = [[WSBlockChainDownloader alloc] initWithStore:store wallet:wallet];
WSPeerGroup *peerGroup = [[WSPeerGroup alloc] initWithParameters:parameters];
[peerGroup startConnections];
[peerGroup startDownloadWithDownloader:downloader];
// strongly retain peer group
self.peerGroup = peerGroup;
}
恢复现有钱包
#import "BitcoinSPV.h"
- (void)restoreWallet
{
WSParameters *parameters = WSParametersForNetworkType(WSNetworkTypeTestnet3);
WSSeed *seed = WSSeedMakeFromISODate(@"enter your bip39 mnemonic seed phrase", @"2014-02-28");
id<WSBlockStore> store = [[WSMemoryBlockStore alloc] initWithParameters:parameters];
WSHDWallet *wallet = [[WSHDWallet alloc] initWithParameters:parameters seed:seed];
WSBlockChainDownloader *downloader = [[WSBlockChainDownloader alloc] initWithStore:store wallet:wallet];
WSPeerGroup *peerGroup = [[WSPeerGroup alloc] initWithParameters:parameters];
[peerGroup startConnections];
[peerGroup startDownloadWithDownloader:downloader];
// strongly retain peer group
self.peerGroup = peerGroup;
}
概述
网络参数
比特币节点可以运行在三个网络之上
- 主网络:这是真实世界的网络,其中的币具有真实价值。
- 测试网络3(Testnet3):测试币非常难以挖掘,但价值微乎其微。存在在线 水龙头(faucets) 以获取测试币。
- 回归测试网络(Regtest):在regtest网络上挖掘时间微不足道,因此非常适合测试手动构建的区块链。
大多数初始化器依赖于网络参数,您可以使用以下代码获取参考
// networkType must be one of: WSNetworkTypeMain, WSNetworkTypeTestnet3, WSNetworkTypeRegtest
WSParameters *networkParameters = WSParametersForNetworkType(WSNetworkTypeTestnet3);
...
警告:在主网络上运行可能会花费您真实金钱,确保您知道自己在做什么!
助记词
BIP39 提供了关于如何将人类可读短语(助记词)生成用于HD钱包的二进制种子的特殊提示。BitcoinSPV在 WSSeedGenerator
类中实现了BIP39规范,可用于
- 生成随机助记词。
- 将助记词转换为二进制数据。
- 将二进制数据转换为助记词。
- 从助记词派生关键数据。
然而,在BitcoinSPV中,助记词通常封装在包含助记词首次创建时间的 WSSeed
对象中。通过指定这样的时间(称为“快速追赶时间”),可以显著加快链同步速度,因为首次找到的区块不会包含对我们的钱包相关的交易,可以安全地跳过。
分层确定性钱包
分层确定性钱包在 BIP32 中进行了描述。在BitcoinSPV中,它们是WSHDWallet
类的实例,并从具有可选间隙限制的 WSSeed
对象构建而成(默认为10)。另外,还内部预生成了额外的预览地址集,以防止每次新事务消耗一个新地址时重新加载Bloom过滤器。
值得注意的是,种子助记词是极其敏感的信息——技术上门户可以持有您所有的硬币——因此,它不会通过 [WSWallet saveToPath:]
方法序列化:这意味着您必须将其存储在其他地方,例如密钥链中。助记词将对于以后使用 [WSHDWallet loadFromPath:parameters:seed:]
方法恢复序列化的钱包至关重要。
块存储
实现 WSBlockStore
协议的类负责序列化区块链。目前有一个实现:《WSMemoryBlockStore》。名称本身就非常通俗易懂。
对等组
WSPeerGroup
类包含连接到比特币网络的全部逻辑,是主要的事件通知源。一个组可以同时连接到多个节点,强制限制连接节点的数量并将区块链下载到块存储中。与钱包一起构建时,也会将相关区块和交易转发给钱包。钱包反过来将它们注册并内部更新其历史记录、未使用输出(UTXOs)、确认信息等。
最后但同样重要的是,与网络的关键交互显然是如何发布交易。不出所料,这是通过 publishTransaction:
方法完成的。
洞察力
字节序
比特币结构通常是小端字节序,一个例子后果是交易和区块哈希在十六进制编辑器中的“反转”与我们看到的像 Blockchain.info 这样的网络区块链探索器相比。尽管如此,还是有一些例外,因为网络地址保留了标准的大端字节序。是的,这一切都使得二进制编码非常容易出错。
这就是为什么 BitcoinSPV 将编码内部封装在 WSBuffer
和 WSMutableBuffer
类中。使用缓冲区类,你可以安全地读取/写入任意字节或基本结构,如哈希、网络地址、库存等,而不必担心协议字节序。
不变性
BitcoinSPV依赖Grand Central Dispatch,这意味着大部分代码都将在多个队列上运行以实现最佳性能。为了限制整体复杂性,我尽量将可变对象的的使用降到最低。不可变方法大大简化了关键部分,并免费保证了序列化数据的一致性。没有Core Data实体是可变的,区块链相关结构通常也不是。想想看,修改一个已接受的区块甚至违背了协议的初衷。
安全
敏感数据永远不会自动序列化,这样客户端就能通过其他更安全的方式保存它们。例如,HD钱包的交易和地址可以安全地写入文件,而秘密助记符则值得更多注意。您可以将它加密保存在密钥链中,也可以从服务提供商处获取并加解密,甚至可以决定完全不离保存。实际上,在保存助记符安全性方面拥有完全的自由。
已知问题
BitcoinSPV仍然是一个正在进行的项目,最终将经历巨大的修改。还剩下一些基本事物要做,按优先级排序:
- 构建多重签名交易(支持不完整)。
- 实现如BIP70/BIP71/BIP72/BIP73所描述的支付协议。
- 通过跟踪对等信心提高SPV安全性。
- 支持带静态密钥的基本钱包。
- 处理Core Data版本。
许可
BitcoinSPV遵循GPLv3许可发布。
基本上,那些希望将比特币SPV用于其软件中的人们被迫发布他们的源代码,因为其整个目的在于尽可能使与比特币相关的软件保持透明,以增加信任和社区贡献。
只要遵循这个经验法则,就没有更多的义务,仍然会在致谢中注明会让人感到高兴。
致谢
- bitcoinj - 最受欢迎的Java比特币库。
- breadwallet - 针对iOS的开源比特币钱包。
- bip32.org - 用于JavaScript的确定性钱包。
免责声明
开发者不对因比特币SPV的正常使用或错误造成的金钱损失或任何损害承担责任。自行承担责任。
联系方式
Twitter: @keeshux
网站: davidederosa.com
捐款
BitcoinSPV是免费软件,捐款非常受欢迎。
比特币地址:16w2AWamiH2SS68NYSMDcrbh5MnZ1c5eju