LCOV - code coverage report
Current view: top level - src/test - bignum.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 77 88 87.5 %
Date: 2015-10-12 22:39:14 Functions: 8 15 53.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2013 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_TEST_BIGNUM_H
       7             : #define BITCOIN_TEST_BIGNUM_H
       8             : 
       9             : #include <algorithm>
      10             : #include <limits>
      11             : #include <stdexcept>
      12             : #include <stdint.h>
      13             : #include <string>
      14             : #include <vector>
      15             : 
      16             : #include <openssl/bn.h>
      17             : 
      18           0 : class bignum_error : public std::runtime_error
      19             : {
      20             : public:
      21           0 :     explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
      22             : };
      23             : 
      24             : 
      25             : /** C++ wrapper for BIGNUM (OpenSSL bignum) */
      26             : class CBigNum : public BIGNUM
      27             : {
      28             : public:
      29           0 :     CBigNum()
      30        8473 :     {
      31        8473 :         BN_init(this);
      32           0 :     }
      33             : 
      34        1248 :     CBigNum(const CBigNum& b)
      35        1248 :     {
      36        1248 :         BN_init(this);
      37        1248 :         if (!BN_copy(this, &b))
      38             :         {
      39           0 :             BN_clear_free(this);
      40           0 :             throw bignum_error("CBigNum::CBigNum(const CBigNum&): BN_copy failed");
      41             :         }
      42        1248 :     }
      43             : 
      44             :     CBigNum& operator=(const CBigNum& b)
      45             :     {
      46             :         if (!BN_copy(this, &b))
      47             :             throw bignum_error("CBigNum::operator=: BN_copy failed");
      48             :         return (*this);
      49             :     }
      50             : 
      51           0 :     ~CBigNum()
      52             :     {
      53       23869 :         BN_clear_free(this);
      54       23869 :     }
      55             : 
      56       12312 :     CBigNum(long long n)          { BN_init(this); setint64(n); }
      57             : 
      58           0 :     explicit CBigNum(const std::vector<unsigned char>& vch)
      59         540 :     {
      60         540 :         BN_init(this);
      61         540 :         setvch(vch);
      62           0 :     }
      63             : 
      64       13069 :     int getint() const
      65             :     {
      66       13069 :         BN_ULONG n = BN_get_word(this);
      67       13069 :         if (!BN_is_negative(this))
      68        8146 :             return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
      69             :         else
      70        4923 :             return (n > (BN_ULONG)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
      71             :     }
      72             : 
      73       13608 :     void setint64(int64_t sn)
      74             :     {
      75             :         unsigned char pch[sizeof(sn) + 6];
      76       13608 :         unsigned char* p = pch + 4;
      77             :         bool fNegative;
      78             :         uint64_t n;
      79             : 
      80       13608 :         if (sn < (int64_t)0)
      81             :         {
      82             :             // Since the minimum signed integer cannot be represented as positive so long as its type is signed, 
      83             :             // and it's not well-defined what happens if you make it unsigned before negating it,
      84             :             // we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
      85        5484 :             n = -(sn + 1);
      86        5484 :             ++n;
      87        5484 :             fNegative = true;
      88             :         } else {
      89        8124 :             n = sn;
      90        8124 :             fNegative = false;
      91             :         }
      92             : 
      93       13608 :         bool fLeadingZeroes = true;
      94      122472 :         for (int i = 0; i < 8; i++)
      95             :         {
      96      108864 :             unsigned char c = (n >> 56) & 0xff;
      97      108864 :             n <<= 8;
      98      108864 :             if (fLeadingZeroes)
      99             :             {
     100       79938 :                 if (c == 0)
     101             :                     continue;
     102       12738 :                 if (c & 0x80)
     103        6362 :                     *p++ = (fNegative ? 0x80 : 0);
     104        6376 :                 else if (fNegative)
     105        2266 :                     c |= 0x80;
     106             :                 fLeadingZeroes = false;
     107             :             }
     108       41664 :             *p++ = c;
     109             :         }
     110       13608 :         unsigned int nSize = p - (pch + 4);
     111       13608 :         pch[0] = (nSize >> 24) & 0xff;
     112       13608 :         pch[1] = (nSize >> 16) & 0xff;
     113       13608 :         pch[2] = (nSize >> 8) & 0xff;
     114       13608 :         pch[3] = (nSize) & 0xff;
     115       13608 :         BN_mpi2bn(pch, p - pch, this);
     116       13608 :     }
     117             : 
     118         540 :     void setvch(const std::vector<unsigned char>& vch)
     119             :     {
     120        1620 :         std::vector<unsigned char> vch2(vch.size() + 4);
     121        1080 :         unsigned int nSize = vch.size();
     122             :         // BIGNUM's byte stream format expects 4 bytes of
     123             :         // big endian size data info at the front
     124         540 :         vch2[0] = (nSize >> 24) & 0xff;
     125         540 :         vch2[1] = (nSize >> 16) & 0xff;
     126         540 :         vch2[2] = (nSize >> 8) & 0xff;
     127         540 :         vch2[3] = (nSize >> 0) & 0xff;
     128             :         // swap data to big endian
     129        1620 :         reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
     130        1080 :         BN_mpi2bn(&vch2[0], vch2.size(), this);
     131         540 :     }
     132             : 
     133       12313 :     std::vector<unsigned char> getvch() const
     134             :     {
     135       12313 :         unsigned int nSize = BN_bn2mpi(this, NULL);
     136       12313 :         if (nSize <= 4)
     137             :             return std::vector<unsigned char>();
     138       19962 :         std::vector<unsigned char> vch(nSize);
     139        9981 :         BN_bn2mpi(this, &vch[0]);
     140       19962 :         vch.erase(vch.begin(), vch.begin() + 4);
     141             :         reverse(vch.begin(), vch.end());
     142        9981 :         return vch;
     143             :     }
     144             : 
     145             :     friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
     146             : };
     147             : 
     148             : 
     149             : 
     150        3591 : inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
     151             : {
     152             :     CBigNum r;
     153        3591 :     if (!BN_add(&r, &a, &b))
     154           0 :         throw bignum_error("CBigNum::operator+: BN_add failed");
     155        3591 :     return r;
     156             : }
     157             : 
     158        4882 : inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
     159             : {
     160             :     CBigNum r;
     161        4882 :     if (!BN_sub(&r, &a, &b))
     162           0 :         throw bignum_error("CBigNum::operator-: BN_sub failed");
     163        4882 :     return r;
     164             : }
     165             : 
     166        1248 : inline const CBigNum operator-(const CBigNum& a)
     167             : {
     168        1248 :     CBigNum r(a);
     169        1248 :     BN_set_negative(&r, !BN_is_negative(&r));
     170        1248 :     return r;
     171             : }
     172             : 
     173        5184 : inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
     174        5184 : inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
     175        5184 : inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
     176        5184 : inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
     177        5184 : inline bool operator<(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) < 0); }
     178        5184 : inline bool operator>(const CBigNum& a, const CBigNum& b)  { return (BN_cmp(&a, &b) > 0); }
     179             : 
     180             : #endif // BITCOIN_TEST_BIGNUM_H

Generated by: LCOV version 1.11