You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

base58.cpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. // Copyright (c) 2014-2017 The Starwels developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include <base58.h>
  5. #include <bech32.h>
  6. #include <hash.h>
  7. #include <script/script.h>
  8. #include <uint256.h>
  9. #include <utilstrencodings.h>
  10. #include <boost/variant/apply_visitor.hpp>
  11. #include <boost/variant/static_visitor.hpp>
  12. #include <algorithm>
  13. #include <assert.h>
  14. #include <string.h>
  15. /** All alphanumeric characters except for "0", "I", "O", and "l" */
  16. static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
  17. bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
  18. {
  19. // Skip leading spaces.
  20. while (*psz && isspace(*psz))
  21. psz++;
  22. // Skip and count leading '1's.
  23. int zeroes = 0;
  24. int length = 0;
  25. while (*psz == '1') {
  26. zeroes++;
  27. psz++;
  28. }
  29. // Allocate enough space in big-endian base256 representation.
  30. int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
  31. std::vector<unsigned char> b256(size);
  32. // Process the characters.
  33. while (*psz && !isspace(*psz)) {
  34. // Decode base58 character
  35. const char* ch = strchr(pszBase58, *psz);
  36. if (ch == nullptr)
  37. return false;
  38. // Apply "b256 = b256 * 58 + ch".
  39. int carry = ch - pszBase58;
  40. int i = 0;
  41. for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
  42. carry += 58 * (*it);
  43. *it = carry % 256;
  44. carry /= 256;
  45. }
  46. assert(carry == 0);
  47. length = i;
  48. psz++;
  49. }
  50. // Skip trailing spaces.
  51. while (isspace(*psz))
  52. psz++;
  53. if (*psz != 0)
  54. return false;
  55. // Skip leading zeroes in b256.
  56. std::vector<unsigned char>::iterator it = b256.begin() + (size - length);
  57. while (it != b256.end() && *it == 0)
  58. it++;
  59. // Copy result into output vector.
  60. vch.reserve(zeroes + (b256.end() - it));
  61. vch.assign(zeroes, 0x00);
  62. while (it != b256.end())
  63. vch.push_back(*(it++));
  64. return true;
  65. }
  66. std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
  67. {
  68. // Skip & count leading zeroes.
  69. int zeroes = 0;
  70. int length = 0;
  71. while (pbegin != pend && *pbegin == 0) {
  72. pbegin++;
  73. zeroes++;
  74. }
  75. // Allocate enough space in big-endian base58 representation.
  76. int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
  77. std::vector<unsigned char> b58(size);
  78. // Process the bytes.
  79. while (pbegin != pend) {
  80. int carry = *pbegin;
  81. int i = 0;
  82. // Apply "b58 = b58 * 256 + ch".
  83. for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
  84. carry += 256 * (*it);
  85. *it = carry % 58;
  86. carry /= 58;
  87. }
  88. assert(carry == 0);
  89. length = i;
  90. pbegin++;
  91. }
  92. // Skip leading zeroes in base58 result.
  93. std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
  94. while (it != b58.end() && *it == 0)
  95. it++;
  96. // Translate the result into a string.
  97. std::string str;
  98. str.reserve(zeroes + (b58.end() - it));
  99. str.assign(zeroes, '1');
  100. while (it != b58.end())
  101. str += pszBase58[*(it++)];
  102. return str;
  103. }
  104. std::string EncodeBase58(const std::vector<unsigned char>& vch)
  105. {
  106. return EncodeBase58(vch.data(), vch.data() + vch.size());
  107. }
  108. bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
  109. {
  110. return DecodeBase58(str.c_str(), vchRet);
  111. }
  112. std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
  113. {
  114. // add 4-byte hash check to the end
  115. std::vector<unsigned char> vch(vchIn);
  116. uint256 hash = Hash(vch.begin(), vch.end());
  117. vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
  118. return EncodeBase58(vch);
  119. }
  120. bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
  121. {
  122. if (!DecodeBase58(psz, vchRet) ||
  123. (vchRet.size() < 4)) {
  124. vchRet.clear();
  125. return false;
  126. }
  127. // re-calculate the checksum, ensure it matches the included 4-byte checksum
  128. uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
  129. if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
  130. vchRet.clear();
  131. return false;
  132. }
  133. vchRet.resize(vchRet.size() - 4);
  134. return true;
  135. }
  136. bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
  137. {
  138. return DecodeBase58Check(str.c_str(), vchRet);
  139. }
  140. CBase58Data::CBase58Data()
  141. {
  142. vchVersion.clear();
  143. vchData.clear();
  144. }
  145. void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
  146. {
  147. vchVersion = vchVersionIn;
  148. vchData.resize(nSize);
  149. if (!vchData.empty())
  150. memcpy(vchData.data(), pdata, nSize);
  151. }
  152. void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
  153. {
  154. SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
  155. }
  156. bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
  157. {
  158. std::vector<unsigned char> vchTemp;
  159. bool rc58 = DecodeBase58Check(psz, vchTemp);
  160. if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
  161. vchData.clear();
  162. vchVersion.clear();
  163. return false;
  164. }
  165. vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
  166. vchData.resize(vchTemp.size() - nVersionBytes);
  167. if (!vchData.empty())
  168. memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
  169. memory_cleanse(vchTemp.data(), vchTemp.size());
  170. return true;
  171. }
  172. bool CBase58Data::SetString(const std::string& str)
  173. {
  174. return SetString(str.c_str());
  175. }
  176. std::string CBase58Data::ToString() const
  177. {
  178. std::vector<unsigned char> vch = vchVersion;
  179. vch.insert(vch.end(), vchData.begin(), vchData.end());
  180. return EncodeBase58Check(vch);
  181. }
  182. int CBase58Data::CompareTo(const CBase58Data& b58) const
  183. {
  184. if (vchVersion < b58.vchVersion)
  185. return -1;
  186. if (vchVersion > b58.vchVersion)
  187. return 1;
  188. if (vchData < b58.vchData)
  189. return -1;
  190. if (vchData > b58.vchData)
  191. return 1;
  192. return 0;
  193. }
  194. namespace
  195. {
  196. class DestinationEncoder : public boost::static_visitor<std::string>
  197. {
  198. private:
  199. const CChainParams& m_params;
  200. public:
  201. DestinationEncoder(const CChainParams& params) : m_params(params) {}
  202. std::string operator()(const CKeyID& id) const
  203. {
  204. std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
  205. data.insert(data.end(), id.begin(), id.end());
  206. return EncodeBase58Check(data);
  207. }
  208. std::string operator()(const CScriptID& id) const
  209. {
  210. std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
  211. data.insert(data.end(), id.begin(), id.end());
  212. return EncodeBase58Check(data);
  213. }
  214. std::string operator()(const WitnessV0KeyHash& id) const
  215. {
  216. std::vector<unsigned char> data = {0};
  217. ConvertBits<8, 5, true>(data, id.begin(), id.end());
  218. return bech32::Encode(m_params.Bech32HRP(), data);
  219. }
  220. std::string operator()(const WitnessV0ScriptHash& id) const
  221. {
  222. std::vector<unsigned char> data = {0};
  223. ConvertBits<8, 5, true>(data, id.begin(), id.end());
  224. return bech32::Encode(m_params.Bech32HRP(), data);
  225. }
  226. std::string operator()(const WitnessUnknown& id) const
  227. {
  228. if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
  229. return {};
  230. }
  231. std::vector<unsigned char> data = {(unsigned char)id.version};
  232. ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
  233. return bech32::Encode(m_params.Bech32HRP(), data);
  234. }
  235. std::string operator()(const CNoDestination& no) const { return {}; }
  236. };
  237. CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
  238. {
  239. std::vector<unsigned char> data;
  240. uint160 hash;
  241. if (DecodeBase58Check(str, data)) {
  242. // base58-encoded Starwels addresses.
  243. // Public-key-hash-addresses have version 0 (or 111 ai).
  244. // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
  245. const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
  246. if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
  247. std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
  248. return CKeyID(hash);
  249. }
  250. // Script-hash-addresses have version 5 (or 196 ai).
  251. // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
  252. const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
  253. if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
  254. std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
  255. return CScriptID(hash);
  256. }
  257. }
  258. data.clear();
  259. auto bech = bech32::Decode(str);
  260. if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
  261. // Bech32 decoding
  262. int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
  263. // The rest of the symbols are converted witness program bytes.
  264. if (ConvertBits<5, 8, false>(data, bech.second.begin() + 1, bech.second.end())) {
  265. if (version == 0) {
  266. {
  267. WitnessV0KeyHash keyid;
  268. if (data.size() == keyid.size()) {
  269. std::copy(data.begin(), data.end(), keyid.begin());
  270. return keyid;
  271. }
  272. }
  273. {
  274. WitnessV0ScriptHash scriptid;
  275. if (data.size() == scriptid.size()) {
  276. std::copy(data.begin(), data.end(), scriptid.begin());
  277. return scriptid;
  278. }
  279. }
  280. return CNoDestination();
  281. }
  282. if (version > 16 || data.size() < 2 || data.size() > 40) {
  283. return CNoDestination();
  284. }
  285. WitnessUnknown unk;
  286. unk.version = version;
  287. std::copy(data.begin(), data.end(), unk.program);
  288. unk.length = data.size();
  289. return unk;
  290. }
  291. }
  292. return CNoDestination();
  293. }
  294. } // namespace
  295. void CStarwelsSecret::SetKey(const CKey& vchSecret)
  296. {
  297. assert(vchSecret.IsValid());
  298. SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
  299. if (vchSecret.IsCompressed())
  300. vchData.push_back(1);
  301. }
  302. CKey CStarwelsSecret::GetKey()
  303. {
  304. CKey ret;
  305. assert(vchData.size() >= 32);
  306. ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
  307. return ret;
  308. }
  309. bool CStarwelsSecret::IsValid() const
  310. {
  311. bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
  312. bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
  313. return fExpectedFormat && fCorrectVersion;
  314. }
  315. bool CStarwelsSecret::SetString(const char* pszSecret)
  316. {
  317. return CBase58Data::SetString(pszSecret) && IsValid();
  318. }
  319. bool CStarwelsSecret::SetString(const std::string& strSecret)
  320. {
  321. return SetString(strSecret.c_str());
  322. }
  323. std::string EncodeDestination(const CTxDestination& dest)
  324. {
  325. return boost::apply_visitor(DestinationEncoder(Params()), dest);
  326. }
  327. CTxDestination DecodeDestination(const std::string& str)
  328. {
  329. return DecodeDestination(str, Params());
  330. }
  331. bool IsValidDestinationString(const std::string& str, const CChainParams& params)
  332. {
  333. return IsValidDestination(DecodeDestination(str, params));
  334. }
  335. bool IsValidDestinationString(const std::string& str)
  336. {
  337. return IsValidDestinationString(str, Params());
  338. }