比特币源码解读-第5章
五、地址管理
5.1 密钥管理
用户公私钥随钱包地址存储在钱包数据文件wallet.dat文件中。
判断默认的vchDefaultKey是否在mapKeys中,如果在,则对应的公钥和私钥保存在keyUser结构中。否则创建一个新的keyUser, 并以名称为“Your Address”保存到向量向量mapAddressBook中;同时写入配置文件wallet.dat中。
if (mapKeys.count(vchDefaultKey))
{
// Set keyUser
keyUser.SetPubKey(vchDefaultKey);
keyUser.SetPrivKey(mapKeys[vchDefaultKey]);
}
else
{
// Create new keyUser and set as default key
keyUser.MakeNewKey();
if (!AddKey(keyUser))
return false;
if (!SetAddressBookName(PubKeyToAddress(keyUser.GetPubKey()), "Your Address"))
return false;
CWalletDB().WriteDefaultKey(keyUser.GetPubKey());
}
5.2 钱包地址
5.2.1 密钥初始化:比特币系统中用于签名验签、加密解密操作的非对称密码算法为基于openssl加密库实现的ECC-secp256k1椭圆曲线密码算法。密钥相关操作在key.h文件中实现。
CKey key;
key.MakeNewKey();
5.2.1.1 实例化密钥对象:CKey key;
//实例化EC_KEY
EC_KEY* pkey;
//调用OpenSSL的EC_KEY_new_by_curve_name初始化key
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
5.2.1.2 初始化密钥:key.MakeNewKey();
//生成公钥与私钥并填充到Key中
EC_KEY_generate_key(pkey);
5.2.2 将密钥添加到全局变量:AddKey(key);
bool AddKey(const CKey& key)
{
//mapKeys保存公钥与私钥之间的对应关系
mapKeys[key.GetPubKey()] = key.GetPrivKey();
//mapPubKeys保存公钥哈希与公钥之间的对应关系
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
//将公私钥写入钱包文件wallet.dat
return CWalletDB().WriteKey(key.GetPubKey(), key.GetPrivKey());
}
5.2.2公钥生成地址
5.2.2.1PubKeyToAddress()函数在base58.h文件中实现
inline string PubKeyToAddress(const vector<unsigned char>& vchPubKey)
{
return Hash160ToAddress(Hash160(vchPubKey));
}
5.2.2.2 其中hash160()函数在util.h文件中实现
inline uint160 Hash160(const vector<unsigned char>& vch)
{
//首先SHA256函数取哈希值
uint256 hash1;
SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
//接下来RIPEMD160函数取哈希值
uint160 hash2;
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
return hash2;
}
5.2.2.3 Hash160ToAddress()函数在base8.h文件中实现
inline string Hash160ToAddress(uint160 hash160)
{
//在地址前加一个四字节的版本号,值为1
vector<unsigned char> vch(1, ADDRESSVERSION);
vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160));
//通过base58编码校验公钥哈希,得到钱包地址
return EncodeBase58Check(vch);
}