X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fbase58.h;h=0ca0fda7da37646e00c6c4d5203a8e1d4b741784;hp=d7fedb1a74144c0b3dac0ebb6266d270b08b09c5;hb=6aba6f08af53e3fa49ab4d1ef002e6771d0ce358;hpb=a93ab877877925c60b2dbf56bdde8aa46b6b7391 diff --git a/src/base58.h b/src/base58.h index d7fedb1..0ca0fda 100644 --- a/src/base58.h +++ b/src/base58.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2011 The Bitcoin Developers +// Copyright (c) 2009-2012 The Bitcoin Developers // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. // @@ -10,165 +10,44 @@ // could be used to create visually identical looking account numbers. // - A string with non-alphanumeric characters is not as easily accepted as an account number. // - E-mail usually won't line-break if there's no punctuation to break at. -// - Doubleclicking selects the whole number as one word if it's all alphanumeric. +// - Double-clicking selects the whole number as one word if it's all alphanumeric. // #ifndef BITCOIN_BASE58_H #define BITCOIN_BASE58_H #include #include +#include // for OPENSSL_cleanse() #include "bignum.h" - -static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; +#include "key.h" +#include "script.h" // Encode a byte sequence as a base58-encoded string -inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) -{ - CAutoBN_CTX pctx; - CBigNum bn58 = 58; - CBigNum bn0 = 0; - - // Convert big endian data to little endian - // Extra zero at the end make sure bignum will interpret as a positive number - std::vector vchTmp(pend-pbegin+1, 0); - reverse_copy(pbegin, pend, vchTmp.begin()); - - // Convert little endian data to bignum - CBigNum bn; - bn.setvch(vchTmp); - - // Convert bignum to std::string - std::string str; - // Expected size increase from base58 conversion is approximately 137% - // use 138% to be safe - str.reserve((pend - pbegin) * 138 / 100 + 1); - CBigNum dv; - CBigNum rem; - while (bn > bn0) - { - if (!BN_div(&dv, &rem, &bn, &bn58, pctx)) - throw bignum_error("EncodeBase58 : BN_div failed"); - bn = dv; - unsigned int c = rem.getulong(); - str += pszBase58[c]; - } - - // Leading zeroes encoded as base58 zeros - for (const unsigned char* p = pbegin; p < pend && *p == 0; p++) - str += pszBase58[0]; - - // Convert little endian std::string to big endian - reverse(str.begin(), str.end()); - return str; -} +std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend); // Encode a byte vector as a base58-encoded string -inline std::string EncodeBase58(const std::vector& vch) -{ - return EncodeBase58(&vch[0], &vch[0] + vch.size()); -} +std::string EncodeBase58(const std::vector& vch); // Decode a base58-encoded string psz into byte vector vchRet -// returns true if decoding is succesful -inline bool DecodeBase58(const char* psz, std::vector& vchRet) -{ - CAutoBN_CTX pctx; - vchRet.clear(); - CBigNum bn58 = 58; - CBigNum bn = 0; - CBigNum bnChar; - while (isspace(*psz)) - psz++; - - // Convert big endian string to bignum - for (const char* p = psz; *p; p++) - { - const char* p1 = strchr(pszBase58, *p); - if (p1 == NULL) - { - while (isspace(*p)) - p++; - if (*p != '\0') - return false; - break; - } - bnChar.setulong(p1 - pszBase58); - if (!BN_mul(&bn, &bn, &bn58, pctx)) - throw bignum_error("DecodeBase58 : BN_mul failed"); - bn += bnChar; - } - - // Get bignum as little endian data - std::vector vchTmp = bn.getvch(); - - // Trim off sign byte if present - if (vchTmp.size() >= 2 && vchTmp.end()[-1] == 0 && vchTmp.end()[-2] >= 0x80) - vchTmp.erase(vchTmp.end()-1); - - // Restore leading zeros - int nLeadingZeros = 0; - for (const char* p = psz; *p == pszBase58[0]; p++) - nLeadingZeros++; - vchRet.assign(nLeadingZeros + vchTmp.size(), 0); - - // Convert little endian data to big endian - reverse_copy(vchTmp.begin(), vchTmp.end(), vchRet.end() - vchTmp.size()); - return true; -} +// returns true if decoding is successful +bool DecodeBase58(const char* psz, std::vector& vchRet); // 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& vchRet) -{ - return DecodeBase58(str.c_str(), vchRet); -} - - - +// returns true if decoding is successful +bool DecodeBase58(const std::string& str, std::vector& vchRet); // Encode a byte vector to a base58-encoded string, including checksum -inline std::string EncodeBase58Check(const std::vector& vchIn) -{ - // add 4-byte hash check to the end - std::vector vch(vchIn); - uint256 hash = Hash(vch.begin(), vch.end()); - vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); - return EncodeBase58(vch); -} +std::string EncodeBase58Check(const std::vector& vchIn); // 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& vchRet) -{ - if (!DecodeBase58(psz, vchRet)) - return false; - if (vchRet.size() < 4) - { - vchRet.clear(); - return false; - } - uint256 hash = Hash(vchRet.begin(), vchRet.end()-4); - if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) - { - vchRet.clear(); - return false; - } - vchRet.resize(vchRet.size()-4); - return true; -} +// returns true if decoding is successful +bool DecodeBase58Check(const char* psz, std::vector& vchRet); // 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& vchRet) -{ - return DecodeBase58Check(str.c_str(), vchRet); -} +// returns true if decoding is successful +bool DecodeBase58Check(const std::string& str, std::vector& vchRet); - - - - -// Base class for all base58-encoded data +/** Base class for all base58-encoded data */ class CBase58Data { protected: @@ -178,72 +57,19 @@ protected: // the actually encoded data std::vector vchData; - CBase58Data() - { - nVersion = 0; - vchData.clear(); - } - - ~CBase58Data() - { - // zero the memory, as it may contain sensitive data - if (!vchData.empty()) - memset(&vchData[0], 0, vchData.size()); - } - - void SetData(int nVersionIn, const void* pdata, size_t nSize) - { - nVersion = nVersionIn; - vchData.resize(nSize); - if (!vchData.empty()) - memcpy(&vchData[0], pdata, nSize); - } + CBase58Data(); + ~CBase58Data(); - void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend) - { - SetData(nVersionIn, (void*)pbegin, pend - pbegin); - } + void SetData(int nVersionIn, const void* pdata, size_t nSize); + void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend); public: - bool SetString(const char* psz) - { - std::vector vchTemp; - DecodeBase58Check(psz, vchTemp); - if (vchTemp.empty()) - { - vchData.clear(); - nVersion = 0; - return false; - } - nVersion = vchTemp[0]; - vchData.resize(vchTemp.size() - 1); - if (!vchData.empty()) - memcpy(&vchData[0], &vchTemp[1], vchData.size()); - memset(&vchTemp[0], 0, vchTemp.size()); - return true; - } - - bool SetString(const std::string& str) - { - return SetString(str.c_str()); - } - - std::string ToString() const - { - std::vector vch(1, nVersion); - vch.insert(vch.end(), vchData.begin(), vchData.end()); - return EncodeBase58Check(vch); - } - - int CompareTo(const CBase58Data& b58) const - { - if (nVersion < b58.nVersion) return -1; - if (nVersion > b58.nVersion) return 1; - if (vchData < b58.vchData) return -1; - if (vchData > b58.vchData) return 1; - return 0; - } + bool SetString(const char* psz); + bool SetString(const std::string& str); + std::string ToString() const; + const std::vector &GetData() const; + int CompareTo(const CBase58Data& b58) const; bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; } bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; } bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; } @@ -251,54 +77,59 @@ 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 +/** base58-encoded Bitcoin addresses. + * Public-key-hash-addresses have version 0 (or 111 testnet). + * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. + * Script-hash-addresses have version 5 (or 196 testnet). + * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. + * Pubkey-pair-addresses have version 1 (or 6 testnet) + * The data vector contains a serialized copy of two compressed ECDSA secp256k1 public keys. + */ +class CBitcoinAddress; +class CBitcoinAddressVisitor : public boost::static_visitor { +private: + CBitcoinAddress *addr; public: - bool SetHash160(const uint160& hash160) - { - SetData(fTestNet ? 111 : 0, &hash160, 20); - return true; - } - - bool SetPubKey(const std::vector& vchPubKey) - { - return SetHash160(Hash160(vchPubKey)); - } - - bool IsValid() const - { - unsigned int nExpectedSize = 20; - bool fExpectTestNet = false; - switch(nVersion) - { - case 0: - break; - - case 111: - fExpectTestNet = true; - break; + CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } + bool operator()(const CKeyID &id) const; + bool operator()(const CScriptID &id) const; + bool operator()(const CMalleablePubKey &mpk) const; + bool operator()(const CNoDestination &no) const; +}; - default: - return false; - } - return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize; - } +class CBitcoinAddress : public CBase58Data +{ +public: + enum + { + PUBKEY_PAIR_ADDRESS = 1, + PUBKEY_ADDRESS = 8, + SCRIPT_ADDRESS = 20, + PUBKEY_PAIR_ADDRESS_TEST = 6, + PUBKEY_ADDRESS_TEST = 111, + SCRIPT_ADDRESS_TEST = 196 + }; + + bool Set(const CKeyID &id); + bool Set(const CScriptID &id); + bool Set(const CTxDestination &dest); + bool Set(const CMalleablePubKey &mpk); + bool Set(const CBitcoinAddress &dest); + bool IsValid() const; CBitcoinAddress() { } - CBitcoinAddress(uint160 hash160In) + CBitcoinAddress(const CTxDestination &dest) { - SetHash160(hash160In); + Set(dest); } - CBitcoinAddress(const std::vector& vchPubKey) + CBitcoinAddress(const CMalleablePubKey &mpk) { - SetPubKey(vchPubKey); + Set(mpk); } CBitcoinAddress(const std::string& strAddress) @@ -311,12 +142,33 @@ public: SetString(pszAddress); } - uint160 GetHash160() const + CTxDestination Get() const; + bool GetKeyID(CKeyID &keyID) const; + bool IsScript() const; + bool IsPubKey() const; + bool IsPair() const; +}; + +bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); } +bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); } +bool inline CBitcoinAddressVisitor::operator()(const CMalleablePubKey &mpk) const { return addr->Set(mpk); } +bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; } + +/** A base58-encoded secret key */ +class CBitcoinSecret : public CBase58Data +{ +public: + void SetSecret(const CSecret& vchSecret, bool fCompressed); + CSecret GetSecret(bool &fCompressedOut); + + bool IsValid() const; + + bool SetString(const char* pszSecret); + bool SetString(const std::string& strSecret); + + CBitcoinSecret(const CSecret& vchSecret, bool fCompressed); + CBitcoinSecret() { - assert(vchData.size() == 20); - uint160 hash160; - memcpy(&hash160, &vchData[0], 20); - return hash160; } };