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.

bignum.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. // Copyright (c) 2009-2010 Satoshi Nakamoto
  2. // Distributed under the MIT/X11 software license, see the accompanying
  3. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
  4. #ifndef BITCOIN_BIGNUM_H
  5. #define BITCOIN_BIGNUM_H
  6. #include <stdexcept>
  7. #include <vector>
  8. #include <openssl/bn.h>
  9. #include "util.h"
  10. class bignum_error : public std::runtime_error
  11. {
  12. public:
  13. explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
  14. };
  15. class CAutoBN_CTX
  16. {
  17. protected:
  18. BN_CTX* pctx;
  19. BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
  20. public:
  21. CAutoBN_CTX()
  22. {
  23. pctx = BN_CTX_new();
  24. if (pctx == NULL)
  25. throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
  26. }
  27. ~CAutoBN_CTX()
  28. {
  29. if (pctx != NULL)
  30. BN_CTX_free(pctx);
  31. }
  32. operator BN_CTX*() { return pctx; }
  33. BN_CTX& operator*() { return *pctx; }
  34. BN_CTX** operator&() { return &pctx; }
  35. bool operator!() { return (pctx == NULL); }
  36. };
  37. class CBigNum : public BIGNUM
  38. {
  39. public:
  40. CBigNum()
  41. {
  42. BN_init(this);
  43. }
  44. CBigNum(const CBigNum& b)
  45. {
  46. BN_init(this);
  47. if (!BN_copy(this, &b))
  48. {
  49. BN_clear_free(this);
  50. throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
  51. }
  52. }
  53. CBigNum& operator=(const CBigNum& b)
  54. {
  55. if (!BN_copy(this, &b))
  56. throw bignum_error("CBigNum::operator= : BN_copy failed");
  57. return (*this);
  58. }
  59. ~CBigNum()
  60. {
  61. BN_clear_free(this);
  62. }
  63. CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
  64. CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
  65. CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
  66. CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
  67. CBigNum(int64 n) { BN_init(this); setint64(n); }
  68. CBigNum(unsigned char n) { BN_init(this); setulong(n); }
  69. CBigNum(unsigned short n) { BN_init(this); setulong(n); }
  70. CBigNum(unsigned int n) { BN_init(this); setulong(n); }
  71. CBigNum(unsigned long n) { BN_init(this); setulong(n); }
  72. CBigNum(uint64 n) { BN_init(this); setuint64(n); }
  73. explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); }
  74. explicit CBigNum(const std::vector<unsigned char>& vch)
  75. {
  76. BN_init(this);
  77. setvch(vch);
  78. }
  79. void setulong(unsigned long n)
  80. {
  81. if (!BN_set_word(this, n))
  82. throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
  83. }
  84. unsigned long getulong() const
  85. {
  86. return BN_get_word(this);
  87. }
  88. unsigned int getuint() const
  89. {
  90. return BN_get_word(this);
  91. }
  92. int getint() const
  93. {
  94. unsigned long n = BN_get_word(this);
  95. if (!BN_is_negative(this))
  96. return (n > INT_MAX ? INT_MAX : n);
  97. else
  98. return (n > INT_MAX ? INT_MIN : -(int)n);
  99. }
  100. void setint64(int64 n)
  101. {
  102. unsigned char pch[sizeof(n) + 6];
  103. unsigned char* p = pch + 4;
  104. bool fNegative = false;
  105. if (n < (int64)0)
  106. {
  107. n = -n;
  108. fNegative = true;
  109. }
  110. bool fLeadingZeroes = true;
  111. for (int i = 0; i < 8; i++)
  112. {
  113. unsigned char c = (n >> 56) & 0xff;
  114. n <<= 8;
  115. if (fLeadingZeroes)
  116. {
  117. if (c == 0)
  118. continue;
  119. if (c & 0x80)
  120. *p++ = (fNegative ? 0x80 : 0);
  121. else if (fNegative)
  122. c |= 0x80;
  123. fLeadingZeroes = false;
  124. }
  125. *p++ = c;
  126. }
  127. unsigned int nSize = p - (pch + 4);
  128. pch[0] = (nSize >> 24) & 0xff;
  129. pch[1] = (nSize >> 16) & 0xff;
  130. pch[2] = (nSize >> 8) & 0xff;
  131. pch[3] = (nSize) & 0xff;
  132. BN_mpi2bn(pch, p - pch, this);
  133. }
  134. void setuint64(uint64 n)
  135. {
  136. unsigned char pch[sizeof(n) + 6];
  137. unsigned char* p = pch + 4;
  138. bool fLeadingZeroes = true;
  139. for (int i = 0; i < 8; i++)
  140. {
  141. unsigned char c = (n >> 56) & 0xff;
  142. n <<= 8;
  143. if (fLeadingZeroes)
  144. {
  145. if (c == 0)
  146. continue;
  147. if (c & 0x80)
  148. *p++ = 0;
  149. fLeadingZeroes = false;
  150. }
  151. *p++ = c;
  152. }
  153. unsigned int nSize = p - (pch + 4);
  154. pch[0] = (nSize >> 24) & 0xff;
  155. pch[1] = (nSize >> 16) & 0xff;
  156. pch[2] = (nSize >> 8) & 0xff;
  157. pch[3] = (nSize) & 0xff;
  158. BN_mpi2bn(pch, p - pch, this);
  159. }
  160. void setuint256(uint256 n)
  161. {
  162. unsigned char pch[sizeof(n) + 6];
  163. unsigned char* p = pch + 4;
  164. bool fLeadingZeroes = true;
  165. unsigned char* pbegin = (unsigned char*)&n;
  166. unsigned char* psrc = pbegin + sizeof(n);
  167. while (psrc != pbegin)
  168. {
  169. unsigned char c = *(--psrc);
  170. if (fLeadingZeroes)
  171. {
  172. if (c == 0)
  173. continue;
  174. if (c & 0x80)
  175. *p++ = 0;
  176. fLeadingZeroes = false;
  177. }
  178. *p++ = c;
  179. }
  180. unsigned int nSize = p - (pch + 4);
  181. pch[0] = (nSize >> 24) & 0xff;
  182. pch[1] = (nSize >> 16) & 0xff;
  183. pch[2] = (nSize >> 8) & 0xff;
  184. pch[3] = (nSize >> 0) & 0xff;
  185. BN_mpi2bn(pch, p - pch, this);
  186. }
  187. uint256 getuint256()
  188. {
  189. unsigned int nSize = BN_bn2mpi(this, NULL);
  190. if (nSize < 4)
  191. return 0;
  192. std::vector<unsigned char> vch(nSize);
  193. BN_bn2mpi(this, &vch[0]);
  194. if (vch.size() > 4)
  195. vch[4] &= 0x7f;
  196. uint256 n = 0;
  197. for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
  198. ((unsigned char*)&n)[i] = vch[j];
  199. return n;
  200. }
  201. void setvch(const std::vector<unsigned char>& vch)
  202. {
  203. std::vector<unsigned char> vch2(vch.size() + 4);
  204. unsigned int nSize = vch.size();
  205. vch2[0] = (nSize >> 24) & 0xff;
  206. vch2[1] = (nSize >> 16) & 0xff;
  207. vch2[2] = (nSize >> 8) & 0xff;
  208. vch2[3] = (nSize >> 0) & 0xff;
  209. reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
  210. BN_mpi2bn(&vch2[0], vch2.size(), this);
  211. }
  212. std::vector<unsigned char> getvch() const
  213. {
  214. unsigned int nSize = BN_bn2mpi(this, NULL);
  215. if (nSize < 4)
  216. return std::vector<unsigned char>();
  217. std::vector<unsigned char> vch(nSize);
  218. BN_bn2mpi(this, &vch[0]);
  219. vch.erase(vch.begin(), vch.begin() + 4);
  220. reverse(vch.begin(), vch.end());
  221. return vch;
  222. }
  223. CBigNum& SetCompact(unsigned int nCompact)
  224. {
  225. unsigned int nSize = nCompact >> 24;
  226. std::vector<unsigned char> vch(4 + nSize);
  227. vch[3] = nSize;
  228. if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
  229. if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
  230. if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
  231. BN_mpi2bn(&vch[0], vch.size(), this);
  232. return *this;
  233. }
  234. unsigned int GetCompact() const
  235. {
  236. unsigned int nSize = BN_bn2mpi(this, NULL);
  237. std::vector<unsigned char> vch(nSize);
  238. nSize -= 4;
  239. BN_bn2mpi(this, &vch[0]);
  240. unsigned int nCompact = nSize << 24;
  241. if (nSize >= 1) nCompact |= (vch[4] << 16);
  242. if (nSize >= 2) nCompact |= (vch[5] << 8);
  243. if (nSize >= 3) nCompact |= (vch[6] << 0);
  244. return nCompact;
  245. }
  246. void SetHex(const std::string& str)
  247. {
  248. // skip 0x
  249. const char* psz = str.c_str();
  250. while (isspace(*psz))
  251. psz++;
  252. bool fNegative = false;
  253. if (*psz == '-')
  254. {
  255. fNegative = true;
  256. psz++;
  257. }
  258. if (psz[0] == '0' && tolower(psz[1]) == 'x')
  259. psz += 2;
  260. while (isspace(*psz))
  261. psz++;
  262. // hex string to bignum
  263. static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
  264. *this = 0;
  265. while (isxdigit(*psz))
  266. {
  267. *this <<= 4;
  268. int n = phexdigit[*psz++];
  269. *this += n;
  270. }
  271. if (fNegative)
  272. *this = 0 - *this;
  273. }
  274. std::string ToString(int nBase=10) const
  275. {
  276. CAutoBN_CTX pctx;
  277. CBigNum bnBase = nBase;
  278. CBigNum bn0 = 0;
  279. std::string str;
  280. CBigNum bn = *this;
  281. BN_set_negative(&bn, false);
  282. CBigNum dv;
  283. CBigNum rem;
  284. if (BN_cmp(&bn, &bn0) == 0)
  285. return "0";
  286. while (BN_cmp(&bn, &bn0) > 0)
  287. {
  288. if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
  289. throw bignum_error("CBigNum::ToString() : BN_div failed");
  290. bn = dv;
  291. unsigned int c = rem.getulong();
  292. str += "0123456789abcdef"[c];
  293. }
  294. if (BN_is_negative(this))
  295. str += "-";
  296. reverse(str.begin(), str.end());
  297. return str;
  298. }
  299. std::string GetHex() const
  300. {
  301. return ToString(16);
  302. }
  303. unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
  304. {
  305. return ::GetSerializeSize(getvch(), nType, nVersion);
  306. }
  307. template<typename Stream>
  308. void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
  309. {
  310. ::Serialize(s, getvch(), nType, nVersion);
  311. }
  312. template<typename Stream>
  313. void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
  314. {
  315. std::vector<unsigned char> vch;
  316. ::Unserialize(s, vch, nType, nVersion);
  317. setvch(vch);
  318. }
  319. bool operator!() const
  320. {
  321. return BN_is_zero(this);
  322. }
  323. CBigNum& operator+=(const CBigNum& b)
  324. {
  325. if (!BN_add(this, this, &b))
  326. throw bignum_error("CBigNum::operator+= : BN_add failed");
  327. return *this;
  328. }
  329. CBigNum& operator-=(const CBigNum& b)
  330. {
  331. *this = *this - b;
  332. return *this;
  333. }
  334. CBigNum& operator*=(const CBigNum& b)
  335. {
  336. CAutoBN_CTX pctx;
  337. if (!BN_mul(this, this, &b, pctx))
  338. throw bignum_error("CBigNum::operator*= : BN_mul failed");
  339. return *this;
  340. }
  341. CBigNum& operator/=(const CBigNum& b)
  342. {
  343. *this = *this / b;
  344. return *this;
  345. }
  346. CBigNum& operator%=(const CBigNum& b)
  347. {
  348. *this = *this % b;
  349. return *this;
  350. }
  351. CBigNum& operator<<=(unsigned int shift)
  352. {
  353. if (!BN_lshift(this, this, shift))
  354. throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
  355. return *this;
  356. }
  357. CBigNum& operator>>=(unsigned int shift)
  358. {
  359. // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
  360. // if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
  361. CBigNum a = 1;
  362. a <<= shift;
  363. if (BN_cmp(&a, this) > 0)
  364. {
  365. *this = 0;
  366. return *this;
  367. }
  368. if (!BN_rshift(this, this, shift))
  369. throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
  370. return *this;
  371. }
  372. CBigNum& operator++()
  373. {
  374. // prefix operator
  375. if (!BN_add(this, this, BN_value_one()))
  376. throw bignum_error("CBigNum::operator++ : BN_add failed");
  377. return *this;
  378. }
  379. const CBigNum operator++(int)
  380. {
  381. // postfix operator
  382. const CBigNum ret = *this;
  383. ++(*this);
  384. return ret;
  385. }
  386. CBigNum& operator--()
  387. {
  388. // prefix operator
  389. CBigNum r;
  390. if (!BN_sub(&r, this, BN_value_one()))
  391. throw bignum_error("CBigNum::operator-- : BN_sub failed");
  392. *this = r;
  393. return *this;
  394. }
  395. const CBigNum operator--(int)
  396. {
  397. // postfix operator
  398. const CBigNum ret = *this;
  399. --(*this);
  400. return ret;
  401. }
  402. friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
  403. friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
  404. friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
  405. };
  406. inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
  407. {
  408. CBigNum r;
  409. if (!BN_add(&r, &a, &b))
  410. throw bignum_error("CBigNum::operator+ : BN_add failed");
  411. return r;
  412. }
  413. inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
  414. {
  415. CBigNum r;
  416. if (!BN_sub(&r, &a, &b))
  417. throw bignum_error("CBigNum::operator- : BN_sub failed");
  418. return r;
  419. }
  420. inline const CBigNum operator-(const CBigNum& a)
  421. {
  422. CBigNum r(a);
  423. BN_set_negative(&r, !BN_is_negative(&r));
  424. return r;
  425. }
  426. inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
  427. {
  428. CAutoBN_CTX pctx;
  429. CBigNum r;
  430. if (!BN_mul(&r, &a, &b, pctx))
  431. throw bignum_error("CBigNum::operator* : BN_mul failed");
  432. return r;
  433. }
  434. inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
  435. {
  436. CAutoBN_CTX pctx;
  437. CBigNum r;
  438. if (!BN_div(&r, NULL, &a, &b, pctx))
  439. throw bignum_error("CBigNum::operator/ : BN_div failed");
  440. return r;
  441. }
  442. inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
  443. {
  444. CAutoBN_CTX pctx;
  445. CBigNum r;
  446. if (!BN_mod(&r, &a, &b, pctx))
  447. throw bignum_error("CBigNum::operator% : BN_div failed");
  448. return r;
  449. }
  450. inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
  451. {
  452. CBigNum r;
  453. if (!BN_lshift(&r, &a, shift))
  454. throw bignum_error("CBigNum:operator<< : BN_lshift failed");
  455. return r;
  456. }
  457. inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
  458. {
  459. CBigNum r = a;
  460. r >>= shift;
  461. return r;
  462. }
  463. inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
  464. inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
  465. inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
  466. inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
  467. inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); }
  468. inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
  469. #endif