比特币源码阅读(1)--杂记与加密部分(爽之小刀)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lihn1987/article/details/80044546

比特币源码阅读(1)–杂记与加密部分(爽之小刀)

欢迎转载和引用
若有问题请联系请联系
Email : [email protected]
QQ:2279557541


最近从成都来到了杭州拼一枪
由于老婆为了圆自己的一个大公司梦来到了杭州
而我也很坎坷
经历了
创业(自动化行业,非创始人),然后虽然上了新三版,但是手里的股票和废纸一样没办法交易。
打工(被老板欠薪),老板每月要给我降薪1w,我只能选择辞职,但是去年的钱老板还差我7,8w的样子,我问他要,他说要我继续维护公司代码,维护至少1年才可能给我。。。这。。。唉~~~~~
为了实现财富自由,我来到了杭州,一方面离老婆近点,一方面,为了财富自由拼一枪吧。
我进入了区块连开发这行!
开始找了很多公司都不要我,也许我要的薪资太高了,我要的3w,但是我发现我太高看自己了。。。根本没人愿意这个价格招我这个小菜鸟。。。不过既然来了杭州就不能灰头土脸的走。
终于有一家公司愿意要我了,做的公链,发币的(我心中也觉得只有公链才有前景),和我的想法不谋而合,而且薪资也不低,够我活下去了,和老板(相当年轻,惭愧啊)在星巴克聊了办小时,一拍即和!就这么定了!不过公司刚起步,私募貌似刚完成,公幕刚开始。我是第一个过来的研发。。。还有个哥们经验比我丰富些,但是区块连完全没接触过,不过他经验丰富,希望用rust来开发,那我当然不会抗拒了,毕竟多学门手艺也是件好事!

于是想让大哥带我的想法就这么泡汤了。。。不过竟然这么多人都能做公链,我相信我也不会有多大问题,我们要做一个基于dag的共识,花了1周基本理解了dag链的构架!
现在我打算写加密部分,不二选读懂比特币,然后抄思想,改代码,翻译成rust,毕竟刚起步,创新什么的等到第一版出来再说吧!
下面不如正题,我第一个看的是比特币的key.cpp和key.h这两个文件
cpp没啥好说的先看h文件,看懂整个思路,在研究cpp的算法部分。
我现在最关心私钥-》公钥-》地址是怎么回事。。。
翻遍了google,没人是继续代码说这个事情的,只有自己来了

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H

#include <pubkey.h>
#include <serialize.h>
#include <support/allocators/secure.h>
#include <uint256.h>

#include <stdexcept>
#include <vector>


/**
 * (PRIVATE_KEY_SIZE bytes)
 * CPrivKey是一个包含了所有参数序列化后的一个私钥,包含了所有参数的私钥长度为PRIVATE_KEY_SIZE。
 */
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;

/** An encapsulated private key. */
class CKey
{
public:
    /**
     * 定义两个静态的大小用来表示普通私钥的长度和压缩后私钥的长度
     */
    static const unsigned int PRIVATE_KEY_SIZE            = 279;
    static const unsigned int COMPRESSED_PRIVATE_KEY_SIZE = 214;
    /**
     * 压缩后的私钥必须要比压缩前小,这是合理的要求了,使用static_assert表示是在编译时检查的
     */
    static_assert(
        PRIVATE_KEY_SIZE >= COMPRESSED_PRIVATE_KEY_SIZE,
        "COMPRESSED_PRIVATE_KEY_SIZE is larger than PRIVATE_KEY_SIZE");

private:
    //!用于表示私钥是否有效
    //! 因为每次key被修改的时候都会做正确性判断,所以fValid应该和真实的状态保持一致。
    bool fValid;

    //! 表示对应私钥的公钥是否被压缩
    bool fCompressed;

    //! 实际的私钥16进制数据。
    std::vector<unsigned char, secure_allocator<unsigned char> > keydata;

    //! Check whether the 32-byte array pointed to by vch is valid keydata.
    //! 判断vch指向的32字节数据是否是有效的密钥数据???密钥?私钥?公钥?
    bool static Check(const unsigned char* vch);

public:
    //! 构造函数,其实啥也美感,就是设置keydata的长度为32
    CKey() : fValid(false), fCompressed(false)
    {
        keydata.resize(32);
    }

    //! 重载==符号,只要密钥数据一致,是否压缩也一直,就表示两个CKey数据相同
    friend bool operator==(const CKey& a, const CKey& b)
    {
        return a.fCompressed == b.fCompressed &&
            a.size() == b.size() &&
            memcmp(a.keydata.data(), b.keydata.data(), a.size()) == 0;
    }

    //! 设置密钥的内容,并通过check判断是否为有效密钥
    template <typename T>
    void Set(const T pbegin, const T pend, bool fCompressedIn)
    {
        if (size_t(pend - pbegin) != keydata.size()) {
            fValid = false;
        } else if (Check(&pbegin[0])) {
            memcpy(keydata.data(), (unsigned char*)&pbegin[0], keydata.size());
            fValid = true;
            fCompressed = fCompressedIn;
        } else {
            fValid = false;
        }
    }

    //! 这块是简单的加了几个方法,能让CKey像一个vector一样用,但其实也不是完全vector毕竟他没有重载[]
    unsigned int size() const { return (fValid ? keydata.size() : 0); }
    const unsigned char* begin() const { return keydata.data(); }
    const unsigned char* end() const { return keydata.data() + size(); }

    //! 通过fValid判断他是否是有效的
    bool IsValid() const { return fValid; }

    //! 判断是否是被压缩过的
    bool IsCompressed() const { return fCompressed; }

    //! 使用随机的方式创建一个新的密钥.
    void MakeNewKey(bool fCompressed);

    /**
     * 将CKey转换为CPrivKey,也就是包含更多参数的CKey而已???哪些参数
     */
    CPrivKey GetPrivKey() const;

    /**
     * 通过私钥计算出一个公钥
     */
    CPubKey GetPubKey() const;

    /**
     * 用于签名的函数,其中test_case使用来调整签名的
     * @param[in] hash 要进行加密的哈希值
     * @param[out] 签名结果
     * @param[test_case] 我也没搞清楚这是干啥的,貌似是传一个和随机数有关的任意数
     */
    bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;

    /**
     * 用于创建压缩签名的函数
     */
    bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;

    //! 貌似是用来扩展密钥的
    bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;

    /**
     * 判断一个公钥是不是一个私钥产生的
     */
    bool VerifyPubKey(const CPubKey& vchPubKey) const;

    //! 加载一个私钥,顺便判断下公钥是否是私钥算出来的,若fSkipCheck为ture,则不判断
    bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck);
};


/**
 * 这个貌似是用于使用BIP扩展密钥的,称之为比特币改进协议BIP32
 */
struct CExtKey {
    unsigned char nDepth;
    unsigned char vchFingerprint[4];
    unsigned int nChild;
    ChainCode chaincode;
    CKey key;

    friend bool operator==(const CExtKey& a, const CExtKey& b)
    {
        return a.nDepth == b.nDepth &&
            memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 &&
            a.nChild == b.nChild &&
            a.chaincode == b.chaincode &&
            a.key == b.key;
    }

    void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
    void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
    bool Derive(CExtKey& out, unsigned int nChild) const;
    CExtPubKey Neuter() const;
    void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
    template <typename Stream>
    void Serialize(Stream& s) const
    {
        unsigned int len = BIP32_EXTKEY_SIZE;
        ::WriteCompactSize(s, len);
        unsigned char code[BIP32_EXTKEY_SIZE];
        Encode(code);
        s.write((const char *)&code[0], len);
    }
    template <typename Stream>
    void Unserialize(Stream& s)
    {
        unsigned int len = ::ReadCompactSize(s);
        unsigned char code[BIP32_EXTKEY_SIZE];
        if (len != BIP32_EXTKEY_SIZE)
            throw std::runtime_error("Invalid extended key size\n");
        s.read((char *)&code[0], len);
        Decode(code);
    }
};

/** 使用椭圆算法加密前必须调用该程序启用上下文 */
void ECC_Start(void);

/** 使用椭圆加密后使用该函数哦销毁加密上下文 */
void ECC_Stop(void);

/** Check that required EC support is available at runtime. */
bool ECC_InitSanityCheck(void);

#endif // BITCOIN_KEY_H

这里面的函数我基本都测试过,过段时间封装个rust的接口出来!!!!

猜你喜欢

转载自blog.csdn.net/lihn1987/article/details/80044546