X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fbase58.h;h=5675c049b8d2cae53e755c599dc5ac792be010eb;hb=6f895c2539c4ddefce658bb2ec7083774bbbd5a3;hp=3f2d82f11b8eeded50ec18ca473d66daf5272ee8;hpb=21d9f36781604e4ca9fc35dc65265593423b73e9;p=novacoin.git diff --git a/src/base58.h b/src/base58.h index 3f2d82f..5675c04 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,17 +10,16 @@ // 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 #include "bignum.h" #include "key.h" +#include "script.h" static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; @@ -52,7 +51,7 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char if (!BN_div(&dv, &rem, &bn, &bn58, pctx)) throw bignum_error("EncodeBase58 : BN_div failed"); bn = dv; - unsigned int c = rem.getulong(); + unsigned int c = rem.getuint32(); str += pszBase58[c]; } @@ -72,7 +71,7 @@ inline std::string EncodeBase58(const std::vector& vch) } // Decode a base58-encoded string psz into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58(const char* psz, std::vector& vchRet) { CAutoBN_CTX pctx; @@ -95,7 +94,7 @@ inline bool DecodeBase58(const char* psz, std::vector& vchRet) return false; break; } - bnChar.setulong(p1 - pszBase58); + bnChar.setuint32(p1 - pszBase58); if (!BN_mul(&bn, &bn, &bn58, pctx)) throw bignum_error("DecodeBase58 : BN_mul failed"); bn += bnChar; @@ -120,7 +119,7 @@ inline bool DecodeBase58(const char* psz, std::vector& vchRet) } // Decode a base58-encoded string str into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58(const std::string& str, std::vector& vchRet) { return DecodeBase58(str.c_str(), vchRet); @@ -140,7 +139,7 @@ inline 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 +// returns true if decoding is successful inline bool DecodeBase58Check(const char* psz, std::vector& vchRet) { if (!DecodeBase58(psz, vchRet)) @@ -161,7 +160,7 @@ inline bool DecodeBase58Check(const char* psz, std::vector& vchRe } // Decode a base58-encoded string str that includes a checksum, into byte vector vchRet -// returns true if decoding is succesful +// returns true if decoding is successful inline bool DecodeBase58Check(const std::string& str, std::vector& vchRet) { return DecodeBase58Check(str.c_str(), vchRet); @@ -171,7 +170,7 @@ inline bool DecodeBase58Check(const std::string& str, std::vector -// Base class for all base58-encoded data +/** Base class for all base58-encoded data */ class CBase58Data { protected: @@ -254,43 +253,53 @@ public: bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } }; -// base58-encoded bitcoin addresses -// Public-key-hash-addresses have version 0 (or 192 testnet) -// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key -// Script-hash-addresses (OP_EVAL) have version 5 (or 196 testnet) -// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script +/** 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. + */ +class CBitcoinAddress; +class CBitcoinAddressVisitor : public boost::static_visitor +{ +private: + CBitcoinAddress *addr; +public: + CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } + bool operator()(const CKeyID &id) const; + bool operator()(const CScriptID &id) const; + bool operator()(const CNoDestination &no) const; +}; + class CBitcoinAddress : public CBase58Data { public: enum { - PUBKEY_ADDRESS = 0, - SCRIPT_ADDRESS = 5, - PUBKEY_ADDRESS_TEST = 192, - PUBKEY_ADDRESS_TEST_LEGACY = 111, // Deprecated: old testnet address + PUBKEY_ADDRESS = 8, + SCRIPT_ADDRESS = 20, + PUBKEY_ADDRESS_TEST = 111, SCRIPT_ADDRESS_TEST = 196, }; - bool SetHash160(const uint160& hash160) - { - SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &hash160, 20); + bool Set(const CKeyID &id) { + SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20); return true; } - void SetPubKey(const std::vector& vchPubKey) - { - SetHash160(Hash160(vchPubKey)); + bool Set(const CScriptID &id) { + SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20); + return true; } - bool SetScriptHash160(const uint160& hash160) + bool Set(const CTxDestination &dest) { - SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &hash160, 20); - return true; + return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); } bool IsValid() const { - int nExpectedSize = 20; + unsigned int nExpectedSize = 20; bool fExpectTestNet = false; switch(nVersion) { @@ -299,11 +308,10 @@ public: fExpectTestNet = false; break; case SCRIPT_ADDRESS: - nExpectedSize = 20; // OP_EVAL, hash of CScript + nExpectedSize = 20; // Hash of CScript fExpectTestNet = false; break; - case PUBKEY_ADDRESS_TEST_LEGACY: case PUBKEY_ADDRESS_TEST: nExpectedSize = 20; fExpectTestNet = true; @@ -318,27 +326,14 @@ public: } 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) + CBitcoinAddress(const CTxDestination &dest) { - SetPubKey(vchPubKey); + Set(dest); } CBitcoinAddress(const std::string& strAddress) @@ -351,53 +346,110 @@ public: SetString(pszAddress); } - uint160 GetHash160() const - { - assert(vchData.size() == 20); - uint160 hash160; - memcpy(&hash160, &vchData[0], 20); - return hash160; + CTxDestination Get() const { + if (!IsValid()) + return CNoDestination(); + switch (nVersion) { + case PUBKEY_ADDRESS: + case PUBKEY_ADDRESS_TEST: { + uint160 id; + memcpy(&id, &vchData[0], 20); + return CKeyID(id); + } + case SCRIPT_ADDRESS: + case SCRIPT_ADDRESS_TEST: { + uint160 id; + memcpy(&id, &vchData[0], 20); + return CScriptID(id); + } + } + return CNoDestination(); + } + + bool GetKeyID(CKeyID &keyID) const { + if (!IsValid()) + return false; + switch (nVersion) { + case PUBKEY_ADDRESS: + case PUBKEY_ADDRESS_TEST: { + uint160 id; + memcpy(&id, &vchData[0], 20); + keyID = CKeyID(id); + return true; + } + default: return false; + } + } + + bool IsScript() const { + if (!IsValid()) + return false; + switch (nVersion) { + case SCRIPT_ADDRESS: + case SCRIPT_ADDRESS_TEST: { + return true; + } + default: return false; + } } }; +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 CNoDestination &id) const { return false; } + +/** A base58-encoded secret key */ class CBitcoinSecret : public CBase58Data { public: - void SetSecret(const CSecret& vchSecret) + void SetSecret(const CSecret& vchSecret, bool fCompressed) { - SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size()); + assert(vchSecret.size() == 32); + SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size()); + if (fCompressed) + vchData.push_back(1); } - CSecret GetSecret() + CSecret GetSecret(bool &fCompressedOut) { CSecret vchSecret; - vchSecret.resize(vchData.size()); - memcpy(&vchSecret[0], &vchData[0], vchData.size()); + vchSecret.resize(32); + memcpy(&vchSecret[0], &vchData[0], 32); + fCompressedOut = vchData.size() == 33; return vchSecret; } bool IsValid() const { - int nExpectedSize = 32; bool fExpectTestNet = false; switch(nVersion) { - case 128: + case (128 + CBitcoinAddress::PUBKEY_ADDRESS): break; - case 239: + case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST): fExpectTestNet = true; break; default: return false; } - return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize; + 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) + CBitcoinSecret(const CSecret& vchSecret, bool fCompressed) { - SetSecret(vchSecret); + SetSecret(vchSecret, fCompressed); } CBitcoinSecret()