#include #include #include #include #include #include "../byteswap.hpp" namespace fc { bigint::bigint( const char* bige, uint32_t l ) { n = BN_bin2bn( (const unsigned char*)bige, l, NULL ); FC_ASSERT( n != nullptr ); } bigint::bigint( const std::vector& bige ) { n = BN_bin2bn( (const unsigned char*)bige.data(), bige.size(), NULL ); FC_ASSERT( n != nullptr ); } bigint::bigint( BIGNUM* in ) { n = BN_dup(in); } bigint::bigint( ) :n(BN_new()) { } BIGNUM* bigint::dup()const { return BN_dup( n ); } bigint::bigint(uint64_t value) { uint64_t big_endian_value = bswap_64(value); n = BN_bin2bn((const unsigned char*)&big_endian_value, sizeof(big_endian_value), NULL); } bigint::bigint( const bigint& c ) { n = BN_dup( c.n ); } bigint::bigint( bigint&& b ) { n = b.n; b.n = 0; } bigint::~bigint() { if(n!=0) BN_free(n); } bool bigint::is_negative()const { return BN_is_negative(n); } int64_t bigint::to_int64() const { FC_ASSERT(BN_num_bits(n) <= 63); size_t size = BN_num_bytes(n); uint64_t abs_value = 0; BN_bn2bin(n, (unsigned char*)&abs_value + (sizeof(uint64_t) - size)); return BN_is_negative(n) ? -(int64_t)bswap_64(abs_value) : bswap_64(abs_value); } int64_t bigint::log2()const { return BN_num_bits(n); } bool bigint::operator < ( const bigint& c )const { return BN_cmp( n, c.n ) < 0; } bool bigint::operator > ( const bigint& c )const { return BN_cmp( n, c.n ) > 0; } bool bigint::operator >= ( const bigint& c )const { return BN_cmp( n, c.n ) >= 0; } bool bigint::operator == ( const bigint& c )const { return BN_cmp( n, c.n ) == 0; } bool bigint::operator != ( const bigint& c )const { return BN_cmp( n, c.n ) != 0; } bigint::operator bool()const { return !BN_is_zero( n ); } bigint bigint::operator++(int) { bigint tmp = *this; *this = *this + bigint(1); return tmp; } bigint& bigint::operator++() { return *this = *this + bigint(1); } bigint bigint::operator--(int) { bigint tmp = *this; *this = *this - bigint(1); return tmp; } bigint& bigint::operator--() { return *this = *this - bigint(1); } bigint bigint::operator + ( const bigint& a )const { bigint tmp(*this); BN_add( tmp.n, n, a.n ); return tmp; } bigint& bigint::operator += ( const bigint& a ){ bigint tmp(*this); BN_add( tmp.n, n, a.n ); std::swap(*this,tmp); return *this; } bigint& bigint::operator -= ( const bigint& a ){ bigint tmp(*this); BN_sub( tmp.n, n, a.n ); std::swap(*this,tmp); return *this; } bigint bigint::operator * ( const bigint& a )const { BN_CTX* ctx = BN_CTX_new(); bigint tmp(*this); BN_mul( tmp.n, n, a.n, ctx ); BN_CTX_free(ctx); return tmp; } bigint bigint::operator / ( const bigint& a ) const { BN_CTX* ctx = BN_CTX_new(); bigint tmp; BN_div( tmp.n, NULL, n, a.n, ctx ); BN_CTX_free(ctx); return tmp; } bigint bigint::operator % ( const bigint& a ) const { BN_CTX* ctx = BN_CTX_new(); bigint tmp; BN_mod( tmp.n, n, a.n, ctx ); BN_CTX_free(ctx); return tmp; } bigint bigint::operator /= ( const bigint& a ) { BN_CTX* ctx = BN_CTX_new(); bigint tmp; BN_div( tmp.n, NULL, n, a.n, ctx ); std::swap( tmp.n, n ); BN_CTX_free(ctx); return tmp; } bigint bigint::operator *= ( const bigint& a ) { auto tmp = *this * a; *this = std::move(tmp); return *this; } bigint& bigint::operator >>= ( uint32_t i ) { bigint tmp; BN_rshift( tmp.n, n, i ); std::swap(*this,tmp); return *this; } bigint& bigint::operator <<= ( uint32_t i ) { bigint tmp; FC_ASSERT( tmp.n != nullptr ); FC_ASSERT( n != nullptr ); BN_lshift( tmp.n, n, i ); std::swap(*this,tmp); return *this; } bigint bigint::operator - ( const bigint& a )const { bigint tmp; BN_sub( tmp.n, n, a.n ); return tmp; } bigint bigint::exp( const bigint& a )const { BN_CTX* ctx = BN_CTX_new(); bigint tmp; BN_exp( tmp.n, n, a.n, ctx ); BN_CTX_free(ctx); return tmp; } bigint& bigint::operator = ( bigint&& a ) { if( &a == this ) return *this; std::swap( a.n, n ); return *this; } bigint& bigint::operator = ( const bigint& a ) { if( &a == this ) return *this; BN_copy( n, a.n ); return *this; } bigint::operator std::string()const { return BN_bn2dec(n); } bigint::operator std::vector()const { std::vector to(BN_num_bytes(n)); BN_bn2bin(n,(unsigned char*)to.data()); return to; } /** encodes the big int as base64 string, or a number */ void to_variant( const bigint& bi, variant& v, uint32_t max_depth ) { std::vector ve = bi; v = fc::variant(base64_encode((unsigned char*)ve.data(),ve.size())); } /** decodes the big int as base64 string, or a number */ void from_variant( const variant& v, bigint& bi, uint32_t max_depth ) { if( v.is_numeric() ) bi = bigint( static_cast(v.as_uint64()) ); else { std::string b64 = v.as_string(); std::string bin = base64_decode(b64); bi = bigint(bin.c_str(), bin.size() ); } } } // namespace fc