1
0
mirror of https://github.com/danog/ton.git synced 2024-12-02 17:38:33 +01:00
ton/crypto/openssl/bignum.h
ton 13140ddf29 updated block header
1. Updated block header, proofs now contain more data
   Notice, that old proofs may become invalid in the future
2. Fixed message routing
3. Fixed block creator id in block header
4. Support for full proofs in tonlib
5. Support for partial state download
6. Some other bugfixes
2019-09-18 21:46:32 +04:00

385 lines
8.6 KiB
C++

/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <string>
#include <iostream>
#include <openssl/bn.h>
#include "td/utils/bits.h"
#include "td/utils/misc.h"
namespace arith {
struct dec_string {
std::string str;
explicit dec_string(const std::string& s) : str(s) {
}
};
struct hex_string {
std::string str;
explicit hex_string(const std::string& s) : str(s) {
}
};
struct bin_string {
std::string str;
explicit bin_string(const std::string& s) : str(s) {
}
};
} // namespace arith
namespace arith {
inline void bn_assert(int cond);
BN_CTX* get_ctx();
class BignumBitref {
BIGNUM* ptr;
int n;
public:
BignumBitref(BIGNUM* x, int _n) : ptr(x), n(_n){};
operator bool() const {
return BN_is_bit_set(ptr, n);
}
BignumBitref& operator=(bool val);
};
class Bignum {
BIGNUM* val;
public:
class bignum_error {};
Bignum() {
val = BN_new();
}
Bignum(long x) {
val = BN_new();
set_long(x);
}
~Bignum() {
BN_free(val);
}
Bignum(const bin_string& bs) {
val = BN_new();
set_dec_str(bs.str);
}
Bignum(const dec_string& ds) {
val = BN_new();
set_dec_str(ds.str);
}
Bignum(const hex_string& hs) {
val = BN_new();
set_hex_str(hs.str);
}
Bignum(const Bignum& x) {
val = BN_new();
BN_copy(val, x.val);
}
//Bignum (Bignum&& x) { val = x.val; }
void clear() {
BN_clear(val);
} // use this for sensitive data
Bignum& operator=(const Bignum& x) {
BN_copy(val, x.val);
return *this;
}
Bignum& operator=(Bignum&& x) {
swap(x);
return *this;
}
Bignum& operator=(long x) {
return set_long(x);
}
Bignum& operator=(const dec_string& ds) {
return set_dec_str(ds.str);
}
Bignum& operator=(const hex_string& hs) {
return set_hex_str(hs.str);
}
Bignum& swap(Bignum& x) {
BN_swap(val, x.val);
return *this;
}
BIGNUM* bn_ptr() {
return val;
}
const BIGNUM* bn_ptr() const {
return val;
}
bool is_zero() const {
return BN_is_zero(val);
}
int sign() const {
return BN_is_zero(val) ? 0 : (BN_is_negative(val) ? -1 : 1);
}
bool odd() const {
return BN_is_odd(val);
}
int num_bits() const {
return BN_num_bits(val);
}
int num_bytes() const {
return BN_num_bytes(val);
}
bool operator[](int n) const {
return BN_is_bit_set(val, n);
}
BignumBitref operator[](int n) {
return BignumBitref(val, n);
}
void export_msb(unsigned char* buffer, std::size_t size) const;
Bignum& import_msb(const unsigned char* buffer, std::size_t size);
Bignum& import_msb(const std::string& s) {
return import_msb((const unsigned char*)s.c_str(), s.size());
}
void export_lsb(unsigned char* buffer, std::size_t size) const;
Bignum& import_lsb(const unsigned char* buffer, std::size_t size);
Bignum& import_lsb(const std::string& s) {
return import_lsb((const unsigned char*)s.c_str(), s.size());
}
Bignum& set_dec_str(std::string s) {
bn_assert(BN_dec2bn(&val, s.c_str()));
return *this;
}
Bignum& set_raw_bytes(std::string s) {
CHECK(BN_bin2bn(reinterpret_cast<const td::uint8*>(s.c_str()), td::narrow_cast<td::uint32>(s.size()), val));
return *this;
}
Bignum& set_hex_str(std::string s) {
bn_assert(BN_hex2bn(&val, s.c_str()));
return *this;
}
Bignum& set_ulong(unsigned long x) {
bn_assert(BN_set_word(val, x));
return *this;
}
Bignum& set_long(long x) {
set_ulong(std::abs(x));
return x < 0 ? negate() : *this;
}
Bignum& negate() {
BN_set_negative(val, !BN_is_negative(val));
return *this;
}
Bignum& operator+=(const Bignum& y) {
bn_assert(BN_add(val, val, y.val));
return *this;
}
Bignum& operator+=(long y) {
bn_assert((y >= 0 ? BN_add_word : BN_sub_word)(val, std::abs(y)));
return *this;
}
Bignum& operator-=(long y) {
bn_assert((y >= 0 ? BN_sub_word : BN_add_word)(val, std::abs(y)));
return *this;
}
Bignum& operator*=(const Bignum& y) {
bn_assert(BN_mul(val, val, y.val, get_ctx()));
return *this;
}
Bignum& operator*=(long y) {
if (y < 0) {
negate();
}
bn_assert(BN_mul_word(val, std::abs(y)));
return *this;
}
Bignum& operator<<=(int r) {
bn_assert(BN_lshift(val, val, r));
return *this;
}
Bignum& operator>>=(int r) {
bn_assert(BN_rshift(val, val, r));
return *this;
}
Bignum& operator/=(const Bignum& y) {
Bignum w;
bn_assert(BN_div(val, w.val, val, y.val, get_ctx()));
return *this;
}
Bignum& operator/=(long y) {
bn_assert(BN_div_word(val, std::abs(y)) != (BN_ULONG)(-1));
return y < 0 ? negate() : *this;
}
Bignum& operator%=(const Bignum& y) {
bn_assert(BN_mod(val, val, y.val, get_ctx()));
return *this;
}
Bignum& operator%=(long y) {
BN_ULONG rem = BN_mod_word(val, std::abs(y));
bn_assert(rem != (BN_ULONG)(-1));
return set_long(static_cast<long>(y < 0 ? td::bits_negate64(rem) : rem));
}
unsigned long divmod(unsigned long y) {
BN_ULONG rem = BN_div_word(val, y);
bn_assert(rem != (BN_ULONG)(-1));
return static_cast<unsigned long>(rem);
}
const Bignum divmod(const Bignum& y);
std::string to_str() const;
std::string to_hex() const;
};
inline void bn_assert(int cond) {
if (!cond) {
throw Bignum::bignum_error();
}
}
BN_CTX* get_ctx(void);
const Bignum operator+(const Bignum& x, const Bignum& y);
const Bignum operator+(const Bignum& x, long y);
/*
const Bignum operator+ (Bignum&& x, long y) {
if (y > 0) {
bn_assert (BN_add_word (x.bn_ptr(), y));
} else if (y < 0) {
bn_assert (BN_sub_word (x.bn_ptr(), -y));
}
return std::move (x);
}
*/
inline const Bignum operator+(long y, const Bignum& x) {
return x + y;
}
/*
const Bignum operator+ (long y, Bignum&& x) {
return x + y;
}
*/
const Bignum operator-(const Bignum& x, const Bignum& y);
inline const Bignum operator-(const Bignum& x, long y) {
return x + (-y);
}
/*
const Bignum operator- (Bignum&& x, long y) {
return x + (-y);
}
*/
const Bignum operator*(const Bignum& x, const Bignum& y);
const Bignum operator*(const Bignum& x, long y);
/*
const Bignum operator* (Bignum&& x, long y) {
if (y > 0) {
bn_assert (BN_mul_word (x.bn_ptr(), y));
} else if (y < 0) {
x.negate();
bn_assert (BN_mul_word (x.bn_ptr(), -y));
} else {
x = 0;
}
return std::move (x);
}
*/
inline const Bignum operator*(long y, const Bignum& x) {
return x * y;
}
const Bignum operator/(const Bignum& x, const Bignum& y);
const Bignum operator%(const Bignum& x, const Bignum& y);
unsigned long operator%(const Bignum& x, unsigned long y);
const Bignum operator<<(const Bignum& x, int r);
const Bignum operator>>(const Bignum& x, int r);
const Bignum abs(const Bignum& x);
const Bignum sqr(const Bignum& x);
std::ostream& operator<<(std::ostream& os, const Bignum& x);
std::istream& operator>>(std::istream& is, Bignum& x);
bool is_prime(const Bignum& p, int nchecks = 64, bool trial_div = true);
inline int cmp(const Bignum& x, const Bignum& y) {
return BN_cmp(x.bn_ptr(), y.bn_ptr());
}
inline bool operator==(const Bignum& x, const Bignum& y) {
return cmp(x, y) == 0;
}
inline bool operator!=(const Bignum& x, const Bignum& y) {
return cmp(x, y) != 0;
}
inline bool operator<(const Bignum& x, const Bignum& y) {
return cmp(x, y) < 0;
}
inline bool operator<=(const Bignum& x, const Bignum& y) {
return cmp(x, y) <= 0;
}
inline bool operator>(const Bignum& x, const Bignum& y) {
return cmp(x, y) > 0;
}
inline bool operator>=(const Bignum& x, const Bignum& y) {
return cmp(x, y) >= 0;
}
inline bool operator==(const Bignum& x, long y) {
if (y >= 0) {
return BN_is_word(x.bn_ptr(), y);
} else {
return x == Bignum(y);
}
}
inline bool operator!=(const Bignum& x, long y) {
if (y >= 0) {
return !BN_is_word(x.bn_ptr(), y);
} else {
return x != Bignum(y);
}
}
} // namespace arith