Added varint unit tests

This commit is contained in:
SChernykh 2022-04-06 16:29:12 +02:00
parent 32533e3c96
commit dee66c3f32
5 changed files with 117 additions and 34 deletions

View file

@ -109,9 +109,9 @@ bool check_keys(const hash& pub, const hash& sec)
return pub == pub_check;
}
static FORCEINLINE void hash_to_scalar(const uint8_t* data, size_t length, uint8_t(&res)[HASH_SIZE])
static FORCEINLINE void hash_to_scalar(const uint8_t* data, int length, uint8_t (&res)[HASH_SIZE])
{
keccak(data, static_cast<int>(length), res, HASH_SIZE);
keccak(data, length, res, HASH_SIZE);
sc_reduce32(res);
}
@ -122,18 +122,13 @@ static FORCEINLINE void derivation_to_scalar(const hash& derivation, size_t outp
uint8_t output_index[(sizeof(size_t) * 8 + 6) / 7];
} buf;
uint8_t* begin = buf.derivation;
uint8_t* end = buf.output_index;
memcpy(buf.derivation, derivation.h, sizeof(buf.derivation));
size_t k = output_index;
while (k >= 0x80) {
*(end++) = (static_cast<uint8_t>(k) & 0x7F) | 0x80;
k >>= 7;
}
*(end++) = static_cast<uint8_t>(k);
uint8_t* p = buf.output_index;
writeVarint(output_index, [&p](uint8_t b) { *(p++) = b; });
hash_to_scalar(begin, end - begin, res);
const uint8_t* data = buf.derivation;
hash_to_scalar(data, static_cast<int>(p - data), res);
}
class Cache

View file

@ -46,29 +46,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
#define READ_BYTE(x) do { if (!read_byte(x)) return __LINE__; } while (0)
#define EXPECT_BYTE(value) do { uint8_t tmp; READ_BYTE(tmp); if (tmp != (value)) return __LINE__; } while (0)
auto read_varint = [&data, data_end](auto& b) -> bool
{
uint64_t result = 0;
int k = 0;
while (data < data_end) {
if (k >= static_cast<int>(sizeof(b)) * 8) {
return false;
}
const uint64_t cur_byte = *(data++);
result |= (cur_byte & 0x7F) << k;
k += 7;
if ((cur_byte & 0x80) == 0) {
b = result;
return true;
}
}
return false;
};
#define READ_VARINT(x) do { if (!read_varint(x)) return __LINE__; } while(0)
#define READ_VARINT(x) do { data = readVarint(data, data_end, x); if (!data) return __LINE__; } while(0)
auto read_buf = [&data, data_end](void* buf, size_t size) -> bool
{

View file

@ -109,6 +109,30 @@ FORCEINLINE void writeVarint(T value, std::vector<uint8_t>& out)
writeVarint(value, [&out](uint8_t b) { out.emplace_back(b); });
}
template<typename T>
const uint8_t* readVarint(const uint8_t* data, const uint8_t* data_end, T& b)
{
uint64_t result = 0;
int k = 0;
while (data < data_end) {
if (k >= static_cast<int>(sizeof(T)) * 8) {
return nullptr;
}
const uint64_t cur_byte = *(data++);
result |= (cur_byte & 0x7F) << k;
k += 7;
if ((cur_byte & 0x80) == 0) {
b = result;
return data;
}
}
return nullptr;
}
template<typename T, size_t N> FORCEINLINE constexpr size_t array_size(T(&)[N]) { return N; }
template<typename T, typename U, size_t N> FORCEINLINE constexpr size_t array_size(T(U::*)[N]) { return N; }

View file

@ -74,6 +74,7 @@ set(SOURCES
src/keccak_tests.cpp
src/main.cpp
src/pool_block_tests.cpp
src/varint_tests.cpp
src/wallet_tests.cpp
../external/src/cryptonote/crypto-ops-data.c
../external/src/cryptonote/crypto-ops.c

View file

@ -0,0 +1,85 @@
/*
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "util.h"
#include "gtest/gtest.h"
namespace p2pool {
TEST(varint, read_write)
{
std::vector<uint8_t> v;
v.reserve(16);
uint64_t check;
// 0...2^7 - 1
for (uint64_t value = 0; value < 0x80; ++value) {
v.clear();
writeVarint(value, v);
ASSERT_EQ(v.size(), 1);
ASSERT_EQ(v[0], value);
ASSERT_EQ(readVarint(v.data(), v.data() + v.size(), check), v.data() + v.size());
ASSERT_EQ(check, value);
}
// 2^7...2^14 - 1
for (uint64_t value = 0x80; value < 0x4000; ++value) {
v.clear();
writeVarint(value, v);
ASSERT_EQ(v.size(), 2);
ASSERT_EQ(v[0], (value & 0x7F) | 0x80);
ASSERT_EQ(v[1], value >> 7);
ASSERT_EQ(readVarint(v.data(), v.data() + v.size(), check), v.data() + v.size());
ASSERT_EQ(check, value);
}
// 2^14...2^21 - 1
for (uint64_t value = 0x4000; value < 0x200000; ++value) {
v.clear();
writeVarint(value, v);
ASSERT_EQ(v.size(), 3);
ASSERT_EQ(v[0], (value & 0x7F) | 0x80);
ASSERT_EQ(v[1], ((value >> 7) & 0x7F) | 0x80);
ASSERT_EQ(v[2], value >> 14);
ASSERT_EQ(readVarint(v.data(), v.data() + v.size(), check), v.data() + v.size());
ASSERT_EQ(check, value);
}
// 2^64 - 1
v.clear();
writeVarint(std::numeric_limits<uint64_t>::max(), v);
ASSERT_EQ(v.size(), 10);
for (int i = 0; i < 9; ++i) {
ASSERT_EQ(v[i], 0xFF);
}
ASSERT_EQ(v[9], 1);
ASSERT_EQ(readVarint(v.data(), v.data() + v.size(), check), v.data() + v.size());
ASSERT_EQ(check, std::numeric_limits<uint64_t>::max());
// Invalid value 1
uint8_t buf[16];
memset(buf, -1, sizeof(buf));
ASSERT_EQ(readVarint(buf, buf + sizeof(buf), check), nullptr);
// Invalid value 2
uint8_t buf2[1] = { 0x80 };
ASSERT_EQ(readVarint(buf2, buf2 + 1, check), nullptr);
}
}