1
0
Fork 0
forked from lthn/blockchain

Merge branch 'master' into frontend

This commit is contained in:
wildkif 2019-04-05 09:33:08 +03:00
commit 6246eccc1b
78 changed files with 4836 additions and 1158 deletions

View file

@ -157,7 +157,7 @@ endif()
message(STATUS "Boost: ${Boost_VERSION} from ${Boost_LIBRARY_DIRS}")
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/contrib/ethereum/libethash)
if(MINGW)
set(Boost_LIBRARIES "${Boost_LIBRARIES};ws2_32;mswsock")
elseif(NOT MSVC)

View file

@ -16,7 +16,11 @@ Building
Recommended OS version: Ubuntu 17.04 LTS.
1. `$ sudo apt install git g++ cmake unzip libicu-dev mesa-common-dev libglu1-mesa-dev qt5-default qtwebengine5-dev`
1. For server version: \
`$ sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git libboost-all-dev screen`\
For GUI version:\
`$ sudo apt-get install -y build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev cmake git libboost-all-dev screen mesa-common-dev libglu1-mesa-dev qt5-default qtwebengine5-dev`
2. `$ cd zano/ && make -j$(nproc) gui`
3. Look for the binaries, including the `Zano` GUI, in the build directory

View file

@ -4,7 +4,7 @@ set(UPNPC_BUILD_TESTS OFF CACHE BOOL "Build test executables")
add_subdirectory(miniupnpc)
add_subdirectory(zlib)
add_subdirectory(db)
add_subdirectory(ethereum)
set_property(TARGET upnpc-static PROPERTY FOLDER "contrib")
@ -13,6 +13,7 @@ set_property(TARGET lmdb PROPERTY FOLDER "contrib")
if(MSVC)
set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
else()

View file

@ -0,0 +1,10 @@
add_subdirectory(libethash)
set_property(TARGET ethash PROPERTY FOLDER "contrib")
if(MSVC)
target_compile_options(ethash PRIVATE /wd4477 /wd4267)
else()
target_compile_options(ethash PRIVATE -Wno-format -Wno-aggregate-return -Wno-empty-body)
endif()

View file

@ -0,0 +1,33 @@
# ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
# Copyright 2018 Pawel Bylica.
# Licensed under the Apache License, Version 2.0. See the LICENSE file.
# set(include_dir ${PROJECT_SOURCE_DIR}/include)
add_library(
ethash
bit_manipulation.h
builtins.h
endianness.hpp
ethash/ethash.h
ethash/ethash.hpp
ethash-internal.hpp
ethash.cpp
ethash/hash_types.h
managed.cpp
ethash/keccak.h
ethash/keccak.hpp
keccak.c
keccakf800.c
keccakf1600.c
kiss99.hpp
primes.h
primes.c
ethash/progpow.hpp
progpow.cpp
)

View file

@ -0,0 +1,81 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
#include "builtins.h"
#include "support/attributes.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
static inline uint32_t rotl32(uint32_t n, unsigned int c)
{
const unsigned int mask = 31;
c &= mask;
unsigned int neg_c = (unsigned int)(-(int)c);
return (n << c) | (n >> (neg_c & mask));
}
static inline uint32_t rotr32(uint32_t n, unsigned int c)
{
const unsigned int mask = 31;
c &= mask;
unsigned int neg_c = (unsigned int)(-(int)c);
return (n >> c) | (n << (neg_c & mask));
}
static inline uint32_t clz32(uint32_t x)
{
return x ? (uint32_t)__builtin_clz(x) : 32;
}
static inline uint32_t popcount32(uint32_t x)
{
return (uint32_t)__builtin_popcount(x);
}
static inline uint32_t mul_hi32(uint32_t x, uint32_t y)
{
return (uint32_t)(((uint64_t)x * (uint64_t)y) >> 32);
}
/** FNV 32-bit prime. */
static const uint32_t fnv_prime = 0x01000193;
/** FNV 32-bit offset basis. */
static const uint32_t fnv_offset_basis = 0x811c9dc5;
/**
* The implementation of FNV-1 hash.
*
* See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1_hash.
*/
NO_SANITIZE("unsigned-integer-overflow")
static inline uint32_t fnv1(uint32_t u, uint32_t v) noexcept
{
return (u * fnv_prime) ^ v;
}
/**
* The implementation of FNV-1a hash.
*
* See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash.
*/
NO_SANITIZE("unsigned-integer-overflow")
static inline uint32_t fnv1a(uint32_t u, uint32_t v) noexcept
{
return (u ^ v) * fnv_prime;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,43 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
/**
* @file
* Implementation of GCC/clang builtins for MSVC compiler.
*/
#pragma once
#ifdef _MSC_VER
#include <intrin.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Returns the number of leading 0-bits in `x`, starting at the most significant bit position.
* If `x` is 0, the result is undefined.
*/
static inline int __builtin_clz(unsigned int x)
{
unsigned long most_significant_bit;
_BitScanReverse(&most_significant_bit, x);
return 31 - (int)most_significant_bit;
}
/**
* Returns the number of 1-bits in `x`.
*/
static inline int __builtin_popcount(unsigned int x)
{
return (int)__popcnt(x);
}
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,98 @@
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
/// @file
/// This file contains helper functions to handle big-endian architectures.
/// The Ethash algorithm is naturally defined for little-endian architectures
/// so for those the helpers are just no-op empty functions.
/// For big-endian architectures we need 32-bit and 64-bit byte swapping in
/// some places.
#pragma once
#include <ethash/ethash.hpp>
#if _WIN32
#include <stdlib.h>
#define bswap32 _byteswap_ulong
#define bswap64 _byteswap_uint64
// On Windows assume little endian.
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#define __BYTE_ORDER __LITTLE_ENDIAN
#elif __APPLE__
#include <machine/endian.h>
#define bswap32 __builtin_bswap32
#define bswap64 __builtin_bswap64
#else
#include <endian.h>
#define bswap32 __builtin_bswap32
#define bswap64 __builtin_bswap64
#endif
namespace ethash
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
struct le
{
static uint32_t uint32(uint32_t x) noexcept { return x; }
static uint64_t uint64(uint64_t x) noexcept { return x; }
static const hash1024& uint32s(const hash1024& h) noexcept { return h; }
static const hash512& uint32s(const hash512& h) noexcept { return h; }
static const hash256& uint32s(const hash256& h) noexcept { return h; }
};
struct be
{
static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); }
};
#elif __BYTE_ORDER == __BIG_ENDIAN
struct le
{
static uint32_t uint32(uint32_t x) noexcept { return bswap32(x); }
static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); }
static hash1024 uint32s(hash1024 h) noexcept
{
for (auto& w : h.word32s)
w = uint32(w);
return h;
}
static hash512 uint32s(hash512 h) noexcept
{
for (auto& w : h.word32s)
w = uint32(w);
return h;
}
static hash256 uint32s(hash256 h) noexcept
{
for (auto& w : h.word32s)
w = uint32(w);
return h;
}
};
struct be
{
static uint64_t uint64(uint64_t x) noexcept { return x; }
};
#endif
} // namespace ethash

View file

@ -0,0 +1,69 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
/// @file
/// Contains declarations of internal ethash functions to allow them to be
/// unit-tested.
#pragma once
#include <ethash/ethash.hpp>
#include "endianness.hpp"
#include <memory>
#include <vector>
extern "C" struct ethash_epoch_context_full : ethash_epoch_context
{
ethash_hash1024* full_dataset;
constexpr ethash_epoch_context_full(int epoch_number, int light_cache_num_items,
const ethash_hash512* light_cache, const uint32_t* l1_cache, int full_dataset_num_items,
ethash_hash1024* full_dataset) noexcept
: ethash_epoch_context{epoch_number, light_cache_num_items, light_cache, l1_cache,
full_dataset_num_items},
full_dataset{full_dataset}
{}
};
namespace ethash
{
inline bool is_less_or_equal(const hash256& a, const hash256& b) noexcept
{
for (size_t i = 0; i < (sizeof(a) / sizeof(a.word64s[0])); ++i)
{
if (be::uint64(a.word64s[i]) > be::uint64(b.word64s[i]))
return false;
if (be::uint64(a.word64s[i]) < be::uint64(b.word64s[i]))
return true;
}
return true;
}
inline bool is_equal(const hash256& a, const hash256& b) noexcept
{
return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0;
}
void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept;
hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept;
hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept;
hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept;
namespace generic
{
using hash_fn_512 = hash512 (*)(const uint8_t* data, size_t size);
using build_light_cache_fn = void (*)(hash512 cache[], int num_items, const hash256& seed);
void build_light_cache(
hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept;
epoch_context_full* create_epoch_context(
build_light_cache_fn build_fn, int epoch_number, bool full) noexcept;
} // namespace generic
} // namespace ethash

View file

@ -0,0 +1,441 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
#include "ethash-internal.hpp"
#include "bit_manipulation.h"
#include "endianness.hpp"
#include "primes.h"
#include "support/attributes.h"
#include <ethash/keccak.hpp>
#include <ethash/progpow.hpp>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <limits>
namespace ethash
{
// Internal constants:
constexpr static int light_cache_init_size = 1 << 24;
constexpr static int light_cache_growth = 1 << 17;
constexpr static int light_cache_rounds = 3;
constexpr static int full_dataset_init_size = 1 << 30;
constexpr static int full_dataset_growth = 1 << 23;
constexpr static int full_dataset_item_parents = 256;
// Verify constants:
static_assert(sizeof(hash512) == ETHASH_LIGHT_CACHE_ITEM_SIZE, "");
static_assert(sizeof(hash1024) == ETHASH_FULL_DATASET_ITEM_SIZE, "");
static_assert(light_cache_item_size == ETHASH_LIGHT_CACHE_ITEM_SIZE, "");
static_assert(full_dataset_item_size == ETHASH_FULL_DATASET_ITEM_SIZE, "");
namespace
{
using ::fnv1;
inline hash512 fnv1(const hash512& u, const hash512& v) noexcept
{
hash512 r;
for (size_t i = 0; i < sizeof(r) / sizeof(r.word32s[0]); ++i)
r.word32s[i] = fnv1(u.word32s[i], v.word32s[i]);
return r;
}
inline hash512 bitwise_xor(const hash512& x, const hash512& y) noexcept
{
hash512 z;
for (size_t i = 0; i < sizeof(z) / sizeof(z.word64s[0]); ++i)
z.word64s[i] = x.word64s[i] ^ y.word64s[i];
return z;
}
} // namespace
int find_epoch_number(const hash256& seed) noexcept
{
static constexpr int num_tries = 30000; // Divisible by 16.
// Thread-local cache of the last search.
static thread_local int cached_epoch_number = 0;
static thread_local hash256 cached_seed = {};
// Load from memory once (memory will be clobbered by keccak256()).
const uint32_t seed_part = seed.word32s[0];
const int e = cached_epoch_number;
hash256 s = cached_seed;
if (s.word32s[0] == seed_part)
return e;
// Try the next seed, will match for sequential epoch access.
s = keccak256(s);
if (s.word32s[0] == seed_part)
{
cached_seed = s;
cached_epoch_number = e + 1;
return e + 1;
}
// Search for matching seed starting from epoch 0.
s = {};
for (int i = 0; i < num_tries; ++i)
{
if (s.word32s[0] == seed_part)
{
cached_seed = s;
cached_epoch_number = i;
return i;
}
s = keccak256(s);
}
return -1;
}
namespace generic
{
void build_light_cache(
hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept
{
hash512 item = hash_fn(seed.bytes, sizeof(seed));
cache[0] = item;
for (int i = 1; i < num_items; ++i)
{
item = hash_fn(item.bytes, sizeof(item));
cache[i] = item;
}
for (int q = 0; q < light_cache_rounds; ++q)
{
for (int i = 0; i < num_items; ++i)
{
const uint32_t index_limit = static_cast<uint32_t>(num_items);
// Fist index: 4 first bytes of the item as little-endian integer.
const uint32_t t = le::uint32(cache[i].word32s[0]);
const uint32_t v = t % index_limit;
// Second index.
const uint32_t w = static_cast<uint32_t>(num_items + (i - 1)) % index_limit;
const hash512 x = bitwise_xor(cache[v], cache[w]);
cache[i] = hash_fn(x.bytes, sizeof(x));
}
}
}
epoch_context_full* create_epoch_context(
build_light_cache_fn build_fn, int epoch_number, bool full) noexcept
{
static_assert(sizeof(epoch_context_full) < sizeof(hash512), "epoch_context too big");
static constexpr size_t context_alloc_size = sizeof(hash512);
const int light_cache_num_items = calculate_light_cache_num_items(epoch_number);
const int full_dataset_num_items = calculate_full_dataset_num_items(epoch_number);
const size_t light_cache_size = get_light_cache_size(light_cache_num_items);
const size_t full_dataset_size =
full ? static_cast<size_t>(full_dataset_num_items) * sizeof(hash1024) :
progpow::l1_cache_size;
const size_t alloc_size = context_alloc_size + light_cache_size + full_dataset_size;
char* const alloc_data = static_cast<char*>(std::calloc(1, alloc_size));
if (!alloc_data)
return nullptr; // Signal out-of-memory by returning null pointer.
hash512* const light_cache = reinterpret_cast<hash512*>(alloc_data + context_alloc_size);
const hash256 epoch_seed = calculate_epoch_seed(epoch_number);
build_fn(light_cache, light_cache_num_items, epoch_seed);
uint32_t* const l1_cache =
reinterpret_cast<uint32_t*>(alloc_data + context_alloc_size + light_cache_size);
hash1024* full_dataset = full ? reinterpret_cast<hash1024*>(l1_cache) : nullptr;
epoch_context_full* const context = new (alloc_data) epoch_context_full{
epoch_number,
light_cache_num_items,
light_cache,
l1_cache,
full_dataset_num_items,
full_dataset,
};
auto* full_dataset_2048 = reinterpret_cast<hash2048*>(l1_cache);
for (uint32_t i = 0; i < progpow::l1_cache_size / sizeof(full_dataset_2048[0]); ++i)
full_dataset_2048[i] = calculate_dataset_item_2048(*context, i);
return context;
}
} // namespace generic
void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept
{
return generic::build_light_cache(keccak512, cache, num_items, seed);
}
struct item_state
{
const hash512* const cache;
const int64_t num_cache_items;
const uint32_t seed;
hash512 mix;
ALWAYS_INLINE item_state(const epoch_context& context, int64_t index) noexcept
: cache{context.light_cache},
num_cache_items{context.light_cache_num_items},
seed{static_cast<uint32_t>(index)}
{
mix = cache[index % num_cache_items];
mix.word32s[0] ^= le::uint32(seed);
mix = le::uint32s(keccak512(mix));
}
ALWAYS_INLINE void update(uint32_t round) noexcept
{
static constexpr size_t num_words = sizeof(mix) / sizeof(uint32_t);
const uint32_t t = fnv1(seed ^ round, mix.word32s[round % num_words]);
const int64_t parent_index = t % num_cache_items;
mix = fnv1(mix, le::uint32s(cache[parent_index]));
}
ALWAYS_INLINE hash512 final() noexcept { return keccak512(le::uint32s(mix)); }
};
hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept
{
item_state item0{context, index};
for (uint32_t j = 0; j < full_dataset_item_parents; ++j)
item0.update(j);
return item0.final();
}
/// Calculates a full dataset item
///
/// This consist of two 512-bit items produced by calculate_dataset_item_partial().
/// Here the computation is done interleaved for better performance.
hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept
{
item_state item0{context, int64_t(index) * 2};
item_state item1{context, int64_t(index) * 2 + 1};
for (uint32_t j = 0; j < full_dataset_item_parents; ++j)
{
item0.update(j);
item1.update(j);
}
return hash1024{{item0.final(), item1.final()}};
}
hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept
{
item_state item0{context, int64_t(index) * 4};
item_state item1{context, int64_t(index) * 4 + 1};
item_state item2{context, int64_t(index) * 4 + 2};
item_state item3{context, int64_t(index) * 4 + 3};
for (uint32_t j = 0; j < full_dataset_item_parents; ++j)
{
item0.update(j);
item1.update(j);
item2.update(j);
item3.update(j);
}
return hash2048{{item0.final(), item1.final(), item2.final(), item3.final()}};
}
namespace
{
using lookup_fn = hash1024 (*)(const epoch_context&, uint32_t);
inline hash512 hash_seed(const hash256& header_hash, uint64_t nonce) noexcept
{
nonce = le::uint64(nonce);
uint8_t init_data[sizeof(header_hash) + sizeof(nonce)];
std::memcpy(&init_data[0], &header_hash, sizeof(header_hash));
std::memcpy(&init_data[sizeof(header_hash)], &nonce, sizeof(nonce));
return keccak512(init_data, sizeof(init_data));
}
inline hash256 hash_final(const hash512& seed, const hash256& mix_hash)
{
uint8_t final_data[sizeof(seed) + sizeof(mix_hash)];
std::memcpy(&final_data[0], seed.bytes, sizeof(seed));
std::memcpy(&final_data[sizeof(seed)], mix_hash.bytes, sizeof(mix_hash));
return keccak256(final_data, sizeof(final_data));
}
inline hash256 hash_kernel(
const epoch_context& context, const hash512& seed, lookup_fn lookup) noexcept
{
static constexpr size_t num_words = sizeof(hash1024) / sizeof(uint32_t);
const uint32_t index_limit = static_cast<uint32_t>(context.full_dataset_num_items);
const uint32_t seed_init = le::uint32(seed.word32s[0]);
hash1024 mix{{le::uint32s(seed), le::uint32s(seed)}};
for (uint32_t i = 0; i < num_dataset_accesses; ++i)
{
const uint32_t p = fnv1(i ^ seed_init, mix.word32s[i % num_words]) % index_limit;
const hash1024 newdata = le::uint32s(lookup(context, p));
for (size_t j = 0; j < num_words; ++j)
mix.word32s[j] = fnv1(mix.word32s[j], newdata.word32s[j]);
}
hash256 mix_hash;
for (size_t i = 0; i < num_words; i += 4)
{
const uint32_t h1 = fnv1(mix.word32s[i], mix.word32s[i + 1]);
const uint32_t h2 = fnv1(h1, mix.word32s[i + 2]);
const uint32_t h3 = fnv1(h2, mix.word32s[i + 3]);
mix_hash.word32s[i / 4] = h3;
}
return le::uint32s(mix_hash);
}
} // namespace
result hash(const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept
{
const hash512 seed = hash_seed(header_hash, nonce);
const hash256 mix_hash = hash_kernel(context, seed, calculate_dataset_item_1024);
return {hash_final(seed, mix_hash), mix_hash};
}
result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept
{
static const auto lazy_lookup = [](const epoch_context& context, uint32_t index) noexcept
{
auto full_dataset = static_cast<const epoch_context_full&>(context).full_dataset;
hash1024& item = full_dataset[index];
if (item.word64s[0] == 0)
{
// TODO: Copy elision here makes it thread-safe?
item = calculate_dataset_item_1024(context, index);
}
return item;
};
const hash512 seed = hash_seed(header_hash, nonce);
const hash256 mix_hash = hash_kernel(context, seed, lazy_lookup);
return {hash_final(seed, mix_hash), mix_hash};
}
bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce,
const hash256& boundary) noexcept
{
const hash512 seed = hash_seed(header_hash, nonce);
return is_less_or_equal(hash_final(seed, mix_hash), boundary);
}
bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash,
uint64_t nonce, const hash256& boundary) noexcept
{
const hash512 seed = hash_seed(header_hash, nonce);
if (!is_less_or_equal(hash_final(seed, mix_hash), boundary))
return false;
const hash256 expected_mix_hash = hash_kernel(context, seed, calculate_dataset_item_1024);
return is_equal(expected_mix_hash, mix_hash);
}
search_result search_light(const epoch_context& context, const hash256& header_hash,
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept
{
const uint64_t end_nonce = start_nonce + iterations;
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
{
result r = hash(context, header_hash, nonce);
if (is_less_or_equal(r.final_hash, boundary))
return {r, nonce};
}
return {};
}
search_result search(const epoch_context_full& context, const hash256& header_hash,
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept
{
const uint64_t end_nonce = start_nonce + iterations;
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
{
result r = hash(context, header_hash, nonce);
if (is_less_or_equal(r.final_hash, boundary))
return {r, nonce};
}
return {};
}
} // namespace ethash
using namespace ethash;
extern "C" {
ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) noexcept
{
ethash_hash256 epoch_seed = {};
for (int i = 0; i < epoch_number; ++i)
epoch_seed = ethash_keccak256_32(epoch_seed.bytes);
return epoch_seed;
}
int ethash_calculate_light_cache_num_items(int epoch_number) noexcept
{
static constexpr int item_size = sizeof(hash512);
static constexpr int num_items_init = light_cache_init_size / item_size;
static constexpr int num_items_growth = light_cache_growth / item_size;
static_assert(
light_cache_init_size % item_size == 0, "light_cache_init_size not multiple of item size");
static_assert(
light_cache_growth % item_size == 0, "light_cache_growth not multiple of item size");
int num_items_upper_bound = num_items_init + epoch_number * num_items_growth;
int num_items = ethash_find_largest_prime(num_items_upper_bound);
return num_items;
}
int ethash_calculate_full_dataset_num_items(int epoch_number) noexcept
{
static constexpr int item_size = sizeof(hash1024);
static constexpr int num_items_init = full_dataset_init_size / item_size;
static constexpr int num_items_growth = full_dataset_growth / item_size;
static_assert(full_dataset_init_size % item_size == 0,
"full_dataset_init_size not multiple of item size");
static_assert(
full_dataset_growth % item_size == 0, "full_dataset_growth not multiple of item size");
int num_items_upper_bound = num_items_init + epoch_number * num_items_growth;
int num_items = ethash_find_largest_prime(num_items_upper_bound);
return num_items;
}
epoch_context* ethash_create_epoch_context(int epoch_number) noexcept
{
return generic::create_epoch_context(build_light_cache, epoch_number, false);
}
epoch_context_full* ethash_create_epoch_context_full(int epoch_number) noexcept
{
return generic::create_epoch_context(build_light_cache, epoch_number, true);
}
void ethash_destroy_epoch_context_full(epoch_context_full* context) noexcept
{
ethash_destroy_epoch_context(context);
}
void ethash_destroy_epoch_context(epoch_context* context) noexcept
{
context->~epoch_context();
std::free(context);
}
} // extern "C"

View file

@ -0,0 +1,99 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
#include <ethash/hash_types.h>
#include <stdint.h>
#ifdef __cplusplus
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* The Ethash algorithm revision implemented as specified in the Ethash spec
* https://github.com/ethereum/wiki/wiki/Ethash.
*/
#define ETHASH_REVISION "23"
#define ETHASH_EPOCH_LENGTH 30000
#define ETHASH_LIGHT_CACHE_ITEM_SIZE 64
#define ETHASH_FULL_DATASET_ITEM_SIZE 128
#define ETHASH_NUM_DATASET_ACCESSES 64
struct ethash_epoch_context
{
const int epoch_number;
const int light_cache_num_items;
const union ethash_hash512* const light_cache;
const uint32_t* const l1_cache;
const int full_dataset_num_items;
};
struct ethash_epoch_context_full;
/**
* Calculates the number of items in the light cache for given epoch.
*
* This function will search for a prime number matching the criteria given
* by the Ethash so the execution time is not constant. It takes ~ 0.01 ms.
*
* @param epoch_number The epoch number.
* @return The number items in the light cache.
*/
int ethash_calculate_light_cache_num_items(int epoch_number) NOEXCEPT;
/**
* Calculates the number of items in the full dataset for given epoch.
*
* This function will search for a prime number matching the criteria given
* by the Ethash so the execution time is not constant. It takes ~ 0.05 ms.
*
* @param epoch_number The epoch number.
* @return The number items in the full dataset.
*/
int ethash_calculate_full_dataset_num_items(int epoch_number) NOEXCEPT;
/**
* Calculates the epoch seed hash.
* @param epoch_number The epoch number.
* @return The epoch seed hash.
*/
union ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) NOEXCEPT;
struct ethash_epoch_context* ethash_create_epoch_context(int epoch_number) NOEXCEPT;
/**
* Creates the epoch context with the full dataset initialized.
*
* The memory for the full dataset is only allocated and marked as "not-generated".
* The items of the full dataset are generated on the fly when hit for the first time.
*
* The memory allocated in the context MUST be freed with ethash_destroy_epoch_context_full().
*
* @param epoch_number The epoch number.
* @return Pointer to the context or null in case of memory allocation failure.
*/
struct ethash_epoch_context_full* ethash_create_epoch_context_full(int epoch_number) NOEXCEPT;
void ethash_destroy_epoch_context(struct ethash_epoch_context* context) NOEXCEPT;
void ethash_destroy_epoch_context_full(struct ethash_epoch_context_full* context) NOEXCEPT;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,160 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
/// @file
///
/// API design decisions:
///
/// 1. Signed integer type is used whenever the size of the type is not
/// restricted by the Ethash specification.
/// See http://www.aristeia.com/Papers/C++ReportColumns/sep95.pdf.
/// See https://stackoverflow.com/questions/10168079/why-is-size-t-unsigned/.
/// See https://github.com/Microsoft/GSL/issues/171.
#pragma once
#include <ethash/ethash.h>
#include <ethash/hash_types.hpp>
#include <cstdint>
#include <cstring>
#include <memory>
namespace ethash
{
constexpr auto revision = ETHASH_REVISION;
static constexpr int epoch_length = ETHASH_EPOCH_LENGTH;
static constexpr int light_cache_item_size = ETHASH_LIGHT_CACHE_ITEM_SIZE;
static constexpr int full_dataset_item_size = ETHASH_FULL_DATASET_ITEM_SIZE;
static constexpr int num_dataset_accesses = ETHASH_NUM_DATASET_ACCESSES;
using epoch_context = ethash_epoch_context;
using epoch_context_full = ethash_epoch_context_full;
/// Constructs a 256-bit hash from an array of bytes.
///
/// @param bytes A pointer to array of at least 32 bytes.
/// @return The constructed hash.
inline hash256 hash256_from_bytes(const uint8_t bytes[32]) noexcept
{
hash256 h;
std::memcpy(&h, bytes, sizeof(h));
return h;
}
struct result
{
hash256 final_hash;
hash256 mix_hash;
};
struct search_result
{
bool solution_found = false;
uint64_t nonce = 0;
hash256 final_hash = {};
hash256 mix_hash = {};
search_result() noexcept = default;
search_result(result res, uint64_t nonce) noexcept
: solution_found(true), nonce(nonce), final_hash(res.final_hash), mix_hash(res.mix_hash)
{}
};
/// Alias for ethash_calculate_light_cache_num_items().
static constexpr auto calculate_light_cache_num_items = ethash_calculate_light_cache_num_items;
/// Alias for ethash_calculate_full_dataset_num_items().
static constexpr auto calculate_full_dataset_num_items = ethash_calculate_full_dataset_num_items;
/// Alias for ethash_calculate_epoch_seed().
static constexpr auto calculate_epoch_seed = ethash_calculate_epoch_seed;
/// Calculates the epoch number out of the block number.
inline constexpr int get_epoch_number(int block_number) noexcept
{
return block_number / epoch_length;
}
/**
* Coverts the number of items of a light cache to size in bytes.
*
* @param num_items The number of items in the light cache.
* @return The size of the light cache in bytes.
*/
inline constexpr size_t get_light_cache_size(int num_items) noexcept
{
return static_cast<size_t>(num_items) * light_cache_item_size;
}
/**
* Coverts the number of items of a full dataset to size in bytes.
*
* @param num_items The number of items in the full dataset.
* @return The size of the full dataset in bytes.
*/
inline constexpr uint64_t get_full_dataset_size(int num_items) noexcept
{
return static_cast<uint64_t>(num_items) * full_dataset_item_size;
}
/// Owned unique pointer to an epoch context.
using epoch_context_ptr = std::unique_ptr<epoch_context, decltype(&ethash_destroy_epoch_context)>;
using epoch_context_full_ptr =
std::unique_ptr<epoch_context_full, decltype(&ethash_destroy_epoch_context_full)>;
/// Creates Ethash epoch context.
///
/// This is a wrapper for ethash_create_epoch_number C function that returns
/// the context as a smart pointer which handles the destruction of the context.
inline epoch_context_ptr create_epoch_context(int epoch_number) noexcept
{
return {ethash_create_epoch_context(epoch_number), ethash_destroy_epoch_context};
}
inline epoch_context_full_ptr create_epoch_context_full(int epoch_number) noexcept
{
return {ethash_create_epoch_context_full(epoch_number), ethash_destroy_epoch_context_full};
}
result hash(const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept;
result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept;
bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce,
const hash256& boundary) noexcept;
bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash,
uint64_t nonce, const hash256& boundary) noexcept;
search_result search_light(const epoch_context& context, const hash256& header_hash,
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept;
search_result search(const epoch_context_full& context, const hash256& header_hash,
const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept;
/// Tries to find the epoch number matching the given seed hash.
///
/// Mining pool protocols (many variants of stratum and "getwork") send out
/// seed hash instead of epoch number to workers. This function tries to recover
/// the epoch number from this seed hash.
///
/// @param seed Ethash seed hash.
/// @return The epoch number or -1 if not found.
int find_epoch_number(const hash256& seed) noexcept;
/// Get global shared epoch context.
const epoch_context& get_global_epoch_context(int epoch_number);
/// Get global shared epoch context with full dataset initialized.
const epoch_context_full& get_global_epoch_context_full(int epoch_number);
} // namespace ethash

View file

@ -0,0 +1,46 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
union ethash_hash256
{
uint64_t word64s[4];
uint32_t word32s[8];
uint8_t bytes[32];
};
union ethash_hash512
{
uint64_t word64s[8];
uint32_t word32s[16];
uint8_t bytes[64];
};
union ethash_hash1024
{
union ethash_hash512 hash512s[2];
uint64_t word64s[16];
uint32_t word32s[32];
uint8_t bytes[128];
};
union ethash_hash2048
{
union ethash_hash512 hash512s[4];
uint64_t word64s[32];
uint32_t word32s[64];
uint8_t bytes[256];
};
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,15 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
#pragma once
#include <ethash/hash_types.h>
namespace ethash
{
using hash256 = ethash_hash256;
using hash512 = ethash_hash512;
using hash1024 = ethash_hash1024;
using hash2048 = ethash_hash2048;
} // namespace ethash

View file

@ -0,0 +1,49 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
#include <ethash/hash_types.h>
#include <stddef.h>
#ifdef __cplusplus
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* The Keccak-f[1600] function.
*
* The implementation of the Keccak-f function with 1600-bit width of the permutation (b).
* The size of the state is also 1600 bit what gives 25 64-bit words.
*
* @param state The state of 25 64-bit words on which the permutation is to be performed.
*/
void ethash_keccakf1600(uint64_t state[25]) NOEXCEPT;
/**
* The Keccak-f[800] function.
*
* The implementation of the Keccak-f function with 800-bit width of the permutation (b).
* The size of the state is also 800 bit what gives 25 32-bit words.
*
* @param state The state of 25 32-bit words on which the permutation is to be performed.
*/
void ethash_keccakf800(uint32_t state[25]) NOEXCEPT;
union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size) NOEXCEPT;
union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) NOEXCEPT;
union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) NOEXCEPT;
union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) NOEXCEPT;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,35 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
#pragma once
#include <ethash/keccak.h>
#include <ethash/hash_types.hpp>
namespace ethash
{
inline hash256 keccak256(const uint8_t* data, size_t size) noexcept
{
return ethash_keccak256(data, size);
}
inline hash256 keccak256(const hash256& input) noexcept
{
return ethash_keccak256_32(input.bytes);
}
inline hash512 keccak512(const uint8_t* data, size_t size) noexcept
{
return ethash_keccak512(data, size);
}
inline hash512 keccak512(const hash512& input) noexcept
{
return ethash_keccak512_64(input.bytes);
}
static constexpr auto keccak256_32 = ethash_keccak256_32;
static constexpr auto keccak512_64 = ethash_keccak512_64;
} // namespace ethash

View file

@ -0,0 +1,47 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
/// @file
///
/// ProgPoW API
///
/// This file provides the public API for ProgPoW as the Ethash API extension.
#include <ethash/ethash.hpp>
namespace progpow
{
using namespace ethash; // Include ethash namespace.
/// The ProgPoW algorithm revision implemented as specified in the spec
/// https://github.com/ifdefelse/ProgPOW#change-history.
constexpr auto revision = "0.9.2";
constexpr int period_length = 50;
constexpr uint32_t num_regs = 32;
constexpr size_t num_lanes = 16;
constexpr int num_cache_accesses = 12;
constexpr int num_math_operations = 20;
constexpr size_t l1_cache_size = 16 * 1024;
constexpr size_t l1_cache_num_items = l1_cache_size / sizeof(uint32_t);
result hash(const epoch_context& context, int block_number, const hash256& header_hash,
uint64_t nonce) noexcept;
result hash(const epoch_context_full& context, int block_number, const hash256& header_hash,
uint64_t nonce) noexcept;
bool verify(const epoch_context& context, int block_number, const hash256& header_hash,
const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept;
search_result search_light(const epoch_context& context, int block_number,
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
size_t iterations) noexcept;
search_result search(const epoch_context_full& context, int block_number,
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
size_t iterations) noexcept;
} // namespace progpow

View file

@ -0,0 +1,18 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2019 Pawel Bylica.
* Licensed under the Apache License, Version 2.0.
*/
#pragma once
/** The ethash library version. */
#define ETHASH_VERSION "0.4.3"
#ifdef __cplusplus
namespace ethash
{
/// The ethash library version.
constexpr auto version = ETHASH_VERSION;
} // namespace ethash
#endif

View file

@ -0,0 +1,123 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#include <ethash/keccak.h>
#include "support/attributes.h"
#include <string.h>
#if _WIN32
/* On Windows assume little endian. */
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#define __BYTE_ORDER __LITTLE_ENDIAN
#elif __APPLE__
#include <machine/endian.h>
#else
#include <endian.h>
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define to_le64(X) X
#else
#define to_le64(X) __builtin_bswap64(X)
#endif
/** Loads 64-bit integer from given memory location as little-endian number. */
static INLINE ALWAYS_INLINE uint64_t load_le(const uint8_t* data)
{
/* memcpy is the best way of expressing the intention. Every compiler will
optimize is to single load instruction if the target architecture
supports unaligned memory access (GCC and clang even in O0).
This is great trick because we are violating C/C++ memory alignment
restrictions with no performance penalty. */
uint64_t word;
memcpy(&word, data, sizeof(word));
return to_le64(word);
}
static INLINE ALWAYS_INLINE void keccak(
uint64_t* out, size_t bits, const uint8_t* data, size_t size)
{
static const size_t word_size = sizeof(uint64_t);
const size_t hash_size = bits / 8;
const size_t block_size = (1600 - bits * 2) / 8;
size_t i;
uint64_t* state_iter;
uint64_t last_word = 0;
uint8_t* last_word_iter = (uint8_t*)&last_word;
uint64_t state[25] = {0};
while (size >= block_size)
{
for (i = 0; i < (block_size / word_size); ++i)
{
state[i] ^= load_le(data);
data += word_size;
}
ethash_keccakf1600(state);
size -= block_size;
}
state_iter = state;
while (size >= word_size)
{
*state_iter ^= load_le(data);
++state_iter;
data += word_size;
size -= word_size;
}
while (size > 0)
{
*last_word_iter = *data;
++last_word_iter;
++data;
--size;
}
*last_word_iter = 0x01;
*state_iter ^= to_le64(last_word);
state[(block_size / word_size) - 1] ^= 0x8000000000000000;
ethash_keccakf1600(state);
for (i = 0; i < (hash_size / word_size); ++i)
out[i] = to_le64(state[i]);
}
union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size)
{
union ethash_hash256 hash;
keccak(hash.word64s, 256, data, size);
return hash;
}
union ethash_hash256 ethash_keccak256_32(const uint8_t data[32])
{
union ethash_hash256 hash;
keccak(hash.word64s, 256, data, 32);
return hash;
}
union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size)
{
union ethash_hash512 hash;
keccak(hash.word64s, 512, data, size);
return hash;
}
union ethash_hash512 ethash_keccak512_64(const uint8_t data[64])
{
union ethash_hash512 hash;
keccak(hash.word64s, 512, data, 64);
return hash;
}

View file

@ -0,0 +1,255 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#include <stdint.h>
static uint64_t rol(uint64_t x, unsigned s)
{
return (x << s) | (x >> (64 - s));
}
static const uint64_t round_constants[24] = {
0x0000000000000001,
0x0000000000008082,
0x800000000000808a,
0x8000000080008000,
0x000000000000808b,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008a,
0x0000000000000088,
0x0000000080008009,
0x000000008000000a,
0x000000008000808b,
0x800000000000008b,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800a,
0x800000008000000a,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008,
};
void ethash_keccakf1600(uint64_t state[25])
{
/* The implementation based on the "simple" implementation by Ronny Van Keer. */
int round;
uint64_t Aba, Abe, Abi, Abo, Abu;
uint64_t Aga, Age, Agi, Ago, Agu;
uint64_t Aka, Ake, Aki, Ako, Aku;
uint64_t Ama, Ame, Ami, Amo, Amu;
uint64_t Asa, Ase, Asi, Aso, Asu;
uint64_t Eba, Ebe, Ebi, Ebo, Ebu;
uint64_t Ega, Ege, Egi, Ego, Egu;
uint64_t Eka, Eke, Eki, Eko, Eku;
uint64_t Ema, Eme, Emi, Emo, Emu;
uint64_t Esa, Ese, Esi, Eso, Esu;
uint64_t Ba, Be, Bi, Bo, Bu;
uint64_t Da, De, Di, Do, Du;
Aba = state[0];
Abe = state[1];
Abi = state[2];
Abo = state[3];
Abu = state[4];
Aga = state[5];
Age = state[6];
Agi = state[7];
Ago = state[8];
Agu = state[9];
Aka = state[10];
Ake = state[11];
Aki = state[12];
Ako = state[13];
Aku = state[14];
Ama = state[15];
Ame = state[16];
Ami = state[17];
Amo = state[18];
Amu = state[19];
Asa = state[20];
Ase = state[21];
Asi = state[22];
Aso = state[23];
Asu = state[24];
for (round = 0; round < 24; round += 2)
{
/* Round (round + 0): Axx -> Exx */
Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa;
Be = Abe ^ Age ^ Ake ^ Ame ^ Ase;
Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi;
Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso;
Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu;
Da = Bu ^ rol(Be, 1);
De = Ba ^ rol(Bi, 1);
Di = Be ^ rol(Bo, 1);
Do = Bi ^ rol(Bu, 1);
Du = Bo ^ rol(Ba, 1);
Ba = Aba ^ Da;
Be = rol(Age ^ De, 44);
Bi = rol(Aki ^ Di, 43);
Bo = rol(Amo ^ Do, 21);
Bu = rol(Asu ^ Du, 14);
Eba = Ba ^ (~Be & Bi) ^ round_constants[round];
Ebe = Be ^ (~Bi & Bo);
Ebi = Bi ^ (~Bo & Bu);
Ebo = Bo ^ (~Bu & Ba);
Ebu = Bu ^ (~Ba & Be);
Ba = rol(Abo ^ Do, 28);
Be = rol(Agu ^ Du, 20);
Bi = rol(Aka ^ Da, 3);
Bo = rol(Ame ^ De, 45);
Bu = rol(Asi ^ Di, 61);
Ega = Ba ^ (~Be & Bi);
Ege = Be ^ (~Bi & Bo);
Egi = Bi ^ (~Bo & Bu);
Ego = Bo ^ (~Bu & Ba);
Egu = Bu ^ (~Ba & Be);
Ba = rol(Abe ^ De, 1);
Be = rol(Agi ^ Di, 6);
Bi = rol(Ako ^ Do, 25);
Bo = rol(Amu ^ Du, 8);
Bu = rol(Asa ^ Da, 18);
Eka = Ba ^ (~Be & Bi);
Eke = Be ^ (~Bi & Bo);
Eki = Bi ^ (~Bo & Bu);
Eko = Bo ^ (~Bu & Ba);
Eku = Bu ^ (~Ba & Be);
Ba = rol(Abu ^ Du, 27);
Be = rol(Aga ^ Da, 36);
Bi = rol(Ake ^ De, 10);
Bo = rol(Ami ^ Di, 15);
Bu = rol(Aso ^ Do, 56);
Ema = Ba ^ (~Be & Bi);
Eme = Be ^ (~Bi & Bo);
Emi = Bi ^ (~Bo & Bu);
Emo = Bo ^ (~Bu & Ba);
Emu = Bu ^ (~Ba & Be);
Ba = rol(Abi ^ Di, 62);
Be = rol(Ago ^ Do, 55);
Bi = rol(Aku ^ Du, 39);
Bo = rol(Ama ^ Da, 41);
Bu = rol(Ase ^ De, 2);
Esa = Ba ^ (~Be & Bi);
Ese = Be ^ (~Bi & Bo);
Esi = Bi ^ (~Bo & Bu);
Eso = Bo ^ (~Bu & Ba);
Esu = Bu ^ (~Ba & Be);
/* Round (round + 1): Exx -> Axx */
Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa;
Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese;
Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi;
Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso;
Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu;
Da = Bu ^ rol(Be, 1);
De = Ba ^ rol(Bi, 1);
Di = Be ^ rol(Bo, 1);
Do = Bi ^ rol(Bu, 1);
Du = Bo ^ rol(Ba, 1);
Ba = Eba ^ Da;
Be = rol(Ege ^ De, 44);
Bi = rol(Eki ^ Di, 43);
Bo = rol(Emo ^ Do, 21);
Bu = rol(Esu ^ Du, 14);
Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1];
Abe = Be ^ (~Bi & Bo);
Abi = Bi ^ (~Bo & Bu);
Abo = Bo ^ (~Bu & Ba);
Abu = Bu ^ (~Ba & Be);
Ba = rol(Ebo ^ Do, 28);
Be = rol(Egu ^ Du, 20);
Bi = rol(Eka ^ Da, 3);
Bo = rol(Eme ^ De, 45);
Bu = rol(Esi ^ Di, 61);
Aga = Ba ^ (~Be & Bi);
Age = Be ^ (~Bi & Bo);
Agi = Bi ^ (~Bo & Bu);
Ago = Bo ^ (~Bu & Ba);
Agu = Bu ^ (~Ba & Be);
Ba = rol(Ebe ^ De, 1);
Be = rol(Egi ^ Di, 6);
Bi = rol(Eko ^ Do, 25);
Bo = rol(Emu ^ Du, 8);
Bu = rol(Esa ^ Da, 18);
Aka = Ba ^ (~Be & Bi);
Ake = Be ^ (~Bi & Bo);
Aki = Bi ^ (~Bo & Bu);
Ako = Bo ^ (~Bu & Ba);
Aku = Bu ^ (~Ba & Be);
Ba = rol(Ebu ^ Du, 27);
Be = rol(Ega ^ Da, 36);
Bi = rol(Eke ^ De, 10);
Bo = rol(Emi ^ Di, 15);
Bu = rol(Eso ^ Do, 56);
Ama = Ba ^ (~Be & Bi);
Ame = Be ^ (~Bi & Bo);
Ami = Bi ^ (~Bo & Bu);
Amo = Bo ^ (~Bu & Ba);
Amu = Bu ^ (~Ba & Be);
Ba = rol(Ebi ^ Di, 62);
Be = rol(Ego ^ Do, 55);
Bi = rol(Eku ^ Du, 39);
Bo = rol(Ema ^ Da, 41);
Bu = rol(Ese ^ De, 2);
Asa = Ba ^ (~Be & Bi);
Ase = Be ^ (~Bi & Bo);
Asi = Bi ^ (~Bo & Bu);
Aso = Bo ^ (~Bu & Ba);
Asu = Bu ^ (~Ba & Be);
}
state[0] = Aba;
state[1] = Abe;
state[2] = Abi;
state[3] = Abo;
state[4] = Abu;
state[5] = Aga;
state[6] = Age;
state[7] = Agi;
state[8] = Ago;
state[9] = Agu;
state[10] = Aka;
state[11] = Ake;
state[12] = Aki;
state[13] = Ako;
state[14] = Aku;
state[15] = Ama;
state[16] = Ame;
state[17] = Ami;
state[18] = Amo;
state[19] = Amu;
state[20] = Asa;
state[21] = Ase;
state[22] = Asi;
state[23] = Aso;
state[24] = Asu;
}

View file

@ -0,0 +1,253 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#include <stdint.h>
static uint32_t rol(uint32_t x, unsigned s)
{
return (x << s) | (x >> (32 - s));
}
static const uint32_t round_constants[22] = {
0x00000001,
0x00008082,
0x0000808A,
0x80008000,
0x0000808B,
0x80000001,
0x80008081,
0x00008009,
0x0000008A,
0x00000088,
0x80008009,
0x8000000A,
0x8000808B,
0x0000008B,
0x00008089,
0x00008003,
0x00008002,
0x00000080,
0x0000800A,
0x8000000A,
0x80008081,
0x00008080,
};
void ethash_keccakf800(uint32_t state[25])
{
/* The implementation directly translated from ethash_keccakf1600. */
int round;
uint32_t Aba, Abe, Abi, Abo, Abu;
uint32_t Aga, Age, Agi, Ago, Agu;
uint32_t Aka, Ake, Aki, Ako, Aku;
uint32_t Ama, Ame, Ami, Amo, Amu;
uint32_t Asa, Ase, Asi, Aso, Asu;
uint32_t Eba, Ebe, Ebi, Ebo, Ebu;
uint32_t Ega, Ege, Egi, Ego, Egu;
uint32_t Eka, Eke, Eki, Eko, Eku;
uint32_t Ema, Eme, Emi, Emo, Emu;
uint32_t Esa, Ese, Esi, Eso, Esu;
uint32_t Ba, Be, Bi, Bo, Bu;
uint32_t Da, De, Di, Do, Du;
Aba = state[0];
Abe = state[1];
Abi = state[2];
Abo = state[3];
Abu = state[4];
Aga = state[5];
Age = state[6];
Agi = state[7];
Ago = state[8];
Agu = state[9];
Aka = state[10];
Ake = state[11];
Aki = state[12];
Ako = state[13];
Aku = state[14];
Ama = state[15];
Ame = state[16];
Ami = state[17];
Amo = state[18];
Amu = state[19];
Asa = state[20];
Ase = state[21];
Asi = state[22];
Aso = state[23];
Asu = state[24];
for (round = 0; round < 22; round += 2)
{
/* Round (round + 0): Axx -> Exx */
Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa;
Be = Abe ^ Age ^ Ake ^ Ame ^ Ase;
Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi;
Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso;
Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu;
Da = Bu ^ rol(Be, 1);
De = Ba ^ rol(Bi, 1);
Di = Be ^ rol(Bo, 1);
Do = Bi ^ rol(Bu, 1);
Du = Bo ^ rol(Ba, 1);
Ba = Aba ^ Da;
Be = rol(Age ^ De, 12);
Bi = rol(Aki ^ Di, 11);
Bo = rol(Amo ^ Do, 21);
Bu = rol(Asu ^ Du, 14);
Eba = Ba ^ (~Be & Bi) ^ round_constants[round];
Ebe = Be ^ (~Bi & Bo);
Ebi = Bi ^ (~Bo & Bu);
Ebo = Bo ^ (~Bu & Ba);
Ebu = Bu ^ (~Ba & Be);
Ba = rol(Abo ^ Do, 28);
Be = rol(Agu ^ Du, 20);
Bi = rol(Aka ^ Da, 3);
Bo = rol(Ame ^ De, 13);
Bu = rol(Asi ^ Di, 29);
Ega = Ba ^ (~Be & Bi);
Ege = Be ^ (~Bi & Bo);
Egi = Bi ^ (~Bo & Bu);
Ego = Bo ^ (~Bu & Ba);
Egu = Bu ^ (~Ba & Be);
Ba = rol(Abe ^ De, 1);
Be = rol(Agi ^ Di, 6);
Bi = rol(Ako ^ Do, 25);
Bo = rol(Amu ^ Du, 8);
Bu = rol(Asa ^ Da, 18);
Eka = Ba ^ (~Be & Bi);
Eke = Be ^ (~Bi & Bo);
Eki = Bi ^ (~Bo & Bu);
Eko = Bo ^ (~Bu & Ba);
Eku = Bu ^ (~Ba & Be);
Ba = rol(Abu ^ Du, 27);
Be = rol(Aga ^ Da, 4);
Bi = rol(Ake ^ De, 10);
Bo = rol(Ami ^ Di, 15);
Bu = rol(Aso ^ Do, 24);
Ema = Ba ^ (~Be & Bi);
Eme = Be ^ (~Bi & Bo);
Emi = Bi ^ (~Bo & Bu);
Emo = Bo ^ (~Bu & Ba);
Emu = Bu ^ (~Ba & Be);
Ba = rol(Abi ^ Di, 30);
Be = rol(Ago ^ Do, 23);
Bi = rol(Aku ^ Du, 7);
Bo = rol(Ama ^ Da, 9);
Bu = rol(Ase ^ De, 2);
Esa = Ba ^ (~Be & Bi);
Ese = Be ^ (~Bi & Bo);
Esi = Bi ^ (~Bo & Bu);
Eso = Bo ^ (~Bu & Ba);
Esu = Bu ^ (~Ba & Be);
/* Round (round + 1): Exx -> Axx */
Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa;
Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese;
Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi;
Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso;
Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu;
Da = Bu ^ rol(Be, 1);
De = Ba ^ rol(Bi, 1);
Di = Be ^ rol(Bo, 1);
Do = Bi ^ rol(Bu, 1);
Du = Bo ^ rol(Ba, 1);
Ba = Eba ^ Da;
Be = rol(Ege ^ De, 12);
Bi = rol(Eki ^ Di, 11);
Bo = rol(Emo ^ Do, 21);
Bu = rol(Esu ^ Du, 14);
Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1];
Abe = Be ^ (~Bi & Bo);
Abi = Bi ^ (~Bo & Bu);
Abo = Bo ^ (~Bu & Ba);
Abu = Bu ^ (~Ba & Be);
Ba = rol(Ebo ^ Do, 28);
Be = rol(Egu ^ Du, 20);
Bi = rol(Eka ^ Da, 3);
Bo = rol(Eme ^ De, 13);
Bu = rol(Esi ^ Di, 29);
Aga = Ba ^ (~Be & Bi);
Age = Be ^ (~Bi & Bo);
Agi = Bi ^ (~Bo & Bu);
Ago = Bo ^ (~Bu & Ba);
Agu = Bu ^ (~Ba & Be);
Ba = rol(Ebe ^ De, 1);
Be = rol(Egi ^ Di, 6);
Bi = rol(Eko ^ Do, 25);
Bo = rol(Emu ^ Du, 8);
Bu = rol(Esa ^ Da, 18);
Aka = Ba ^ (~Be & Bi);
Ake = Be ^ (~Bi & Bo);
Aki = Bi ^ (~Bo & Bu);
Ako = Bo ^ (~Bu & Ba);
Aku = Bu ^ (~Ba & Be);
Ba = rol(Ebu ^ Du, 27);
Be = rol(Ega ^ Da, 4);
Bi = rol(Eke ^ De, 10);
Bo = rol(Emi ^ Di, 15);
Bu = rol(Eso ^ Do, 24);
Ama = Ba ^ (~Be & Bi);
Ame = Be ^ (~Bi & Bo);
Ami = Bi ^ (~Bo & Bu);
Amo = Bo ^ (~Bu & Ba);
Amu = Bu ^ (~Ba & Be);
Ba = rol(Ebi ^ Di, 30);
Be = rol(Ego ^ Do, 23);
Bi = rol(Eku ^ Du, 7);
Bo = rol(Ema ^ Da, 9);
Bu = rol(Ese ^ De, 2);
Asa = Ba ^ (~Be & Bi);
Ase = Be ^ (~Bi & Bo);
Asi = Bi ^ (~Bo & Bu);
Aso = Bo ^ (~Bu & Ba);
Asu = Bu ^ (~Ba & Be);
}
state[0] = Aba;
state[1] = Abe;
state[2] = Abi;
state[3] = Abo;
state[4] = Abu;
state[5] = Aga;
state[6] = Age;
state[7] = Agi;
state[8] = Ago;
state[9] = Agu;
state[10] = Aka;
state[11] = Ake;
state[12] = Aki;
state[13] = Ako;
state[14] = Aku;
state[15] = Ama;
state[16] = Ame;
state[17] = Ami;
state[18] = Amo;
state[19] = Amu;
state[20] = Asa;
state[21] = Ase;
state[22] = Asi;
state[23] = Aso;
state[24] = Asu;
}

View file

@ -0,0 +1,64 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
#include "support/attributes.h"
#include <stdint.h>
/**
* KISS PRNG by the spec from 1999.
*
* The implementation of KISS pseudo-random number generator
* by the specification published on 21 Jan 1999 in
* http://www.cse.yorku.ca/~oz/marsaglia-rng.html.
* The KISS is not versioned so here we are using `kiss99` prefix to indicate
* the version from 1999.
*
* The specification uses `unsigned long` type with the intention for 32-bit
* values. Because in GCC/clang for 64-bit architectures `unsigned long` is
* 64-bit size type, here the explicit `uint32_t` type is used.
*
* @defgroup kiss99 KISS99
* @{
*/
/**
* The KISS generator.
*/
class kiss99
{
uint32_t z = 362436069;
uint32_t w = 521288629;
uint32_t jsr = 123456789;
uint32_t jcong = 380116160;
public:
/** Creates KISS generator state with default values provided by the specification. */
kiss99() noexcept = default;
/** Creates KISS generator state with provided init values.*/
kiss99(uint32_t z, uint32_t w, uint32_t jsr, uint32_t jcong) noexcept
: z{z}, w{w}, jsr{jsr}, jcong{jcong}
{}
/** Generates next number from the KISS generator. */
NO_SANITIZE("unsigned-integer-overflow")
uint32_t operator()() noexcept
{
z = 36969 * (z & 0xffff) + (z >> 16);
w = 18000 * (w & 0xffff) + (w >> 16);
jcong = 69069 * jcong + 1234567;
jsr ^= (jsr << 17);
jsr ^= (jsr >> 13);
jsr ^= (jsr << 5);
return (((z << 16) + w) ^ jcong) + jsr;
}
};
/** @} */

View file

@ -0,0 +1,100 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
#include "ethash-internal.hpp"
#include <memory>
#include <mutex>
#if !defined(__has_cpp_attribute)
#define __has_cpp_attribute(x) 0
#endif
#if __has_cpp_attribute(gnu::noinline)
#define ATTRIBUTE_NOINLINE [[gnu::noinline]]
#elif _MSC_VER
#define ATTRIBUTE_NOINLINE __declspec(noinline)
#else
#define ATTRIBUTE_NOINLINE
#endif
namespace ethash
{
namespace
{
std::mutex shared_context_mutex;
std::shared_ptr<epoch_context> shared_context;
thread_local std::shared_ptr<epoch_context> thread_local_context;
std::mutex shared_context_full_mutex;
std::shared_ptr<epoch_context_full> shared_context_full;
thread_local std::shared_ptr<epoch_context_full> thread_local_context_full;
/// Update thread local epoch context.
///
/// This function is on the slow path. It's separated to allow inlining the fast
/// path.
///
/// @todo: Redesign to guarantee deallocation before new allocation.
ATTRIBUTE_NOINLINE
void update_local_context(int epoch_number)
{
// Release the shared pointer of the obsoleted context.
thread_local_context.reset();
// Local context invalid, check the shared context.
std::lock_guard<std::mutex> lock{shared_context_mutex};
if (!shared_context || shared_context->epoch_number != epoch_number)
{
// Release the shared pointer of the obsoleted context.
shared_context.reset();
// Build new context.
shared_context = create_epoch_context(epoch_number);
}
thread_local_context = shared_context;
}
ATTRIBUTE_NOINLINE
void update_local_context_full(int epoch_number)
{
// Release the shared pointer of the obsoleted context.
thread_local_context_full.reset();
// Local context invalid, check the shared context.
std::lock_guard<std::mutex> lock{shared_context_full_mutex};
if (!shared_context_full || shared_context_full->epoch_number != epoch_number)
{
// Release the shared pointer of the obsoleted context.
shared_context_full.reset();
// Build new context.
shared_context_full = create_epoch_context_full(epoch_number);
}
thread_local_context_full = shared_context_full;
}
} // namespace
const epoch_context& get_global_epoch_context(int epoch_number)
{
// Check if local context matches epoch number.
if (!thread_local_context || thread_local_context->epoch_number != epoch_number)
update_local_context(epoch_number);
return *thread_local_context;
}
const epoch_context_full& get_global_epoch_context_full(int epoch_number)
{
// Check if local context matches epoch number.
if (!thread_local_context_full || thread_local_context_full->epoch_number != epoch_number)
update_local_context_full(epoch_number);
return *thread_local_context_full;
}
} // namespace ethash

View file

@ -0,0 +1,43 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#include "primes.h"
/** Checks if the number is prime. Requires the number to be > 2 and odd. */
static int is_odd_prime(int number)
{
int d;
/* Check factors up to sqrt(number).
To avoid computing sqrt, compare d*d <= number with 64-bit precision. */
for (d = 3; (int64_t)d * (int64_t)d <= (int64_t)number; d += 2)
{
if (number % d == 0)
return 0;
}
return 1;
}
int ethash_find_largest_prime(int upper_bound)
{
int n = upper_bound;
if (n < 2)
return 0;
if (n == 2)
return 2;
/* If even number, skip it. */
if (n % 2 == 0)
--n;
/* Test descending odd numbers. */
while (!is_odd_prime(n))
n -= 2;
return n;
}

View file

@ -0,0 +1,25 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
#include <ethash/ethash.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Finds the largest prime number not greater than the provided upper bound.
*
* @param upper_bound The upper bound. SHOULD be greater than 1.
* @return The largest prime number `p` such `p <= upper_bound`.
* In case `upper_bound <= 1`, returns 0.
*/
int ethash_find_largest_prime(int upper_bound) NOEXCEPT;
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,360 @@
// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
// Copyright 2018 Pawel Bylica.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
#include <ethash/progpow.hpp>
#include "bit_manipulation.h"
#include "endianness.hpp"
#include "ethash-internal.hpp"
#include "kiss99.hpp"
#include <ethash/keccak.hpp>
#include <array>
namespace progpow
{
namespace
{
/// A variant of Keccak hash function for ProgPoW.
///
/// This Keccak hash function uses 800-bit permutation (Keccak-f[800]) with 576 bitrate.
/// It take exactly 576 bits of input (split across 3 arguments) and adds no padding.
///
/// @param header_hash The 256-bit header hash.
/// @param nonce The 64-bit nonce.
/// @param mix_hash Additional 256-bits of data.
/// @return The 256-bit output of the hash function.
hash256 keccak_progpow_256(
const hash256& header_hash, uint64_t nonce, const hash256& mix_hash) noexcept
{
static constexpr size_t num_words =
sizeof(header_hash.word32s) / sizeof(header_hash.word32s[0]);
uint32_t state[25] = {};
size_t i;
for (i = 0; i < num_words; ++i)
state[i] = le::uint32(header_hash.word32s[i]);
state[i++] = static_cast<uint32_t>(nonce);
state[i++] = static_cast<uint32_t>(nonce >> 32);
for (uint32_t mix_word : mix_hash.word32s)
state[i++] = le::uint32(mix_word);
ethash_keccakf800(state);
hash256 output;
for (i = 0; i < num_words; ++i)
output.word32s[i] = le::uint32(state[i]);
return output;
}
/// The same as keccak_progpow_256() but uses null mix
/// and returns top 64 bits of the output being a big-endian prefix of the 256-bit hash.
inline uint64_t keccak_progpow_64(const hash256& header_hash, uint64_t nonce) noexcept
{
const hash256 h = keccak_progpow_256(header_hash, nonce, {});
return be::uint64(h.word64s[0]);
}
/// ProgPoW mix RNG state.
///
/// Encapsulates the state of the random number generator used in computing ProgPoW mix.
/// This includes the state of the KISS99 RNG and the precomputed random permutation of the
/// sequence of mix item indexes.
class mix_rng_state
{
public:
inline explicit mix_rng_state(uint64_t seed) noexcept;
uint32_t next_dst() noexcept { return dst_seq[(dst_counter++) % num_regs]; }
uint32_t next_src() noexcept { return src_seq[(src_counter++) % num_regs]; }
kiss99 rng;
private:
size_t dst_counter = 0;
std::array<uint32_t, num_regs> dst_seq;
size_t src_counter = 0;
std::array<uint32_t, num_regs> src_seq;
};
mix_rng_state::mix_rng_state(uint64_t seed) noexcept
{
const auto seed_lo = static_cast<uint32_t>(seed);
const auto seed_hi = static_cast<uint32_t>(seed >> 32);
const auto z = fnv1a(fnv_offset_basis, seed_lo);
const auto w = fnv1a(z, seed_hi);
const auto jsr = fnv1a(w, seed_lo);
const auto jcong = fnv1a(jsr, seed_hi);
rng = kiss99{z, w, jsr, jcong};
// Create random permutations of mix destinations / sources.
// Uses Fisher-Yates shuffle.
for (uint32_t i = 0; i < num_regs; ++i)
{
dst_seq[i] = i;
src_seq[i] = i;
}
for (uint32_t i = num_regs; i > 1; --i)
{
std::swap(dst_seq[i - 1], dst_seq[rng() % i]);
std::swap(src_seq[i - 1], src_seq[rng() % i]);
}
}
NO_SANITIZE("unsigned-integer-overflow")
inline uint32_t random_math(uint32_t a, uint32_t b, uint32_t selector) noexcept
{
switch (selector % 11)
{
default:
case 0:
return a + b;
case 1:
return a * b;
case 2:
return mul_hi32(a, b);
case 3:
return std::min(a, b);
case 4:
return rotl32(a, b);
case 5:
return rotr32(a, b);
case 6:
return a & b;
case 7:
return a | b;
case 8:
return a ^ b;
case 9:
return clz32(a) + clz32(b);
case 10:
return popcount32(a) + popcount32(b);
}
}
/// Merge data from `b` and `a`.
/// Assuming `a` has high entropy, only do ops that retain entropy even if `b`
/// has low entropy (i.e. do not do `a & b`).
NO_SANITIZE("unsigned-integer-overflow")
inline void random_merge(uint32_t& a, uint32_t b, uint32_t selector) noexcept
{
const auto x = (selector >> 16) % 31 + 1; // Additional non-zero selector from higher bits.
switch (selector % 4)
{
case 0:
a = (a * 33) + b;
break;
case 1:
a = (a ^ b) * 33;
break;
case 2:
a = rotl32(a, x) ^ b;
break;
case 3:
a = rotr32(a, x) ^ b;
break;
}
}
using lookup_fn = hash2048 (*)(const epoch_context&, uint32_t);
using mix_array = std::array<std::array<uint32_t, num_regs>, num_lanes>;
void round(
const epoch_context& context, uint32_t r, mix_array& mix, mix_rng_state state, lookup_fn lookup)
{
const uint32_t num_items = static_cast<uint32_t>(context.full_dataset_num_items / 2);
const uint32_t item_index = mix[r % num_lanes][0] % num_items;
const hash2048 item = lookup(context, item_index);
constexpr size_t num_words_per_lane = sizeof(item) / (sizeof(uint32_t) * num_lanes);
constexpr int max_operations =
num_cache_accesses > num_math_operations ? num_cache_accesses : num_math_operations;
// Process lanes.
for (int i = 0; i < max_operations; ++i)
{
if (i < num_cache_accesses) // Random access to cached memory.
{
const auto src = state.next_src();
const auto dst = state.next_dst();
const auto sel = state.rng();
for (size_t l = 0; l < num_lanes; ++l)
{
const size_t offset = mix[l][src] % l1_cache_num_items;
random_merge(mix[l][dst], le::uint32(context.l1_cache[offset]), sel);
}
}
if (i < num_math_operations) // Random math.
{
// Generate 2 unique source indexes.
const auto src_rnd = state.rng() % (num_regs * (num_regs - 1));
const auto src1 = src_rnd % num_regs; // O <= src1 < num_regs
auto src2 = src_rnd / num_regs; // 0 <= src2 < num_regs - 1
if (src2 >= src1)
++src2;
const auto sel1 = state.rng();
const auto dst = state.next_dst();
const auto sel2 = state.rng();
for (size_t l = 0; l < num_lanes; ++l)
{
const uint32_t data = random_math(mix[l][src1], mix[l][src2], sel1);
random_merge(mix[l][dst], data, sel2);
}
}
}
// DAG access pattern.
uint32_t dsts[num_words_per_lane];
uint32_t sels[num_words_per_lane];
for (size_t i = 0; i < num_words_per_lane; ++i)
{
dsts[i] = i == 0 ? 0 : state.next_dst();
sels[i] = state.rng();
}
// DAG access.
for (size_t l = 0; l < num_lanes; ++l)
{
const auto offset = ((l ^ r) % num_lanes) * num_words_per_lane;
for (size_t i = 0; i < num_words_per_lane; ++i)
{
const auto word = le::uint32(item.word32s[offset + i]);
random_merge(mix[l][dsts[i]], word, sels[i]);
}
}
}
mix_array init_mix(uint64_t seed)
{
const uint32_t z = fnv1a(fnv_offset_basis, static_cast<uint32_t>(seed));
const uint32_t w = fnv1a(z, static_cast<uint32_t>(seed >> 32));
mix_array mix;
for (uint32_t l = 0; l < mix.size(); ++l)
{
const uint32_t jsr = fnv1a(w, l);
const uint32_t jcong = fnv1a(jsr, l);
kiss99 rng{z, w, jsr, jcong};
for (auto& row : mix[l])
row = rng();
}
return mix;
}
hash256 hash_mix(
const epoch_context& context, int block_number, uint64_t seed, lookup_fn lookup) noexcept
{
auto mix = init_mix(seed);
mix_rng_state state{uint64_t(block_number / period_length)};
for (uint32_t i = 0; i < 64; ++i)
round(context, i, mix, state, lookup);
// Reduce mix data to a single per-lane result.
uint32_t lane_hash[num_lanes];
for (size_t l = 0; l < num_lanes; ++l)
{
lane_hash[l] = fnv_offset_basis;
for (uint32_t i = 0; i < num_regs; ++i)
lane_hash[l] = fnv1a(lane_hash[l], mix[l][i]);
}
// Reduce all lanes to a single 256-bit result.
static constexpr size_t num_words = sizeof(hash256) / sizeof(uint32_t);
hash256 mix_hash;
for (uint32_t& w : mix_hash.word32s)
w = fnv_offset_basis;
for (size_t l = 0; l < num_lanes; ++l)
mix_hash.word32s[l % num_words] = fnv1a(mix_hash.word32s[l % num_words], lane_hash[l]);
return le::uint32s(mix_hash);
}
} // namespace
result hash(const epoch_context& context, int block_number, const hash256& header_hash,
uint64_t nonce) noexcept
{
const uint64_t seed = keccak_progpow_64(header_hash, nonce);
const hash256 mix_hash = hash_mix(context, block_number, seed, calculate_dataset_item_2048);
const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash);
return {final_hash, mix_hash};
}
result hash(const epoch_context_full& context, int block_number, const hash256& header_hash,
uint64_t nonce) noexcept
{
static const auto lazy_lookup = [](const epoch_context& context, uint32_t index) noexcept
{
auto* full_dataset_1024 = static_cast<const epoch_context_full&>(context).full_dataset;
auto* full_dataset_2048 = reinterpret_cast<hash2048*>(full_dataset_1024);
hash2048& item = full_dataset_2048[index];
if (item.word64s[0] == 0)
{
// TODO: Copy elision here makes it thread-safe?
item = calculate_dataset_item_2048(context, index);
}
return item;
};
const uint64_t seed = keccak_progpow_64(header_hash, nonce);
const hash256 mix_hash = hash_mix(context, block_number, seed, lazy_lookup);
const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash);
return {final_hash, mix_hash};
}
bool verify(const epoch_context& context, int block_number, const hash256& header_hash,
const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept
{
const uint64_t seed = keccak_progpow_64(header_hash, nonce);
const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash);
if (!is_less_or_equal(final_hash, boundary))
return false;
const hash256 expected_mix_hash =
hash_mix(context, block_number, seed, calculate_dataset_item_2048);
return is_equal(expected_mix_hash, mix_hash);
}
search_result search_light(const epoch_context& context, int block_number,
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
size_t iterations) noexcept
{
const uint64_t end_nonce = start_nonce + iterations;
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
{
result r = hash(context, block_number, header_hash, nonce);
if (is_less_or_equal(r.final_hash, boundary))
return {r, nonce};
}
return {};
}
search_result search(const epoch_context_full& context, int block_number,
const hash256& header_hash, const hash256& boundary, uint64_t start_nonce,
size_t iterations) noexcept
{
const uint64_t end_nonce = start_nonce + iterations;
for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce)
{
result r = hash(context, block_number, header_hash, nonce);
if (is_less_or_equal(r.final_hash, boundary))
return {r, nonce};
}
return {};
}
} // namespace progpow

View file

@ -0,0 +1,33 @@
/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm.
* Copyright 2018 Pawel Bylica.
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
*/
#pragma once
/** inline */
#if _MSC_VER || __STDC_VERSION__
#define INLINE inline
#else
#define INLINE
#endif
/** [[always_inline]] */
#if _MSC_VER
#define ALWAYS_INLINE __forceinline
#elif defined(__has_attribute) && __STDC_VERSION__
#if __has_attribute(always_inline)
#define ALWAYS_INLINE __attribute__((always_inline))
#endif
#endif
#if !defined(ALWAYS_INLINE)
#define ALWAYS_INLINE
#endif
/** [[no_sanitize()]] */
#if __clang__
#define NO_SANITIZE(sanitizer) \
__attribute__((no_sanitize(sanitizer)))
#else
#define NO_SANITIZE(sanitizer)
#endif

View file

@ -49,6 +49,7 @@ file(GLOB_RECURSE DAEMON daemon/*)
file(GLOB_RECURSE P2P p2p/*)
file(GLOB_RECURSE RPC rpc/*)
file(GLOB_RECURSE STRATUM stratum/*)
file(GLOB_RECURSE SIMPLEWALLET simplewallet/*)
file(GLOB_RECURSE CONN_TOOL connectivity_tool/*)
file(GLOB_RECURSE WALLET wallet/*)
@ -73,6 +74,7 @@ source_group(currency_protocol FILES ${CURRENCY_PROTOCOL})
source_group(daemon FILES ${DAEMON})
source_group(p2p FILES ${P2P})
source_group(rpc FILES ${RPC})
source_group(stratum FILES ${STRATUM})
source_group(simplewallet FILES ${SIMPLEWALLET})
source_group(connectivity-tool FILES ${CONN_TOOL})
source_group(wallet FILES ${WALLET})
@ -106,6 +108,10 @@ add_library(rpc ${RPC})
add_dependencies(rpc version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(RPC)
add_library(stratum ${STRATUM})
add_dependencies(stratum version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(STRATUM)
add_library(wallet ${WALLET})
add_dependencies(wallet version ${PCH_LIB_NAME})
ENABLE_SHARED_PCH(WALLET)
@ -114,23 +120,23 @@ target_link_libraries(currency_core lmdb)
add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL})
add_dependencies(daemon version)
target_link_libraries(daemon rpc currency_core crypto common upnpc-static zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(daemon rpc stratum currency_core crypto common upnpc-static zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
ENABLE_SHARED_PCH(DAEMON)
ENABLE_SHARED_PCH_EXECUTABLE(daemon)
add_executable(connectivity_tool ${CONN_TOOL})
add_dependencies(connectivity_tool version)
target_link_libraries(connectivity_tool currency_core crypto common zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(connectivity_tool currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
ENABLE_SHARED_PCH(CONN_TOOL)
ENABLE_SHARED_PCH_EXECUTABLE(connectivity_tool)
add_executable(simplewallet ${SIMPLEWALLET})
add_dependencies(simplewallet version)
target_link_libraries(simplewallet wallet rpc currency_core crypto common zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(simplewallet wallet rpc currency_core crypto common zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
ENABLE_SHARED_PCH(SIMPLEWALLET)
ENABLE_SHARED_PCH_EXECUTABLE(simplewallet)
set_property(TARGET common crypto currency_core rpc wallet PROPERTY FOLDER "libs")
set_property(TARGET common crypto currency_core rpc stratum wallet PROPERTY FOLDER "libs")
set_property(TARGET daemon simplewallet connectivity_tool PROPERTY FOLDER "prog")
set_property(TARGET daemon PROPERTY OUTPUT_NAME "zanod")
@ -150,7 +156,7 @@ if(BUILD_GUI)
QT5_USE_MODULES(Zano WebEngineWidgets WebChannel)
find_package(Qt5PrintSupport REQUIRED)
target_link_libraries(Zano wallet rpc currency_core crypto common zlibstatic Qt5::WebEngineWidgets Qt5::PrintSupport ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(Zano wallet rpc currency_core crypto common zlibstatic ethash Qt5::WebEngineWidgets Qt5::PrintSupport ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
if(APPLE)
target_link_libraries(Zano ${COCOA_LIBRARY})

View file

@ -1,136 +0,0 @@
// keccak.c
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
// A baseline Keccak (3rd round) implementation.
// Memory-hard extension of keccak for PoW
// Copyright (c) 2014 The Boolberry developers
// Copyright (c) 2019 The Hyle Team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "wild_keccak.h"
#include "include_base_utils.h"
namespace crypto
{
const uint64_t keccakf_rndc[24] =
{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
const int keccakf_rotc[24] =
{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
const int keccakf_piln[24] =
{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};
// update the state with given number of rounds
void regular_f::keccakf(uint64_t st[25], int rounds)
{
int i, j, round;
uint64_t t, bc[5];
for (round = 0; round < rounds; round++) {
// Theta
for (i = 0; i < 5; i++)
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
for (i = 0; i < 5; i++) {
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
for (j = 0; j < 25; j += 5)
st[j + i] ^= t;
}
// Rho Pi
t = st[1];
for (i = 0; i < 24; i++) {
j = keccakf_piln[i];
bc[0] = st[j];
st[j] = ROTL64(t, keccakf_rotc[i]);
t = bc[0];
}
// Chi
for (j = 0; j < 25; j += 5) {
for (i = 0; i < 5; i++)
bc[i] = st[j + i];
for (i = 0; i < 5; i++)
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
// Iota
st[0] ^= keccakf_rndc[round];
}
}
bool generate_scratchpad(const crypto::hash& seed_data, std::vector<crypto::hash>& result_data, uint64_t target_size)
{
result_data.resize(target_size);
result_data[0] = crypto::cn_fast_hash(&seed_data, sizeof(seed_data));
for (size_t i = 1; i < target_size; i++)
{
result_data[i] = crypto::cn_fast_hash(&result_data[i - 1], sizeof(result_data[i - 1]));
}
return true;
}
bool generate_scratchpad_light(const crypto::hash& seed_data, std::vector<crypto::hash>& result_data, uint64_t target_size)
{
CHECK_AND_ASSERT_THROW_MES(target_size % 10 == 0, "wrong target_size = " << target_size);
result_data.reserve(target_size/10);
result_data.push_back(crypto::cn_fast_hash(&seed_data, sizeof(seed_data)));
crypto::hash prev_hash = result_data[0];
for (size_t i = 1; i < target_size; i++)
{
prev_hash = crypto::cn_fast_hash(&prev_hash, sizeof(prev_hash));
if (!(i % 10))
{
result_data.push_back(prev_hash);
}
}
return true;
}
bool get_wild_keccak_light(const std::string& bd, crypto::hash& res, const std::vector<crypto::hash>& scratchpad_light)
{
if (!scratchpad_light.size())
return false;
auto light_scr_accessor = [&](uint64_t i)
{
//get index of int64 item in scratchpad from i, where is is random number in whole uint64_t range
uint64_t int64_mod_index = i%(scratchpad_light.size() * 10 * 4);
//get related hash index
uint64_t hash_index = int64_mod_index / 4;
//get_in hash index (from 0 to 3)
uint64_t in_hash_index = int64_mod_index % 4;
//get index of primary hash in scratchpad_light
uint64_t primary_item_index = (hash_index - (hash_index % 10)) / 10;
uint64_t sha_count = hash_index % 10;
crypto::hash res = scratchpad_light[primary_item_index];
for (uint64_t i = 0; i != sha_count; i++)
{
res = cn_fast_hash(&res, sizeof(res));
}
return ((uint64_t*)&res)[in_hash_index];
};
return get_wild_keccak_light(bd, res, light_scr_accessor);
}
}

View file

@ -1,169 +0,0 @@
// keccak.h
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
// Copyright (c) 2014 The Boolberry developers
// Copyright (c) 2019 The Hyle Team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <stdint.h>
#include <string.h>
#include "crypto.h"
extern "C" {
//#include "crypto/alt/KeccakNISTInterface.h"
}
#ifndef KECCAK_ROUNDS
#define KECCAK_ROUNDS 24
#endif
#ifndef ROTL64
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
#endif
#define KK_MIXIN_SIZE 24
namespace crypto
{
typedef uint64_t state_t_m[25];
typedef uint64_t mixin_t[KK_MIXIN_SIZE];
template<class f_traits, class callback_t>
int wild_keccak2(const uint8_t *in, size_t inlen, uint8_t *md, size_t mdlen, callback_t cb)
{
state_t_m st;
uint8_t temp[144];
uint64_t rsiz, rsizw;
rsiz = sizeof(state_t_m) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen;
rsizw = rsiz / 8;
memset(&st[0], 0, 25 * sizeof(st[0]));
for (; inlen >= rsiz; inlen -= rsiz, in += rsiz)
{
for (size_t i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *)in)[i];
for (int keccak_round = 0; keccak_round != KECCAK_ROUNDS; keccak_round++)
{
f_traits::keccakf(st, keccak_round);
cb(st);
}
}
// last block and padding
memcpy(temp, in, inlen);
temp[inlen++] = 1;
memset(temp + inlen, 0, rsiz - inlen);
temp[rsiz - 1] |= 0x80;
for (size_t i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *)temp)[i];
for (int keccak_round = 0; keccak_round != KECCAK_ROUNDS; keccak_round++)
{
f_traits::keccakf(st, keccak_round);
cb(st);
}
memcpy(md, st, mdlen);
return 0;
}
template<class f_traits, class callback_t>
int wild_keccak2_dbl(const uint8_t *in, size_t inlen, uint8_t *md, size_t mdlen, callback_t cb)
{
//Satoshi's classic
wild_keccak2<f_traits>(in, inlen, md, mdlen, cb);
wild_keccak2<f_traits>(md, mdlen, md, mdlen, cb);
return 0;
}
class regular_f
{
public:
static void keccakf(uint64_t st[25], int rounds);
};
//------------------------------------------------------------------
inline
bool get_wild_keccak2(const std::string& bd, crypto::hash& res, const uint64_t* int_array_ptr_scratch, uint64_t int64_sz)
{
uint64_t count_access = 0;
crypto::wild_keccak2_dbl<crypto::regular_f>(reinterpret_cast<const uint8_t*>(bd.data()), bd.size(), reinterpret_cast<uint8_t*>(&res), sizeof(res), [&](crypto::state_t_m& st)
{
++count_access;
if (!int64_sz)
{
return;
}
for (size_t i = 0; i != sizeof(st) / sizeof(st[0]); i++)
{
size_t depend_index = 0;
if (i == 0)
{
depend_index = sizeof(st) / sizeof(st[0]) - 1;
}
else
{
depend_index = i - 1;
}
st[i] ^= int_array_ptr_scratch[int_array_ptr_scratch[int_array_ptr_scratch[st[depend_index] % int64_sz] % int64_sz] % int64_sz];
}
});
return true;
}
//------------------------------------------------------------------
inline
bool get_wild_keccak2(const std::string& bd, crypto::hash& res, const std::vector<crypto::hash>& scratchpad, uint64_t sz)
{
const uint64_t* int_array_ptr = (const uint64_t*)&scratchpad[0];
size_t int64_sz = sz * 4;
return get_wild_keccak2(bd, res, int_array_ptr, int64_sz);
}
//------------------------------------------------------------------
template<class t_items_accessor>
bool get_wild_keccak_light(const std::string& bd, crypto::hash& res, t_items_accessor cb_get_item)
{
crypto::wild_keccak2_dbl<crypto::regular_f>(reinterpret_cast<const uint8_t*>(bd.data()), bd.size(), reinterpret_cast<uint8_t*>(&res), sizeof(res), [&](crypto::state_t_m& st)
{
for (size_t i = 0; i != sizeof(st) / sizeof(st[0]); i++)
{
size_t depend_index = 0;
if (i == 0)
{
depend_index = sizeof(st) / sizeof(st[0]) - 1;
}
else
{
depend_index = i - 1;
}
st[i] ^= cb_get_item(cb_get_item(cb_get_item(st[depend_index])));
}
});
return true;
}
//------------------------------------------------------------------
bool get_wild_keccak_light(const std::string& bd, crypto::hash& res, const std::vector<crypto::hash>& scratchpad_light);
//------------------------------------------------------------------
inline
bool get_wild_keccak2(const std::string& bd, crypto::hash& res, const std::vector<crypto::hash>& scratchpad)
{
return get_wild_keccak2(bd, res, scratchpad, scratchpad.size());
}
//------------------------------------------------------------------
bool generate_scratchpad(const crypto::hash& source_data, std::vector<crypto::hash>& result_data, uint64_t target_size);
bool generate_scratchpad_light(const crypto::hash& seed_data, std::vector<crypto::hash>& result_data, uint64_t target_size);
}

View file

@ -98,7 +98,7 @@ namespace currency
//cut the last timestamp word from restore_dats
std::list<std::string> words;
boost::split(words, restore_data_, boost::is_space());
CHECK_AND_ASSERT_THROW_MES(words.size() == BRAINWALLET_DEFAULT_WORDS_COUNT, "Words count missmatch: " << words.size());
CHECK_AND_ASSERT_MES(words.size() == BRAINWALLET_DEFAULT_WORDS_COUNT, false, "Words count missmatch: " << words.size());
std::string timestamp_word = words.back();
words.erase(--words.end());

View file

@ -0,0 +1,74 @@
// Copyright (c) 2018-2019 Zano Project
// Copyright (c) 2018-2019 Hyle Team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "include_base_utils.h"
using namespace epee;
#include "basic_pow_helpers.h"
#include "currency_format_utils.h"
#include "serialization/binary_utils.h"
#include "serialization/stl_containers.h"
#include "currency_core/currency_config.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "common/int-util.h"
#include "ethereum/libethash/ethash/ethash.hpp"
#include "ethereum/libethash/ethash/progpow.hpp"
namespace currency
{
//--------------------------------------------------------------
//global object
// crypto::ethash::cache_manager cache;
// void ethash_set_use_dag(bool use_dag)
// {
// cache.set_use_dag(use_dag);
// }
// //------------------------------------------------------------------
// const uint8_t* ethash_get_dag(uint64_t epoch, uint64_t& dag_size)
// {
// return cache.get_dag(epoch, dag_size);
// }
//------------------------------------------------------------------
int ethash_height_to_epoch(uint64_t height)
{
return height / ETHASH_EPOCH_LENGTH;
}
//--------------------------------------------------------------
crypto::hash get_block_longhash(uint64_t height, const crypto::hash& block_long_ash, uint64_t nonce)
{
int epoch = ethash_height_to_epoch(height);
const auto& context = progpow::get_global_epoch_context_full(static_cast<int>(epoch));
auto res_eth = progpow::hash(context, height, *(ethash::hash256*)&block_long_ash, nonce);
crypto::hash result = currency::null_hash;
memcpy(&result.data, &res_eth.final_hash, sizeof(res_eth.final_hash));
return result;
}
//---------------------------------------------------------------
void get_block_longhash(const block& b, crypto::hash& res)
{
/*
Since etherium hash has a bit different approach in minig, to adopt our code we made little hack:
etherium hash calculates from block's hash and(!) nonce, both passed into PoW hash function.
To achieve the same effect we make blob of data from block in normal way, but then set to zerro nonce
inside serialized buffer, and then pass this nonce to ethash algo as a second argument, as it expected.
*/
blobdata bd = get_block_hashing_blob(b);
access_nonce_in_block_blob(bd) = 0;
crypto::hash bl_hash = crypto::cn_fast_hash(bd.data(), bd.size());
res = get_block_longhash(get_block_height(b), bl_hash, b.nonce);
}
//---------------------------------------------------------------
crypto::hash get_block_longhash(const block& b)
{
crypto::hash p = null_hash;
get_block_longhash(b, p);
return p;
}
}

View file

@ -0,0 +1,44 @@
// Copyright (c) 2014-2018 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <typeindex>
#include <unordered_set>
#include <unordered_map>
#include "account.h"
#include "include_base_utils.h"
#include "currency_format_utils_abstract.h"
#include "common/crypto_stream_operators.h"
#include "currency_protocol/currency_protocol_defs.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "difficulty.h"
//#include "offers_services_helpers.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "bc_payments_id_service.h"
#include "bc_attachments_helpers_basic.h"
#include "blockchain_storage_basic.h"
#define CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET 1
namespace currency
{
int ethash_height_to_epoch(uint64_t height);
crypto::hash get_block_longhash(uint64_t h, const crypto::hash& block_long_ash, uint64_t nonce);
void get_block_longhash(const block& b, crypto::hash& res);
crypto::hash get_block_longhash(const block& b);
inline uint64_t& access_nonce_in_block_blob(blobdata& bd)
{
return *reinterpret_cast<uint64_t*>(&bd[CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET]);
}
inline const uint64_t& access_nonce_in_block_blob(const blobdata& bd)
{
return *reinterpret_cast<const uint64_t*>(&bd[CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET]);
}
}

View file

@ -31,6 +31,7 @@
#include "miner_common.h"
#include "storages/portable_storage_template_helper.h"
#include "common/db_backend_lmdb.h"
#include "basic_pow_helpers.h"
#include "version.h"
#undef LOG_DEFAULT_CHANNEL
@ -99,9 +100,7 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(std::share
m_current_fee_median(0),
m_current_fee_median_effective_index(0),
m_is_reorganize_in_process(false),
m_deinit_is_done(false),
m_current_scratchpad_seed(currency::null_hash),
m_current_scratchpad_seed_height(0)
m_deinit_is_done(false)
{
@ -291,9 +290,6 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
initialize_db_solo_options_values();
get_seed_for_scratchpad(m_db_blocks.size(), m_current_scratchpad_seed);
m_current_scratchpad_seed_height = m_db_blocks.size();
m_services_mgr.init(config_folder, vm);
@ -1112,16 +1108,16 @@ uint64_t blockchain_storage::get_current_comulative_blocksize_limit() const
return m_db_current_block_cumul_sz_limit;
}
//------------------------------------------------------------------
bool blockchain_storage::create_block_template(block& b, crypto::hash& seed,
bool blockchain_storage::create_block_template(block& b,
const account_public_address& miner_address,
wide_difficulty_type& diffic,
uint64_t& height,
const blobdata& ex_nonce) const
{
return create_block_template(b, seed, miner_address, miner_address, diffic, height, ex_nonce, false, pos_entry());
return create_block_template(b, miner_address, miner_address, diffic, height, ex_nonce, false, pos_entry());
}
//------------------------------------------------------------------
bool blockchain_storage::create_block_template(block& b, crypto::hash& seed,
bool blockchain_storage::create_block_template(block& b,
const account_public_address& miner_address,
const account_public_address& stakeholder_address,
wide_difficulty_type& diffic,
@ -1131,7 +1127,6 @@ bool blockchain_storage::create_block_template(block& b, crypto::hash& seed,
const pos_entry& pe,
fill_block_template_func_t custom_fill_block_template_func /* = nullptr */) const
{
seed = m_current_scratchpad_seed;
size_t median_size;
uint64_t already_generated_coins;
CRITICAL_REGION_BEGIN(m_read_lock);
@ -1456,10 +1451,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
}
else
{
crypto::hash seed = null_hash;
get_seed_for_scratchpad_alt_chain(abei.height, seed, alt_chain);
proof_of_work = m_scratchpad.get_pow_hash(abei.bl, seed);
proof_of_work = get_block_longhash(abei.bl);
if (!check_hash(proof_of_work, current_diff))
{
@ -1613,7 +1605,7 @@ bool blockchain_storage::pre_validate_relayed_block(block& bl, block_verificatio
}
else
{
proof_hash = m_scratchpad.get_pow_hash(bl, m_current_scratchpad_seed); //get_block_longhash(bl);
proof_hash = get_block_longhash(bl); //get_block_longhash(bl);
if (!check_hash(proof_hash, current_diffic))
{
@ -1738,9 +1730,6 @@ bool blockchain_storage::get_main_block_rpc_details(uint64_t i, block_rpc_extend
CRITICAL_REGION_LOCAL(m_read_lock);
auto core_bei_ptr = m_db_blocks[i];
crypto::hash id = get_block_hash(core_bei_ptr->bl);
crypto::hash pow_seed = null_hash;
get_seed_for_scratchpad(i, pow_seed);
bei.pow_seed = epee::string_tools::pod_to_hex(pow_seed);
bei.is_orphan = false;
bei.total_fee = 0;
bei.total_txs_size = 0;
@ -2763,7 +2752,6 @@ bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx
CHECK_AND_ASSERT_MES(back_item->tx_id == tx_id, false, "transactions outs global index consistency broken: tx id missmatch");
CHECK_AND_ASSERT_MES(back_item->out_no == i, false, "transactions outs global index consistency broken: in transaction index missmatch");
m_db_outputs.pop_back_item(ot.amount);
//do not let to exist empty m_outputs entries - this will broke scratchpad selector
//if (!it->second.size())
// m_db_outputs.erase(it);
}
@ -4301,18 +4289,13 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
}
else
{
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
//precaution(do we really need this check?)
check_scratchpad();
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
proof_hash = m_scratchpad.get_pow_hash(bl, m_current_scratchpad_seed);
proof_hash = get_block_longhash(bl);
if (!check_hash(proof_hash, current_diffic))
{
LOG_ERROR("Block with id: " << id << ENDL
<< "PoW hash: " << proof_hash << ENDL
<< "PoW seed: " << m_current_scratchpad_seed << ENDL
<< "unexpected difficulty: " << current_diffic);
bvc.m_verification_failed = true;
return false;
@ -4575,28 +4558,16 @@ void blockchain_storage::on_block_added(const block_extended_info& bei, const cr
{
update_next_comulative_size_limit();
m_timestamps_median_cache.clear();
check_scratchpad();
m_tx_pool.on_blockchain_inc(bei.height, id);
TIME_MEASURE_START_PD(raise_block_core_event);
rise_core_event(CORE_EVENT_BLOCK_ADDED, void_struct());
TIME_MEASURE_FINISH_PD(raise_block_core_event);
}
//------------------------------------------------------------------
bool blockchain_storage::check_scratchpad()
{
if(get_scratchpad_last_update_rebuild_height(m_db_blocks.size()) != m_current_scratchpad_seed_height)
{
get_seed_for_scratchpad(m_db_blocks.size(), m_current_scratchpad_seed);
m_current_scratchpad_seed_height = get_scratchpad_last_update_rebuild_height(m_db_blocks.size());
}
return true;
}
//------------------------------------------------------------------
void blockchain_storage::on_block_removed(const block_extended_info& bei)
{
m_tx_pool.on_blockchain_dec(m_db_blocks.size() - 1, get_top_block_id());
m_timestamps_median_cache.clear();
check_scratchpad();
LOG_PRINT_L2("block at height " << bei.height << " was removed from the blockchain");
}
//------------------------------------------------------------------
@ -5330,42 +5301,6 @@ bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx
return false;
}
//------------------------------------------------------------------
bool blockchain_storage::get_seed_for_scratchpad(uint64_t height, crypto::hash& seed)const
{
CRITICAL_REGION_LOCAL(m_read_lock);
LOG_PRINT_MAGENTA("Get seed for scratchpad [main_chain] on height " << height, LOG_LEVEL_0);
return get_seed_for_scratchpad_cb(height, seed, [&](uint64_t index) -> crypto::hash
{
return get_block_hash(m_db_blocks[index]->bl);
});
}
//------------------------------------------------------------------
bool blockchain_storage::get_seed_for_scratchpad_alt_chain(uint64_t height, crypto::hash& seed, const alt_chain_type& alt_chain)const
{
CRITICAL_REGION_LOCAL(m_read_lock);
//alt_chain: front -> mainchain, back -> alternative head
uint64_t connection_to_main_chain = height;
if (alt_chain.size())
connection_to_main_chain = alt_chain.front()->second.height;
return get_seed_for_scratchpad_cb(height, seed, [&](uint64_t index) -> crypto::hash
{
if (index < connection_to_main_chain)
{
//addressed to main chain
return get_block_hash(m_db_blocks[index]->bl);
}
else
{
//addressed to alt chain
uint64_t offset = index - connection_to_main_chain;
CHECK_AND_ASSERT_THROW_MES(offset < alt_chain.size(), "Internal error: failed to validate offset(" << offset << ") < alt_chain.size()("<< alt_chain.size() <<")");
CHECK_AND_ASSERT_THROW_MES(alt_chain[offset]->second.height == index, "Internal error: failed to validate offset(" << offset << ") < alt_chain.size()(" << alt_chain.size() << ")");
return get_block_hash(alt_chain[offset]->second.bl);
}
});
}
//------------------------------------------------------------------
bool blockchain_storage::get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr<transaction>& tx_ptr, uint64_t min_allowed_block_height /* = 0 */) const
{
tx_ptr.reset(new transaction());

View file

@ -39,7 +39,7 @@
#include "dispatch_core_events.h"
#include "bc_attachments_service_manager.h"
#include "common/median_db_cache.h"
#include "scratchpad_helper.h"
MARK_AS_POD_C11(crypto::key_image);
@ -231,8 +231,8 @@ namespace currency
wide_difficulty_type get_cached_next_difficulty(bool pos) const;
typedef bool fill_block_template_func_t(block &bl, bool pos, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t height);
bool create_block_template(block& b, crypto::hash& seed, const account_public_address& miner_address, const account_public_address& stakeholder_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe, fill_block_template_func_t custom_fill_block_template_func = nullptr) const;
bool create_block_template(block& b, crypto::hash& seed, const account_public_address& miner_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce) const;
bool create_block_template(block& b, const account_public_address& miner_address, const account_public_address& stakeholder_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe, fill_block_template_func_t custom_fill_block_template_func = nullptr) const;
bool create_block_template(block& b, const account_public_address& miner_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce) const;
bool have_block(const crypto::hash& id) const;
size_t get_total_transactions()const;
@ -510,10 +510,7 @@ namespace currency
//work like a cache to avoid
mutable uint64_t m_current_fee_median;
mutable uint64_t m_current_fee_median_effective_index;
bool m_is_reorganize_in_process;
mutable scratchpad_light_pool m_scratchpad; //TODO: optimization for using full scratchpad in mainchain
crypto::hash m_current_scratchpad_seed;
uint64_t m_current_scratchpad_seed_height;
bool m_is_reorganize_in_process;
mutable std::atomic<bool> m_deinit_is_done;
@ -542,10 +539,6 @@ namespace currency
bool validate_alt_block_txs(const block& b, const crypto::hash& id, std::set<crypto::key_image>& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const;
bool update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei)const;
bool get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr<transaction>& tx_ptr, uint64_t min_allowed_block_height = 0) const;
bool get_seed_for_scratchpad(uint64_t height, crypto::hash& seed)const ;
bool get_seed_for_scratchpad_alt_chain(uint64_t height, crypto::hash& seed, const alt_chain_type& alt_chain) const ;
bool check_scratchpad();
bool prevalidate_miner_transaction(const block& b, uint64_t height, bool pos)const;
bool validate_transaction(const block& b, uint64_t height, const transaction& tx)const;
@ -572,7 +565,6 @@ namespace currency
uint64_t get_adjusted_time()const;
bool complete_timestamps_vector(uint64_t start_height, std::vector<uint64_t>& timestamps);
bool update_next_comulative_size_limit();
//bool get_block_for_scratchpad_alt(uint64_t connection_height, uint64_t block_index, std::list<blockchain_storage::blocks_ext_by_hash::iterator>& alt_chain, block & b);
bool process_blockchain_tx_extra(const transaction& tx);
bool unprocess_blockchain_tx_extra(const transaction& tx);
bool process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp);

View file

@ -7,7 +7,7 @@
#pragma once
#define CURRENCY_FORMATION_VERSION 76
#define CURRENCY_FORMATION_VERSION 78
#define CURRENCY_MAX_BLOCK_NUMBER 500000000
@ -46,12 +46,6 @@
#define BASE_REWARD_DUST_THRESHOLD ((uint64_t)1000000) // pow(10, 6) - change this will cause hard-fork!
#define DEFAULT_DUST_THRESHOLD ((uint64_t)0)//((uint64_t)100000) // pow(10, 5)
#define CURRENCY_SCRATCHPAD_BASE_SIZE 16777210 //count in crypto::hash, to get size in bytes x32
#define CURRENCY_SCRATCHPAD_REBUILD_INTERVAL 720 //once a day if block goes once in 2 minute
#define CURRENCY_SCRATCHPAD_BASE_INDEX_ID_OFFSET 20 //offset down from last rebuild height to block id, that used for indexing seed blocks in CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW
#define CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW 700 //window for addressing seed block ids
#define CURRENCY_SCRATCHPAD_GENESIS_SEED "4c98962ddce32c7763bb9326933a4692975ca29a76349ae7a139faa3430cc5ab"
#define TX_DEFAULT_FEE ((uint64_t)100000) // pow(10, 5)
#define TX_MINIMUM_FEE ((uint64_t)100000) // pow(10, 5)

View file

@ -401,14 +401,9 @@ namespace currency
return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, kept_by_block);
}
//-----------------------------------------------------------------------------------------------
bool core::get_block_template(block& b, crypto::hash& seed, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe)
{
return m_blockchain_storage.create_block_template(b, seed, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe);
}
bool core::get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe)
{
crypto::hash seed_subst = currency::null_hash;
return m_blockchain_storage.create_block_template(b, seed_subst, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe);
return m_blockchain_storage.create_block_template(b, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe);
}
//-----------------------------------------------------------------------------------------------
bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const

View file

@ -51,9 +51,7 @@ namespace currency
//-------------------- i_miner_handler -----------------------
virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr);
virtual bool get_block_template(block& b, crypto::hash& seed, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
miner& get_miner(){ return m_miner; }
static void init_options(boost::program_options::options_description& desc);

View file

@ -1212,7 +1212,7 @@ namespace currency
//---------------------------------------------------------------
std::string get_word_from_timstamp(uint64_t timestamp)
{
uint64_t date_offset = timestamp ? timestamp - WALLET_BRAIN_DATE_OFFSET : 0;
uint64_t date_offset = timestamp > WALLET_BRAIN_DATE_OFFSET ? timestamp - WALLET_BRAIN_DATE_OFFSET : 0;
uint64_t weeks_count = date_offset / WALLET_BRAIN_DATE_QUANTUM;
CHECK_AND_ASSERT_THROW_MES(weeks_count < std::numeric_limits<uint32_t>::max(), "internal error: unable to converto to uint32, val = " << weeks_count);
uint32_t weeks_count_32 = static_cast<uint32_t>(weeks_count);
@ -1664,24 +1664,7 @@ namespace currency
}
return true;
}
// //--------------------------------------------------------------
// crypto::hash get_block_longhash(uint64_t height, const crypto::hash& block_long_ash, uint64_t nonce)
// {
// //TODO: add wild keccak 2
// return null_hash;//TODO;
// }
// //---------------------------------------------------------------
// void get_block_longhash(const block& b, crypto::hash& res)
// {
// //TODO: add wild keccak 2
// }
// //---------------------------------------------------------------
// crypto::hash get_block_longhash(const block& b)
// {
// crypto::hash p = null_hash;
// get_block_longhash(b, p);
// return p;
// }
//---------------------------------------------------------------
uint64_t get_alias_coast_from_fee(const std::string& alias, uint64_t median_fee)
{
@ -2405,21 +2388,6 @@ namespace currency
return CURRENCY_TESTNET_CONST_REWARD;
}
//-----------------------------------------------------------------------------------------------
uint64_t get_scratchpad_last_update_rebuild_height(uint64_t h)
{
return h - (h%CURRENCY_SCRATCHPAD_REBUILD_INTERVAL);
}
//-----------------------------------------------------------------------------------------------
uint64_t get_scratchpad_size_for_height(uint64_t h)
{
if (h < CURRENCY_BLOCKS_PER_DAY * 7)
{
return 100;
}
//let's have ~250MB/year if block interval is 2 minutes
return CURRENCY_SCRATCHPAD_BASE_SIZE + get_scratchpad_last_update_rebuild_height(h)*30;
}
//-----------------------------------------------------------------------------------------------
bool get_block_reward(bool is_pos, size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint64_t height)
{
uint64_t base_reward = get_base_block_reward(is_pos, already_generated_coins, height);

View file

@ -295,11 +295,6 @@ namespace currency
bool parse_amount(uint64_t& amount, const std::string& str_amount);
// crypto::hash get_block_longhash(uint64_t h, const crypto::hash& block_long_ash, uint64_t nonce);
// void get_block_longhash(const block& b, crypto::hash& res);
// crypto::hash get_block_longhash(const block& b);
bool unserialize_block_complete_entry(const COMMAND_RPC_GET_BLOCKS_FAST::response& serialized,
COMMAND_RPC_GET_BLOCKS_DIRECT::response& unserialized);
@ -389,8 +384,6 @@ namespace currency
size_t get_max_tx_size();
bool get_block_reward(bool is_pos, size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint64_t height);
uint64_t get_base_block_reward(bool is_pos, uint64_t already_generated_coins, uint64_t height);
uint64_t get_scratchpad_last_update_rebuild_height(uint64_t h);
uint64_t get_scratchpad_size_for_height(uint64_t h);
bool is_payment_id_size_ok(const std::string& payment_id);
std::string get_account_address_as_str(const account_public_address& addr);
std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const std::string& payment_id);
@ -520,41 +513,6 @@ namespace currency
}
return false;
}
//---------------------------------------------------------------
template<class block_chain_accessor_t>
bool get_seed_for_scratchpad_cb(uint64_t height, crypto::hash& seed, block_chain_accessor_t cb)
{
//CHECK_AND_ASSERT_THROW_MES(m_db_blocks.size() > height, "Internal error: m_db_blocks.size()=" << m_db_blocks.size() << " > height=" << height);
uint64_t last_upd_h = get_scratchpad_last_update_rebuild_height(height);
std::vector<crypto::hash> seed_data;
if (last_upd_h == 0)
{
crypto::hash genesis_seed = null_hash;
bool r = epee::string_tools::hex_to_pod(CURRENCY_SCRATCHPAD_GENESIS_SEED, genesis_seed);
CHECK_AND_ASSERT_THROW_MES(r, "Unable to parse CURRENCY_SCRATCHPAD_GENESIS_SEED " << CURRENCY_SCRATCHPAD_GENESIS_SEED);
LOG_PRINT_MAGENTA("[SCRATCHPAD] GENESIS SEED SELECTED: " << genesis_seed, LOG_LEVEL_0);
seed = genesis_seed;
return true;
}
uint64_t low_bound_window = 0;
CHECK_AND_ASSERT_THROW_MES(last_upd_h >= CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW, "Internal error: last_upd_h(" << last_upd_h << ") < CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW(" << CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW << ")");
low_bound_window = last_upd_h - CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW;
crypto::hash selector_id = cb(last_upd_h - CURRENCY_SCRATCHPAD_BASE_INDEX_ID_OFFSET);
const uint64_t* pselectors = (const uint64_t*)&selector_id;
std::stringstream ss;
for (size_t i = 0; i != 4; i++)
{
seed_data.push_back(cb(low_bound_window + pselectors[i] % CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW));
ss << "[" << std::setw(8) << std::hex << pselectors[i] << "->" << low_bound_window + pselectors[i] % CURRENCY_SCRATCHPAD_SEED_BLOCKS_WINDOW << "]" << seed_data.back() << ENDL;
}
seed = crypto::cn_fast_hash(&seed_data[0], sizeof(seed_data[0]) * seed_data.size());
LOG_PRINT_MAGENTA("[SCRATCHPAD] SEED SELECTED: h = " << last_upd_h << ", selector: " << selector_id << ENDL << ss.str() << "SEED: " << seed, LOG_LEVEL_0);
return true;
}
//---------------------------------------------------------------
// 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold

View file

@ -114,12 +114,12 @@ namespace currency {
return false;
// usual slow check
boost::multiprecision::uint512_t hashVal = 0;
for (int i = 1; i < 4; i++)
{ // highest word is zero
hashVal |= swap64le(((const uint64_t *)&h)[3 - i]);
hashVal << 64;
for(int i = 0; i < 4; i++)
{
hashVal <<= 64;
hashVal |= swap64le(((const uint64_t *) &h)[3-i]);
}
return (hashVal * difficulty > max256bit);
return (hashVal * difficulty <= max256bit);
}
uint64_t difficulty_to_boundary(wide_difficulty_type difficulty)

View file

@ -20,6 +20,7 @@
#include "string_coding.h"
#include "version.h"
#include "storages/portable_storage_template_helper.h"
#include "basic_pow_helpers.h"
using namespace epee;
@ -64,16 +65,14 @@ namespace currency
stop();
}
//-----------------------------------------------------------------------------------------------------
bool miner::set_block_template(const block& bl, const wide_difficulty_type& di, uint64_t height, const crypto::hash& seed)
bool miner::set_block_template(const block& bl, const wide_difficulty_type& di, uint64_t height)
{
CRITICAL_REGION_LOCAL(m_template_lock);
m_template = bl;
m_diffic = di;
m_height = height;
m_seed = seed;
++m_template_no;
m_starter_nonce = crypto::rand<uint32_t>();
m_scratchpad.generate(m_seed, height);
return true;
}
//-----------------------------------------------------------------------------------------------------
@ -96,13 +95,12 @@ namespace currency
{
extra_nonce += std::string("|") + m_extra_messages[m_config.current_extra_message_index];
}
crypto::hash seed = null_hash;
if(!m_phandler->get_block_template(bl, seed, m_mine_address, m_mine_address, di, height, extra_nonce))
if(!m_phandler->get_block_template(bl, m_mine_address, m_mine_address, di, height, extra_nonce))
{
LOG_ERROR("Failed to get_block_template()");
return false;
}
set_block_template(bl, di, height, seed);
set_block_template(bl, di, height);
return true;
}
//-----------------------------------------------------------------------------------------------------
@ -309,8 +307,8 @@ namespace currency
wide_difficulty_type local_diff = 0;
uint32_t local_template_ver = 0;
blobdata local_blob_data;
crypto::hash local_seed = null_hash;
uint64_t local_height = 0;
crypto::hash local_blob_data_hash = null_hash;
//uint64_t local_template_height = 0;
block b;
@ -327,14 +325,15 @@ namespace currency
{
CRITICAL_REGION_BEGIN(m_template_lock);
b = m_template;
b.nonce = 0;
local_diff = m_diffic;
local_seed = m_seed;
local_height = m_height;
CRITICAL_REGION_END();
//local_template_height = get_block_height(b);
local_template_ver = m_template_no;
nonce = m_starter_nonce + th_local_index;
local_blob_data = get_block_hashing_blob(b);
local_blob_data_hash = crypto::cn_fast_hash(local_blob_data.data(), local_blob_data.size());
}
if(!local_template_ver)//no any set_block_template call
@ -343,14 +342,15 @@ namespace currency
epee::misc_utils::sleep_no_w(1000);
continue;
}
b.nonce = nonce;
access_nonce_in_block_blob(local_blob_data) = b.nonce;
crypto::hash h = m_scratchpad.get_pow_hash_from_blob(local_blob_data, local_height, local_seed);
//b.nonce = nonce;
//access_nonce_in_block_blob(local_blob_data) = b.nonce;
crypto::hash h = get_block_longhash(local_height, local_blob_data_hash, nonce);
if(check_hash(h, local_diff))
{
b.nonce = nonce;
++m_config.current_extra_message_index;
LOG_PRINT_GREEN("Found block for difficulty: " << local_diff, LOG_LEVEL_0);
LOG_PRINT_GREEN("Found block for difficulty: " << local_diff << ", height: " << local_height << ", PoW hash: " << h << ", local_blob_data_hash: " << local_blob_data_hash << ", nonce: " << std::hex << nonce, LOG_LEVEL_0);
if(!m_phandler->handle_block_found(b))
{
--m_config.current_extra_message_index;

View file

@ -14,26 +14,17 @@
#include "difficulty.h"
#include "math_helper.h"
#include "blockchain_storage.h"
#include "basic_pow_helpers.h"
#define CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET 1
namespace currency
{
inline uint64_t& access_nonce_in_block_blob(blobdata& bd)
{
return *reinterpret_cast<uint64_t*>(&bd[CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET]);
}
inline const uint64_t& access_nonce_in_block_blob(const blobdata& bd)
{
return *reinterpret_cast<const uint64_t*>(&bd[CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET]);
}
struct i_miner_handler
{
virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr) = 0;
virtual bool get_block_template(block& b, crypto::hash& seed, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry()) = 0;
virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry()) = 0;
protected:
~i_miner_handler(){};
};
@ -63,17 +54,17 @@ namespace currency
void do_print_hashrate(bool do_hr);
inline
static bool find_nonce_for_given_block(block& bl, const wide_difficulty_type& diffic, uint64_t height, const crypto::hash& seed, scratchpad_keeper& sk)
static bool find_nonce_for_given_block(block& bl, const wide_difficulty_type& diffic, uint64_t height)
{
bl.nonce = 0;
blobdata bd = get_block_hashing_blob(bl);
uint64_t& nonce_ref = access_nonce_in_block_blob(bd);
nonce_ref = 0;
crypto::hash bd_hash = crypto::cn_fast_hash(bd.data(), bd.size());
//uint64_t& nonce_ref = access_nonce_in_block_blob(bd);
//nonce_ref = 0;
for(; bl.nonce != std::numeric_limits<uint64_t>::max(); bl.nonce++)
{
nonce_ref = bl.nonce;
crypto::hash h = sk.get_pow_hash_from_blob(bd, height, seed);
crypto::hash h = get_block_longhash(height, bd_hash, bl.nonce);
if(check_hash(h, diffic))
{
LOG_PRINT_L0("Found nonce for block: " << get_block_hash(bl) << "[" << height << "]: PoW:" << h << "(diff:" << diffic << "), ts: " << bl.timestamp);
@ -84,7 +75,7 @@ namespace currency
}
private:
bool set_block_template(const block& bl, const wide_difficulty_type& diffic, uint64_t height, const crypto::hash& seed);
bool set_block_template(const block& bl, const wide_difficulty_type& diffic, uint64_t height);
bool worker_thread();
bool request_block_template();
void merge_hr();
@ -106,8 +97,6 @@ namespace currency
std::atomic<uint32_t> m_starter_nonce;
wide_difficulty_type m_diffic;
std::atomic<uint64_t> m_height;
scratchpad_keeper m_scratchpad;
crypto::hash m_seed;
volatile uint32_t m_thread_index;
volatile uint32_t m_threads_total;
std::atomic<int32_t> m_pausers_count;

View file

@ -6,25 +6,3 @@
#pragma once
#define SCRATCHPAD_DEFAULT_FILENAME "scratchpad.bin"
#define WILD_KECCAK_ADDENDUMS_ARRAY_SIZE 10
#pragma pack (push, 1)
struct export_scratchpad_hi
{
crypto::hash prevhash;
uint64_t height;
};
struct export_addendums_array_entry
{
export_scratchpad_hi prev_hi;
uint64_t add_size;
};
struct export_scratchpad_file_header
{
export_scratchpad_hi current_hi;
export_addendums_array_entry add_arr[WILD_KECCAK_ADDENDUMS_ARRAY_SIZE];
uint64_t scratchpad_size;
};
#pragma pack(pop)

View file

@ -1,76 +0,0 @@
// Copyright (c) 2018-2019 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "scratchpad_helper.h"
#include "currency_format_utils.h"
namespace currency
{
scratchpad_keeper::scratchpad_keeper():m_seed(null_hash)
{
}
//------------------------------------------------------------------------------------
bool scratchpad_keeper::generate(const crypto::hash& scr_seed, uint64_t height)
{
bool r = false;
CRITICAL_REGION_BEGIN(m_lock);
r = crypto::generate_scratchpad(scr_seed, m_scratchpad, get_scratchpad_size_for_height(height));
if (r)
m_seed = scr_seed;
CRITICAL_REGION_END();
return r;
}
//------------------------------------------------------------------------------------
crypto::hash scratchpad_keeper::get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& scr_seed)
{
CRITICAL_REGION_LOCAL(m_lock);
crypto::hash res_hash = null_hash;
if (scr_seed != m_seed || get_scratchpad_size_for_height(height) != this->size())
{
bool r = generate(scr_seed, height);
CHECK_AND_ASSERT_THROW_MES(r, "Unable to generate scratchpad");
}
CHECK_AND_ASSERT_THROW_MES(get_scratchpad_size_for_height(height) == this->size(), "Fatal error on hash calculation: scratchpad_size=" << m_scratchpad.size() << " at height=" << height << ", scr_seed=" << scr_seed << ", m_seed=" << m_seed);
CHECK_AND_ASSERT_THROW_MES(scr_seed == m_seed, "Fatal error on hash calculation: scratchpad_seed missmatch scr_seed=" << scr_seed << ", m_seed=" << m_seed);
bool res = get_wild_keccak2(bd, res_hash, m_scratchpad);
CHECK_AND_ASSERT_THROW_MES(res, "Fatal error on hash calculation: scratchpad_size=" << m_scratchpad.size());
return res_hash;
}
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
uint64_t scratchpad_keeper::size()
{
return m_scratchpad.size();
}
//------------------------------------------------------------------------------------
crypto::hash scratchpad_light_pool::get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& seed)
{
CRITICAL_REGION_LOCAL(m_lock);
std::shared_ptr<std::vector<crypto::hash>> pscr_light;
if (!m_scratchpad_pools.get(seed, pscr_light))
{
LOG_PRINT_MAGENTA("Generating scratchpad light for " << seed << "["<< height <<"]", LOG_LEVEL_0);
pscr_light.reset(new std::vector<crypto::hash>());
bool r = crypto::generate_scratchpad_light(seed, *pscr_light, currency::get_scratchpad_size_for_height(height));
CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate_scratchpad_light");
m_scratchpad_pools.set(seed, pscr_light);
LOG_PRINT_MAGENTA("Generated ok", LOG_LEVEL_0);
}
CHECK_AND_ASSERT_THROW_MES(pscr_light->size()*10 == currency::get_scratchpad_size_for_height(height),
"Wrong size of cached scratchpad = " << pscr_light->size() << ", expected " << currency::get_scratchpad_size_for_height(height) << " for height " << height);
crypto::hash res = currency::null_hash;
bool r = crypto::get_wild_keccak_light(bd, res, *pscr_light);
CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_wild_keccak_light");
return res;
}
//------------------------------------------------------------------------------------
}

View file

@ -1,53 +0,0 @@
// Copyright (c) 2014-2018 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "crypto/wild_keccak.h"
#include "currency_protocol/blobdatatype.h"
#include "currency_core/currency_basic.h"
#include "cache_helper.h"
#include "currency_core/currency_format_utils.h"
#include "currency_core/currency_format_utils_blocks.h"
namespace currency
{
template<class t_parent>
class scratchpad_keeper_base
{
public:
crypto::hash get_pow_hash(const block& b, const crypto::hash& scr_seed)
{
blobdata bl = get_block_hashing_blob(b);
return static_cast<t_parent*>(this)->get_pow_hash_from_blob(bl, get_block_height(b), scr_seed);
}
};
class scratchpad_keeper: public scratchpad_keeper_base<scratchpad_keeper>
{
public:
scratchpad_keeper();
bool generate(const crypto::hash& seed, uint64_t height);
crypto::hash get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& seed);
uint64_t size();
private:
scratchpad_keeper(const scratchpad_keeper&) {}
crypto::hash m_seed;
std::vector<crypto::hash> m_scratchpad;
std::recursive_mutex m_lock;
};
class scratchpad_light_pool : public scratchpad_keeper_base<scratchpad_light_pool>
{
public:
scratchpad_light_pool() {}
crypto::hash get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& seed);
private:
//map of seed to
epee::misc_utils::cache_base<false, crypto::hash, std::shared_ptr<std::vector<crypto::hash>>, 4> m_scratchpad_pools;
std::recursive_mutex m_lock;
};
}

View file

@ -20,6 +20,7 @@ using namespace epee;
#include "currency_core/checkpoints_create.h"
#include "currency_core/currency_core.h"
#include "rpc/core_rpc_server.h"
#include "stratum/stratum_server.h"
#include "currency_protocol/currency_protocol_handler.h"
#include "daemon_commands_handler.h"
#include "common/miniupnp_helper.h"
@ -85,6 +86,7 @@ int main(int argc, char* argv[])
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> >::init_options(desc_cmd_sett);
currency::miner::init_options(desc_cmd_sett);
bc_services::bc_offers_service::init_options(desc_cmd_sett);
currency::stratum_server::init_options(desc_cmd_sett);
po::options_description desc_options("Allowed options");
@ -146,8 +148,8 @@ int main(int argc, char* argv[])
}
// stratum server is enabled if any of its options present
bool stratum_enabled = currency::stratum_server::should_start(vm);
LOG_PRINT("Module folder: " << argv[0], LOG_LEVEL_0);
//create objects and link them
@ -162,6 +164,9 @@ int main(int argc, char* argv[])
daemon_cmmands_handler dch(p2psrv, rpc_server);
tools::miniupnp_helper upnp_helper;
//ccore.get_blockchain_storage().get_attachment_services_manager().add_service(&offers_service);
std::shared_ptr<currency::stratum_server> stratum_server_ptr;
if (stratum_enabled)
stratum_server_ptr = std::make_shared<currency::stratum_server>(&ccore);
if (command_line::get_arg(vm, command_line::arg_show_rpc_autodoc))
{
@ -206,6 +211,15 @@ int main(int argc, char* argv[])
res = ccore.init(vm);
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core");
LOG_PRINT_L0("Core initialized OK");
if (stratum_enabled)
{
LOG_PRINT_L0("Initializing stratum server...");
res = stratum_server_ptr->init(vm);
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize stratum server.");
}
auto& bcs = ccore.get_blockchain_storage();
if (!offers_service.is_disabled() && bcs.get_current_blockchain_size() > 1 && bcs.get_top_block_id() != offers_service.get_last_seen_block_id())
@ -231,16 +245,35 @@ int main(int argc, char* argv[])
CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core rpc server.");
LOG_PRINT_L0("Core rpc server started ok");
//start stratum only after core got initialized
if (stratum_enabled)
{
LOG_PRINT_L0("Starting stratum server...");
res = stratum_server_ptr->run(false);
CHECK_AND_ASSERT_MES(res, 1, "Failed to start stratum server.");
LOG_PRINT_L0("Stratum server started ok");
}
tools::signal_handler::install([&dch, &p2psrv] {
tools::signal_handler::install([&dch, &p2psrv, &stratum_server_ptr] {
dch.stop_handling();
p2psrv.send_stop_signal();
if (stratum_server_ptr)
stratum_server_ptr->send_stop_signal();
});
LOG_PRINT_L0("Starting p2p net loop...");
p2psrv.run();
LOG_PRINT_L0("p2p net loop stopped");
//stop components
if (stratum_enabled)
{
LOG_PRINT_L0("Stopping stratum server...");
stratum_server_ptr->send_stop_signal();
stratum_server_ptr->timed_wait_server_stop(1000);
LOG_PRINT_L0("Stratum server stopped");
}
LOG_PRINT_L0("Stopping core rpc server...");
rpc_server.send_stop_signal();
rpc_server.timed_wait_server_stop(5000);
@ -253,6 +286,9 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Deinitializing market...");
(static_cast<currency::i_bc_service&>(offers_service)).deinit();
LOG_PRINT_L0("Deinitializing stratum server ...");
stratum_server_ptr.reset();
LOG_PRINT_L0("Deinitializing rpc server ...");
rpc_server.deinit();
LOG_PRINT_L0("Deinitializing currency_protocol...");

File diff suppressed because it is too large Load diff

View file

@ -783,7 +783,7 @@ namespace currency
//pe.keyimage key image will be set in the wallet
//pe.wallet_index is not included in serialization map, TODO: refactoring here
if (!m_core.get_block_template(b, res.seed, miner_address, stakeholder_address, dt, res.height, req.extra_text, req.pos_block, pe))
if (!m_core.get_block_template(b, miner_address, stakeholder_address, dt, res.height, req.extra_text, req.pos_block, pe))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template";

View file

@ -120,34 +120,6 @@ namespace mining
};
};
struct COMMAND_RPC_GET_FULLSCRATCHPAD
{
RPC_METHOD_NAME("getfullscratchpad");
struct request
{
std::string id;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(id)
END_KV_SERIALIZE_MAP()
};
struct response
{
height_info hi;
std::string scratchpad_hex;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(hi)
KV_SERIALIZE(scratchpad_hex)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
};
struct COMMAND_RPC_SUBMITSHARE
{
RPC_METHOD_NAME("submit");
@ -177,31 +149,5 @@ namespace mining
};
};
struct COMMAND_RPC_STORE_SCRATCHPAD
{
RPC_METHOD_NAME("store_scratchpad");
struct request
{
std::string local_file_path;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(local_file_path)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
};
}

View file

@ -0,0 +1,248 @@
// Copyright (c) 2018-2019 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <string>
#include "epee/include/misc_language.h"
#include "epee/include/storages/parserse_base_utils.h"
#include "epee/include/storages/portable_storage.h"
#include "ethereum/libethash/ethash/ethash.h"
#include "ethereum/libethash/ethash/keccak.h"
#include "currency_core/currency_format_utils.h"
namespace stratum
{
//------------------------------------------------------------------------------------------------------------------------------
// Small helper for extracting separate JSON-RPC requests from input buffer.
// TODO: currently it does not handle curly brackets within strings to make things simplier
struct json_helper
{
void feed(const std::string& s)
{
feed(s.c_str(), s.size());
}
void feed(const char* str, size_t size)
{
m_buffer.append(str, size);
int b_count = 0;
for(size_t i = 0; i < m_buffer.size(); )
{
char c = m_buffer[i];
if (c == '{')
++b_count;
else if (c == '}')
{
if (--b_count == 0)
{
m_objects.push_back(m_buffer.substr(0, i + 1));
m_buffer.erase(0, i + 1);
i = 0;
continue;
}
}
++i;
}
}
bool has_objects() const
{
return !m_objects.empty();
}
bool pop_object(std::string &destination)
{
if (m_objects.empty())
return false;
destination = m_objects.front();
m_objects.pop_front();
return true;
}
std::string m_buffer;
std::list<std::string> m_objects;
};
template<class t_value>
bool ps_get_value_noexcept(epee::serialization::portable_storage& ps, const std::string& value_name, t_value& val, epee::serialization::portable_storage::hsection hparent_section)
{
try
{
return ps.get_value(value_name, val, hparent_section);
}
catch (...)
{
return false;
}
}
std::string trim_0x(const std::string& s)
{
if (s.length() >= 2 && s[0] == '0' && s[1] == 'x')
return s.substr(2);
return s;
}
constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
constexpr char hexmap_backward[] =
{ //0 1 2 3 4 5 6 7 8 9 A B C D E F
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 0
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 1
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 2
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 20, 20, 20, 20, 20, // 3
20, 10, 11, 12, 13, 14, 15, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 4
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 5
20, 10, 11, 12, 13, 14, 15, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 6
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 7
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 8
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 9
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // A
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // B
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // C
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // D
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // E
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 // F
};
template<class pod_t>
std::string pod_to_net_format(const pod_t &h)
{
const char* data = reinterpret_cast<const char*>(&h);
size_t len = sizeof h;
std::string s(len * 2, ' ');
for (size_t i = 0; i < len; ++i) {
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
s[2 * i + 1] = hexmap[(data[i] & 0x0F)];
}
return "0x" + s;
}
template<class pod_t>
std::string pod_to_net_format_reverse(const pod_t &h)
{
const char* data = reinterpret_cast<const char*>(&h);
size_t len = sizeof h;
std::string s(len * 2, ' ');
for (size_t i = 0; i < len; ++i) {
s[2 * i] = hexmap[(data[len - i - 1] & 0xF0) >> 4]; // reverse bytes order in data
s[2 * i + 1] = hexmap[(data[len - i - 1] & 0x0F)];
}
return "0x" + s;
}
template<class pod_t>
bool pod_from_net_format(const std::string& str, pod_t& result, bool assume_following_zeroes = false)
{
std::string s = trim_0x(str);
if (s.size() != sizeof(pod_t) * 2)
{
if (!assume_following_zeroes || s.size() > sizeof(pod_t) * 2)
return false; // invalid string length
s.insert(s.size() - 1, sizeof(pod_t) * 2 - s.size(), '0'); // add zeroes at the end
}
const unsigned char* hex_str = reinterpret_cast<const unsigned char*>(s.c_str());
char* pod_data = reinterpret_cast<char*>(&result);
for (size_t i = 0; i < sizeof(pod_t); ++i)
{
char a = hexmap_backward[hex_str[2 * i + 1]];
char b = hexmap_backward[hex_str[2 * i + 0]];
if (a > 15 || b > 15)
return false; // invalid character
pod_data[i] = a | (b << 4);
}
return true;
}
template<class pod_t>
bool pod_from_net_format_reverse(const std::string& str, pod_t& result, bool assume_leading_zeroes = false)
{
std::string s = trim_0x(str);
if (s.size() != sizeof(pod_t) * 2)
{
if (!assume_leading_zeroes || s.size() > sizeof(pod_t) * 2)
return false; // invalid string length
s.insert(0, sizeof(pod_t) * 2 - s.size(), '0'); // add zeroes at the beginning
}
const unsigned char* hex_str = reinterpret_cast<const unsigned char*>(s.c_str());
char* pod_data = reinterpret_cast<char*>(&result);
for (size_t i = 0; i < sizeof(pod_t); ++i)
{
char a = hexmap_backward[hex_str[2 * i + 1]];
char b = hexmap_backward[hex_str[2 * i + 0]];
if (a > 15 || b > 15)
return false; // invalid character
pod_data[sizeof(pod_t) - i - 1] = a | (b << 4); // reverse byte order
}
return true;
}
uint64_t epoch_by_seedhash(const ethash_hash256& seed_hash)
{
ethash_hash256 epoch_seed = {};
for (uint32_t i = 0; i < 2016; ++i) // 2016 epoches will be enough until 2038
{
if (memcmp(&seed_hash, &epoch_seed, sizeof seed_hash) == 0)
return i;
epoch_seed = ethash_keccak256_32(epoch_seed.bytes);
}
return UINT64_MAX;
}
//------------------------------------------------------------------------------------------------------------------------------
// http://www.jsonrpc.org/specification
// 'id' -- an identifier established by the Client that MUST contain a String, Number, or NULL value if included.
// The Server MUST reply with the same value in the Response object if included.
struct jsonrpc_id_null_t {};
typedef boost::variant<int64_t, std::string, jsonrpc_id_null_t> jsonrpc_id_t;
std::string jsonrpc_id_to_value_str(const jsonrpc_id_t& id)
{
if (id.type() == typeid(int64_t))
return boost::to_string(boost::get<int64_t>(id));
if (id.type() == typeid(std::string))
return '"' + boost::to_string(boost::get<std::string>(id)) + '"';
return "null";
}
namespace details
{
struct jsonrpc_id_visitor : public boost::static_visitor<>
{
explicit jsonrpc_id_visitor(jsonrpc_id_t &value) : m_value(value) {}
void operator()(const uint64_t id) { m_value = id; }
void operator()(const int64_t id) { m_value = id; }
void operator()(const std::string& id) { m_value = id; }
template<typename T>
void operator()(const T&) { /* nothing */ }
jsonrpc_id_t &m_value;
};
}
bool read_jsonrpc_id(epee::serialization::portable_storage& ps, jsonrpc_id_t& result)
{
epee::serialization::storage_entry se;
if (!ps.get_value("id", se, nullptr))
return false;
details::jsonrpc_id_visitor vis(result);
boost::apply_visitor(vis, se);
return true;
}
} // namespace stratum
inline std::ostream &operator <<(std::ostream &o, const ethash_hash256 &v) { return print256(o, v); }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,42 @@
// Copyright (c) 2018-2019 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#undef LOG_DEFAULT_CHANNEL
#define LOG_DEFAULT_CHANNEL "stratum"
namespace currency
{
class core;
struct stratum_server_impl;
class stratum_server
{
public:
static void init_options(boost::program_options::options_description& desc);
static bool should_start(const boost::program_options::variables_map& vm);
stratum_server(core* c);
~stratum_server();
bool init(const boost::program_options::variables_map& vm);
bool run(bool wait = true);
bool deinit();
bool timed_wait_server_stop(uint64_t ms);
bool send_stop_signal();
private:
size_t m_threads_count;
stratum_server_impl* m_impl;
core* m_p_core;
};
}
#undef LOG_DEFAULT_CHANNEL
#define LOG_DEFAULT_CHANNEL NULL

View file

@ -2,6 +2,6 @@
#define BUILD_COMMIT_ID "@VERSION@"
#define PROJECT_VERSION "1.0"
#define PROJECT_VERSION_BUILD_NO 9
#define PROJECT_VERSION_BUILD_NO 12
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"

View file

@ -29,13 +29,13 @@ add_executable(net_load_tests_srv net_load_tests/srv.cpp)
add_dependencies(coretests version)
target_link_libraries(coretests currency_core common crypto wallet rpc zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(difficulty-tests currency_core ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(functional_tests wallet currency_core crypto common rpc zlibstatic upnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(hash-tests crypto)
target_link_libraries(hash-target-tests crypto currency_core ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(performance_tests currency_core common crypto zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(unit_tests wallet currency_core crypto common gtest_main zlibstatic ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(coretests currency_core common crypto wallet rpc zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(difficulty-tests currency_core ${CMAKE_THREAD_LIBS_INIT} ethash ${Boost_LIBRARIES})
target_link_libraries(functional_tests wallet currency_core crypto common rpc zlibstatic ethash upnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(hash-tests crypto ethash)
target_link_libraries(hash-target-tests crypto currency_core ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(performance_tests currency_core common crypto zlibstatic ethash${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(unit_tests wallet currency_core crypto common gtest_main zlibstatic ethash${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(net_load_tests_clt currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(net_load_tests_srv currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})

View file

@ -381,8 +381,7 @@ bool gen_alias_tests::check_too_many_aliases_registration(currency::core& c, siz
wide_difficulty_type diff;
uint64_t height;
blobdata extra = AUTO_VAL_INIT(extra);
crypto::hash seed = currency::null_hash;
bool r = c.get_block_template(b, seed, ai.m_address, ai.m_address, diff, height, extra);
bool r = c.get_block_template(b, ai.m_address, ai.m_address, diff, height, extra);
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
CHECK_AND_ASSERT_MES(b.tx_hashes.empty(), false, "block template has some txs, expected--none");
@ -413,7 +412,7 @@ bool gen_alias_tests::check_too_many_aliases_registration(currency::core& c, siz
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == total_alias_to_gen, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count() << ", expected: " << total_alias_to_gen);
// complete block template and try to process it
r = miner::find_nonce_for_given_block(b, diff, height, seed, m_scratchpad_keeper);
r = miner::find_nonce_for_given_block(b, diff, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
@ -1289,12 +1288,11 @@ bool gen_alias_switch_and_check_block_template::add_block_from_template(currency
currency::block b;
wide_difficulty_type diff;
uint64_t height;
crypto::hash seed = currency::null_hash;
blobdata extra = AUTO_VAL_INIT(extra);
bool r = c.get_block_template(b, seed, acc.get_public_address(), acc.get_public_address(), diff, height, extra);
bool r = c.get_block_template(b, acc.get_public_address(), acc.get_public_address(), diff, height, extra);
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
r = miner::find_nonce_for_given_block(b, diff, height, seed, m_scratchpad_keeper);
r = miner::find_nonce_for_given_block(b, diff, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
@ -1409,12 +1407,11 @@ bool gen_alias_too_many_regs_in_block_template::add_block_from_template(currency
currency::block b;
wide_difficulty_type diff;
uint64_t height;
crypto::hash seed = currency::null_hash;
blobdata extra = AUTO_VAL_INIT(extra);
bool r = c.get_block_template(b, seed, acc.get_public_address(), acc.get_public_address(), diff, height, extra);
bool r = c.get_block_template(b, acc.get_public_address(), acc.get_public_address(), diff, height, extra);
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
r = miner::find_nonce_for_given_block(b, diff, height, seed, m_scratchpad_keeper);
r = miner::find_nonce_for_given_block(b, diff, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);

View file

@ -87,8 +87,7 @@ bool block_template_against_txs_size::c1(currency::core& c, size_t ev_index, con
wide_difficulty_type diff = 0;
uint64_t height = 0;
g_block_txs_total_size = txs_total_size; // passing an argument to custom_fill_block_template_func via global variable (not perfect but works well)
crypto::hash seed = currency::null_hash;
r = bcs.create_block_template(b, seed, miner_addr, miner_addr, diff, height, ex_nonce, is_pos != 0, pe, &custom_fill_block_template_func);
r = bcs.create_block_template(b, miner_addr, miner_addr, diff, height, ex_nonce, is_pos != 0, pe, &custom_fill_block_template_func);
CHECK_AND_ASSERT_MES(r, false, "create_block_template failed, txs_total_size = " << txs_total_size);
CHECK_AND_ASSERT_MES(height == top_block_height + 1, false, "Incorrect height: " << height << ", expected: " << top_block_height + 1 << ", txs_total_size = " << txs_total_size);

View file

@ -693,15 +693,8 @@ bool test_generator::find_nounce(currency::block& blk, std::vector<const block_i
{
if(height != blocks.size())
throw std::runtime_error("wrong height in find_nounce");
crypto::hash seed = currency::null_hash;
currency::get_seed_for_scratchpad_cb(height, seed, [&](uint64_t index) -> crypto::hash
{
return currency::get_block_hash(blocks[index]->b);
});
return miner::find_nonce_for_given_block(blk, dif, height, seed, m_scratchpad);
return miner::find_nonce_for_given_block(blk, dif, height);
}
bool test_generator::construct_genesis_block(currency::block& blk, const currency::account_base& miner_acc, uint64_t timestamp)

View file

@ -14,7 +14,6 @@
#include "wallet/wallet2.h"
#include "test_core_time.h"
#include "chaingen_helpers.h"
#include "currency_core/scratchpad_helper.h"
#define TESTS_DEFAULT_FEE ((uint64_t)TX_DEFAULT_FEE)
#define MK_TEST_COINS(amount) (static_cast<uint64_t>(amount) * TESTS_DEFAULT_FEE)
@ -306,7 +305,6 @@ protected:
uint64_t height;
crypto::hash hash;
};
currency::scratchpad_keeper m_scratchpad_keeper;
size_t m_invalid_block_index;
size_t m_invalid_tx_index;
size_t m_orphan_block_index;
@ -507,7 +505,6 @@ private:
std::unordered_map<crypto::hash, block_info> m_blocks_info;
static test_gentime_settings m_test_gentime_settings;
static test_gentime_settings m_test_gentime_settings_default;
mutable currency::scratchpad_keeper m_scratchpad;
};
extern const crypto::signature invalid_signature; // invalid non-null signature for test purpose
@ -872,7 +869,6 @@ namespace crypto {
return o <<
"account: " << std::endl <<
" addr: " << get_account_address_as_str(acc.get_public_address()) << std::endl <<
" seed: " << epee::string_tools::buff_to_hex_nodelimer(acc.get_restore_data()) << std::endl <<
" spend secret key: " << acc.get_keys().m_spend_secret_key << std::endl <<
" spend public key: " << acc.get_public_address().m_spend_public_key << std::endl <<
" view secret key: " << acc.get_keys().m_view_secret_key << std::endl <<

View file

@ -11,14 +11,13 @@
// chaingen-independent helpers that may be used outside of core_tests (for ex. in functional_tests)
inline bool mine_next_pow_block_in_playtime(currency::scratchpad_keeper& scr_keeper, const currency::account_public_address& miner_addr, currency::core& c, currency::block* output = nullptr)
inline bool mine_next_pow_block_in_playtime(const currency::account_public_address& miner_addr, currency::core& c, currency::block* output = nullptr)
{
currency::block b = AUTO_VAL_INIT(b);
currency::wide_difficulty_type diff;
uint64_t height;
currency::blobdata extra = AUTO_VAL_INIT(extra);
crypto::hash seed = currency::null_hash;
bool r = c.get_block_template(b, seed, miner_addr, miner_addr, diff, height, extra);
bool r = c.get_block_template(b, miner_addr, miner_addr, diff, height, extra);
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
// adjust block's timestamp to keep difficulty low
@ -28,7 +27,7 @@ inline bool mine_next_pow_block_in_playtime(currency::scratchpad_keeper& scr_kee
// keep global time up with blocks' timestamps
test_core_time::adjust(b.timestamp);
r = currency::miner::find_nonce_for_given_block(b, diff, height, seed, scr_keeper);
r = currency::miner::find_nonce_for_given_block(b, diff, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
@ -41,7 +40,7 @@ inline bool mine_next_pow_block_in_playtime(currency::scratchpad_keeper& scr_kee
return true;
}
inline bool mine_next_pow_block_in_playtime_with_given_txs(currency::scratchpad_keeper& scr_keeper, const currency::account_public_address& miner_addr, currency::core& c, const std::vector<currency::transaction>& txs, const crypto::hash& prev_id, uint64_t height, currency::block* output = nullptr)
inline bool mine_next_pow_block_in_playtime_with_given_txs(const currency::account_public_address& miner_addr, currency::core& c, const std::vector<currency::transaction>& txs, const crypto::hash& prev_id, uint64_t height, currency::block* output = nullptr)
{
struct loc_helper
{
@ -73,12 +72,11 @@ inline bool mine_next_pow_block_in_playtime_with_given_txs(currency::scratchpad_
uint64_t height_from_template = 0;
currency::blobdata extra = AUTO_VAL_INIT(extra);
currency::pos_entry pe = AUTO_VAL_INIT(pe);
crypto::hash seed;
bool r = false;
{
CRITICAL_REGION_LOCAL(s_locker);
loc_helper::txs_accessor() = &txs;
r = c.get_blockchain_storage().create_block_template(b, seed, miner_addr, miner_addr, diff, height_from_template, extra, false, pe, loc_helper::fill_block_template_func);
r = c.get_blockchain_storage().create_block_template(b, miner_addr, miner_addr, diff, height_from_template, extra, false, pe, loc_helper::fill_block_template_func);
}
CHECK_AND_ASSERT_MES(r, false, "get_block_template failed");
@ -106,7 +104,7 @@ inline bool mine_next_pow_block_in_playtime_with_given_txs(currency::scratchpad_
height = height_from_template;
}
r = currency::miner::find_nonce_for_given_block(b, diff, height, seed, scr_keeper);
r = currency::miner::find_nonce_for_given_block(b, diff, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
@ -119,15 +117,15 @@ inline bool mine_next_pow_block_in_playtime_with_given_txs(currency::scratchpad_
return true;
}
inline bool mine_next_pow_block_in_playtime_with_given_txs(currency::scratchpad_keeper& scr_keeper, const currency::account_public_address& miner_addr, currency::core& c, const std::vector<currency::transaction>& txs, currency::block* output = nullptr)
inline bool mine_next_pow_block_in_playtime_with_given_txs(const currency::account_public_address& miner_addr, currency::core& c, const std::vector<currency::transaction>& txs, currency::block* output = nullptr)
{
return mine_next_pow_block_in_playtime_with_given_txs(scr_keeper, miner_addr, c, txs, currency::null_hash, SIZE_MAX, output);
return mine_next_pow_block_in_playtime_with_given_txs(miner_addr, c, txs, currency::null_hash, SIZE_MAX, output);
}
inline bool mine_next_pow_blocks_in_playtime(currency::scratchpad_keeper& scr_keeper, const currency::account_public_address& miner_addr, currency::core& c, size_t blocks_count)
inline bool mine_next_pow_blocks_in_playtime(const currency::account_public_address& miner_addr, currency::core& c, size_t blocks_count)
{
for (size_t i = 0; i != blocks_count; i++)
if (!mine_next_pow_block_in_playtime(scr_keeper, miner_addr, c))
if (!mine_next_pow_block_in_playtime(miner_addr, c))
return false;
return true;

View file

@ -628,7 +628,7 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t
crc.pos_minimum_heigh = 1;
c.get_blockchain_storage().set_core_runtime_config(crc);
m_checkpoints.add_checkpoint(12, "4ba98ca9d92e99e28a30bd5395a305213be2fc18372bbf94ef216ba017640e56");
m_checkpoints.add_checkpoint(12, "b28d40aa02b30d1f0e807147151b5073dc8dc930414cbbdbde11a9502f9c6936");
c.set_checkpoints(currency::checkpoints(m_checkpoints));
return true;
@ -683,19 +683,19 @@ bool gen_no_attchments_in_coinbase::c1(currency::core& c, size_t ev_index, const
test_core_time::adjust(blk_0r.timestamp + DIFFICULTY_TOTAL_TARGET);
block blk_a;
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_miner_acc.get_public_address(), c, &blk_a);
r = mine_next_pow_block_in_playtime(m_miner_acc.get_public_address(), c, &blk_a);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
test_core_time::adjust(blk_a.timestamp + DIFFICULTY_TOTAL_TARGET);
block blk_b;
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_miner_acc.get_public_address(), c, &blk_b);
r = mine_next_pow_block_in_playtime(m_miner_acc.get_public_address(), c, &blk_b);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
test_core_time::adjust(blk_b.timestamp + DIFFICULTY_TOTAL_TARGET);
block blk_c;
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_miner_acc.get_public_address(), c, &blk_c);
r = mine_next_pow_block_in_playtime(m_miner_acc.get_public_address(), c, &blk_c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
// make sure the checkpoint zone is successfully left behind

View file

@ -66,10 +66,9 @@ bool emission_test::c1(currency::core& c, size_t ev_index, const std::vector<tes
currency::block b = AUTO_VAL_INIT(b);
blobdata extra = AUTO_VAL_INIT(extra);
uint64_t height_from_template = 0;
crypto::hash seed = currency::null_hash;
r = c.get_block_template(b, seed, m_miner_acc.get_public_address(), m_miner_acc.get_public_address(), difficulty, height_from_template, extra);
r = c.get_block_template(b, m_miner_acc.get_public_address(), m_miner_acc.get_public_address(), difficulty, height_from_template, extra);
CHECK_AND_ASSERT_MES(r || height_from_template != height, false, "get_block_template failed");
r = miner::find_nonce_for_given_block(b, difficulty, height, seed, m_scratchpad_keeper);
r = miner::find_nonce_for_given_block(b, difficulty, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
c.handle_incoming_block(t_serializable_object_to_blob(b), bvc);
CHECK_AND_NO_ASSERT_MES(!bvc.m_verification_failed && !bvc.m_marked_as_orphaned && !bvc.m_already_exists, false, "block verification context check failed");
@ -241,7 +240,7 @@ bool pos_emission_test::c1(currency::core& c, size_t ev_index, const std::vector
if (ts < ideal_next_pow_block_ts)
ts = ideal_next_pow_block_ts; // "wait" until ideal_next_pow_block_ts if it was not already happened (fast forward but don't wayback the time)
test_core_time::adjust(ts);
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "invalid number of txs in tx pool: " << c.get_pool_transactions_count());
@ -355,7 +354,7 @@ bool pos_emission_test::c2(currency::core& c, size_t ev_index, const std::vector
if (ts < ideal_next_pow_block_ts)
ts = ideal_next_pow_block_ts; // "wait" until ideal_next_pow_block_ts if it was not already happened (fast forward but don't wayback the time)
test_core_time::adjust(ts);
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "invalid number of txs in tx pool: " << c.get_pool_transactions_count());
@ -501,7 +500,7 @@ bool pos_emission_test::c3(currency::core& c, size_t ev_index, const std::vector
ts = ideal_next_pow_block_ts; // "wait" until ideal_next_pow_block_ts if it was not already happened (fast forward but don't wayback the time)
test_core_time::adjust(ts);
size_t tx_count_before = c.get_pool_transactions_count();
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(tx_count_before == 0 || c.get_pool_transactions_count() < tx_count_before, false, "invalid number of txs in tx pool: " << c.get_pool_transactions_count() << ", was: " << tx_count_before);
//uint64_t pow_blocks_interval = ts - last_pow_block_ts;

View file

@ -85,7 +85,7 @@ bool escrow_altchain_meta_impl::generate(std::vector<test_event_entry>& events)
bool escrow_altchain_meta_impl::mine_next_block_with_tx(currency::core& c, const currency::transaction& tx)
{
block b = AUTO_VAL_INIT(b);
bool r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ tx }), m_last_block_hash, m_last_block_height + 1, &b);
bool r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ tx }), m_last_block_hash, m_last_block_height + 1, &b);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
m_last_block_hash = get_block_hash(b);
m_last_block_height = get_block_height(b);
@ -95,7 +95,7 @@ bool escrow_altchain_meta_impl::mine_next_block_with_tx(currency::core& c, const
bool escrow_altchain_meta_impl::mine_next_block_with_no_tx(currency::core& c)
{
block b = AUTO_VAL_INIT(b);
bool r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>(), m_last_block_hash, m_last_block_height + 1, &b);
bool r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>(), m_last_block_hash, m_last_block_height + 1, &b);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
m_last_block_hash = get_block_hash(b);
m_last_block_height = get_block_height(b);

View file

@ -80,7 +80,7 @@ bool escrow_wallet_test::prepare_proposal_accepted_test(currency::core& c, const
miner_wlt->transfer(AMOUNT_TO_TRANSFER_ESCROW + TX_DEFAULT_FEE * 2, accunt_seller.get_public_address());
LOG_PRINT_MAGENTA("Transaction sent to seller_account: " << AMOUNT_TO_TRANSFER_ESCROW + TX_DEFAULT_FEE * 2, LOG_LEVEL_0);
bool r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
bool r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
@ -121,7 +121,7 @@ bool escrow_wallet_test::prepare_proposal_accepted_test(currency::core& c, const
LOG_PRINT_MAGENTA("Escrow proposal sent bseller_account: escrow_proposal_tx id: " << currency::get_transaction_hash(escrow_proposal_tx) << ", multisig_id: " << multisig_id, LOG_LEVEL_0);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, 2);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 2);
wallet_buyer->refresh();
wallet_seller->refresh();
@ -147,7 +147,7 @@ bool escrow_wallet_test::prepare_proposal_accepted_test(currency::core& c, const
//----------------------
wallet_seller->accept_proposal(multisig_id, TX_DEFAULT_FEE);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
wallet_buyer->refresh();
wallet_seller->refresh();
@ -197,7 +197,7 @@ bool escrow_wallet_test::exec_test_with_specific_release_type(currency::core& c,
tools::wallet2::escrow_contracts_container contracts_buyer, contracts_seller;
wallet_buyer->finish_contract(multisig_id, release_instruction);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, 2);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 2);
wallet_buyer->refresh();
wallet_seller->refresh();
wallet_buyer->get_contracts(contracts_buyer);
@ -230,11 +230,11 @@ bool escrow_wallet_test::exec_test_with_cancel_release_type(currency::core& c, c
wallet_miner = init_playtime_test_wallet(events, c, m_mining_accunt);
wallet_miner->refresh();
wallet_miner->transfer(TX_DEFAULT_FEE, wallet_buyer->get_account().get_public_address());
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, 10);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 10);
wallet_buyer->refresh();
tools::wallet2::escrow_contracts_container contracts_buyer, contracts_seller;
wallet_buyer->request_cancel_contract(multisig_id, TX_DEFAULT_FEE, 60 * 60);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, 2);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 2);
wallet_buyer->refresh();
wallet_seller->refresh();
wallet_buyer->get_contracts(contracts_buyer);
@ -252,7 +252,7 @@ bool escrow_wallet_test::exec_test_with_cancel_release_type(currency::core& c, c
//cancel contract
wallet_seller->accept_cancel_contract(multisig_id);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, 2);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, 2);
wallet_buyer->refresh();
wallet_seller->refresh();
wallet_buyer->get_contracts(contracts_buyer);
@ -396,7 +396,7 @@ bool escrow_w_and_fake_outputs::c1(currency::core& c, size_t ev_index, const std
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -406,7 +406,7 @@ bool escrow_w_and_fake_outputs::c1(currency::core& c, size_t ev_index, const std
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -416,7 +416,7 @@ bool escrow_w_and_fake_outputs::c1(currency::core& c, size_t ev_index, const std
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, WALLET_DEFAULT_TX_SPENDABLE_AGE);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, WALLET_DEFAULT_TX_SPENDABLE_AGE);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -441,7 +441,7 @@ bool escrow_w_and_fake_outputs::c1(currency::core& c, size_t ev_index, const std
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -651,7 +651,7 @@ bool escrow_incorrect_proposal::check_normal_proposal(currency::core& c, size_t
alice_wlt->accept_proposal(contract_id, TX_DEFAULT_FEE);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -661,7 +661,7 @@ bool escrow_incorrect_proposal::check_normal_proposal(currency::core& c, size_t
miner_wlt->finish_contract(contract_id, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -788,7 +788,7 @@ bool escrow_proposal_expiration::c1(currency::core& c, size_t ev_index, const st
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
// mine a block with proposal transport tx
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -797,7 +797,7 @@ bool escrow_proposal_expiration::c1(currency::core& c, size_t ev_index, const st
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_contract_state("Bob", bob_wlt, tools::wallet_rpc::escrow_contract_details::proposal_sent, ms_id, 1), false, "");
// mine few block to shift the timestamp median far enough
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
// check Alice's balance
@ -866,7 +866,7 @@ bool escrow_proposal_expiration::c2(currency::core& c, size_t ev_index, const st
// mine a few blocks with no txs
for (size_t i = 0; i < TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW + 1; ++i)
{
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
}
@ -896,7 +896,7 @@ bool escrow_proposal_expiration::c2(currency::core& c, size_t ev_index, const st
CHECK_AND_ASSERT_MES(r, false, "Bob tried to accept an expired proposal, but wallet exception was not caught");
// mine a block with proposal transport tx
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
// check it has left tx pool
@ -1022,7 +1022,7 @@ bool escrow_proposal_and_accept_expiration::c1(currency::core& c, size_t ev_inde
// mine a few blocks with no txs
for (size_t i = 0; i < TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW + 1; ++i)
{
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
}
@ -1057,7 +1057,7 @@ bool escrow_proposal_and_accept_expiration::c1(currency::core& c, size_t ev_inde
CHECK_AND_ASSERT_MES(r, false, "Bob tried to accept an expired proposal, but wallet exception was not caught");
LOG_PRINT_CYAN("%%%%% mine a block with proposal transport tx", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
// check it has left tx pool
@ -1336,7 +1336,7 @@ bool escrow_incorrect_proposal_acceptance::check_normal_acceptance(currency::cor
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -1673,7 +1673,7 @@ bool escrow_custom_test::do_custom_test(currency::core& c, size_t ev_index, cons
CHECK_AND_ASSERT_MES(check_wallet_balance_blocked_for_escrow(*alice_wlt.get(), "Alice", cd.cpd.amount_a_pledge + cd.cpd.amount_to_pay), false, "");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -1712,7 +1712,7 @@ bool escrow_custom_test::do_custom_test(currency::core& c, size_t ev_index, cons
false, "");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -1751,7 +1751,7 @@ bool escrow_custom_test::do_custom_test(currency::core& c, size_t ev_index, cons
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_expected_balance, 0, INVALID_BALANCE_VAL, 0, 0), false, ""); // should not change
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -1795,7 +1795,7 @@ bool escrow_custom_test::do_custom_test(currency::core& c, size_t ev_index, cons
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_expected_balance, 0, INVALID_BALANCE_VAL, cd.is_release_normal() ? cd.cpd.amount_b_pledge + cd.cpd.amount_to_pay : 0, cd.is_release_normal() ? 0 : ms_amount - cd.b_release_fee), false, "");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -1842,7 +1842,7 @@ bool escrow_custom_test::do_custom_test(currency::core& c, size_t ev_index, cons
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_expected_balance, 0, INVALID_BALANCE_VAL, bob_expected_aw_in_balance, 0), false, "");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -2096,7 +2096,7 @@ bool escrow_incorrect_cancel_proposal::check_normal_cancel_proposal(currency::co
bob_wlt->accept_cancel_contract(ms_id);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -2273,7 +2273,7 @@ bool escrow_proposal_not_enough_money::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "Alice", MK_TEST_COINS(30), 0, MK_TEST_COINS(30), 0, 0), false, "");
// mine few blocks to make sure there's no problem
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, 5);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, 5);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
// and check balance again
@ -2359,7 +2359,7 @@ bool escrow_cancellation_and_tx_order::c1(currency::core& c, size_t ev_index, co
// mine a block, containing escrow proposal tx
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2377,7 +2377,7 @@ bool escrow_cancellation_and_tx_order::c1(currency::core& c, size_t ev_index, co
// mine a block containing contract acceptance
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2437,8 +2437,8 @@ bool escrow_cancellation_and_tx_order::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(contracts.begin()->second.state == tools::wallet_rpc::escrow_contract_details::contract_released_cancelled, false, "Bob has invalid contract state: " << tools::wallet_rpc::get_escrow_contract_state_name(contracts.begin()->second.state));
// mine a block containing only cancel_request_acceptance_tx (this should trigger contracts' states swtiching into contract_released_cancelled)
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, cancel_request_acceptance_tx)", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({cancel_request_acceptance_tx}));
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime_with_given_txs(cancel_request_acceptance_tx)", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({cancel_request_acceptance_tx}));
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2458,8 +2458,8 @@ bool escrow_cancellation_and_tx_order::c1(currency::core& c, size_t ev_index, co
// mine a block containing only cancel_request_tx (this SHOULD NOT trigger contracts' states swtiching into contract_cancel_proposal_sent or anything)
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, cancel_request_tx)", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({cancel_request_tx}));
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime_with_given_txs(cancel_request_tx)", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({cancel_request_tx}));
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2563,7 +2563,7 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
// mine a block, containing escrow proposal tx
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2584,7 +2584,7 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
// mine a block containing contract acceptance
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2621,7 +2621,7 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
// mine a few blocks with no txs to shift expiration median
for(size_t i = 0; i < 7; ++i)
{
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
}
// cancellation request is still in the pool
@ -2649,8 +2649,8 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_1_contract_state("Bob", bob_wlt, tools::wallet_rpc::escrow_contract_details::contract_accepted, 7), false, "");
// mine a block containing cancel_request_tx (already expired) -- should be okay
LOG_PRINT_GREEN("\n\n\n" "mine_next_pow_block_in_playtime(m_scratchpad_keeper, ) -- including expires contract cancellation request" "\n\n", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
LOG_PRINT_GREEN("\n\n\n" "mine_next_pow_block_in_playtime() -- including expires contract cancellation request" "\n\n", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2684,8 +2684,8 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_1_contract_state("Bob", bob_wlt, tools::wallet_rpc::escrow_contract_details::contract_cancel_proposal_sent, 0), false, "");
// mine a block containing cancel_request_tx
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime(m_scratchpad_keeper, )", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime()", LOG_LEVEL_0);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2694,8 +2694,8 @@ bool escrow_cancellation_proposal_expiration::c1(currency::core& c, size_t ev_in
CHECK_AND_ASSERT_MES(refresh_wallet_and_check_1_contract_state("Bob", bob_wlt, tools::wallet_rpc::escrow_contract_details::contract_cancel_proposal_sent, 1), false, "");
// mine one more block (it's necessary for triggering expiration checks in wallets and shifting an expiration ts median)
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime(m_scratchpad_keeper, )", LOG_LEVEL_0);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, 7);
LOG_PRINT_GREEN("\n" "mine_next_pow_block_in_playtime()", LOG_LEVEL_0);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, 7);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2810,7 +2810,7 @@ bool escrow_cancellation_acceptance_expiration::c1(currency::core& c, size_t ev_
// mine a block, containing escrow proposal tx
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2825,7 +2825,7 @@ bool escrow_cancellation_acceptance_expiration::c1(currency::core& c, size_t ev_
// mine a block containing contract acceptance
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2838,7 +2838,7 @@ bool escrow_cancellation_acceptance_expiration::c1(currency::core& c, size_t ev_
// confirm cancellation request in blockchain
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// contract state in wallets should be cancel_proposal_sent for both parties
@ -2862,7 +2862,7 @@ bool escrow_cancellation_acceptance_expiration::c1(currency::core& c, size_t ev_
// mine a few blocks with no txs to shift expiration median, cancellation acceptance is still in the pool
for(size_t i = 0; i < 7; ++i)
{
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
}
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -2886,7 +2886,7 @@ bool escrow_cancellation_acceptance_expiration::c1(currency::core& c, size_t ev_
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// mine a block with cancel_accept_tx (already expired). It should be rejected
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ cancel_accept_tx }));
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ cancel_accept_tx }));
CHECK_AND_ASSERT_MES(!r, false, "mine_next_pow_block_in_playtime_with_given_txs should have been failed as block contains expired tx");
// no changes with contract state expected
@ -2968,6 +2968,6 @@ bool escrow_proposal_acceptance_in_alt_chain::generate(std::vector<test_event_en
bool escrow_proposal_acceptance_in_alt_chain::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
//mine_next_pow_block_in_playtime(m_scratchpad_keeper, )
//mine_next_pow_block_in_playtime()
return true;
}

View file

@ -347,7 +347,7 @@ bool block_template_vs_invalid_txs_from_pool::check_block_template(currency::cor
bool r = false;
currency::block b = AUTO_VAL_INIT(b);
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, addr, c, &b);
r = mine_next_pow_block_in_playtime(addr, c, &b);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
return true;

View file

@ -289,7 +289,7 @@ bool mix_in_spent_outs::c1(currency::core& c, size_t ev_index, const std::vector
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect number of txs in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are txs in the pool");

View file

@ -160,7 +160,7 @@ bool multisig_wallet_test::c1(currency::core& c, size_t ev_index, const std::vec
transaction result_tx = AUTO_VAL_INIT(result_tx);
miner_wlt->transfer(dst, 0, 0, TX_DEFAULT_FEE, extra, attachments, tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), result_tx);
bool r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
bool r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
//findout multisig out intex
@ -175,7 +175,7 @@ bool multisig_wallet_test::c1(currency::core& c, size_t ev_index, const std::vec
crypto::hash multisig_id = get_multisig_out_id(result_tx, i);
CHECK_AND_ASSERT_MES(multisig_id != null_hash, false, "Multisig failed: failed to get get_multisig_out_id");
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
std::shared_ptr<tools::wallet2> wallet_a = init_playtime_test_wallet(events, c, m_accunt_a);
@ -208,7 +208,7 @@ bool multisig_wallet_test::c1(currency::core& c, size_t ev_index, const std::vec
tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD),
result_tx);
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
r = mine_next_pow_blocks_in_playtime(m_mining_accunt.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
wallet_a->refresh();
@ -300,7 +300,7 @@ bool multisig_wallet_test_many_dst::c1(currency::core& c, size_t ev_index, const
CHECK_AND_ASSERT_MES(it != result_tx.vout.end(), false, "Can't find output txout_multisig");
size_t multisig_index = it - result_tx.vout.begin();
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
std::shared_ptr<tools::wallet2> w = init_playtime_test_wallet(events, c, addresses[0]);
@ -317,7 +317,7 @@ bool multisig_wallet_test_many_dst::c1(currency::core& c, size_t ev_index, const
transfer_multisig(*w.get(), owner_keys, get_multisig_out_id(result_tx, multisig_index), std::vector<tx_destination_entry>({ de2 }), 0, TESTS_DEFAULT_FEE, std::vector<currency::extra_v>(), std::vector<currency::attachment_v>(), tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), tx);
TMP_LOG_RESTORE;
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, m_accounts[ALICE_ACC_IDX]);
@ -428,7 +428,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
// Mine a block and make sure tx was put into it
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -487,7 +487,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
0, TX_DEFAULT_FEE, std::vector<currency::extra_v>(), std::vector<currency::attachment_v>(), tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), tx);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
// Once Bob refreshes his wallet he should see that Alice has already spent they shared multisig
@ -549,7 +549,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
0, TX_DEFAULT_FEE, std::vector<currency::extra_v>(), std::vector<currency::attachment_v>(), tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), tx);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are txs in the pool.");
@ -584,7 +584,7 @@ bool multisig_wallet_heterogenous_dst::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(caught, false, "Dan was able to make multisig tx for alreadly spent output");
// Miner mines the next PoW block, confirming Alice's transaction.
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are txs in the pool.");
@ -689,7 +689,7 @@ bool multisig_wallet_same_dst_addr::c1(currency::core& c, size_t ev_index, const
// mine the next PoW and make sure everythig is allright
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect number of tx in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are transactions in the pool");
@ -707,7 +707,7 @@ bool multisig_wallet_same_dst_addr::c1(currency::core& c, size_t ev_index, const
0, TX_DEFAULT_FEE, empty_extra, empty_attachment, tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), tx);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect number of tx in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are transactions in the pool");
@ -778,7 +778,7 @@ bool multisig_wallet_ms_to_ms::c1(currency::core& c, size_t ev_index, const std:
// mine the next PoW and make sure everythig is allright
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect number of tx in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are transactions in the pool");
@ -802,7 +802,7 @@ bool multisig_wallet_ms_to_ms::c1(currency::core& c, size_t ev_index, const std:
// check the pool and mine a block
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect number of tx in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are transactions in the pool");
@ -818,7 +818,7 @@ bool multisig_wallet_ms_to_ms::c1(currency::core& c, size_t ev_index, const std:
0, TX_DEFAULT_FEE, empty_extra, empty_attachment, tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), tx);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect number of tx in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "There are transactions in the pool");
@ -1625,7 +1625,7 @@ multisig_and_checkpoints::multisig_and_checkpoints()
bool multisig_and_checkpoints::set_cp(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
currency::checkpoints checkpoints;
checkpoints.add_checkpoint(15, "816f96e8a0e259491ed7e03ef0f2eea69762276152f4990d71f657b1e37d8764");
checkpoints.add_checkpoint(15, "b9adef016fc8de02ad6d0db526e536a3c2211ee23a2d906f56989465c3e38602");
c.set_checkpoints(std::move(checkpoints));
return true;
@ -2490,14 +2490,14 @@ bool multisig_unconfirmed_transfer_and_multiple_scan_pool_calls::c1(currency::co
transaction key_to_ms_tx = AUTO_VAL_INIT(key_to_ms_tx);
miner_wlt->transfer(dst, 0, 0, TX_DEFAULT_FEE, extra, attachments, tools::detail::digit_split_strategy, tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD), key_to_ms_tx);
bool r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, miner_acc.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
bool r = mine_next_pow_blocks_in_playtime(miner_acc.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
size_t ms_out_idx = get_multisig_out_index(key_to_ms_tx.vout);
crypto::hash multisig_id = get_multisig_out_id(key_to_ms_tx, ms_out_idx);
CHECK_AND_ASSERT_MES(multisig_id != null_hash, false, "Multisig failed: failed to get get_multisig_out_id");
//r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, miner_acc.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
//r = mine_next_pow_blocks_in_playtime(miner_acc.get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
//CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, alice_acc);

View file

@ -567,7 +567,7 @@ bool offers_handling_on_chain_switching::c1(currency::core& c, size_t ev_index,
uint64_t blk_1r_height = c.get_current_blockchain_size() - 2;
crypto::hash blk_1r_id = c.get_block_id_by_height(blk_1r_height);
block blk_2a = AUTO_VAL_INIT(blk_2a);
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>(), blk_1r_id, blk_1r_height + 1, &blk_2a);
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>(), blk_1r_id, blk_1r_height + 1, &blk_2a);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -577,7 +577,7 @@ bool offers_handling_on_chain_switching::c1(currency::core& c, size_t ev_index,
// mine second alt block (include offer tx) -- this should trigger chain switching
block blk_3a = AUTO_VAL_INIT(blk_3a);
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({tx_1}), get_block_hash(blk_2a), blk_1r_height + 2, &blk_3a);
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({tx_1}), get_block_hash(blk_2a), blk_1r_height + 2, &blk_3a);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
@ -673,7 +673,7 @@ bool offer_removing_and_selected_output::check_offers(currency::core& c, size_t
crypto::hash create_offer_tx_id = get_transaction_hash(create_offer_tx);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
refresh_wallet_and_check_balance("offer's put into the blockchain", "Alice", alice_wlt, alice_start_balance - od.fee, true, 1);
@ -699,7 +699,7 @@ bool offer_removing_and_selected_output::check_offers(currency::core& c, size_t
// add it to the blockchain
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
// Alice's banace should not change
@ -937,7 +937,7 @@ bool offers_updating_hack::update_foreign_offer(currency::core& c, size_t ev_ind
// put in a block 'tx', leave Alice's tx in the pool
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ tx })), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ tx })), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
LOG_PRINT_L0(ENDL << c.get_tx_pool().print_pool(true));
@ -1005,7 +1005,7 @@ bool offers_updating_hack::delete_foreign_offer(currency::core& c, size_t ev_ind
// put in a block 'tx', leave Alice's tx in the pool
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ tx_c })), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>({ tx_c })), false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool: " << c.get_pool_transactions_count());
LOG_PRINT_L0(ENDL << c.get_tx_pool().print_pool(true));
@ -1264,7 +1264,7 @@ bool offer_lifecycle_via_tx_pool::c1(currency::core& c, size_t ev_index, const s
CATCH_ENTRY2(false);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, some_addr, c);
r = mine_next_pow_block_in_playtime(some_addr, c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
@ -1280,7 +1280,7 @@ bool offer_lifecycle_via_tx_pool::c1(currency::core& c, size_t ev_index, const s
CATCH_ENTRY2(false);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, some_addr, c);
r = mine_next_pow_block_in_playtime(some_addr, c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
@ -1297,7 +1297,7 @@ bool offer_lifecycle_via_tx_pool::c1(currency::core& c, size_t ev_index, const s
CATCH_ENTRY2(false);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, some_addr, c);
r = mine_next_pow_block_in_playtime(some_addr, c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
@ -1313,7 +1313,7 @@ bool offer_lifecycle_via_tx_pool::c1(currency::core& c, size_t ev_index, const s
CATCH_ENTRY2(false);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, some_addr, c);
r = mine_next_pow_block_in_playtime(some_addr, c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Invalid tx pool count: " << c.get_pool_transactions_count() << ENDL << "tx pool:" << ENDL << c.get_tx_pool().print_pool(true));

View file

@ -495,7 +495,7 @@ bool pos_wallet_minting_same_amount_diff_outs::prepare_wallets_0(currency::core&
r = populate_wallet_with_stake_coins(w.w, alice_wlt, w.pos_entries_count, m_wallet_stake_amount, pos_amounts);
CHECK_AND_ASSERT_MES(r, false, "populate_wallet_with_stake_coins failed");
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, alice_wlt->get_account().get_public_address(), c, WALLET_DEFAULT_TX_SPENDABLE_AGE + 1); // to preventing run out of the money for Alice
r = mine_next_pow_blocks_in_playtime(alice_wlt->get_account().get_public_address(), c, WALLET_DEFAULT_TX_SPENDABLE_AGE + 1); // to preventing run out of the money for Alice
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
c.get_blockchain_storage().get_top_block(b);
uint64_t ts = b.timestamp;
@ -552,7 +552,7 @@ bool pos_wallet_minting_same_amount_diff_outs::prepare_wallets_1(currency::core&
r = populate_wallet_with_stake_coins(w.w, alice_wlt, w.pos_entries_count, m_wallet_stake_amount, pos_amounts);
CHECK_AND_ASSERT_MES(r, false, "populate_wallet_with_stake_coins failed");
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, alice_wlt->get_account().get_public_address(), c, WALLET_DEFAULT_TX_SPENDABLE_AGE + 1); // to preventing run out of the money for Alice
r = mine_next_pow_blocks_in_playtime(alice_wlt->get_account().get_public_address(), c, WALLET_DEFAULT_TX_SPENDABLE_AGE + 1); // to preventing run out of the money for Alice
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
c.get_blockchain_storage().get_top_block(b);
uint64_t ts = b.timestamp;
@ -662,7 +662,7 @@ bool pos_wallet_minting_same_amount_diff_outs::c1(currency::core& c, size_t ev_i
ts = ideal_next_pow_block_ts; // "wait" until ideal_next_pow_block_ts if it was not already happened (fast forward but don't wayback the time)
test_core_time::adjust(ts);
size_t tx_count_before = c.get_pool_transactions_count();
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(tx_count_before == 0 || c.get_pool_transactions_count() < tx_count_before, false, "invalid number of txs in tx pool: " << c.get_pool_transactions_count() << ", was: " << tx_count_before);
last_pow_block_ts = ts;

View file

@ -1309,7 +1309,7 @@ bool tx_expiration_time_and_block_template::c1(currency::core& c, size_t ev_inde
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect tx count in the pool: " << c.get_pool_transactions_count());
account_public_address addr = AUTO_VAL_INIT(addr);
bool r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, addr, c);
bool r = mine_next_pow_block_in_playtime(addr, c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
// tx MAY stay in the pool, check it as forced condition (may change in future)

View file

@ -137,7 +137,7 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "enexpected pool txs count: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count());
@ -171,7 +171,7 @@ bool wallet_rpc_integrated_address_transfer::c1(currency::core& c, size_t ev_ind
CHECK_AND_ASSERT_MES(r, false, "RPC call failed, code: " << je.code << ", msg: " << je.message);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "enexpected pool txs count: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count());

View file

@ -1179,7 +1179,7 @@ bool gen_wallet_oversized_payment_id::c1(currency::core& c, size_t ev_index, con
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Tx pool has incorrect number of txs: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count());
@ -1215,7 +1215,7 @@ bool gen_wallet_oversized_payment_id::c1(currency::core& c, size_t ev_index, con
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Tx pool has incorrect number of txs: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Tx pool is not empty: " << c.get_pool_transactions_count());
@ -1769,7 +1769,7 @@ bool gen_wallet_alias_via_special_wallet_funcs::c1(currency::core& c, size_t ev_
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
bool r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
bool r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -1790,7 +1790,7 @@ bool gen_wallet_alias_via_special_wallet_funcs::c1(currency::core& c, size_t ev_
CHECK_AND_ASSERT_MES(l->m_result, false, "Wrong wti received via callback");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
CHECK_AND_ASSERT_MES(c.get_current_blockchain_size() == 2 + CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1 + WALLET_DEFAULT_TX_SPENDABLE_AGE + 2, false, "Incorrect blockchain size");
@ -1803,7 +1803,7 @@ bool gen_wallet_alias_via_special_wallet_funcs::c1(currency::core& c, size_t ev_
alice_wlt->request_alias_update(ai, res_tx, TX_DEFAULT_FEE, 0);
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
CHECK_AND_ASSERT_MES(c.get_current_blockchain_size() == 2 + CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1 + WALLET_DEFAULT_TX_SPENDABLE_AGE + 3, false, "Incorrect blockchain size");
@ -2072,7 +2072,7 @@ bool gen_wallet_offers_basic::c1(currency::core& c, size_t ev_index, const std::
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "Incorrect txs count in the pool");
bool r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
bool r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -2123,7 +2123,7 @@ bool gen_wallet_offers_basic::c1(currency::core& c, size_t ev_index, const std::
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -2154,7 +2154,7 @@ bool gen_wallet_offers_basic::c1(currency::core& c, size_t ev_index, const std::
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Incorrect txs count in the pool");
@ -2274,7 +2274,7 @@ bool gen_wallet_offers_size_limit::c1(currency::core& c, size_t ev_index, const
log_space::get_set_log_detalisation_level(true, log_level); // restore
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
miner_wlt->refresh(blocks_fetched, received_money, atomic_false);
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect numbers of blocks fetched");
@ -2373,7 +2373,7 @@ bool gen_wallet_dust_to_account::c1(currency::core& c, size_t ev_index, const st
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
bool r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
bool r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
miner_wlt->refresh(blocks_fetched, received_money, atomic_false);
@ -2473,7 +2473,7 @@ bool gen_wallet_selecting_pos_entries::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(c.get_current_blockchain_size() == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3 + 1 + WALLET_DEFAULT_TX_SPENDABLE_AGE - 1, false, "Incorrect current blockchain height");
// this block should unlock the money and PoS-entries should become available
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
alice_wlt->refresh(blocks_fetched, received_money, atomic_false);
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect number of blocks fetched");
@ -2497,7 +2497,7 @@ bool gen_wallet_selecting_pos_entries::c1(currency::core& c, size_t ev_index, co
alice_wlt->transfer(dst, 0, 0, TX_DEFAULT_FEE, std::vector<extra_v>(), std::vector<attachment_v>());
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
alice_wlt->refresh(blocks_fetched, received_money, atomic_false);
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect number of blocks fetched");
@ -2571,7 +2571,7 @@ bool gen_wallet_spending_coinstake_after_minting::c1(currency::core& c, size_t e
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Incorrect txs count in the pool");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
alice_wlt->refresh(blocks_fetched, received_money, atomic_false);
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect number of blocks fetched");
@ -2878,7 +2878,7 @@ bool mined_balance_wallet_test::c1(currency::core& c, size_t ev_index, const std
std::list<currency::block> blocks;
size_t n = CURRENCY_MINED_MONEY_UNLOCK_WINDOW;
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, n);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, n);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
r = bcs.get_blocks(bcs.get_current_blockchain_size() - n, n, blocks);
CHECK_AND_ASSERT_MES(r, false, "get_blocks failed");
@ -2994,11 +2994,11 @@ bool wallet_outputs_with_same_key_image::c1(currency::core& c, size_t ev_index,
bool r = refresh_wallet_and_check_balance("before tx_1 and tx_2 added", "Alice", alice_wlt, MK_TEST_COINS(3) * 2, true, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2, 0);
CHECK_AND_ASSERT_MES(r, false, "");
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "there are txs in the pool!");
r = mine_next_pow_blocks_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
// only one tx_1 output is counted as the tx_2 output has the very same key image
@ -3017,7 +3017,7 @@ bool wallet_outputs_with_same_key_image::c1(currency::core& c, size_t ev_index,
}
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "wrong tx count in the pool: " << c.get_pool_transactions_count());
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "there are txs in the pool!");
@ -3097,7 +3097,7 @@ bool wallet_unconfirmed_tx_expiration::c1(currency::core& c, size_t ev_index, co
// mine a few block with no tx, so Alice's tx is expired in the pool
for (size_t i = 0; i < 5; ++i)
{
r = mine_next_pow_block_in_playtime_with_given_txs(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
r = mine_next_pow_block_in_playtime_with_given_txs(m_accounts[MINER_ACC_IDX].get_public_address(), c, std::vector<transaction>());
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime_with_given_txs failed");
}
@ -3114,7 +3114,7 @@ bool wallet_unconfirmed_tx_expiration::c1(currency::core& c, size_t ev_index, co
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Invalid txs count in the pool: " << c.get_pool_transactions_count());
// mine one more block to trigger wallet's on_idle() and outdated tx clearing
r = mine_next_pow_block_in_playtime(m_scratchpad_keeper, m_accounts[MINER_ACC_IDX].get_public_address(), c);
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
// make sure all Alice's money are unlocked and no coins were actually spent

View file

@ -101,17 +101,14 @@ bool generate_events(currency::core& c, cct_events_t& events, const cct_wallets_
const currency::account_public_address& miner_addr = wallets[random_in_range(0, wallets.size() - 1)]->get_account().get_public_address();
currency::block b = AUTO_VAL_INIT(b);
currency::scratchpad_keeper sk;
crypto::hash seed = currency::null_hash;
sk.generate(seed, height);
if (is_in_main_chain)
{
blobdata ex_nonce;
wide_difficulty_type diff = 0;
if (prev_block.height != 0)
test_core_time::adjust(prev_block.bl.timestamp + DIFFICULTY_POW_TARGET);
r = bcs.create_block_template(b, seed, miner_addr, diff, height, ex_nonce);
r = bcs.create_block_template(b, miner_addr, diff, height, ex_nonce);
CHECK_AND_ASSERT_MES(r, false, "create_block_template failed");
}
else
@ -145,7 +142,7 @@ bool generate_events(currency::core& c, cct_events_t& events, const cct_wallets_
test_core_time::adjust(b.timestamp);
currency::wide_difficulty_type diff = 0;
r = currency::miner::find_nonce_for_given_block(b, diff, height, seed, sk);
r = currency::miner::find_nonce_for_given_block(b, diff, height);
CHECK_AND_ASSERT_MES(r, false, "find_nonce_for_given_block failed");
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);

View file

@ -4,126 +4,92 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "crypto/crypto.h"
#include "currency_core/currency_basic.h"
#include "profile_tools.h"
extern "C" {
#include "crypto/keccak.h"
//#include "crypto/alt/KeccakNISTInterface.h"
}
#include "crypto/wild_keccak.h"
//#include "crypto/wild_keccak2.h"
#include "../core_tests/random_helper.h"
#include "crypto/hash.h"
#define TEST_BUFF_LEN 200
class test_keccak_base
{
public:
static const size_t loop_count = 100000;
bool init()
{
currency::block b;
m_buff = currency::get_block_hashing_blob(b);
m_buff.append(32 * 4, 0);
return true;
}
bool pretest()
{
++m_buff[0];
if (!m_buff[0])
++m_buff[0];
return true;
}
protected:
std::string m_buff;
};
// class test_keccak : public test_keccak_base
//
// #include "crypto/crypto.h"
// #include "currency_core/currency_basic.h"
// #include "profile_tools.h"
//
// extern "C" {
// #include "crypto/keccak.h"
// //#include "crypto/alt/KeccakNISTInterface.h"
// }
//
//
// #include "crypto/wild_keccak.h"
// //#include "crypto/wild_keccak2.h"
// #include "../core_tests/random_helper.h"
// #include "crypto/hash.h"
//
//
//
//
// #define TEST_BUFF_LEN 200
//
// class test_keccak_base
// {
// public:
// static const size_t loop_count = 100000;
//
// bool init()
// {
// currency::block b;
// m_buff = currency::get_block_hashing_blob(b);
// m_buff.append(32 * 4, 0);
// return true;
// }
//
// bool pretest()
// {
// ++m_buff[0];
// if (!m_buff[0])
// ++m_buff[0];
// return true;
// }
// protected:
// std::string m_buff;
// };
//
// // class test_keccak : public test_keccak_base
// // {
// // public:
// // bool test()
// // {
// // pretest();
// // crypto::hash h;
// // keccak(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h));
// // LOG_PRINT_L4(h);
// // return true;
// // }
// // };
//
//
// class test_keccak_generic : public test_keccak_base
// {
// public:
// bool test()
// {
// pretest();
// crypto::hash h;
// keccak(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h));
// crypto::keccak_generic<crypto::regular_f>(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h));
// LOG_PRINT_L4(h);
// return true;
// }
// };
class test_keccak_generic : public test_keccak_base
{
public:
bool test()
{
pretest();
crypto::hash h;
crypto::keccak_generic<crypto::regular_f>(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h));
LOG_PRINT_L4(h);
return true;
}
};
class test_keccak_generic_with_mul : public test_keccak_base
{
public:
bool test()
{
pretest();
crypto::hash h;
crypto::keccak_generic<crypto::mul_f>(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h));
return true;
}
};
template<int scratchpad_size>
class test_wild_keccak : public test_keccak_base
{
public:
bool init()
{
m_scratchpad_vec.resize(scratchpad_size / sizeof(crypto::hash));
for (auto& h : m_scratchpad_vec)
h = crypto::rand<crypto::hash>();
return test_keccak_base::init();
}
bool test()
{
pretest();
crypto::hash h;
crypto::wild_keccak_dbl<crypto::mul_f>(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h), [&](crypto::state_t_m& st, crypto::mixin_t& mix)
{
#define SCR_I(i) m_scratchpad_vec[st[i]%m_scratchpad_vec.size()]
for (size_t i = 0; i != 6; i++)
{
OPT_XOR_4_RES(SCR_I(i * 4), SCR_I(i * 4 + 1), SCR_I(i * 4 + 2), SCR_I(i * 4 + 3), *(crypto::hash*)&mix[i * 4]);
}
});
return true;
}
protected:
std::vector<crypto::hash> m_scratchpad_vec;
};
//
// class test_keccak_generic_with_mul : public test_keccak_base
// {
// public:
// bool test()
// {
// pretest();
// crypto::hash h;
// crypto::keccak_generic<crypto::mul_f>(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h));
// return true;
// }
// };
//
// template<int scratchpad_size>
// class test_wild_keccak2 : public test_keccak_base
// class test_wild_keccak : public test_keccak_base
// {
// public:
// bool init()
@ -139,102 +105,136 @@ protected:
// {
// pretest();
//
// crypto::hash h2;
// crypto::wild_keccak_dbl_opt(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h2), sizeof(h2), (const UINT64*)&m_scratchpad_vec[0], m_scratchpad_vec.size() * 4);
// LOG_PRINT_L4("HASH:" << h2);
// crypto::hash h;
// crypto::wild_keccak_dbl<crypto::mul_f>(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h), sizeof(h), [&](crypto::state_t_m& st, crypto::mixin_t& mix)
// {
// #define SCR_I(i) m_scratchpad_vec[st[i]%m_scratchpad_vec.size()]
// for (size_t i = 0; i != 6; i++)
// {
// OPT_XOR_4_RES(SCR_I(i * 4), SCR_I(i * 4 + 1), SCR_I(i * 4 + 2), SCR_I(i * 4 + 3), *(crypto::hash*)&mix[i * 4]);
// }
// });
//
// return true;
// }
// protected:
// std::vector<crypto::hash> m_scratchpad_vec;
// };
#ifdef _DEBUG
#define max_measere_scratchpad 100000
#else
#define max_measere_scratchpad 50000000
#endif
#define measere_rounds 10000
void generate_scratchpad()
{
crypto::hash seed = crypto::cn_fast_hash("sdssdsffdss", 10);
std::vector<crypto::hash> scratchpad;
size_t count = 500000000 / 32;
TIME_MEASURE_START_MS(gen_time);
LOG_PRINT_L0("Generating....");
crypto::generate_scratchpad2(seed, scratchpad, count);
TIME_MEASURE_FINISH_MS(gen_time);
LOG_PRINT_L0("Generated scratchpad " << (scratchpad.size() * 32) / (1024 * 1024) << "MB in " << gen_time << "ms");
}
void generate_light_scratchpad()
{
crypto::hash seed = crypto::cn_fast_hash("sdssdsffdss", 10);
std::vector<crypto::hash> scratchpad;
size_t count = 500000000 / 32;
TIME_MEASURE_START_MS(gen_time);
LOG_PRINT_L0("Generating....");
crypto::generate_scratchpad_light(seed, scratchpad, count);
TIME_MEASURE_FINISH_MS(gen_time);
LOG_PRINT_L0("Generated scratchpad " << (scratchpad.size() * 32) / (1024 * 1024) << "MB in " << gen_time << "ms");
}
void measure_keccak_over_scratchpad(uint64_t start_scratchpad_size, uint64_t step_size)
{
// std::cout << std::setw(20) << std::left << "sz\t" <<
//std::setw(10) << "original\t" <<
// std::setw(10) << "original opt\t" <<
// std::setw(10) << "w2\t" <<
// std::setw(10) << "w2_opt" << ENDL;
std::vector<crypto::hash> scratchpad_vec;
scratchpad_vec.resize(max_measere_scratchpad);
std::string has_str = "Keccak is a family of sponge functions. The sponge function is a generalization of the concept of cryptographic hash function with infinite output and can perform quasi all symmetric cryptographic functions, from hashing to pseudo-random number generation to authenticated encryption";
for (size_t j = 0; j != scratchpad_vec.size(); j++)
scratchpad_vec[j] = crypto::rand<crypto::hash>();
for (uint64_t i = start_scratchpad_size; i < max_measere_scratchpad; i += i/10)
{
crypto::hash res_h = currency::null_hash;
uint64_t ticks_a = epee::misc_utils::get_tick_count();
*(uint64_t*)(&has_str[8]) = i;
uint64_t ticks_b = epee::misc_utils::get_tick_count();
for (size_t r = 0; r != measere_rounds; r++)
{
*(size_t*)(&has_str[1]) = r;
crypto::get_wild_keccak(has_str, res_h, 1, scratchpad_vec, i);
}
//wild keccak 2
uint64_t ticks_c = epee::misc_utils::get_tick_count();
for (size_t r = 0; r != measere_rounds; r++)
{
*(size_t*)(&has_str[1]) = r;
res_h = crypto::cn_fast_hash(has_str.data(), has_str.size());
}
//wild keccak 2 opt
uint64_t ticks_d = epee::misc_utils::get_tick_count();
for (size_t r = 0; r != measere_rounds; r++)
{
crypto::get_wild_keccak2(has_str, res_h, scratchpad_vec, i);
}
uint64_t ticks_e = epee::misc_utils::get_tick_count();
std::cout << std::setw(20) << std::left << i * sizeof(crypto::hash) << "\t" <<
//std::setw(10) << ticks_b - ticks_a << "\t" <<
//std::setw(10) << ticks_c - ticks_b << "\t" <<
std::setw(10) << ticks_d - ticks_c << "\t" <<
std::setw(10) << ticks_e - ticks_d << ENDL;
}
}
void measure_keccak_over_scratchpad()
{
//measure_keccak_over_scratchpad(100/32, 100/32);
//measure_keccak_over_scratchpad(10, max_measere_scratchpad / 10);
measure_keccak_over_scratchpad(max_measere_scratchpad/10, 0);
}
//
// //
// // template<int scratchpad_size>
// // class test_wild_keccak2 : public test_keccak_base
// // {
// // public:
// // bool init()
// // {
// // m_scratchpad_vec.resize(scratchpad_size / sizeof(crypto::hash));
// // for (auto& h : m_scratchpad_vec)
// // h = crypto::rand<crypto::hash>();
// //
// // return test_keccak_base::init();
// // }
// //
// // bool test()
// // {
// // pretest();
// //
// // crypto::hash h2;
// // crypto::wild_keccak_dbl_opt(reinterpret_cast<const uint8_t*>(&m_buff[0]), m_buff.size(), reinterpret_cast<uint8_t*>(&h2), sizeof(h2), (const UINT64*)&m_scratchpad_vec[0], m_scratchpad_vec.size() * 4);
// // LOG_PRINT_L4("HASH:" << h2);
// // return true;
// // }
// // protected:
// // std::vector<crypto::hash> m_scratchpad_vec;
// // };
//
// #ifdef _DEBUG
// #define max_measere_scratchpad 100000
// #else
// #define max_measere_scratchpad 50000000
// #endif
// #define measere_rounds 10000
//
// void generate_scratchpad()
// {
// crypto::hash seed = crypto::cn_fast_hash("sdssdsffdss", 10);
// std::vector<crypto::hash> scratchpad;
// size_t count = 500000000 / 32;
// TIME_MEASURE_START_MS(gen_time);
// LOG_PRINT_L0("Generating....");
// crypto::generate_scratchpad2(seed, scratchpad, count);
// TIME_MEASURE_FINISH_MS(gen_time);
// LOG_PRINT_L0("Generated scratchpad " << (scratchpad.size() * 32) / (1024 * 1024) << "MB in " << gen_time << "ms");
// }
//
// void generate_light_scratchpad()
// {
// crypto::hash seed = crypto::cn_fast_hash("sdssdsffdss", 10);
// std::vector<crypto::hash> scratchpad;
// size_t count = 500000000 / 32;
// TIME_MEASURE_START_MS(gen_time);
// LOG_PRINT_L0("Generating....");
// crypto::generate_scratchpad_light(seed, scratchpad, count);
// TIME_MEASURE_FINISH_MS(gen_time);
// LOG_PRINT_L0("Generated scratchpad " << (scratchpad.size() * 32) / (1024 * 1024) << "MB in " << gen_time << "ms");
// }
//
//
// void measure_keccak_over_scratchpad(uint64_t start_scratchpad_size, uint64_t step_size)
// {
// // std::cout << std::setw(20) << std::left << "sz\t" <<
// //std::setw(10) << "original\t" <<
// // std::setw(10) << "original opt\t" <<
// // std::setw(10) << "w2\t" <<
// // std::setw(10) << "w2_opt" << ENDL;
//
// std::vector<crypto::hash> scratchpad_vec;
// scratchpad_vec.resize(max_measere_scratchpad);
// std::string has_str = "Keccak is a family of sponge functions. The sponge function is a generalization of the concept of cryptographic hash function with infinite output and can perform quasi all symmetric cryptographic functions, from hashing to pseudo-random number generation to authenticated encryption";
//
// for (size_t j = 0; j != scratchpad_vec.size(); j++)
// scratchpad_vec[j] = crypto::rand<crypto::hash>();
//
// for (uint64_t i = start_scratchpad_size; i < max_measere_scratchpad; i += i/10)
// {
//
// crypto::hash res_h = currency::null_hash;
// uint64_t ticks_a = epee::misc_utils::get_tick_count();
// *(uint64_t*)(&has_str[8]) = i;
//
// uint64_t ticks_b = epee::misc_utils::get_tick_count();
// for (size_t r = 0; r != measere_rounds; r++)
// {
// *(size_t*)(&has_str[1]) = r;
// crypto::get_wild_keccak(has_str, res_h, 1, scratchpad_vec, i);
// }
//
// //wild keccak 2
// uint64_t ticks_c = epee::misc_utils::get_tick_count();
// for (size_t r = 0; r != measere_rounds; r++)
// {
// *(size_t*)(&has_str[1]) = r;
// res_h = crypto::cn_fast_hash(has_str.data(), has_str.size());
// }
// //wild keccak 2 opt
// uint64_t ticks_d = epee::misc_utils::get_tick_count();
// for (size_t r = 0; r != measere_rounds; r++)
// {
// crypto::get_wild_keccak2(has_str, res_h, scratchpad_vec, i);
// }
//
// uint64_t ticks_e = epee::misc_utils::get_tick_count();
// std::cout << std::setw(20) << std::left << i * sizeof(crypto::hash) << "\t" <<
// //std::setw(10) << ticks_b - ticks_a << "\t" <<
// //std::setw(10) << ticks_c - ticks_b << "\t" <<
// std::setw(10) << ticks_d - ticks_c << "\t" <<
// std::setw(10) << ticks_e - ticks_d << ENDL;
// }
// }
//
// void measure_keccak_over_scratchpad()
// {
// //measure_keccak_over_scratchpad(100/32, 100/32);
// //measure_keccak_over_scratchpad(10, max_measere_scratchpad / 10);
// measure_keccak_over_scratchpad(max_measere_scratchpad/10, 0);
// }

View file

@ -38,7 +38,7 @@ int main(int argc, char** argv)
//generate_scratchpad();
//generate_light_scratchpad();
//measure_keccak_over_scratchpad();
test_scratchpad_against_light_scratchpad();
//test_scratchpad_against_light_scratchpad();
/*
TEST_PERFORMANCE2(test_construct_tx, 1, 1);
TEST_PERFORMANCE2(test_construct_tx, 1, 2);

View file

@ -10,42 +10,42 @@
#include "crypto/crypto.h"
#include "currency_core/currency_basic.h"
#include "profile_tools.h"
#include "crypto/wild_keccak.h"
//#include "crypto/wild_keccak.h"
#include "currency_core/currency_format_utils.h"
using namespace currency;
bool test_scratchpad_against_light_scratchpad()
{
crypto::hash seed = crypto::cn_fast_hash("sdssdsffdss", 10);
std::vector<crypto::hash> scratchpad;
size_t count = 400;
TIME_MEASURE_START_MS(gen_time);
LOG_PRINT_L0("Generating full ....");
crypto::generate_scratchpad2(seed, scratchpad, count);
TIME_MEASURE_FINISH_MS(gen_time);
LOG_PRINT_L0("Generated full scratchpad " << (scratchpad.size() * 32) / (1024 * 1024) << "MB in " << gen_time << "ms");
std::vector<crypto::hash> scratchpad_light;
crypto::generate_scratchpad_light(seed, scratchpad_light, count);
std::string hashing_str = "dsfssfadfada";
crypto::hash full_h = currency::null_hash;
crypto::hash light_h = currency::null_hash;
crypto::get_wild_keccak2(hashing_str, full_h, scratchpad);
crypto::get_wild_keccak_light(hashing_str, light_h, scratchpad_light);
if (full_h != light_h)
{
LOG_ERROR("Hash missmatch");
return false;
}
return true;
}
TEST(pow_tests, test_full_against_light)
{
bool res = test_scratchpad_against_light_scratchpad();
ASSERT_TRUE(res);
}
//
// bool test_scratchpad_against_light_scratchpad()
// {
// crypto::hash seed = crypto::cn_fast_hash("sdssdsffdss", 10);
// std::vector<crypto::hash> scratchpad;
// size_t count = 400;
// TIME_MEASURE_START_MS(gen_time);
// LOG_PRINT_L0("Generating full ....");
// crypto::generate_scratchpad2(seed, scratchpad, count);
// TIME_MEASURE_FINISH_MS(gen_time);
// LOG_PRINT_L0("Generated full scratchpad " << (scratchpad.size() * 32) / (1024 * 1024) << "MB in " << gen_time << "ms");
// std::vector<crypto::hash> scratchpad_light;
// crypto::generate_scratchpad_light(seed, scratchpad_light, count);
//
// std::string hashing_str = "dsfssfadfada";
// crypto::hash full_h = currency::null_hash;
// crypto::hash light_h = currency::null_hash;
// crypto::get_wild_keccak2(hashing_str, full_h, scratchpad);
// crypto::get_wild_keccak_light(hashing_str, light_h, scratchpad_light);
// if (full_h != light_h)
// {
// LOG_ERROR("Hash missmatch");
// return false;
// }
// return true;
// }
//
// TEST(pow_tests, test_full_against_light)
// {
// bool res = test_scratchpad_against_light_scratchpad();
// ASSERT_TRUE(res);
// }

View file

@ -4,4 +4,4 @@ cd ..
@mkdir build_msvc2015_64
cd build_msvc2015_64
cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2015_64 -D BUILD_GUI=TRUE -D USE_OPENCL=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.0" -G "Visual Studio 14 2015 Win64" -T host=x64 ".."
cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2015_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.0" -G "Visual Studio 14 2015 Win64" -T host=x64 ".."

View file

@ -4,4 +4,4 @@ cd ..
@mkdir build_msvc2017_64
cd build_msvc2017_64
cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2017_64 -D BUILD_GUI=TRUE -D USE_OPENCL=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 15 2017 Win64" -T host=x64 ".."
cmake -D USE_PCH=TRUE -D BUILD_TESTS=TRUE -D CMAKE_PREFIX_PATH="%QT_PREFIX_PATH%"\msvc2017_64 -D BUILD_GUI=TRUE -D STATIC=FALSE -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_ROOT%\lib64-msvc-14.1" -G "Visual Studio 15 2017 Win64" -T host=x64 ".."