Mercurial > hg > bitcoin
changeset 1482:89b5602e80e4 draft
Merge pull request #611 from sipa/docs
Some extra comments
author | Wladimir J. van der Laan <laanwj@gmail.com> |
---|---|
date | Tue, 08 Nov 2011 23:39:41 -0800 |
parents | 1e2f196dc604 (current diff) 5f0271a5e9cb (diff) |
children | f517ddd2c417 |
files | |
diffstat | 7 files changed, 80 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/base58.h +++ b/src/base58.h @@ -21,7 +21,7 @@ static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - +// Encode a byte sequence as a base58-encoded string inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) { CAutoBN_CTX pctx; @@ -62,11 +62,14 @@ return str; } +// Encode a byte vector as a base58-encoded string inline std::string EncodeBase58(const std::vector<unsigned char>& vch) { return EncodeBase58(&vch[0], &vch[0] + vch.size()); } +// Decode a base58-encoded string psz into byte vector vchRet +// returns true if decoding is succesful inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet) { CAutoBN_CTX pctx; @@ -113,6 +116,8 @@ return true; } +// Decode a base58-encoded string str into byte vector vchRet +// returns true if decoding is succesful inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet) { return DecodeBase58(str.c_str(), vchRet); @@ -121,7 +126,7 @@ - +// Encode a byte vector to a base58-encoded string, including checksum inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn) { // add 4-byte hash check to the end @@ -131,6 +136,8 @@ return EncodeBase58(vch); } +// Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet +// returns true if decoding is succesful inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet) { if (!DecodeBase58(psz, vchRet)) @@ -150,6 +157,8 @@ return true; } +// Decode a base58-encoded string str that includes a checksum, into byte vector vchRet +// returns true if decoding is succesful inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet) { return DecodeBase58Check(str.c_str(), vchRet); @@ -159,11 +168,14 @@ - +// Base class for all base58-encoded data class CBase58Data { protected: + // the version byte unsigned char nVersion; + + // the actually encoded data std::vector<unsigned char> vchData; CBase58Data() @@ -174,6 +186,7 @@ ~CBase58Data() { + // zero the memory, as it may contain sensitive data if (!vchData.empty()) memset(&vchData[0], 0, vchData.size()); } @@ -238,7 +251,9 @@ bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } }; - +// base58-encoded bitcoin addresses +// Addresses have version 0 or 111 (testnet) +// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key class CBitcoinAddress : public CBase58Data { public:
--- a/src/crypter.h +++ b/src/crypter.h @@ -13,15 +13,15 @@ Private key encryption is done based on a CMasterKey, which holds a salt and random encryption key. -CMasterKeys is encrypted using AES-256-CBC using a key +CMasterKeys are encrypted using AES-256-CBC using a key derived using derivation method nDerivationMethod (0 == EVP_sha512()) and derivation iterations nDeriveIterations. vchOtherDerivationParameters is provided for alternative algorithms which may require more parameters (such as scrypt). Wallet Private Keys are then encrypted using AES-256-CBC -with the double-sha256 of the private key as the IV, and the -master key's key as the encryption key. +with the double-sha256 of the public key as the IV, and the +master key's key as the encryption key (see keystore.[ch]). */ class CMasterKey
--- a/src/key.h +++ b/src/key.h @@ -39,6 +39,7 @@ // see www.keylength.com // script supports up to 75 for single byte push +// Generate a private key from just the secret parameter int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) { int ok = 0; @@ -75,6 +76,9 @@ return(ok); } +// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields +// recid selects which key is recovered +// if check is nonzero, additional checks are performed int static inline ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) { if (!eckey) return 0; @@ -154,7 +158,9 @@ // secure_allocator is defined in serialize.h +// CPrivKey is a serialized private key, with all parameters included (279 bytes) typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey; +// CSecret is a serialization of just the secret parameter (32 bytes) typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret; class CKey @@ -292,6 +298,9 @@ } // create a compact signature (65 bytes), which allows reconstructing the used public key + // The format is one header byte, followed by two times 32 bytes for the serialized r and s values. + // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, + // 0x1D = second key with even y, 0x1E = second key with odd y bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig) { bool fOk = false; @@ -318,7 +327,7 @@ } if (nRecId == -1) - throw key_error("CKEy::SignCompact() : unable to construct recoverable key"); + throw key_error("CKey::SignCompact() : unable to construct recoverable key"); vchSig[0] = nRecId+27; BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]); @@ -330,6 +339,9 @@ } // reconstruct public key from a compact signature + // This is only slightly more CPU intensive than just verifying it. + // If this function succeeds, the recovered public key is guaranteed to be valid + // (the signature is a valid signature of the given data for that key) bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.size() != 65) @@ -359,6 +371,7 @@ return true; } + // Verify a compact signature bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig) { CKey key; @@ -369,6 +382,7 @@ return true; } + // Get the address corresponding to this key CBitcoinAddress GetAddress() const { return CBitcoinAddress(GetPubKey());
--- a/src/keystore.h +++ b/src/keystore.h @@ -7,21 +7,34 @@ #include "crypter.h" +// A virtual base class for key stores class CKeyStore { protected: mutable CCriticalSection cs_KeyStore; public: + // Add a key to the store. virtual bool AddKey(const CKey& key) =0; + + // Check whether a key corresponding to a given address is present in the store. virtual bool HaveKey(const CBitcoinAddress &address) const =0; + + // Retrieve a key corresponding to a given address from the store. + // Return true if succesful. virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0; + + // Retrieve only the public key corresponding to a given address. + // This may succeed even if GetKey fails (e.g., encrypted wallets) virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const; + + // Generate a new key, and add it to the store virtual std::vector<unsigned char> GenerateNewKey(); }; typedef std::map<CBitcoinAddress, CSecret> KeyMap; +// Basic key store, that keeps keys in an address->secret map class CBasicKeyStore : public CKeyStore { protected: @@ -53,6 +66,8 @@ typedef std::map<CBitcoinAddress, std::pair<std::vector<unsigned char>, std::vector<unsigned char> > > CryptedKeyMap; +// Keystore which keeps the private keys encrypted +// It derives from the basic key store, which is used if no encryption is active. class CCryptoKeyStore : public CBasicKeyStore { private:
--- a/src/main.cpp +++ b/src/main.cpp @@ -70,6 +70,9 @@ // dispatching functions // +// These functions dispatch to one or all registered wallets + + void RegisterWallet(CWallet* pwalletIn) { CRITICAL_BLOCK(cs_setpwalletRegistered) @@ -86,6 +89,7 @@ } } +// check whether the passed transaction is from us bool static IsFromMe(CTransaction& tx) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) @@ -94,6 +98,7 @@ return false; } +// get the wallet transaction with the given hash (if it exists) bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) @@ -102,42 +107,49 @@ return false; } +// erases transaction with the given hash from all wallets void static EraseFromWallets(uint256 hash) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->EraseFromWallet(hash); } +// make sure all wallets know about the given transaction, in the given block void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); } +// notify wallets about a new best chain void static SetBestChain(const CBlockLocator& loc) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->SetBestChain(loc); } +// notify wallets about an updated transaction void static UpdatedTransaction(const uint256& hashTx) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->UpdatedTransaction(hashTx); } +// dump all wallets void static PrintWallets(const CBlock& block) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->PrintWallet(block); } +// notify wallets about an incoming inventory (for request counts) void static Inventory(const uint256& hash) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->Inventory(hash); } +// ask wallets to resend their transactions void static ResendWalletTransactions() { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
--- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -289,6 +289,9 @@ return true; } +// Add a transaction to the wallet, or update it. +// pblock is optional, but should be provided if the transaction is known to be in a block. +// If fUpdate is true, existing transactions will be updated. bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) { uint256 hash = tx.GetHash(); @@ -551,6 +554,9 @@ return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this); } +// Scan the block chain (starting in pindexStart) for transactions +// from or to us. If fUpdate is true, found transactions that already +// exist in the wallet will be updated. int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) { int ret = 0;
--- a/src/wallet.h +++ b/src/wallet.h @@ -13,6 +13,9 @@ class CReserveKey; class CWalletDB; +// A CWallet is an extension of a keystore, which also maintains a set of +// transactions and balances, and provides the ability to create new +// transactions class CWallet : public CCryptoKeyStore { private: @@ -57,9 +60,14 @@ std::vector<unsigned char> vchDefaultKey; // keystore implementation + // Adds a key to the store, and saves it to disk. bool AddKey(const CKey& key); + // Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); } + + // Adds an encrypted key to the store, and saves it to disk. bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret); + // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet) bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); } bool Unlock(const std::string& strWalletPassphrase); @@ -244,7 +252,7 @@ unsigned int nTimeReceived; // time received by this node char fFromMe; std::string strFromAccount; - std::vector<char> vfSpent; + std::vector<char> vfSpent; // which outputs are already spent // memory only mutable char fDebitCached; @@ -371,6 +379,7 @@ return fReturn; } + // make sure balances are recalculated void MarkDirty() { fCreditCached = false;