Some extra comments
authorPieter Wuille <pieter.wuille@gmail.com>
Sun, 6 Nov 2011 23:05:42 +0000 (00:05 +0100)
committerPieter Wuille <pieter.wuille@gmail.com>
Sun, 6 Nov 2011 23:11:34 +0000 (00:11 +0100)
src/base58.h
src/crypter.h
src/key.h
src/keystore.h
src/main.cpp
src/wallet.cpp
src/wallet.h

index 592756f..cace423 100644 (file)
@@ -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 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char
     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 @@ inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
     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 @@ inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vch
 
 
 
-
+// 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 @@ inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
     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 @@ inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRe
     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 @@ inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>
 
 
 
-
+// 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 @@ protected:
 
     ~CBase58Data()
     {
+        // zero the memory, as it may contain sensitive data
         if (!vchData.empty())
             memset(&vchData[0], 0, vchData.size());
     }
@@ -238,7 +251,9 @@ public:
     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:
index 5b95ea4..e8ca30a 100644 (file)
@@ -13,15 +13,15 @@ const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
 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
index 5ffd7b9..df5cfeb 100644 (file)
--- 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 @@ err:
     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 @@ public:
 
 
 // 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 @@ public:
     }
 
     // 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 @@ public:
             }
 
             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 @@ public:
     }
 
     // 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 @@ public:
         return true;
     }
 
+    // Verify a compact signature
     bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
     {
         CKey key;
@@ -369,6 +382,7 @@ public:
         return true;
     }
 
+    // Get the address corresponding to this key
     CBitcoinAddress GetAddress() const
     {
         return CBitcoinAddress(GetPubKey());
index 1f2c6ae..4d88914 100644 (file)
@@ -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 @@ public:
 
 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:
index 45de76a..47f1090 100644 (file)
@@ -70,6 +70,9 @@ int fUseUPnP = false;
 // dispatching functions
 //
 
+// These functions dispatch to one or all registered wallets
+
+
 void RegisterWallet(CWallet* pwalletIn)
 {
     CRITICAL_BLOCK(cs_setpwalletRegistered)
@@ -86,6 +89,7 @@ void UnregisterWallet(CWallet* pwalletIn)
     }
 }
 
+// check whether the passed transaction is from us
 bool static IsFromMe(CTransaction& tx)
 {
     BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
@@ -94,6 +98,7 @@ bool static IsFromMe(CTransaction& tx)
     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 @@ bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
     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)
index 46c57e2..64ee5c3 100644 (file)
@@ -289,6 +289,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
     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 @@ bool CWalletTx::WriteToDisk()
     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;
index b6df1aa..03c4703 100644 (file)
@@ -13,6 +13,9 @@ class CWalletTx;
 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 @@ public:
     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 @@ public:
     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 @@ public:
         return fReturn;
     }
 
+    // make sure balances are recalculated
     void MarkDirty()
     {
         fCreditCached = false;