Merge pull request 'tag-release' (#435) from wowario/wownero:tag-release into master
Reviewed-on: https://git.wownero.com/wownero/wownero/pulls/435
This commit is contained in:
commit
ab42be18f2
20
README.md
20
README.md
|
@ -16,16 +16,21 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||||
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
|
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
|
||||||
- Telegram: [t.me/wownero](https://t.me/wownero)
|
- Telegram: [t.me/wownero](https://t.me/wownero)
|
||||||
- Wowlet Desktop Wallet: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet/releases)
|
- Wowlet Desktop Wallet: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet/releases)
|
||||||
- WOW Stash Web Wallet: [wowstash.app](https://wowstash.app)
|
- Stack Wallet iOS & Android Mobile Wallet: [stackwallet.com](https://stackwallet.com)
|
||||||
|
- Wonerujo Android Mobile Wallet: [google store](https://play.google.com/store/apps/details?id=com.m2049r.wowwallet)
|
||||||
- Public Node Status: [monero.fail](https://monero.fail/?crypto=wownero)
|
- Public Node Status: [monero.fail](https://monero.fail/?crypto=wownero)
|
||||||
- Map of Nodes: [wownero.fyi](https://wownero.fyi)
|
|
||||||
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
|
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
|
||||||
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
|
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
|
||||||
|
|
||||||
|
## Exchanges
|
||||||
|
|
||||||
|
- [AltQuick](https://altquick.com/market/Wownero)
|
||||||
|
- [Majestic Bank](https://majesticbank.sc)
|
||||||
|
- [TradeOgre](https://tradeogre.com/exchange/BTC-WOW)
|
||||||
|
|
||||||
### Blockchain Explorers
|
### Blockchain Explorers
|
||||||
|
|
||||||
- https://explore.wownero.com
|
- https://explore.wownero.com
|
||||||
- http://gffjxd5nn2heslj6jv5ts2ok5j6xi6m3pwlpz7le4i5bu56sirbxfiqd.onion:8081
|
|
||||||
- https://wownero.club
|
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
@ -72,13 +77,13 @@ Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](
|
||||||
|
|
||||||
Join `#wownero` on IRC OFTC to participate in development conversation.
|
Join `#wownero` on IRC OFTC to participate in development conversation.
|
||||||
|
|
||||||
## Scheduled software upgrades
|
## Scheduled software/network upgrades
|
||||||
|
|
||||||
Wownero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Wownero (end users and service providers) should run current versions and upgrade their software on a regular schedule. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Wownero software version. Below is the historical schedule and the projected schedule for the next upgrade.
|
Wownero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Wownero (end users and service providers) should run current versions and upgrade their software on a regular schedule. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Wownero software version. Below is the historical schedule and the projected schedule for the next upgrade.
|
||||||
Dates are provided in the format YYYY-MM-DD.
|
Dates are provided in the format YYYY-MM-DD.
|
||||||
|
|
||||||
| Software upgrade block height | Date | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
|
| Software upgrade block height | Date | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
|
||||||
| ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- |
|
|-------------------------------|------------| ----------------- |-------------------------|-----------------------------| ---------------------------------------------------------------------------------- |
|
||||||
| 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
|
| 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
|
||||||
| 69,69 | 2018-04-24 | Busty Brazzers | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
|
| 69,69 | 2018-04-24 | Busty Brazzers | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
|
||||||
| 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
|
| 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
|
||||||
|
@ -88,7 +93,8 @@ Dates are provided in the format YYYY-MM-DD.
|
||||||
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
||||||
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
||||||
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
||||||
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.1.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
|
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.2.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
|
||||||
|
| XXX,XXX | 2023-XX-XX | Kunty Karen | v0.11.0.0 | v0.11.0.0 | View tags, fee changes, adjusted dynamic block weight algorithm, multisig security fixes, RPC broadcast node donation sub-address
|
||||||
|
|
||||||
X's indicate that these details have not been determined as of commit date.
|
X's indicate that these details have not been determined as of commit date.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2014-2020, The Monero Project
|
// Copyright (c) 2014-2022, The Monero Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -40,6 +40,9 @@
|
||||||
#include "oaes_lib.h"
|
#include "oaes_lib.h"
|
||||||
#include "variant2_int_sqrt.h"
|
#include "variant2_int_sqrt.h"
|
||||||
#include "variant4_random_math.h"
|
#include "variant4_random_math.h"
|
||||||
|
#include "CryptonightR_JIT.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#define MEMORY (1 << 21) // 2MB scratchpad
|
#define MEMORY (1 << 21) // 2MB scratchpad
|
||||||
#define ITER (1 << 20)
|
#define ITER (1 << 20)
|
||||||
|
@ -48,9 +51,72 @@
|
||||||
#define INIT_SIZE_BLK 8
|
#define INIT_SIZE_BLK 8
|
||||||
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
|
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define THREADV __declspec(thread)
|
||||||
|
#else
|
||||||
|
#define THREADV __thread
|
||||||
|
#endif
|
||||||
|
|
||||||
extern void aesb_single_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
extern void aesb_single_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
||||||
extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
||||||
|
|
||||||
|
static void local_abort(const char *msg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", msg);
|
||||||
|
#ifdef NDEBUG
|
||||||
|
_exit(1);
|
||||||
|
#else
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile int use_v4_jit_flag = -1;
|
||||||
|
|
||||||
|
static inline int use_v4_jit(void)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
|
||||||
|
if (use_v4_jit_flag != -1)
|
||||||
|
return use_v4_jit_flag;
|
||||||
|
|
||||||
|
const char *env = getenv("MONERO_USE_CNV4_JIT");
|
||||||
|
if (!env) {
|
||||||
|
use_v4_jit_flag = 1;
|
||||||
|
}
|
||||||
|
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||||
|
use_v4_jit_flag = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
use_v4_jit_flag = 1;
|
||||||
|
}
|
||||||
|
return use_v4_jit_flag;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__aarch64__)
|
||||||
|
static inline int force_software_aes(void)
|
||||||
|
{
|
||||||
|
static int use = -1;
|
||||||
|
|
||||||
|
if (use != -1)
|
||||||
|
return use;
|
||||||
|
|
||||||
|
const char *env = getenv("MONERO_USE_SOFTWARE_AES");
|
||||||
|
if (!env) {
|
||||||
|
use = 0;
|
||||||
|
}
|
||||||
|
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||||
|
use = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
use = 1;
|
||||||
|
}
|
||||||
|
return use;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VARIANT1_1(p) \
|
#define VARIANT1_1(p) \
|
||||||
do if (variant == 1) \
|
do if (variant == 1) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -117,48 +183,74 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||||
#define VARIANT2_SHUFFLE_ADD_SSE2(base_ptr, offset) \
|
#define VARIANT2_SHUFFLE_ADD_SSE2(base_ptr, offset) \
|
||||||
do if (variant >= 2) \
|
do if (variant >= 2) \
|
||||||
{ \
|
{ \
|
||||||
const __m128i chunk1 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10))); \
|
__m128i chunk1 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10))); \
|
||||||
const __m128i chunk2 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20))); \
|
const __m128i chunk2 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20))); \
|
||||||
const __m128i chunk3 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30))); \
|
const __m128i chunk3 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30))); \
|
||||||
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10)), _mm_add_epi64(chunk3, _b1)); \
|
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10)), _mm_add_epi64(chunk3, _b1)); \
|
||||||
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20)), _mm_add_epi64(chunk1, _b)); \
|
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20)), _mm_add_epi64(chunk1, _b)); \
|
||||||
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30)), _mm_add_epi64(chunk2, _a)); \
|
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30)), _mm_add_epi64(chunk2, _a)); \
|
||||||
|
if (variant >= 4) \
|
||||||
|
{ \
|
||||||
|
chunk1 = _mm_xor_si128(chunk1, chunk2); \
|
||||||
|
_c = _mm_xor_si128(_c, chunk3); \
|
||||||
|
_c = _mm_xor_si128(_c, chunk1); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define VARIANT2_SHUFFLE_ADD_NEON(base_ptr, offset) \
|
#define VARIANT2_SHUFFLE_ADD_NEON(base_ptr, offset) \
|
||||||
do if (variant >= 2) \
|
do if (variant >= 2) \
|
||||||
{ \
|
{ \
|
||||||
const uint64x2_t chunk1 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x10))); \
|
uint64x2_t chunk1 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x10))); \
|
||||||
const uint64x2_t chunk2 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x20))); \
|
const uint64x2_t chunk2 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x20))); \
|
||||||
const uint64x2_t chunk3 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x30))); \
|
const uint64x2_t chunk3 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x30))); \
|
||||||
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x10)), vaddq_u64(chunk3, vreinterpretq_u64_u8(_b1))); \
|
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x10)), vaddq_u64(chunk3, vreinterpretq_u64_u8(_b1))); \
|
||||||
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x20)), vaddq_u64(chunk1, vreinterpretq_u64_u8(_b))); \
|
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x20)), vaddq_u64(chunk1, vreinterpretq_u64_u8(_b))); \
|
||||||
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x30)), vaddq_u64(chunk2, vreinterpretq_u64_u8(_a))); \
|
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x30)), vaddq_u64(chunk2, vreinterpretq_u64_u8(_a))); \
|
||||||
|
if (variant >= 4) \
|
||||||
|
{ \
|
||||||
|
chunk1 = veorq_u64(chunk1, chunk2); \
|
||||||
|
_c = vreinterpretq_u8_u64(veorq_u64(vreinterpretq_u64_u8(_c), chunk3)); \
|
||||||
|
_c = vreinterpretq_u8_u64(veorq_u64(vreinterpretq_u64_u8(_c), chunk1)); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define VARIANT2_PORTABLE_SHUFFLE_ADD(base_ptr, offset) \
|
#define VARIANT2_PORTABLE_SHUFFLE_ADD(out, a_, base_ptr, offset) \
|
||||||
do if (variant >= 2) \
|
do if (variant >= 2) \
|
||||||
{ \
|
{ \
|
||||||
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
|
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
|
||||||
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
|
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
|
||||||
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
|
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
|
||||||
\
|
\
|
||||||
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
|
uint64_t chunk1_old[2] = { SWAP64LE(chunk1[0]), SWAP64LE(chunk1[1]) }; \
|
||||||
|
const uint64_t chunk2_old[2] = { SWAP64LE(chunk2[0]), SWAP64LE(chunk2[1]) }; \
|
||||||
|
const uint64_t chunk3_old[2] = { SWAP64LE(chunk3[0]), SWAP64LE(chunk3[1]) }; \
|
||||||
\
|
\
|
||||||
uint64_t b1[2]; \
|
uint64_t b1[2]; \
|
||||||
memcpy_swap64le(b1, b + 16, 2); \
|
memcpy_swap64le(b1, b + 16, 2); \
|
||||||
chunk1[0] = SWAP64LE(SWAP64LE(chunk3[0]) + b1[0]); \
|
chunk1[0] = SWAP64LE(chunk3_old[0] + b1[0]); \
|
||||||
chunk1[1] = SWAP64LE(SWAP64LE(chunk3[1]) + b1[1]); \
|
chunk1[1] = SWAP64LE(chunk3_old[1] + b1[1]); \
|
||||||
\
|
\
|
||||||
uint64_t a0[2]; \
|
uint64_t a0[2]; \
|
||||||
memcpy_swap64le(a0, a, 2); \
|
memcpy_swap64le(a0, a_, 2); \
|
||||||
chunk3[0] = SWAP64LE(SWAP64LE(chunk2[0]) + a0[0]); \
|
chunk3[0] = SWAP64LE(chunk2_old[0] + a0[0]); \
|
||||||
chunk3[1] = SWAP64LE(SWAP64LE(chunk2[1]) + a0[1]); \
|
chunk3[1] = SWAP64LE(chunk2_old[1] + a0[1]); \
|
||||||
\
|
\
|
||||||
uint64_t b0[2]; \
|
uint64_t b0[2]; \
|
||||||
memcpy_swap64le(b0, b, 2); \
|
memcpy_swap64le(b0, b, 2); \
|
||||||
chunk2[0] = SWAP64LE(SWAP64LE(chunk1_old[0]) + b0[0]); \
|
chunk2[0] = SWAP64LE(chunk1_old[0] + b0[0]); \
|
||||||
chunk2[1] = SWAP64LE(SWAP64LE(chunk1_old[1]) + b0[1]); \
|
chunk2[1] = SWAP64LE(chunk1_old[1] + b0[1]); \
|
||||||
|
if (variant >= 4) \
|
||||||
|
{ \
|
||||||
|
uint64_t out_copy[2]; \
|
||||||
|
memcpy_swap64le(out_copy, out, 2); \
|
||||||
|
chunk1_old[0] ^= chunk2_old[0]; \
|
||||||
|
chunk1_old[1] ^= chunk2_old[1]; \
|
||||||
|
out_copy[0] ^= chunk3_old[0]; \
|
||||||
|
out_copy[1] ^= chunk3_old[1]; \
|
||||||
|
out_copy[0] ^= chunk1_old[0]; \
|
||||||
|
out_copy[1] ^= chunk1_old[1]; \
|
||||||
|
memcpy_swap64le(out, out_copy, 2); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
|
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
|
||||||
|
@ -201,18 +293,18 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VARIANT2_2_PORTABLE() \
|
#define VARIANT2_2_PORTABLE() \
|
||||||
if (variant >= 2) { \
|
if (variant == 2 || variant == 3) { \
|
||||||
xor_blocks(long_state + (j ^ 0x10), d); \
|
xor_blocks(long_state + (j ^ 0x10), d); \
|
||||||
xor_blocks(d, long_state + (j ^ 0x20)); \
|
xor_blocks(d, long_state + (j ^ 0x20)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VARIANT2_2() \
|
#define VARIANT2_2() \
|
||||||
do if (variant >= 2) \
|
do if (variant == 2 || variant == 3) \
|
||||||
{ \
|
{ \
|
||||||
*U64(hp_state + (j ^ 0x10)) ^= SWAP64LE(hi); \
|
*U64(local_hp_state + (j ^ 0x10)) ^= SWAP64LE(hi); \
|
||||||
*(U64(hp_state + (j ^ 0x10)) + 1) ^= SWAP64LE(lo); \
|
*(U64(local_hp_state + (j ^ 0x10)) + 1) ^= SWAP64LE(lo); \
|
||||||
hi ^= SWAP64LE(*U64(hp_state + (j ^ 0x20))); \
|
hi ^= SWAP64LE(*U64(local_hp_state + (j ^ 0x20))); \
|
||||||
lo ^= SWAP64LE(*(U64(hp_state + (j ^ 0x20)) + 1)); \
|
lo ^= SWAP64LE(*(U64(local_hp_state + (j ^ 0x20)) + 1)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define V4_REG_LOAD(dst, src) \
|
#define V4_REG_LOAD(dst, src) \
|
||||||
|
@ -225,34 +317,56 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define VARIANT4_RANDOM_MATH_INIT() \
|
#define VARIANT4_RANDOM_MATH_INIT() \
|
||||||
v4_reg r[8]; \
|
v4_reg r[9]; \
|
||||||
struct V4_Instruction code[TOTAL_LATENCY * ALU_COUNT + 1]; \
|
struct V4_Instruction code[NUM_INSTRUCTIONS_MAX + 1]; \
|
||||||
|
int jit = use_v4_jit(); \
|
||||||
do if (variant >= 4) \
|
do if (variant >= 4) \
|
||||||
{ \
|
{ \
|
||||||
for (int i = 0; i < 4; ++i) \
|
for (int i = 0; i < 4; ++i) \
|
||||||
V4_REG_LOAD(r + i, (uint8_t*)(state.hs.w + 12) + sizeof(v4_reg) * i); \
|
V4_REG_LOAD(r + i, (uint8_t*)(state.hs.w + 12) + sizeof(v4_reg) * i); \
|
||||||
v4_random_math_init(code, height); \
|
v4_random_math_init(code, height); \
|
||||||
|
if (jit) \
|
||||||
|
{ \
|
||||||
|
int ret = v4_generate_JIT_code(code, hp_jitfunc, 4096); \
|
||||||
|
if (ret < 0) \
|
||||||
|
local_abort("Error generating CryptonightR code"); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define VARIANT4_RANDOM_MATH(a, b, r, _b, _b1) \
|
#define VARIANT4_RANDOM_MATH(a, b, r, _b, _b1) \
|
||||||
do if (variant >= 4) \
|
do if (variant >= 4) \
|
||||||
{ \
|
{ \
|
||||||
uint64_t t; \
|
uint64_t t[2]; \
|
||||||
memcpy(&t, b, sizeof(uint64_t)); \
|
memcpy(t, b, sizeof(uint64_t)); \
|
||||||
\
|
\
|
||||||
if (sizeof(v4_reg) == sizeof(uint32_t)) \
|
if (sizeof(v4_reg) == sizeof(uint32_t)) \
|
||||||
t ^= SWAP64LE((r[0] + r[1]) | ((uint64_t)(r[2] + r[3]) << 32)); \
|
t[0] ^= SWAP64LE((r[0] + r[1]) | ((uint64_t)(r[2] + r[3]) << 32)); \
|
||||||
else \
|
else \
|
||||||
t ^= SWAP64LE((r[0] + r[1]) ^ (r[2] + r[3])); \
|
t[0] ^= SWAP64LE((r[0] + r[1]) ^ (r[2] + r[3])); \
|
||||||
\
|
\
|
||||||
memcpy(b, &t, sizeof(uint64_t)); \
|
memcpy(b, t, sizeof(uint64_t)); \
|
||||||
\
|
\
|
||||||
V4_REG_LOAD(r + 4, a); \
|
V4_REG_LOAD(r + 4, a); \
|
||||||
V4_REG_LOAD(r + 5, (uint64_t*)(a) + 1); \
|
V4_REG_LOAD(r + 5, (uint64_t*)(a) + 1); \
|
||||||
V4_REG_LOAD(r + 6, _b); \
|
V4_REG_LOAD(r + 6, _b); \
|
||||||
V4_REG_LOAD(r + 7, _b1); \
|
V4_REG_LOAD(r + 7, _b1); \
|
||||||
|
V4_REG_LOAD(r + 8, (uint64_t*)(_b1) + 1); \
|
||||||
\
|
\
|
||||||
|
if (jit) \
|
||||||
|
(*hp_jitfunc)(r); \
|
||||||
|
else \
|
||||||
v4_random_math(code, r); \
|
v4_random_math(code, r); \
|
||||||
|
\
|
||||||
|
memcpy(t, a, sizeof(uint64_t) * 2); \
|
||||||
|
\
|
||||||
|
if (sizeof(v4_reg) == sizeof(uint32_t)) { \
|
||||||
|
t[0] ^= SWAP64LE(r[2] | ((uint64_t)(r[3]) << 32)); \
|
||||||
|
t[1] ^= SWAP64LE(r[0] | ((uint64_t)(r[1]) << 32)); \
|
||||||
|
} else { \
|
||||||
|
t[0] ^= SWAP64LE(r[2] ^ r[3]); \
|
||||||
|
t[1] ^= SWAP64LE(r[0] ^ r[1]); \
|
||||||
|
} \
|
||||||
|
memcpy(a, t, sizeof(uint64_t) * 2); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,7 +432,7 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||||
|
|
||||||
#define pre_aes() \
|
#define pre_aes() \
|
||||||
j = state_index(a); \
|
j = state_index(a); \
|
||||||
_c = _mm_load_si128(R128(&hp_state[j])); \
|
_c = _mm_load_si128(R128(&local_hp_state[j])); \
|
||||||
_a = _mm_load_si128(R128(a)); \
|
_a = _mm_load_si128(R128(a)); \
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -331,32 +445,26 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||||
* This code is based upon an optimized implementation by dga.
|
* This code is based upon an optimized implementation by dga.
|
||||||
*/
|
*/
|
||||||
#define post_aes() \
|
#define post_aes() \
|
||||||
VARIANT2_SHUFFLE_ADD_SSE2(hp_state, j); \
|
VARIANT2_SHUFFLE_ADD_SSE2(local_hp_state, j); \
|
||||||
_mm_store_si128(R128(c), _c); \
|
_mm_store_si128(R128(c), _c); \
|
||||||
_mm_store_si128(R128(&hp_state[j]), _mm_xor_si128(_b, _c)); \
|
_mm_store_si128(R128(&local_hp_state[j]), _mm_xor_si128(_b, _c)); \
|
||||||
VARIANT1_1(&hp_state[j]); \
|
VARIANT1_1(&local_hp_state[j]); \
|
||||||
j = state_index(c); \
|
j = state_index(c); \
|
||||||
p = U64(&hp_state[j]); \
|
p = U64(&local_hp_state[j]); \
|
||||||
b[0] = p[0]; b[1] = p[1]; \
|
b[0] = p[0]; b[1] = p[1]; \
|
||||||
VARIANT2_INTEGER_MATH_SSE2(b, c); \
|
VARIANT2_INTEGER_MATH_SSE2(b, c); \
|
||||||
VARIANT4_RANDOM_MATH(a, b, r, &_b, &_b1); \
|
VARIANT4_RANDOM_MATH(a, b, r, &_b, &_b1); \
|
||||||
__mul(); \
|
__mul(); \
|
||||||
VARIANT2_2(); \
|
VARIANT2_2(); \
|
||||||
VARIANT2_SHUFFLE_ADD_SSE2(hp_state, j); \
|
VARIANT2_SHUFFLE_ADD_SSE2(local_hp_state, j); \
|
||||||
a[0] += hi; a[1] += lo; \
|
a[0] += hi; a[1] += lo; \
|
||||||
p = U64(&hp_state[j]); \
|
p = U64(&local_hp_state[j]); \
|
||||||
p[0] = a[0]; p[1] = a[1]; \
|
p[0] = a[0]; p[1] = a[1]; \
|
||||||
a[0] ^= b[0]; a[1] ^= b[1]; \
|
a[0] ^= b[0]; a[1] ^= b[1]; \
|
||||||
VARIANT1_2(p + 1); \
|
VARIANT1_2(p + 1); \
|
||||||
_b1 = _b; \
|
_b1 = _b; \
|
||||||
_b = _c; \
|
_b = _c; \
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define THREADV __declspec(thread)
|
|
||||||
#else
|
|
||||||
#define THREADV __thread
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
union cn_slow_hash_state
|
union cn_slow_hash_state
|
||||||
{
|
{
|
||||||
|
@ -371,6 +479,9 @@ union cn_slow_hash_state
|
||||||
|
|
||||||
THREADV uint8_t *hp_state = NULL;
|
THREADV uint8_t *hp_state = NULL;
|
||||||
THREADV int hp_allocated = 0;
|
THREADV int hp_allocated = 0;
|
||||||
|
THREADV v4_random_math_JIT_func hp_jitfunc = NULL;
|
||||||
|
THREADV uint8_t *hp_jitfunc_memory = NULL;
|
||||||
|
THREADV int hp_jitfunc_allocated = 0;
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define cpuid(info,x) __cpuidex(info,x,0)
|
#define cpuid(info,x) __cpuidex(info,x,0)
|
||||||
|
@ -409,25 +520,6 @@ STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
|
||||||
* @return true if the CPU supports AES, false otherwise
|
* @return true if the CPU supports AES, false otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC INLINE int force_software_aes(void)
|
|
||||||
{
|
|
||||||
static int use = -1;
|
|
||||||
|
|
||||||
if (use != -1)
|
|
||||||
return use;
|
|
||||||
|
|
||||||
const char *env = getenv("MONERO_USE_SOFTWARE_AES");
|
|
||||||
if (!env) {
|
|
||||||
use = 0;
|
|
||||||
}
|
|
||||||
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
|
||||||
use = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
use = 1;
|
|
||||||
}
|
|
||||||
return use;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC INLINE int check_aes_hw(void)
|
STATIC INLINE int check_aes_hw(void)
|
||||||
{
|
{
|
||||||
|
@ -666,10 +758,10 @@ void cn_slow_hash_allocate_state(void)
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||||
defined(__DragonFly__) || defined(__NetBSD__)
|
defined(__DragonFly__) || defined(__NetBSD__)
|
||||||
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANON, 0, 0);
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
#else
|
#else
|
||||||
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, 0, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
|
||||||
#endif
|
#endif
|
||||||
if(hp_state == MAP_FAILED)
|
if(hp_state == MAP_FAILED)
|
||||||
hp_state = NULL;
|
hp_state = NULL;
|
||||||
|
@ -680,6 +772,35 @@ void cn_slow_hash_allocate_state(void)
|
||||||
hp_allocated = 0;
|
hp_allocated = 0;
|
||||||
hp_state = (uint8_t *) malloc(MEMORY);
|
hp_state = (uint8_t *) malloc(MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
hp_jitfunc_memory = (uint8_t *) VirtualAlloc(hp_jitfunc_memory, 4096 + 4095,
|
||||||
|
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||||
|
defined(__DragonFly__) || defined(__NetBSD__)
|
||||||
|
#ifdef __NetBSD__
|
||||||
|
#define RESERVED_FLAGS PROT_MPROTECT(PROT_EXEC)
|
||||||
|
#else
|
||||||
|
#define RESERVED_FLAGS 0
|
||||||
|
#endif
|
||||||
|
hp_jitfunc_memory = mmap(0, 4096 + 4096, PROT_READ | PROT_WRITE | RESERVED_FLAGS,
|
||||||
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
|
#else
|
||||||
|
hp_jitfunc_memory = mmap(0, 4096 + 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
#endif
|
||||||
|
if(hp_jitfunc_memory == MAP_FAILED)
|
||||||
|
hp_jitfunc_memory = NULL;
|
||||||
|
#endif
|
||||||
|
hp_jitfunc_allocated = 1;
|
||||||
|
if (hp_jitfunc_memory == NULL)
|
||||||
|
{
|
||||||
|
hp_jitfunc_allocated = 0;
|
||||||
|
hp_jitfunc_memory = malloc(4096 + 4095);
|
||||||
|
}
|
||||||
|
hp_jitfunc = (v4_random_math_JIT_func)((size_t)(hp_jitfunc_memory + 4095) & ~4095);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -702,8 +823,22 @@ void cn_slow_hash_free_state(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!hp_jitfunc_allocated)
|
||||||
|
free(hp_jitfunc_memory);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
VirtualFree(hp_jitfunc_memory, 0, MEM_RELEASE);
|
||||||
|
#else
|
||||||
|
munmap(hp_jitfunc_memory, 4096 + 4095);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
hp_state = NULL;
|
hp_state = NULL;
|
||||||
hp_allocated = 0;
|
hp_allocated = 0;
|
||||||
|
hp_jitfunc = NULL;
|
||||||
|
hp_jitfunc_memory = NULL;
|
||||||
|
hp_jitfunc_allocated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -787,7 +922,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
{
|
{
|
||||||
aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK);
|
aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK);
|
||||||
memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -799,7 +934,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
for(j = 0; j < INIT_SIZE_BLK; j++)
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||||
|
|
||||||
memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,7 +982,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
{
|
{
|
||||||
// add the xor to the pseudo round
|
// add the xor to the pseudo round
|
||||||
aes_pseudo_round_xor(text, text, expandedKey, &hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
aes_pseudo_round_xor(text, text, expandedKey, &local_hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -857,7 +992,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
{
|
{
|
||||||
for(j = 0; j < INIT_SIZE_BLK; j++)
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
{
|
{
|
||||||
xor_blocks(&text[j * AES_BLOCK_SIZE], &hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
xor_blocks(&text[j * AES_BLOCK_SIZE], &local_hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||||
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -877,6 +1012,44 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif !defined NO_AES && (defined(__arm__) || defined(__aarch64__))
|
#elif !defined NO_AES && (defined(__arm__) || defined(__aarch64__))
|
||||||
|
#ifdef __aarch64__
|
||||||
|
#include <sys/mman.h>
|
||||||
|
THREADV uint8_t *hp_state = NULL;
|
||||||
|
THREADV int hp_malloced = 0;
|
||||||
|
|
||||||
|
void cn_slow_hash_allocate_state(void)
|
||||||
|
{
|
||||||
|
if(hp_state != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifndef MAP_HUGETLB
|
||||||
|
#define MAP_HUGETLB 0
|
||||||
|
#endif
|
||||||
|
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0);
|
||||||
|
|
||||||
|
if(hp_state == MAP_FAILED)
|
||||||
|
hp_state = NULL;
|
||||||
|
if(hp_state == NULL)
|
||||||
|
{
|
||||||
|
hp_malloced = 1;
|
||||||
|
hp_state = (uint8_t *) malloc(MEMORY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cn_slow_hash_free_state(void)
|
||||||
|
{
|
||||||
|
if(hp_state == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hp_malloced)
|
||||||
|
free(hp_state);
|
||||||
|
else
|
||||||
|
munmap(hp_state, MEMORY);
|
||||||
|
hp_state = NULL;
|
||||||
|
hp_malloced = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
void cn_slow_hash_allocate_state(void)
|
void cn_slow_hash_allocate_state(void)
|
||||||
{
|
{
|
||||||
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
||||||
|
@ -888,6 +1061,7 @@ void cn_slow_hash_free_state(void)
|
||||||
// As above
|
// As above
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define RDATA_ALIGN16 __attribute__ ((aligned(16)))
|
#define RDATA_ALIGN16 __attribute__ ((aligned(16)))
|
||||||
|
@ -901,6 +1075,8 @@ void cn_slow_hash_free_state(void)
|
||||||
|
|
||||||
#define U64(x) ((uint64_t *) (x))
|
#define U64(x) ((uint64_t *) (x))
|
||||||
|
|
||||||
|
#define hp_jitfunc ((v4_random_math_JIT_func)NULL)
|
||||||
|
|
||||||
STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
|
STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
|
||||||
{
|
{
|
||||||
*a ^= b;
|
*a ^= b;
|
||||||
|
@ -926,6 +1102,23 @@ union cn_slow_hash_state
|
||||||
* and moving between vector and regular registers stalls the pipeline.
|
* and moving between vector and regular registers stalls the pipeline.
|
||||||
*/
|
*/
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
#ifndef __APPLE__
|
||||||
|
#include <sys/auxv.h>
|
||||||
|
#include <asm/hwcap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STATIC INLINE int check_aes_hw(void)
|
||||||
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
static int supported = -1;
|
||||||
|
|
||||||
|
if(supported < 0)
|
||||||
|
supported = (getauxval(AT_HWCAP) & HWCAP_AES) != 0;
|
||||||
|
return supported;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE)
|
#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE)
|
||||||
|
|
||||||
|
@ -935,24 +1128,24 @@ union cn_slow_hash_state
|
||||||
|
|
||||||
#define pre_aes() \
|
#define pre_aes() \
|
||||||
j = state_index(a); \
|
j = state_index(a); \
|
||||||
_c = vld1q_u8(&hp_state[j]); \
|
_c = vld1q_u8(&local_hp_state[j]); \
|
||||||
_a = vld1q_u8((const uint8_t *)a); \
|
_a = vld1q_u8((const uint8_t *)a); \
|
||||||
|
|
||||||
#define post_aes() \
|
#define post_aes() \
|
||||||
VARIANT2_SHUFFLE_ADD_NEON(hp_state, j); \
|
VARIANT2_SHUFFLE_ADD_NEON(local_hp_state, j); \
|
||||||
vst1q_u8((uint8_t *)c, _c); \
|
vst1q_u8((uint8_t *)c, _c); \
|
||||||
vst1q_u8(&hp_state[j], veorq_u8(_b, _c)); \
|
vst1q_u8(&local_hp_state[j], veorq_u8(_b, _c)); \
|
||||||
VARIANT1_1(&hp_state[j]); \
|
VARIANT1_1(&local_hp_state[j]); \
|
||||||
j = state_index(c); \
|
j = state_index(c); \
|
||||||
p = U64(&hp_state[j]); \
|
p = U64(&local_hp_state[j]); \
|
||||||
b[0] = p[0]; b[1] = p[1]; \
|
b[0] = p[0]; b[1] = p[1]; \
|
||||||
VARIANT2_PORTABLE_INTEGER_MATH(b, c); \
|
VARIANT2_PORTABLE_INTEGER_MATH(b, c); \
|
||||||
VARIANT4_RANDOM_MATH(a, b, r, &_b, &_b1); \
|
VARIANT4_RANDOM_MATH(a, b, r, &_b, &_b1); \
|
||||||
__mul(); \
|
__mul(); \
|
||||||
VARIANT2_2(); \
|
VARIANT2_2(); \
|
||||||
VARIANT2_SHUFFLE_ADD_NEON(hp_state, j); \
|
VARIANT2_SHUFFLE_ADD_NEON(local_hp_state, j); \
|
||||||
a[0] += hi; a[1] += lo; \
|
a[0] += hi; a[1] += lo; \
|
||||||
p = U64(&hp_state[j]); \
|
p = U64(&local_hp_state[j]); \
|
||||||
p[0] = a[0]; p[1] = a[1]; \
|
p[0] = a[0]; p[1] = a[1]; \
|
||||||
a[0] ^= b[0]; a[1] ^= b[1]; \
|
a[0] ^= b[0]; a[1] ^= b[1]; \
|
||||||
VARIANT1_2(p + 1); \
|
VARIANT1_2(p + 1); \
|
||||||
|
@ -1022,7 +1215,6 @@ __asm__(
|
||||||
STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey, int nblocks)
|
STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey, int nblocks)
|
||||||
{
|
{
|
||||||
const uint8x16_t *k = (const uint8x16_t *)expandedKey, zero = {0};
|
const uint8x16_t *k = (const uint8x16_t *)expandedKey, zero = {0};
|
||||||
uint8x16_t tmp;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<nblocks; i++)
|
for (i=0; i<nblocks; i++)
|
||||||
|
@ -1057,7 +1249,6 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u
|
||||||
{
|
{
|
||||||
const uint8x16_t *k = (const uint8x16_t *)expandedKey;
|
const uint8x16_t *k = (const uint8x16_t *)expandedKey;
|
||||||
const uint8x16_t *x = (const uint8x16_t *)xor;
|
const uint8x16_t *x = (const uint8x16_t *)xor;
|
||||||
uint8x16_t tmp;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<nblocks; i++)
|
for (i=0; i<nblocks; i++)
|
||||||
|
@ -1110,16 +1301,17 @@ STATIC INLINE void aligned_free(void *ptr)
|
||||||
}
|
}
|
||||||
#endif /* FORCE_USE_HEAP */
|
#endif /* FORCE_USE_HEAP */
|
||||||
|
|
||||||
|
STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b)
|
||||||
|
{
|
||||||
|
U64(a)[0] ^= U64(b)[0];
|
||||||
|
U64(a)[1] ^= U64(b)[1];
|
||||||
|
}
|
||||||
|
|
||||||
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height)
|
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height)
|
||||||
{
|
{
|
||||||
RDATA_ALIGN16 uint8_t expandedKey[240];
|
RDATA_ALIGN16 uint8_t expandedKey[240];
|
||||||
|
|
||||||
#ifndef FORCE_USE_HEAP
|
uint8_t *local_hp_state;
|
||||||
RDATA_ALIGN16 uint8_t hp_state[MEMORY];
|
|
||||||
#else
|
|
||||||
uint8_t *hp_state = (uint8_t *)aligned_malloc(MEMORY,16);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t text[INIT_SIZE_BYTE];
|
uint8_t text[INIT_SIZE_BYTE];
|
||||||
RDATA_ALIGN16 uint64_t a[2];
|
RDATA_ALIGN16 uint64_t a[2];
|
||||||
RDATA_ALIGN16 uint64_t b[4];
|
RDATA_ALIGN16 uint64_t b[4];
|
||||||
|
@ -1130,12 +1322,22 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
|
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
uint64_t *p = NULL;
|
uint64_t *p = NULL;
|
||||||
|
oaes_ctx *aes_ctx = NULL;
|
||||||
|
int useAes = !force_software_aes() && check_aes_hw();
|
||||||
|
|
||||||
static void (*const extra_hashes[4])(const void *, size_t, char *) =
|
static void (*const extra_hashes[4])(const void *, size_t, char *) =
|
||||||
{
|
{
|
||||||
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
|
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// this isn't supposed to happen, but guard against it for now.
|
||||||
|
if(hp_state == NULL)
|
||||||
|
cn_slow_hash_allocate_state();
|
||||||
|
|
||||||
|
// locals to avoid constant TLS dereferencing
|
||||||
|
local_hp_state = hp_state;
|
||||||
|
|
||||||
|
// locals to avoid constant TLS dereferencing
|
||||||
/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */
|
/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */
|
||||||
|
|
||||||
if (prehashed) {
|
if (prehashed) {
|
||||||
|
@ -1153,11 +1355,26 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
* the 2MB large random access buffer.
|
* the 2MB large random access buffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if(useAes)
|
||||||
|
{
|
||||||
aes_expand_key(state.hs.b, expandedKey);
|
aes_expand_key(state.hs.b, expandedKey);
|
||||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
{
|
{
|
||||||
aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK);
|
aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK);
|
||||||
memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aes_ctx = (oaes_ctx *) oaes_alloc();
|
||||||
|
oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
|
||||||
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
|
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||||
|
|
||||||
|
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0];
|
U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0];
|
||||||
|
@ -1173,6 +1390,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
_b = vld1q_u8((const uint8_t *)b);
|
_b = vld1q_u8((const uint8_t *)b);
|
||||||
_b1 = vld1q_u8(((const uint8_t *)b) + AES_BLOCK_SIZE);
|
_b1 = vld1q_u8(((const uint8_t *)b) + AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if(useAes)
|
||||||
|
{
|
||||||
for(i = 0; i < ITER / 2; i++)
|
for(i = 0; i < ITER / 2; i++)
|
||||||
{
|
{
|
||||||
pre_aes();
|
pre_aes();
|
||||||
|
@ -1181,6 +1400,17 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
_c = veorq_u8(_c, _a);
|
_c = veorq_u8(_c, _a);
|
||||||
post_aes();
|
post_aes();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = 0; i < ITER / 2; i++)
|
||||||
|
{
|
||||||
|
pre_aes();
|
||||||
|
aesb_single_round((uint8_t *) &_c, (uint8_t *) &_c, (uint8_t *) &_a);
|
||||||
|
post_aes();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* CryptoNight Step 4: Sequentially pass through the mixing buffer and use 10 rounds
|
/* CryptoNight Step 4: Sequentially pass through the mixing buffer and use 10 rounds
|
||||||
* of AES encryption to mix the random data back into the 'text' buffer. 'text'
|
* of AES encryption to mix the random data back into the 'text' buffer. 'text'
|
||||||
|
@ -1188,11 +1418,27 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
|
|
||||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||||
|
|
||||||
|
if(useAes)
|
||||||
|
{
|
||||||
aes_expand_key(&state.hs.b[32], expandedKey);
|
aes_expand_key(&state.hs.b[32], expandedKey);
|
||||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
{
|
{
|
||||||
// add the xor to the pseudo round
|
// add the xor to the pseudo round
|
||||||
aes_pseudo_round_xor(text, text, expandedKey, &hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
aes_pseudo_round_xor(text, text, expandedKey, &local_hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
|
{
|
||||||
|
xor_blocks(&text[j * AES_BLOCK_SIZE], &local_hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oaes_free((OAES_CTX **) &aes_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CryptoNight Step 5: Apply Keccak to the state again, and then
|
/* CryptoNight Step 5: Apply Keccak to the state again, and then
|
||||||
|
@ -1205,10 +1451,6 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
memcpy(state.init, text, INIT_SIZE_BYTE);
|
memcpy(state.init, text, INIT_SIZE_BYTE);
|
||||||
hash_permutation(&state.hs);
|
hash_permutation(&state.hs);
|
||||||
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
||||||
|
|
||||||
#ifdef FORCE_USE_HEAP
|
|
||||||
aligned_free(hp_state);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#else /* aarch64 && crypto */
|
#else /* aarch64 && crypto */
|
||||||
|
|
||||||
|
@ -1330,6 +1572,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
{
|
{
|
||||||
uint8_t text[INIT_SIZE_BYTE];
|
uint8_t text[INIT_SIZE_BYTE];
|
||||||
uint8_t a[AES_BLOCK_SIZE];
|
uint8_t a[AES_BLOCK_SIZE];
|
||||||
|
uint8_t a1[AES_BLOCK_SIZE];
|
||||||
uint8_t b[AES_BLOCK_SIZE * 2];
|
uint8_t b[AES_BLOCK_SIZE * 2];
|
||||||
uint8_t c[AES_BLOCK_SIZE];
|
uint8_t c[AES_BLOCK_SIZE];
|
||||||
uint8_t c1[AES_BLOCK_SIZE];
|
uint8_t c1[AES_BLOCK_SIZE];
|
||||||
|
@ -1389,10 +1632,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
// Iteration 1
|
// Iteration 1
|
||||||
j = state_index(a);
|
j = state_index(a);
|
||||||
p = &long_state[j];
|
p = &long_state[j];
|
||||||
aesb_single_round(p, p, a);
|
aesb_single_round(p, c1, a);
|
||||||
copy_block(c1, p);
|
|
||||||
|
|
||||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||||
|
copy_block(p, c1);
|
||||||
xor_blocks(p, b);
|
xor_blocks(p, b);
|
||||||
VARIANT1_1(p);
|
VARIANT1_1(p);
|
||||||
|
|
||||||
|
@ -1401,14 +1644,15 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
p = &long_state[j];
|
p = &long_state[j];
|
||||||
copy_block(c, p);
|
copy_block(c, p);
|
||||||
|
|
||||||
|
copy_block(a1, a);
|
||||||
VARIANT2_PORTABLE_INTEGER_MATH(c, c1);
|
VARIANT2_PORTABLE_INTEGER_MATH(c, c1);
|
||||||
VARIANT4_RANDOM_MATH(a, c, r, b, b + AES_BLOCK_SIZE);
|
VARIANT4_RANDOM_MATH(a1, c, r, b, b + AES_BLOCK_SIZE);
|
||||||
mul(c1, c, d);
|
mul(c1, c, d);
|
||||||
VARIANT2_2_PORTABLE();
|
VARIANT2_2_PORTABLE();
|
||||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||||
sum_half_blocks(a, d);
|
sum_half_blocks(a1, d);
|
||||||
swap_blocks(a, c);
|
swap_blocks(a1, c);
|
||||||
xor_blocks(a, c);
|
xor_blocks(a1, c);
|
||||||
VARIANT1_2(U64(c) + 1);
|
VARIANT1_2(U64(c) + 1);
|
||||||
copy_block(p, c);
|
copy_block(p, c);
|
||||||
|
|
||||||
|
@ -1416,6 +1660,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
copy_block(b + AES_BLOCK_SIZE, b);
|
copy_block(b + AES_BLOCK_SIZE, b);
|
||||||
}
|
}
|
||||||
copy_block(b, c1);
|
copy_block(b, c1);
|
||||||
|
copy_block(a, a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||||
|
@ -1443,7 +1688,9 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
#else
|
#else
|
||||||
// Portable implementation as a fallback
|
// Portable implementation as a fallback
|
||||||
|
|
||||||
void slow_hash_allocate_state(void)
|
#define hp_jitfunc ((v4_random_math_JIT_func)NULL)
|
||||||
|
|
||||||
|
void cn_slow_hash_allocate_state(void)
|
||||||
{
|
{
|
||||||
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
||||||
return;
|
return;
|
||||||
|
@ -1536,6 +1783,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
union cn_slow_hash_state state;
|
union cn_slow_hash_state state;
|
||||||
uint8_t text[INIT_SIZE_BYTE];
|
uint8_t text[INIT_SIZE_BYTE];
|
||||||
uint8_t a[AES_BLOCK_SIZE];
|
uint8_t a[AES_BLOCK_SIZE];
|
||||||
|
uint8_t a1[AES_BLOCK_SIZE];
|
||||||
uint8_t b[AES_BLOCK_SIZE * 2];
|
uint8_t b[AES_BLOCK_SIZE * 2];
|
||||||
uint8_t c1[AES_BLOCK_SIZE];
|
uint8_t c1[AES_BLOCK_SIZE];
|
||||||
uint8_t c2[AES_BLOCK_SIZE];
|
uint8_t c2[AES_BLOCK_SIZE];
|
||||||
|
@ -1579,7 +1827,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
j = e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
|
j = e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
|
||||||
copy_block(c1, &long_state[j]);
|
copy_block(c1, &long_state[j]);
|
||||||
aesb_single_round(c1, c1, a);
|
aesb_single_round(c1, c1, a);
|
||||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||||
copy_block(&long_state[j], c1);
|
copy_block(&long_state[j], c1);
|
||||||
xor_blocks(&long_state[j], b);
|
xor_blocks(&long_state[j], b);
|
||||||
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
|
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
|
||||||
|
@ -1587,23 +1835,22 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||||
/* Iteration 2 */
|
/* Iteration 2 */
|
||||||
j = e2i(c1, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
|
j = e2i(c1, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
|
||||||
copy_block(c2, &long_state[j]);
|
copy_block(c2, &long_state[j]);
|
||||||
|
copy_block(a1, a);
|
||||||
VARIANT2_PORTABLE_INTEGER_MATH(c2, c1);
|
VARIANT2_PORTABLE_INTEGER_MATH(c2, c1);
|
||||||
VARIANT4_RANDOM_MATH(a, c2, r, b, b + AES_BLOCK_SIZE);
|
VARIANT4_RANDOM_MATH(a1, c2, r, b, b + AES_BLOCK_SIZE);
|
||||||
mul(c1, c2, d);
|
mul(c1, c2, d);
|
||||||
VARIANT2_2_PORTABLE();
|
VARIANT2_2_PORTABLE();
|
||||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||||
swap_blocks(a, c1);
|
sum_half_blocks(a1, d);
|
||||||
sum_half_blocks(c1, d);
|
swap_blocks(a1, c2);
|
||||||
swap_blocks(c1, c2);
|
xor_blocks(a1, c2);
|
||||||
xor_blocks(c1, c2);
|
|
||||||
VARIANT1_2(c2 + 8);
|
VARIANT1_2(c2 + 8);
|
||||||
copy_block(&long_state[j], c2);
|
copy_block(&long_state[j], c2);
|
||||||
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
|
|
||||||
if (variant >= 2) {
|
if (variant >= 2) {
|
||||||
copy_block(b + AES_BLOCK_SIZE, b);
|
copy_block(b + AES_BLOCK_SIZE, b);
|
||||||
}
|
}
|
||||||
copy_block(b, a);
|
copy_block(b, c1);
|
||||||
copy_block(a, c1);
|
copy_block(a, a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||||
|
|
|
@ -12,6 +12,12 @@ enum V4_Settings
|
||||||
// Always generate at least 60 instructions
|
// Always generate at least 60 instructions
|
||||||
NUM_INSTRUCTIONS = 60,
|
NUM_INSTRUCTIONS = 60,
|
||||||
|
|
||||||
|
// Always generate at least 60 instructions
|
||||||
|
NUM_INSTRUCTIONS_MIN = 60,
|
||||||
|
|
||||||
|
// Never generate more than 70 instructions (final RET instruction doesn't count here)
|
||||||
|
NUM_INSTRUCTIONS_MAX = 70,
|
||||||
|
|
||||||
// Available ALUs for MUL
|
// Available ALUs for MUL
|
||||||
// Modern CPUs typically have only 1 ALU which can do multiplications
|
// Modern CPUs typically have only 1 ALU which can do multiplications
|
||||||
ALU_COUNT_MUL = 1,
|
ALU_COUNT_MUL = 1,
|
||||||
|
|
|
@ -691,8 +691,6 @@ namespace nodetool
|
||||||
std::set<std::string> full_addrs;
|
std::set<std::string> full_addrs;
|
||||||
if (m_nettype == cryptonote::TESTNET)
|
if (m_nettype == cryptonote::TESTNET)
|
||||||
{
|
{
|
||||||
full_addrs.insert("207.254.29.107:11180");
|
|
||||||
full_addrs.insert("135.148.138.255:11180");
|
|
||||||
}
|
}
|
||||||
else if (m_nettype == cryptonote::STAGENET)
|
else if (m_nettype == cryptonote::STAGENET)
|
||||||
{
|
{
|
||||||
|
@ -702,8 +700,8 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
full_addrs.insert("158.69.60.225:34567"); // OVH France
|
full_addrs.insert("158.69.60.225:34567"); // explore.wownero.com
|
||||||
full_addrs.insert("159.65.91.59:34567"); // DigiO london
|
full_addrs.insert("159.65.91.59:34567"); // jw
|
||||||
full_addrs.insert("164.90.230.176:34567"); // de1.wownodes.com
|
full_addrs.insert("164.90.230.176:34567"); // de1.wownodes.com
|
||||||
full_addrs.insert("64.227.81.144:34567"); // us1.wownodes.com
|
full_addrs.insert("64.227.81.144:34567"); // us1.wownodes.com
|
||||||
full_addrs.insert("188.166.237.187:34567"); // sg1.wownodes.com
|
full_addrs.insert("188.166.237.187:34567"); // sg1.wownodes.com
|
||||||
|
@ -711,6 +709,11 @@ namespace nodetool
|
||||||
full_addrs.insert("167.114.196.241:34567"); // wowbux.org
|
full_addrs.insert("167.114.196.241:34567"); // wowbux.org
|
||||||
full_addrs.insert("135.148.138.255:34567");
|
full_addrs.insert("135.148.138.255:34567");
|
||||||
full_addrs.insert("207.254.29.107:34567");
|
full_addrs.insert("207.254.29.107:34567");
|
||||||
|
full_addrs.insert("142.93.144.79:34567"); // idontwanttogototoronto.wow.fail
|
||||||
|
full_addrs.insert("51.75.76.161:34567"); // eu-west-1.wow.xmr.pm
|
||||||
|
full_addrs.insert("145.239.93.75:34567"); // eu-west-2.wow.xmr.pm
|
||||||
|
full_addrs.insert("88.198.199.23:34567");
|
||||||
|
full_addrs.insert("167.114.119.46:34567"); // wownero.stackwallet.com
|
||||||
}
|
}
|
||||||
return full_addrs;
|
return full_addrs;
|
||||||
}
|
}
|
||||||
|
@ -843,6 +846,7 @@ namespace nodetool
|
||||||
"nepc4lxndsooj2akn7ofrj3ooqc25242obchcag6tw3f2mxrms2uuvyd.onion:34566",
|
"nepc4lxndsooj2akn7ofrj3ooqc25242obchcag6tw3f2mxrms2uuvyd.onion:34566",
|
||||||
"666l2ajxqjgj5lskvbokvworjysgvqag4oitokjuy7wz6juisul4jqad.onion:34566",
|
"666l2ajxqjgj5lskvbokvworjysgvqag4oitokjuy7wz6juisul4jqad.onion:34566",
|
||||||
"ty7ppqozzodz75audgvkprekiiqsovbyrkfdjwadrkbe3etyzloatxad.onion:34566",
|
"ty7ppqozzodz75audgvkprekiiqsovbyrkfdjwadrkbe3etyzloatxad.onion:34566",
|
||||||
|
"77uase4p6y6jsjdf6z2kdgpxgh7nkvywagvhurzphbm7vrkyj2d2gdid.onion:34566",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|
Loading…
Reference in New Issue