forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@1 1a98c847-1fd6-4fd8-948a-caf3550aa51b
- Loading branch information
0 parents
commit e071a3f
Showing
45 changed files
with
32,239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
// Copyright (c) 2009 Satoshi Nakamoto | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file license.txt or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
|
||
// | ||
// Why base-58 instead of standard base-64 encoding? | ||
// - Don't want 0OIl characters that look the same in some fonts and | ||
// 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. | ||
// | ||
|
||
|
||
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | ||
|
||
|
||
inline 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 | ||
vector<unsigned char> 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 string | ||
string str; | ||
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 string to big endian | ||
reverse(str.begin(), str.end()); | ||
return str; | ||
} | ||
|
||
inline string EncodeBase58(const vector<unsigned char>& vch) | ||
{ | ||
return EncodeBase58(&vch[0], &vch[0] + vch.size()); | ||
} | ||
|
||
inline bool DecodeBase58(const char* psz, vector<unsigned char>& 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 | ||
vector<unsigned char> 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; | ||
} | ||
|
||
inline bool DecodeBase58(const string& str, vector<unsigned char>& vchRet) | ||
{ | ||
return DecodeBase58(str.c_str(), vchRet); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
inline string EncodeBase58Check(const vector<unsigned char>& vchIn) | ||
{ | ||
// add 4-byte hash check to the end | ||
vector<unsigned char> vch(vchIn); | ||
uint256 hash = Hash(vch.begin(), vch.end()); | ||
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); | ||
return EncodeBase58(vch); | ||
} | ||
|
||
inline bool DecodeBase58Check(const char* psz, vector<unsigned char>& 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; | ||
} | ||
|
||
inline bool DecodeBase58Check(const string& str, vector<unsigned char>& vchRet) | ||
{ | ||
return DecodeBase58Check(str.c_str(), vchRet); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
static const unsigned char ADDRESSVERSION = 0; | ||
|
||
inline string Hash160ToAddress(uint160 hash160) | ||
{ | ||
// add 1-byte version number to the front | ||
vector<unsigned char> vch(1, ADDRESSVERSION); | ||
vch.insert(vch.end(), UBEGIN(hash160), UEND(hash160)); | ||
return EncodeBase58Check(vch); | ||
} | ||
|
||
inline bool AddressToHash160(const char* psz, uint160& hash160Ret) | ||
{ | ||
vector<unsigned char> 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); | ||
} | ||
|
||
inline bool AddressToHash160(const string& str, uint160& hash160Ret) | ||
{ | ||
return AddressToHash160(str.c_str(), hash160Ret); | ||
} | ||
|
||
inline bool IsValidBitcoinAddress(const char* psz) | ||
{ | ||
uint160 hash160; | ||
return AddressToHash160(psz, hash160); | ||
} | ||
|
||
inline bool IsValidBitcoinAddress(const string& str) | ||
{ | ||
return IsValidBitcoinAddress(str.c_str()); | ||
} | ||
|
||
|
||
|
||
|
||
inline string PubKeyToAddress(const vector<unsigned char>& vchPubKey) | ||
{ | ||
return Hash160ToAddress(Hash160(vchPubKey)); | ||
} |
Oops, something went wrong.