比特币源码研读----密钥和地址

1、基本概念

    比特币的所有权是通过数字密钥、比特币地址数字签名来确定的。数字密钥实际上并不存储在网络中,而是由用户生成之后,存储在钱包文件(wallet.dat)或简单的数据库中。存储在用户钱包中的数字密钥完全独立于比特币协议,可由用户的钱包软件生成并管理,而无需参照区块链或访问网络。

    比特币钱包中包含一系列的密钥对,每个密钥对包括一个私钥,和由其衍生出的唯一的公钥。公钥用于接收比特币,而私钥用于比特币支付时的交易签名。数字签名也称为见证(witness),用于支出资金的。

    支付比特币时,比特币的当前所有者需要在交易中提交其公钥和签名(每次交易的签名都不同,但均从同一个私钥生成)。比特币网络中的所有人都可以通过所提交的公钥和签名进行验证,并确认该交易是否有效,即确认支付者在该时刻对所交易的比特币拥有所有权。


2、我们动手体验一下地址的生成过程

//启动单机测试链

./bitcoind -regtest &

//用ethan的钱包,生成一个新的地址

./bitcoin-cli -regtest getnewaddress ethan

//查看地址对应的私钥

./bitcoin-cli dumpprivkey 2MyVDtxTHnoFzPRZ5DhvfeBADfiAjw2JrCp

//查看地址全部的信息

./bitcoin-cli getaddressinfo 2MyVDtxTHnoFzPRZ5DhvfeBADfiAjw2JrCp

比特币源码研读----密钥和地址_第1张图片

address:有效的比特币地址

scriptPubKey:由地址加密后得到的十六进制字符串

script:输出的脚本类型

witness_program:数字签名的十六进制形式

pubkey:原生的十六进制公钥


3、接下来我们阅读一下JSON-RPC接口对应的源码,我的源码版本是0.16.3。

//文件路径:src/wallet/rpcwallet.cpp

//接口名:static UniValue getnewaddress(const JSONRPCRequest& request)

比特币源码研读----密钥和地址_第2张图片
getnewaddress()

前面还对钱包的有效性进行了校验,这里只贴出来后半部分的代码。新建CPubKey类型的对象。

比特币源码研读----密钥和地址_第3张图片
GetKeyFromPool()

调用接口GetKeyFromPool()获取一个公钥,先尝试从密钥池中取预留的key,如果取不到,才会重新生成一个新的。链接钱包数据库,最后会把成功生成的公钥保存在数据库,并刷入磁盘。

比特币源码研读----密钥和地址_第4张图片
MakeNewKey()

GenerateNewKey()中新建了一个CKey类型的对象,我这里走软钱包流程,调用接口MakeNewKey()获取强随机数,随机数通过验证,即有效的私钥。 

比特币源码研读----密钥和地址_第5张图片
GetPubKey()

secp256k1应该就是椭圆曲线算法,secp256k1_ec_pubkey_create()接口中begin()即前面得到的私钥。运算结果校验通过后,返回值即公钥,然后调用接口AddKeyPubKeyWithDB(),将公钥添加到数据库。

LearnRelatedScripts()和GetDestinationForKey()总是在一起使用。前者通过公钥得到数字签名类型和交易脚本,后者对公钥进行hash160签名即双hash运算,得到二进制态的比特币地址。

CTxDestination数据类型包括:CNoDestination、CKeyID、WitnessV0ScriptHash、WitnessV0KeyHash和WitnessUnknown。不同类型对应不同的交易标准,保证节点之间的交易信息能够被识别:CKeyID---P2PKH、CScriptID--P2SH、WitnessV0ScriptHash---P2WSH、WitnessV0KeyHash---P2WPKH

比特币源码研读----密钥和地址_第6张图片
SetAddressBook()

将生成的二进制地址保存下来,EncodeDestination(dest)执行后,将数据还原为我们看到的地址形态。

你可能感兴趣的:(比特币源码研读----密钥和地址)