X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fbase58.h;h=0accbf998546e3587c4eea8d60ec9238c640fecd;hb=0561bbd1c69263dceb24ffacf850788e6e961a13;hp=580bd3fc63b38300ade9a0c17f186a06f4efb921;hpb=ba4081c1fcaddf361abd61b2721994eff5475bb3;p=novacoin.git diff --git a/src/base58.h b/src/base58.h index 580bd3f..0accbf9 100644 --- a/src/base58.h +++ b/src/base58.h @@ -1,6 +1,8 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin Developers +// Copyright (c) 2011-2012 The PPCoin 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. // @@ -17,10 +19,11 @@ #include #include #include "bignum.h" +#include "key.h" 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; @@ -38,6 +41,8 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char // 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; @@ -59,11 +64,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& 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& vchRet) { CAutoBN_CTX pctx; @@ -110,6 +118,8 @@ inline bool DecodeBase58(const char* psz, std::vector& 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& vchRet) { return DecodeBase58(str.c_str(), vchRet); @@ -118,7 +128,7 @@ inline bool DecodeBase58(const std::string& str, std::vector& vch - +// 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 @@ -128,6 +138,8 @@ inline std::string EncodeBase58Check(const std::vector& 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& vchRet) { if (!DecodeBase58(psz, vchRet)) @@ -147,6 +159,8 @@ inline bool DecodeBase58Check(const char* psz, std::vector& 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& vchRet) { return DecodeBase58Check(str.c_str(), vchRet); @@ -156,53 +170,251 @@ inline bool DecodeBase58Check(const std::string& str, std::vector +/** Base class for all base58-encoded data */ +class CBase58Data +{ +protected: + // the version byte + unsigned char nVersion; -#define ADDRESSVERSION ((unsigned char)(fTestNet ? 111 : 0)) + // the actually encoded data + std::vector vchData; -inline std::string Hash160ToAddress(uint160 hash160) -{ - // add 1-byte version number to the front - std::vector vch(1, ADDRESSVERSION); - vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160)); - return EncodeBase58Check(vch); -} + CBase58Data() + { + nVersion = 0; + vchData.clear(); + } -inline bool AddressToHash160(const char* psz, uint160& hash160Ret) -{ - std::vector vch; - if (!DecodeBase58Check(psz, vch)) - return false; - if (vch.empty()) - return false; - unsigned char nVersion = vch[0]; - if (vch.size() != sizeof(hash160Ret) + 1) - return false; - memcpy(&hash160Ret, &vch[1], sizeof(hash160Ret)); - return (nVersion <= ADDRESSVERSION); -} + ~CBase58Data() + { + // zero the memory, as it may contain sensitive data + if (!vchData.empty()) + memset(&vchData[0], 0, vchData.size()); + } -inline bool AddressToHash160(const std::string& str, uint160& hash160Ret) -{ - return AddressToHash160(str.c_str(), hash160Ret); -} + void SetData(int nVersionIn, const void* pdata, size_t nSize) + { + nVersion = nVersionIn; + vchData.resize(nSize); + if (!vchData.empty()) + memcpy(&vchData[0], pdata, nSize); + } -inline bool IsValidBitcoinAddress(const char* psz) -{ - uint160 hash160; - return AddressToHash160(psz, hash160); -} + void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend) + { + SetData(nVersionIn, (void*)pbegin, pend - pbegin); + } + +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; + } -inline bool IsValidBitcoinAddress(const std::string& str) + 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; } + bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; } + bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } +}; + +/** base58-encoded bitcoin addresses. + * Public-key-hash-addresses have version 55 (or 111 testnet). + * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. + * Script-hash-addresses have version 57 (or 196 testnet). + * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. + */ +class CBitcoinAddress : public CBase58Data { - return IsValidBitcoinAddress(str.c_str()); -} +public: + enum + { + PUBKEY_ADDRESS = 55, // ppcoin: addresses begin with 'P' + SCRIPT_ADDRESS = 57, // ppcoin: addresses begin with 'Q' + PUBKEY_ADDRESS_TEST = 111, + SCRIPT_ADDRESS_TEST = 196, + }; + bool SetHash160(const uint160& hash160) + { + SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &hash160, 20); + return true; + } + void SetPubKey(const std::vector& vchPubKey) + { + SetHash160(Hash160(vchPubKey)); + } + bool SetScriptHash160(const uint160& hash160) + { + SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &hash160, 20); + return true; + } -inline std::string PubKeyToAddress(const std::vector& vchPubKey) + bool IsValid() const + { + unsigned int nExpectedSize = 20; + bool fExpectTestNet = false; + switch(nVersion) + { + case PUBKEY_ADDRESS: + nExpectedSize = 20; // Hash of public key + fExpectTestNet = false; + break; + case SCRIPT_ADDRESS: + nExpectedSize = 20; // Hash of CScript + fExpectTestNet = false; + break; + + case PUBKEY_ADDRESS_TEST: + nExpectedSize = 20; + fExpectTestNet = true; + break; + case SCRIPT_ADDRESS_TEST: + nExpectedSize = 20; + fExpectTestNet = true; + break; + + default: + return false; + } + return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize; + } + bool IsScript() const + { + if (!IsValid()) + return false; + if (fTestNet) + return nVersion == SCRIPT_ADDRESS_TEST; + return nVersion == SCRIPT_ADDRESS; + } + + CBitcoinAddress() + { + } + + CBitcoinAddress(uint160 hash160In) + { + SetHash160(hash160In); + } + + CBitcoinAddress(const std::vector& vchPubKey) + { + SetPubKey(vchPubKey); + } + + CBitcoinAddress(const std::string& strAddress) + { + SetString(strAddress); + } + + CBitcoinAddress(const char* pszAddress) + { + SetString(pszAddress); + } + + uint160 GetHash160() const + { + assert(vchData.size() == 20); + uint160 hash160; + memcpy(&hash160, &vchData[0], 20); + return hash160; + } +}; + +/** A base58-encoded secret key */ +class CBitcoinSecret : public CBase58Data { - return Hash160ToAddress(Hash160(vchPubKey)); -} +public: + void SetSecret(const CSecret& vchSecret, bool fCompressed) + { + assert(vchSecret.size() == 32); + SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size()); + if (fCompressed) + vchData.push_back(1); + } + + CSecret GetSecret(bool &fCompressedOut) + { + CSecret vchSecret; + vchSecret.resize(32); + memcpy(&vchSecret[0], &vchData[0], 32); + fCompressedOut = vchData.size() == 33; + return vchSecret; + } + + bool IsValid() const + { + bool fExpectTestNet = false; + switch(nVersion) + { + case 128: + break; + + case 239: + fExpectTestNet = true; + break; + + default: + return false; + } + return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1)); + } + + bool SetString(const char* pszSecret) + { + return CBase58Data::SetString(pszSecret) && IsValid(); + } + + bool SetString(const std::string& strSecret) + { + return SetString(strSecret.c_str()); + } + + CBitcoinSecret(const CSecret& vchSecret, bool fCompressed) + { + SetSecret(vchSecret, fCompressed); + } + + CBitcoinSecret() + { + } +}; #endif