Repository: bitcoin/bitcoin
File: src/uint256.h (C/C++)

Code before:
    }

    constexpr bool IsNull() const
    {
        return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
            return val == 0;
        });
    }

    constexpr void SetNull()
    {
        std::fill(m_data.begin(), m_data.end(), 0);
    }

    constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); }

    friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
    friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
    friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }

    // Hex string representations are little-endian.
    std::string GetHex() const;
    /** Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated */
    void SetHexDeprecated(std::string_view str);
    std::string ToString() const;

    constexpr const unsigned char* data() const { return m_data.data(); }
    constexpr unsigned char* data() { return m_data.data(); }

    constexpr unsigned char* begin() { return m_data.data(); }
    constexpr unsigned char* end() { return m_data.data() + WIDTH; }

    constexpr const unsigned char* begin() const { return m_data.data(); }
    constexpr const unsigned char* end() const { return m_data.data() + WIDTH; }

    static constexpr unsigned int size() { return WIDTH; }

    constexpr uint64_t GetUint64(int pos) const { return ReadLE64(m_data.data() + pos * 8); }

    template<typename Stream>
    void Serialize(Stream& s) const
    {
        s << Span(m_data);
    }

    template<typename Stream>
    void Unserialize(Stream& s)
    {
        s.read(MakeWritableByteSpan(m_data));
    }
};

Review comment (suggestion):
In commit "doc + test: Correct uint256 hex string endianness" (07de45a882d43fd5567b2a6b7c8a2da3d6dbda3d)

Statement "This is consistent with the internal array of arith_* being little-endian." seems a bit vague to me. Also calling internal representation of the arithmetic class little endian might not be ideal because endianness normally refers to bytes, and the arithmetic class stores an array of uint32_t numbers, not of bytes.

I think I would suggest changing line to:

- The reverse-byte hex representation is a convenient way to view the blob as a number, because it is consistent with the way the `base_uint` class converts blobs to numbers.

  `base_uint` treats the blob as an array of bytes with the numerically least significant byte first and the most significant byte last. Because numbers are typically written with the most significant digit first and the least significant digit last, the reverse hex display of the blob corresponds to the same numeric value that `base_uint` interprets from the blob.


Code after:
    }

    constexpr bool IsNull() const
    {
        return std::all_of(m_data.begin(), m_data.end(), [](uint8_t val) {
            return val == 0;
        });
    }

    constexpr void SetNull()
    {
        std::fill(m_data.begin(), m_data.end(), 0);
    }

    /** Lexicographic ordering
     * @note Does NOT match the ordering on the corresponding \ref
     *       base_uint::CompareTo, which starts comparing from the end.
     */
    constexpr int Compare(const base_blob& other) const { return std::memcmp(m_data.data(), other.m_data.data(), WIDTH); }

    friend constexpr bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
    friend constexpr bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
    friend constexpr bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }

    /** @name Hex representation
     *
     * The reverse-byte hex representation is a convenient way to view the blob
     * as a number, because it is consistent with the way the base_uint class
     * converts blobs to numbers.
     *
     * @note base_uint treats the blob as an array of bytes with the numerically
     * least significant byte first and the most significant byte last. Because
     * numbers are typically written with the most significant digit first and
     * the least significant digit last, the reverse hex display of the blob
     * corresponds to the same numeric value that base_uint interprets from the
     * blob.
     * @{*/
    std::string GetHex() const;
    /** Unlike FromHex this accepts any invalid input, thus it is fragile and deprecated!
     *
     * - Hex numbers that don't specify enough bytes to fill the internal array
     *   will be treated as setting the beginning of it, which corresponds to
     *   the least significant bytes when converted to base_uint.
     *
     * - Hex numbers specifying too many bytes will have the numerically most
     *   significant bytes (the beginning of the string) narrowed away.
     *
     * - An odd count of hex digits will result in the high bits of the leftmost
     *   byte being zero.
     *   "0x123" => {0x23, 0x1, 0x0, ..., 0x0}
     */