如果有人想发送比特币给你,或者你从别人那里买几个比特币,就要把地址给对方,对方才能把币打到你指定的地址上。那么,讲解才能拥有一个地址呢,下面的我们就来讲讲这个问题。
比特币核心提供了很多 RPC 来供客户端调用,其中一个就是我们这里要讲的 生成一个新的地址,通过这个 RPC ,我们就可以生成一个新的地址,有了这个地址,别人就可以给我们转账了。
RPC 可以接收两个参数,第一个地址的标签,第二个是地址的类型。如果没有提供标签,那么默认的标签就是空,地址的类型当前支持:legacy、p2sh-segwit、bech32,默认类型由 参数指定,当前为 p2sh-segwit。
如果我们想看下这个 RPC 的帮助文档,可以执行如下的命令:
就会显示帮助信息
这个 RPC 对应的方法实现位于 文件,方法名称就是 RPC 名称,下面的我们来看这个方法。
方法内部实现如下:
- 调用 方法,从请求对象中取得钱包的名字,如果用户指定了钱包名字,那么把钱包名字保存在参数 上,并返回真,否则返回假。
- 如果可以获得用户指定的钱包名称,则调用 方法,从钱包集合 中取得指定的钱包,然后返回钱包。
- 如果用户没有指定钱包或指定的钱包不存在,那么调用 方法,返回钱包集合 。如果钱包集合中只有一个钱包,或者在用户指定了帮助的情况下,至少有一个上面这些的钱包,那么返回第一个钱包,即默认的钱包。默认钱包在系统启动时候创建的。
填充密钥这个方法,我们前面已经讲过,这里只简单友们下,不做详细分析。因为在衍生子钥的过程中,、 已经完全填充完了,所以导致 、 两个变量都为 0,从而不会重新再次衍生子密钥,所以实际上本方法在这里基本没有执行,而直接返回真。
方法,我们在下面的详细讲解,此处略过。
- 调用 方法,生成 对象。
- 调用 方法,获取对应的脚本。
方法内部调用 ,以访问者模式来根据不同的 id,获取其对应的脚本对象。
对象继承自 对象,实现了访问者模式,并通过重载 操作符来定义不同类型的 id。
- 如果目标参数类型是 ,则调用脚本对象的 方法,清除脚本内容。
- 如果目标参数类型是 ,则:首先调用脚本对象的 方法,清除脚本内容;然后,初始化脚本 。
- 如果目标参数类型是 ,则:首先调用脚本对象的 方法,清除脚本内容;然后,初始化脚本 。
- 如果目标参数类型是 ,则:首先调用脚本对象的 方法,清除脚本内容;然后,初始化脚本 。
- 如果目标参数类型是 ,则:首先调用脚本对象的 方法,清除脚本内容;然后,初始化脚本 。
- 如果目标参数类型是 ,则:首先调用脚本对象的 方法,清除脚本内容;然后,初始化脚本 。
- 调用 方法,保存脚本对象。 方法,首先调用 方法,把脚本保存到 key store 的 集合中;然后,调用数据库访问对象的 方法,以 为键把脚本保存到数据库中。
- CNoDestination没有目的地设置
- CKeyIDP2PKH 目的
- CScriptIDP2SH 目的
- WitnessV0ScriptHashP2WSH 目的
- WitnessV0KeyHashP2WPKH 目的
- WitnessUnknown未知目的 P2W?
方法,使用 表达式来根据不同的地址类型,生成不同的目的 。
- 如果地址类型是 ,则直接返回公钥的 。内部把公钥的数据通过 SHA256 和 RIPEMD160 双重哈希之后,构造一个 对象。
- 如果地址类型是 ,或 ,则处理如下:
- 如果公钥不是压缩的,处理方法 。
- 否则,生成 对象,然后调用 方法,获取对应的脚本,最后根据不同的地址类型生成的目的。
对于默认的、不传地址类型的情况,就会返回 类型的 ,这个返回值在下面的两步中都会用到。
方法执行如下:
- 从 集合中,取得对应的目的数据。
- 根据集合中是否有对应的数据设置变量是否为更新。
- 把标签保存为地址对应的 的 属性。
- 如果参数 不空,则更新地址对应的 的 属性。
- 调用数据库访问对象的 方法,保存参数 到数据库中。
- 调用数据库访问对象的 方法,保存地址到数据库中。
为用户提供的标签。 方法,我们在下一步讲解。
- 调用当前网络参数的 方法,返回脚本前缀。
对于主网络前缀是 5,测试网络是 196,回归测试网络是 196。
- 把当前 20 个字节的数据加在前缀后面形成 21 个字节的字符串。
- 调用 方法,编码成 Base58Check 格式,并返回其值。
下面的,我们来看下 这个方法的处理。它的内部执行流程如下:用 21 个字节的字符串生成一个向量,同时调用 方法,生成一个 32 字节长的哈希字符串;然后把其最前面的 4个字节作为校验各加在 21 个字节的向量尾部,从而生成一个长度为 25个字节的字符串;最后,调用 方法,进行 Base58 编码。
在 这个方法中,使用了双重 SHA256 哈希算法。 这个方法,读者可以自行阅读,这里不再展开。
本方法从密钥池中生成一个公钥。第一个参数为公钥的引用,第二个参数 ,默认为假。
内部逻辑如下:
这个方法,在创建钱包过程中,我们已经重点分析,这里不浪费口舌,我们重点看下 方法。这个方法的执行流程如下:
- 生成一个公钥,并设置为密钥池的 属性。
- 如果钱包没有被锁,则填充密钥池。
这个方法,我们也讲过,这里直接略过。
- 如果钱包启用了 HD,并且可以支持 HD 分割,并且参数 为真,则设置变量 为真。在调用本方法时,这个参数没有指定,而默认为假,所以变量 设置假。
- 根据集合 是否为空,设置变量 的值。因为这里 集合为空,所以变量 为真。
- 根据变量 、 确定从哪个集合中获取密钥池对象。根据上面分析,我们最终会从 集合中取数据。
- 如果要数据的集合为为空,则返回假。
- 生成数据库访问对象。
- 从 取得其第一个元素,并从集合中删除它。
- 从数据库取得索引对应的密钥池。如果失败,则抛出异常。
- 从密钥池中取得公钥对应的 ID,并且检测其是否在 、或 集合之一,如果不在,则抛出异常。我们在创建钱包过程时候讲过,生成的私钥根据是否加密会保存在这两个集合之一。
- 如果变量 为真,并且密钥池的 属性不等于变量 ,那么抛出异常。
- 如果密钥池中保存的公钥是无效的,那么抛出异常。
- 从 集合中消除对应的索引。
- 返回真。
由于本人水平所限,文中错误在所难免,欢迎您踊跃指出错误,在下感激不尽。我的微信联系方式:joepeak。
本文采摘于网络,不代表本站立场,转载联系作者并注明出处:http://www.fjxmta.com/chanye/jieneng/45415.html