git / moonbite-core / src/libmw/include/mw/models/crypto/BigInteger.h · raw

#pragma once// Copyright (c) 2018-2019 David Burkett// Distributed under the MIT software license, see the accompanying// file LICENSE or http://www.opensource.org/licenses/mit-license.php.#include <mw/common/Traits.h>#include <util/strencodings.h>#include <cassert>#include <stdexcept>#include <sstream>#include <iomanip>#include <algorithm>#include <array>#ifdef _MSC_VER#pragma warning(disable: 4505)#endiftemplate<size_t NUM_BYTES, class ALLOC = std::allocator<uint8_t>>class BigInt :    public Traits::IPrintable,    public Traits::ISerializable{public:    //    // Constructors    //    BigInt() noexcept : m_bytes(NUM_BYTES) { }    BigInt(const std::vector<uint8_t, ALLOC>& bytes) : m_bytes(bytes) { assert(m_bytes.size() == NUM_BYTES); }    BigInt(std::vector<uint8_t, ALLOC>&& bytes) : m_bytes(std::move(bytes)) { assert(m_bytes.size() == NUM_BYTES); }    BigInt(const std::array<uint8_t, NUM_BYTES>& bytes) : m_bytes(bytes.cbegin(), bytes.cend()) { }    explicit BigInt(const uint8_t* arr) : m_bytes(arr, arr + NUM_BYTES) { }    BigInt(const BigInt& bigInteger) = default;    BigInt(BigInt&& bigInteger) noexcept = default;    //    // Destructor    //    virtual ~BigInt()    {        for (size_t i = 0; i < m_bytes.size(); i++)        {            m_bytes[i] = 0;        }    }    static size_t size() noexcept { return NUM_BYTES; }    const std::vector<uint8_t, ALLOC>& vec() const { return m_bytes; }    uint8_t* data() { return m_bytes.data(); }    const uint8_t* data() const { return m_bytes.data(); }    bool IsZero() const noexcept    {        assert(m_bytes.size() == NUM_BYTES);        for (uint8_t byte : m_bytes)        {            if (byte != 0) {                return false;            }        }        return true;    }    static BigInt<NUM_BYTES, ALLOC> ValueOf(const uint8_t value)    {        std::vector<uint8_t, ALLOC> bytes(NUM_BYTES);        bytes[NUM_BYTES - 1] = value;        return BigInt<NUM_BYTES, ALLOC>(std::move(bytes));    }    static BigInt<NUM_BYTES, ALLOC> FromHex(const std::string& hex)    {        assert(hex.length() == NUM_BYTES * 2);        std::vector<uint8_t> bytes = ParseHex(hex);        assert(bytes.size() == NUM_BYTES);        return BigInt<NUM_BYTES, ALLOC>(std::move(bytes));    }    static BigInt<NUM_BYTES, ALLOC> Max()    {        std::vector<uint8_t, ALLOC> bytes(NUM_BYTES);        for (size_t i = 0; i < NUM_BYTES; i++)        {            bytes[i] = 0xFF;        }        return BigInt<NUM_BYTES, ALLOC>(std::move(bytes));    }    std::array<uint8_t, NUM_BYTES> ToArray() const noexcept    {        std::array<uint8_t, NUM_BYTES> arr;        std::copy_n(m_bytes.begin(), NUM_BYTES, arr.begin());        return arr;    }    std::string ToHex() const noexcept { return HexStr(m_bytes); }    std::string Format() const noexcept final { return ToHex(); }    //    // Operators    //    BigInt& operator=(const BigInt& other) = default;    BigInt& operator=(BigInt&& other) noexcept = default;    BigInt operator^(const BigInt& rhs) const    {        BigInt<NUM_BYTES, ALLOC> result = *this;        for (size_t i = 0; i < NUM_BYTES; i++)        {            result[i] ^= rhs[i];        }        return result;    }    uint8_t& operator[] (const size_t x) { return m_bytes[x]; }    const uint8_t& operator[] (const size_t x) const { return m_bytes[x]; }    bool operator<(const BigInt& rhs) const noexcept    {        if (this == &rhs)        {            return false;        }        assert(m_bytes.size() == NUM_BYTES && rhs.m_bytes.size() == NUM_BYTES);        for (size_t i = 0; i < NUM_BYTES; i++)        {            if (m_bytes[i] != rhs.m_bytes[i])            {                return m_bytes[i] < rhs.m_bytes[i];            }        }        return false;    }    bool operator>(const BigInt& rhs) const    {        return rhs < *this;    }    bool operator==(const BigInt& rhs) const    {        return this == &rhs || this->m_bytes == rhs.m_bytes;    }    bool operator!=(const BigInt& rhs) const    {        return !(*this == rhs);    }    bool operator<=(const BigInt& rhs) const    {        return *this < rhs || *this == rhs;    }    bool operator>=(const BigInt& rhs) const    {        return *this > rhs || *this == rhs;    }    BigInt operator^=(const BigInt& rhs)    {        *this = *this ^ rhs;        return *this;    }    //    // Serialization/Deserialization    //    IMPL_SERIALIZED(BigInt);    template <typename Stream>    void Serialize(Stream& s) const    {        s.write((const char*)m_bytes.data(), NUM_BYTES);    }    template <typename Stream>    void Unserialize(Stream& s)    {        s.read((char*)m_bytes.data(), NUM_BYTES);    }private:    std::vector<uint8_t, ALLOC> m_bytes;};